luet commited on
Commit
840d1ee
·
1 Parent(s): cb8f33f

timeline difference previous release don't work

Browse files
Files changed (1) hide show
  1. app.py +307 -183
app.py CHANGED
@@ -2,218 +2,342 @@ import gradio as gr
2
  import json
3
  import os
4
  from datetime import datetime
 
 
 
5
 
6
- # File to store model data
7
- MODEL_FILE = "models.json"
8
-
9
- # Load existing data or create a new file if it doesn't exist
10
- def load_models():
11
- if os.path.exists(MODEL_FILE):
12
- with open(MODEL_FILE, "r") as f:
13
- return json.load(f)
14
- return []
15
-
16
- # Save data to the JSON file
17
- def save_models(models):
18
- with open(MODEL_FILE, "w") as f:
19
- json.dump(models, f, indent=4)
20
-
21
- # Helper function to calculate time differences between releases
22
- def calculate_time_difference(models):
23
- for i in range(1, len(models)):
24
- prev_date = datetime.strptime(models[i - 1]['dateOfRelease'], "%Y-%m-%d")
25
- curr_date = datetime.strptime(models[i]['dateOfRelease'], "%Y-%m-%d")
26
- models[i]['time_difference'] = (curr_date - prev_date).days
27
- return models
28
-
29
- # Function to display all models with optional filters
30
- def display_models(developer=None, use_case=None, year_range=None):
31
- models = load_models()
32
- if not models:
33
- return "No models have been added yet."
34
-
35
- # Apply filters if provided
36
- if developer:
37
- models = [m for m in models if m.get('developer') == developer]
38
- if use_case:
39
- models = [m for m in models if m.get('use_case') == use_case]
40
- if year_range:
41
- start_year, end_year = year_range
42
- models = [m for m in models if start_year <= int(m['dateOfRelease'][:4]) <= end_year]
43
-
44
- models = sorted(models, key=lambda x: x['dateOfRelease'], reverse=True) # Sort by release date
45
-
46
- # Calculate time differences before using them
47
- models = calculate_time_difference(models) # Ensure time differences are calculated here
48
-
49
- output = "<div style='display: flex; flex-direction: column; align-items: flex-start; gap: 20px;'>"
50
- for i, model in enumerate(models):
51
- time_gap = model.get('time_difference', 0) * 2 # Scale time gap for visualization
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- if i < len(models) - 1: # To show time difference text only between cards, not after the last one
54
- # Safely access the time difference and display it
55
- time_diff = model.get('time_difference', None)
56
- if time_diff is not None:
57
- time_diff_text = f"<div style='color: #ccc; font-style: italic;'>"
58
- time_diff_text += f"{time_diff} days between releases</div>"
59
- output += time_diff_text
60
 
61
- # Add the model card with the time gap applied between models
62
- # output += f"<div class='ai-card' style='margin-top: {time_gap}px;'>"
63
- output += f"<div class='ai-card'>"
64
- output += f"<h3 style='color: #2d89ef;'>{model['name']} ({model['dateOfRelease']})</h3>"
65
- output += f"<p><strong>Description:</strong> {model['description']}</p>"
66
- output += f"<p><strong>Developer:</strong> {model.get('developer', 'Unknown')}</p>"
67
- output += f"<p><strong>Use Case:</strong> {model.get('use_case', 'General')}</p>"
68
- output += f"<p><strong>Impact:</strong> {model.get('impact', 'Not specified')}</p>"
69
- output += "</div>"
70
 
 
 
71
 
72
- output += "</div>"
73
- return output
74
-
75
-
76
- # Function to add a new model
77
- def add_model(name, description, dateOfRelease, developer, use_case, impact):
78
- models = load_models()
79
- models.append({
80
- "name": name,
81
- "description": description,
82
- "dateOfRelease": dateOfRelease,
83
- "developer": developer,
84
- "use_case": use_case,
85
- "impact": impact
86
- })
87
- save_models(models)
88
- return "Model added successfully!", display_models()
89
-
90
- # Function to edit an existing model
91
- def edit_model(index, name, description, dateOfRelease, developer, use_case, impact):
92
- models = load_models()
93
- if index < 1 or index > len(models):
94
- return "Invalid index. Please provide a valid model number.", display_models()
95
- models[index - 1] = {
96
- "name": name,
97
- "description": description,
98
- "dateOfRelease": dateOfRelease,
99
- "developer": developer,
100
- "use_case": use_case,
101
- "impact": impact
102
- }
103
- save_models(models)
104
- return "Model updated successfully!", display_models()
 
 
 
105
 
106
- # Get the current month
107
- def get_current_month():
108
- return datetime.now().strftime("%B %Y")
109
 
110
- # Gradio interface
111
- with gr.Blocks(css="""
112
  body {
113
  font-family: 'Arial', sans-serif;
114
- background-color: #121212; /* Dark background color */
115
- color: white; /* White text color for better contrast */
116
  margin: 0;
117
  padding: 0;
118
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  .gradio-container {
120
  width: 80%;
121
  margin: auto;
122
  padding: 20px;
123
  }
124
  .gradio-markdown {
125
- color: white; /* Ensure markdown text is white */
126
  }
127
  .gr-button {
128
- background-color: #333; /* Dark button background */
129
- color: white; /* White button text */
130
  }
131
  .gr-button:hover {
132
- background-color: #555; /* Lighter shade on hover */
133
  }
134
  .gr-dropdown, .gr-textbox {
135
- background-color: #333; /* Dark input fields */
136
- color: white; /* White text */
137
- border: 1px solid #555; /* Lighter border */
138
  }
139
-
140
- /* Styling for the AI cards */
141
- .ai-card {
142
- background-color: #2b2b2b; /* Dark background for cards */
143
- color: white; /* White text on cards */
144
- border-radius: 10px;
145
- padding: 15px;
146
- margin: 10px 0;
147
- border: 1px solid #444; /* Lighter border for card separation */
148
- box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.5); /* Shadow effect */
149
  }
150
-
151
- .ai-card h3 {
152
- color: #2d89ef; /* Blue color for card titles */
 
 
 
 
153
  }
154
-
155
- .ai-card p {
156
- color: #ccc; /* Lighter text color for card description */
 
 
 
 
157
  }
 
158
 
159
- .ai-card strong {
160
- color: #bbb; /* Lighter color for strong text */
161
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
- """) as app:
164
- gr.Markdown("# AI Timeline\n\nVisualize the development of AI models through an interactive timeline.")
165
- current_month = get_current_month() # Get the current month
166
-
167
- # Display current month in the interface
168
- gr.Markdown(f"## Current Month: {current_month}")
169
-
170
- with gr.Tab("View Timeline"):
171
- with gr.Row():
172
- developer_filter = gr.Dropdown(label="Filter by Developer", choices=["All"] + list(set([m['developer'] for m in load_models()])), value="All")
173
- use_case_filter = gr.Dropdown(label="Filter by Use Case", choices=["All"] + list(set([m['use_case'] for m in load_models()])), value="All")
174
- year_range_filter = gr.Slider(label="Filter by Year Range", minimum=2000, maximum=2025, value=(2000, 2025), step=1)
175
- filter_button = gr.Button("Apply Filters")
176
- view_output = gr.HTML()
177
-
178
- def apply_filters(developer, use_case, year_range):
179
- dev = None if developer == "All" else developer
180
- use = None if use_case == "All" else use_case
181
- return display_models(developer=dev, use_case=use, year_range=year_range)
182
-
183
- filter_button.click(apply_filters, inputs=[developer_filter, use_case_filter, year_range_filter], outputs=view_output)
184
-
185
- with gr.Tab("Add Model"):
186
- with gr.Row():
187
- name_input = gr.Textbox(label="Model Name", placeholder="Enter model name")
188
- year_input = gr.Textbox(label="Publication Date", placeholder="Enter date of publication (YYYY-MM-DD)")
189
- description_input = gr.Textbox(label="Description", placeholder="Enter a short description")
190
- developer_input = gr.Textbox(label="Developer", placeholder="Enter the developer or organization")
191
- use_case_input = gr.Textbox(label="Use Case", placeholder="Enter the primary use case")
192
- impact_input = gr.Textbox(label="Impact", placeholder="Enter the model's impact")
193
- add_button = gr.Button("Add Model")
194
- add_output = gr.Markdown()
195
- add_button.click(
196
- add_model,
197
- inputs=[name_input, description_input, year_input, developer_input, use_case_input, impact_input],
198
- outputs=[add_output, view_output]
199
- )
200
 
201
- with gr.Tab("Edit Model"):
202
- edit_index = gr.Number(label="Model Number", precision=0)
203
- with gr.Row():
204
- edit_name = gr.Textbox(label="New Model Name", placeholder="Enter new model name")
205
- edit_year = gr.Textbox(label="New Publication Date", placeholder="Enter new date of publication (YYYY-MM-DD)")
206
- edit_description = gr.Textbox(label="New Description", placeholder="Enter new description")
207
- edit_developer = gr.Textbox(label="New Developer", placeholder="Enter new developer or organization")
208
- edit_use_case = gr.Textbox(label="New Use Case", placeholder="Enter new primary use case")
209
- edit_impact = gr.Textbox(label="New Impact", placeholder="Enter new impact")
210
- edit_button = gr.Button("Edit Model")
211
- edit_output = gr.Markdown()
212
- edit_button.click(
213
- edit_model,
214
- inputs=[edit_index, edit_name, edit_description, edit_year, edit_developer, edit_use_case, edit_impact],
215
- outputs=[edit_output, view_output]
216
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
- # Run the app
219
- app.launch()
 
 
 
2
  import json
3
  import os
4
  from datetime import datetime
5
+ from typing import Dict, List, Optional, Union
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
 
9
+ # Type definitions and data structures
10
+ @dataclass
11
+ class AIModel:
12
+ name: str
13
+ description: str
14
+ date_of_release: str
15
+ developer: str
16
+ use_case: str
17
+ impact: str
18
+ time_difference: Optional[int] = None
19
+
20
+ def to_dict(self) -> Dict:
21
+ return {
22
+ "name": self.name,
23
+ "description": self.description,
24
+ "dateOfRelease": self.date_of_release,
25
+ "developer": self.developer,
26
+ "use_case": self.use_case,
27
+ "impact": self.impact,
28
+ "time_difference": self.time_difference
29
+ }
30
+
31
+ @classmethod
32
+ def from_dict(cls, data: Dict) -> 'AIModel':
33
+ return cls(
34
+ name=data.get('name', ''),
35
+ description=data.get('description', ''),
36
+ date_of_release=data.get('dateOfRelease', ''),
37
+ developer=data.get('developer', ''),
38
+ use_case=data.get('use_case', ''),
39
+ impact=data.get('impact', ''),
40
+ time_difference=data.get('time_difference')
41
+ )
42
+
43
+ class ModelRepository:
44
+ def __init__(self, file_path: str = "models.json"):
45
+ self.file_path = Path(file_path)
46
+ self.models: List[AIModel] = []
47
+ self.load_models()
48
+
49
+ def load_models(self) -> None:
50
+ if self.file_path.exists():
51
+ try:
52
+ with open(self.file_path, "r") as f:
53
+ data = json.load(f)
54
+ self.models = [AIModel.from_dict(model_data) for model_data in data]
55
+ except json.JSONDecodeError:
56
+ print(f"Error reading {self.file_path}. Starting with empty model list.")
57
+ self.models = []
58
+ else:
59
+ self.models = []
60
+
61
+ def save_models(self) -> None:
62
+ with open(self.file_path, "w") as f:
63
+ json.dump([model.to_dict() for model in self.models], f, indent=4)
64
+
65
+ def add_model(self, model: AIModel) -> None:
66
+ self.models.append(model)
67
+ self.calculate_time_differences()
68
+ self.save_models()
69
+
70
+ def update_model(self, index: int, model: AIModel) -> bool:
71
+ if 0 <= index < len(self.models):
72
+ self.models[index] = model
73
+ self.calculate_time_differences()
74
+ self.save_models()
75
+ return True
76
+ return False
77
+
78
+ def get_filtered_models(
79
+ self,
80
+ developer: Optional[str] = None,
81
+ use_case: Optional[str] = None
82
+ ) -> List[AIModel]:
83
+ filtered_models = self.models.copy()
84
+
85
+ if developer and developer != "All":
86
+ filtered_models = [m for m in filtered_models if m.developer == developer]
87
+
88
+ if use_case and use_case != "All":
89
+ filtered_models = [m for m in filtered_models if m.use_case == use_case]
90
+
91
+ return sorted(filtered_models, key=lambda x: x.date_of_release, reverse=True)
92
+
93
+ def calculate_time_differences(self) -> None:
94
+ # Sort by date in ascending order
95
+ sorted_models = sorted(self.models, key=lambda x: x.date_of_release)
96
 
97
+ # Reset all time differences
98
+ for model in sorted_models:
99
+ model.time_difference = None
 
 
 
 
100
 
101
+ # Calculate time differences starting from the most recent
102
+ for i in range(len(sorted_models)-1, 0, -1):
103
+ curr_date = datetime.strptime(sorted_models[i].date_of_release, "%Y-%m-%d")
104
+ prev_date = datetime.strptime(sorted_models[i-1].date_of_release, "%Y-%m-%d")
105
+ sorted_models[i].time_difference = (curr_date - prev_date).days
 
 
 
 
106
 
107
+ def get_unique_developers(self) -> List[str]:
108
+ return sorted(list(set(model.developer for model in self.models)))
109
 
110
+ def get_unique_use_cases(self) -> List[str]:
111
+ return sorted(list(set(model.use_case for model in self.models)))
112
+
113
+ class UIRenderer:
114
+ @staticmethod
115
+ def render_model_card(model: AIModel) -> str:
116
+ return f"""
117
+ <div class='ai-card'>
118
+ <h3>{model.name} ({model.date_of_release})</h3>
119
+ <p><strong>Description:</strong> {model.description}</p>
120
+ <p><strong>Developer:</strong> {model.developer}</p>
121
+ <p><strong>Use Case:</strong> {model.use_case}</p>
122
+ <p><strong>Impact:</strong> {model.impact}</p>
123
+ </div>
124
+ """
125
+
126
+ @staticmethod
127
+ def render_time_difference(days: int) -> str:
128
+ if days <= 0:
129
+ return ""
130
+ gap_height = days * 2 # Scale the gap based on days
131
+ return f"""
132
+ <div class='time-difference' style='margin: {gap_height}px 0;'>
133
+ <div class='time-line'></div>
134
+ <div class='time-text'>{days} days between releases</div>
135
+ </div>
136
+ """
137
+
138
+ @staticmethod
139
+ def render_timeline(models: List[AIModel]) -> str:
140
+ output = "<div class='timeline-container'>"
141
+
142
+ for model in models: # models are already sorted in reverse order
143
+ if model.time_difference: # Check if there's a time difference
144
+ output += UIRenderer.render_time_difference(model.time_difference)
145
+ output += UIRenderer.render_model_card(model)
146
 
147
+ output += "</div>"
148
+ return output
 
149
 
150
+ def create_ui(repository: ModelRepository) -> gr.Blocks:
151
+ css = """
152
  body {
153
  font-family: 'Arial', sans-serif;
154
+ background-color: #121212;
155
+ color: white;
156
  margin: 0;
157
  padding: 0;
158
  }
159
+ .timeline-container {
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 1.5rem;
163
+ padding: 1rem;
164
+ }
165
+ .ai-card {
166
+ background: linear-gradient(145deg, #2b2b2b, #333);
167
+ border-radius: 1rem;
168
+ padding: 1.5rem;
169
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
170
+ border: 1px solid rgba(255, 255, 255, 0.1);
171
+ transition: transform 0.2s, box-shadow 0.2s;
172
+ }
173
+ .ai-card:hover {
174
+ transform: translateY(-2px);
175
+ box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
176
+ }
177
+ .ai-card h3 {
178
+ color: #60a5fa;
179
+ margin: 0 0 1rem 0;
180
+ font-size: 1.25rem;
181
+ }
182
+ .ai-card p {
183
+ color: #e5e7eb;
184
+ margin: 0.5rem 0;
185
+ line-height: 1.5;
186
+ }
187
+ .ai-card strong {
188
+ color: #93c5fd;
189
+ }
190
  .gradio-container {
191
  width: 80%;
192
  margin: auto;
193
  padding: 20px;
194
  }
195
  .gradio-markdown {
196
+ color: white;
197
  }
198
  .gr-button {
199
+ background-color: #333;
200
+ color: white;
201
  }
202
  .gr-button:hover {
203
+ background-color: #555;
204
  }
205
  .gr-dropdown, .gr-textbox {
206
+ background-color: #333;
207
+ color: white;
208
+ border: 1px solid #555;
209
  }
210
+ .time-difference {
211
+ text-align: center;
212
+ color: #9ca3af;
213
+ font-style: italic;
214
+ position: relative;
215
+ padding: 20px 0;
 
 
 
 
216
  }
217
+ .time-line {
218
+ position: absolute;
219
+ left: 50%;
220
+ top: 0;
221
+ bottom: 0;
222
+ width: 2px;
223
+ background: linear-gradient(to bottom, transparent, #555, transparent);
224
  }
225
+ .time-text {
226
+ background-color: #1a1a1a;
227
+ padding: 5px 15px;
228
+ border-radius: 15px;
229
+ display: inline-block;
230
+ position: relative;
231
+ z-index: 1;
232
  }
233
+ """
234
 
235
+ with gr.Blocks(css=css) as app:
236
+ gr.Markdown("# AI Timeline\n\nVisualize the development of AI models through an interactive timeline.")
237
+
238
+ with gr.Tab("View Timeline"):
239
+ with gr.Row():
240
+ developer_filter = gr.Dropdown(
241
+ label="Filter by Developer",
242
+ choices=["All"] + repository.get_unique_developers(),
243
+ value="All"
244
+ )
245
+ use_case_filter = gr.Dropdown(
246
+ label="Filter by Use Case",
247
+ choices=["All"] + repository.get_unique_use_cases(),
248
+ value="All"
249
+ )
250
+
251
+ filter_button = gr.Button("Apply Filters", variant="primary")
252
+ timeline_output = gr.HTML()
253
 
254
+ def update_timeline(developer: str, use_case: str) -> str:
255
+ filtered_models = repository.get_filtered_models(developer, use_case)
256
+ return UIRenderer.render_timeline(filtered_models)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
+ filter_button.click(
259
+ update_timeline,
260
+ inputs=[developer_filter, use_case_filter],
261
+ outputs=[timeline_output]
262
+ )
263
+
264
+ with gr.Tab("Add Model"):
265
+ with gr.Row():
266
+ name_input = gr.Textbox(label="Model Name", placeholder="Enter model name")
267
+ date_input = gr.Textbox(label="Release Date (YYYY-MM-DD)", placeholder="Enter date of release")
268
+ description_input = gr.Textbox(label="Description", placeholder="Enter a short description", lines=3)
269
+ with gr.Row():
270
+ developer_input = gr.Textbox(label="Developer", placeholder="Enter the developer or organization")
271
+ use_case_input = gr.Textbox(label="Use Case", placeholder="Enter the primary use case")
272
+ impact_input = gr.Textbox(label="Impact", placeholder="Enter the model's impact", lines=2)
273
+
274
+ add_button = gr.Button("Add Model", variant="primary")
275
+ add_output = gr.Markdown()
276
+
277
+ def add_new_model(name, description, date, developer, use_case, impact):
278
+ try:
279
+ datetime.strptime(date, "%Y-%m-%d")
280
+ model = AIModel(
281
+ name=name,
282
+ description=description,
283
+ date_of_release=date,
284
+ developer=developer,
285
+ use_case=use_case,
286
+ impact=impact
287
+ )
288
+ repository.add_model(model)
289
+ return "Model added successfully!", UIRenderer.render_timeline(repository.get_filtered_models())
290
+ except ValueError:
291
+ return "Error: Invalid date format. Please use YYYY-MM-DD", ""
292
+
293
+ add_button.click(
294
+ add_new_model,
295
+ inputs=[name_input, description_input, date_input,
296
+ developer_input, use_case_input, impact_input],
297
+ outputs=[add_output, timeline_output]
298
+ )
299
+
300
+ with gr.Tab("Edit Model"):
301
+ edit_index = gr.Number(label="Model Number", precision=0)
302
+ with gr.Row():
303
+ edit_name = gr.Textbox(label="New Model Name", placeholder="Enter new model name")
304
+ edit_date = gr.Textbox(label="New Release Date", placeholder="Enter new date (YYYY-MM-DD)")
305
+ edit_description = gr.Textbox(label="New Description", placeholder="Enter new description", lines=3)
306
+ with gr.Row():
307
+ edit_developer = gr.Textbox(label="New Developer", placeholder="Enter new developer")
308
+ edit_use_case = gr.Textbox(label="New Use Case", placeholder="Enter new use case")
309
+ edit_impact = gr.Textbox(label="New Impact", placeholder="Enter new impact", lines=2)
310
+
311
+ edit_button = gr.Button("Edit Model", variant="primary")
312
+ edit_output = gr.Markdown()
313
+
314
+ def edit_existing_model(index, name, description, date, developer, use_case, impact):
315
+ try:
316
+ datetime.strptime(date, "%Y-%m-%d")
317
+ model = AIModel(
318
+ name=name,
319
+ description=description,
320
+ date_of_release=date,
321
+ developer=developer,
322
+ use_case=use_case,
323
+ impact=impact
324
+ )
325
+ if repository.update_model(int(index) - 1, model):
326
+ return "Model updated successfully!", UIRenderer.render_timeline(repository.get_filtered_models())
327
+ return "Error: Invalid model number", ""
328
+ except ValueError:
329
+ return "Error: Invalid date format. Please use YYYY-MM-DD", ""
330
+
331
+ edit_button.click(
332
+ edit_existing_model,
333
+ inputs=[edit_index, edit_name, edit_description, edit_date,
334
+ edit_developer, edit_use_case, edit_impact],
335
+ outputs=[edit_output, timeline_output]
336
+ )
337
+
338
+ return app
339
 
340
+ if __name__ == "__main__":
341
+ repository = ModelRepository()
342
+ app = create_ui(repository)
343
+ app.launch()