Spaces:
Running
Running
| import gradio as gr | |
| import json | |
| import os | |
| from datetime import datetime | |
| from typing import Dict, List, Optional, Union | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| # Type definitions and data structures | |
| class AIModel: | |
| name: str | |
| description: str | |
| date_of_release: str | |
| developer: str | |
| use_case: str | |
| impact: str | |
| time_difference: Optional[int] = None | |
| def to_dict(self) -> Dict: | |
| return { | |
| "name": self.name, | |
| "description": self.description, | |
| "dateOfRelease": self.date_of_release, | |
| "developer": self.developer, | |
| "use_case": self.use_case, | |
| "impact": self.impact, | |
| "time_difference": self.time_difference | |
| } | |
| def from_dict(cls, data: Dict) -> 'AIModel': | |
| return cls( | |
| name=data.get('name', ''), | |
| description=data.get('description', ''), | |
| date_of_release=data.get('dateOfRelease', ''), | |
| developer=data.get('developer', ''), | |
| use_case=data.get('use_case', ''), | |
| impact=data.get('impact', ''), | |
| time_difference=data.get('time_difference') | |
| ) | |
| class ModelRepository: | |
| def __init__(self, file_path: str = "models.json"): | |
| self.file_path = Path(file_path) | |
| self.models: List[AIModel] = [] | |
| self.load_models() | |
| def load_models(self) -> None: | |
| if self.file_path.exists(): | |
| try: | |
| with open(self.file_path, "r") as f: | |
| data = json.load(f) | |
| self.models = [AIModel.from_dict(model_data) for model_data in data] | |
| except json.JSONDecodeError: | |
| print(f"Error reading {self.file_path}. Starting with empty model list.") | |
| self.models = [] | |
| else: | |
| self.models = [] | |
| def save_models(self) -> None: | |
| with open(self.file_path, "w") as f: | |
| json.dump([model.to_dict() for model in self.models], f, indent=4) | |
| def add_model(self, model: AIModel) -> None: | |
| self.models.append(model) | |
| self.calculate_time_differences() | |
| self.save_models() | |
| def update_model(self, index: int, model: AIModel) -> bool: | |
| if 0 <= index < len(self.models): | |
| self.models[index] = model | |
| self.calculate_time_differences() | |
| self.save_models() | |
| return True | |
| return False | |
| def get_filtered_models( | |
| self, | |
| developer: Optional[str] = None, | |
| use_case: Optional[str] = None | |
| ) -> List[AIModel]: | |
| filtered_models = self.models.copy() | |
| if developer and developer != "All": | |
| filtered_models = [m for m in filtered_models if m.developer == developer] | |
| if use_case and use_case != "All": | |
| filtered_models = [m for m in filtered_models if m.use_case == use_case] | |
| return sorted(filtered_models, key=lambda x: x.date_of_release, reverse=True) | |
| def calculate_time_differences(self) -> None: | |
| # Sort by date in ascending order | |
| sorted_models = sorted(self.models, key=lambda x: x.date_of_release) | |
| # Reset all time differences | |
| for model in sorted_models: | |
| model.time_difference = None | |
| # Calculate time differences starting from the most recent | |
| for i in range(len(sorted_models)-1, 0, -1): | |
| curr_date = datetime.strptime(sorted_models[i].date_of_release, "%Y-%m-%d") | |
| prev_date = datetime.strptime(sorted_models[i-1].date_of_release, "%Y-%m-%d") | |
| sorted_models[i].time_difference = (curr_date - prev_date).days | |
| def get_unique_developers(self) -> List[str]: | |
| return sorted(list(set(model.developer for model in self.models))) | |
| def get_unique_use_cases(self) -> List[str]: | |
| return sorted(list(set(model.use_case for model in self.models))) | |
| class UIRenderer: | |
| def render_model_card(model: AIModel) -> str: | |
| return f""" | |
| <div class='ai-card'> | |
| <h3>{model.name} ({model.date_of_release})</h3> | |
| <p><strong>Description:</strong> {model.description}</p> | |
| <p><strong>Developer:</strong> {model.developer}</p> | |
| <p><strong>Use Case:</strong> {model.use_case}</p> | |
| <p><strong>Impact:</strong> {model.impact}</p> | |
| </div> | |
| """ | |
| def render_time_difference(days: int) -> str: | |
| if days <= 0: | |
| return "" | |
| gap_height = days * 2 # Scale the gap based on days | |
| return f""" | |
| <div class='time-difference' style='margin: {gap_height}px 0;'> | |
| <div class='time-line'></div> | |
| <div class='time-text'>{days} days between releases</div> | |
| </div> | |
| """ | |
| def render_timeline(models: List[AIModel]) -> str: | |
| output = "<div class='timeline-container'>" | |
| for model in models: # models are already sorted in reverse order | |
| if model.time_difference: # Check if there's a time difference | |
| output += UIRenderer.render_time_difference(model.time_difference) | |
| output += UIRenderer.render_model_card(model) | |
| output += "</div>" | |
| return output | |
| def create_ui(repository: ModelRepository) -> gr.Blocks: | |
| css = """ | |
| body { | |
| font-family: 'Arial', sans-serif; | |
| background-color: #121212; | |
| color: white; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .timeline-container { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1.5rem; | |
| padding: 1rem; | |
| } | |
| .ai-card { | |
| background: linear-gradient(145deg, #2b2b2b, #333); | |
| border-radius: 1rem; | |
| padding: 1.5rem; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| transition: transform 0.2s, box-shadow 0.2s; | |
| } | |
| .ai-card:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2); | |
| } | |
| .ai-card h3 { | |
| color: #60a5fa; | |
| margin: 0 0 1rem 0; | |
| font-size: 1.25rem; | |
| } | |
| .ai-card p { | |
| color: #e5e7eb; | |
| margin: 0.5rem 0; | |
| line-height: 1.5; | |
| } | |
| .ai-card strong { | |
| color: #93c5fd; | |
| } | |
| .gradio-container { | |
| width: 80%; | |
| margin: auto; | |
| padding: 20px; | |
| } | |
| .gradio-markdown { | |
| color: white; | |
| } | |
| .gr-button { | |
| background-color: #333; | |
| color: white; | |
| } | |
| .gr-button:hover { | |
| background-color: #555; | |
| } | |
| .gr-dropdown, .gr-textbox { | |
| background-color: #333; | |
| color: white; | |
| border: 1px solid #555; | |
| } | |
| .time-difference { | |
| text-align: center; | |
| color: #9ca3af; | |
| font-style: italic; | |
| position: relative; | |
| padding: 20px 0; | |
| } | |
| .time-line { | |
| position: absolute; | |
| left: 50%; | |
| top: 0; | |
| bottom: 0; | |
| width: 2px; | |
| background: linear-gradient(to bottom, transparent, #555, transparent); | |
| } | |
| .time-text { | |
| background-color: #1a1a1a; | |
| padding: 5px 15px; | |
| border-radius: 15px; | |
| display: inline-block; | |
| position: relative; | |
| z-index: 1; | |
| } | |
| """ | |
| with gr.Blocks(css=css) as app: | |
| gr.Markdown("# AI Timeline\n\nVisualize the development of AI models through an interactive timeline.") | |
| with gr.Tab("View Timeline"): | |
| with gr.Row(): | |
| developer_filter = gr.Dropdown( | |
| label="Filter by Developer", | |
| choices=["All"] + repository.get_unique_developers(), | |
| value="All" | |
| ) | |
| use_case_filter = gr.Dropdown( | |
| label="Filter by Use Case", | |
| choices=["All"] + repository.get_unique_use_cases(), | |
| value="All" | |
| ) | |
| filter_button = gr.Button("Apply Filters", variant="primary") | |
| timeline_output = gr.HTML() | |
| def update_timeline(developer: str, use_case: str) -> str: | |
| filtered_models = repository.get_filtered_models(developer, use_case) | |
| return UIRenderer.render_timeline(filtered_models) | |
| filter_button.click( | |
| update_timeline, | |
| inputs=[developer_filter, use_case_filter], | |
| outputs=[timeline_output] | |
| ) | |
| with gr.Tab("Add Model"): | |
| with gr.Row(): | |
| name_input = gr.Textbox(label="Model Name", placeholder="Enter model name") | |
| date_input = gr.Textbox(label="Release Date (YYYY-MM-DD)", placeholder="Enter date of release") | |
| description_input = gr.Textbox(label="Description", placeholder="Enter a short description", lines=3) | |
| with gr.Row(): | |
| developer_input = gr.Textbox(label="Developer", placeholder="Enter the developer or organization") | |
| use_case_input = gr.Textbox(label="Use Case", placeholder="Enter the primary use case") | |
| impact_input = gr.Textbox(label="Impact", placeholder="Enter the model's impact", lines=2) | |
| add_button = gr.Button("Add Model", variant="primary") | |
| add_output = gr.Markdown() | |
| def add_new_model(name, description, date, developer, use_case, impact): | |
| try: | |
| datetime.strptime(date, "%Y-%m-%d") | |
| model = AIModel( | |
| name=name, | |
| description=description, | |
| date_of_release=date, | |
| developer=developer, | |
| use_case=use_case, | |
| impact=impact | |
| ) | |
| repository.add_model(model) | |
| return "Model added successfully!", UIRenderer.render_timeline(repository.get_filtered_models()) | |
| except ValueError: | |
| return "Error: Invalid date format. Please use YYYY-MM-DD", "" | |
| add_button.click( | |
| add_new_model, | |
| inputs=[name_input, description_input, date_input, | |
| developer_input, use_case_input, impact_input], | |
| outputs=[add_output, timeline_output] | |
| ) | |
| with gr.Tab("Edit Model"): | |
| edit_index = gr.Number(label="Model Number", precision=0) | |
| with gr.Row(): | |
| edit_name = gr.Textbox(label="New Model Name", placeholder="Enter new model name") | |
| edit_date = gr.Textbox(label="New Release Date", placeholder="Enter new date (YYYY-MM-DD)") | |
| edit_description = gr.Textbox(label="New Description", placeholder="Enter new description", lines=3) | |
| with gr.Row(): | |
| edit_developer = gr.Textbox(label="New Developer", placeholder="Enter new developer") | |
| edit_use_case = gr.Textbox(label="New Use Case", placeholder="Enter new use case") | |
| edit_impact = gr.Textbox(label="New Impact", placeholder="Enter new impact", lines=2) | |
| edit_button = gr.Button("Edit Model", variant="primary") | |
| edit_output = gr.Markdown() | |
| def edit_existing_model(index, name, description, date, developer, use_case, impact): | |
| try: | |
| datetime.strptime(date, "%Y-%m-%d") | |
| model = AIModel( | |
| name=name, | |
| description=description, | |
| date_of_release=date, | |
| developer=developer, | |
| use_case=use_case, | |
| impact=impact | |
| ) | |
| if repository.update_model(int(index) - 1, model): | |
| return "Model updated successfully!", UIRenderer.render_timeline(repository.get_filtered_models()) | |
| return "Error: Invalid model number", "" | |
| except ValueError: | |
| return "Error: Invalid date format. Please use YYYY-MM-DD", "" | |
| edit_button.click( | |
| edit_existing_model, | |
| inputs=[edit_index, edit_name, edit_description, edit_date, | |
| edit_developer, edit_use_case, edit_impact], | |
| outputs=[edit_output, timeline_output] | |
| ) | |
| return app | |
| if __name__ == "__main__": | |
| repository = ModelRepository() | |
| app = create_ui(repository) | |
| app.launch() |