Spaces:
Running
Running
| # visuals.py | |
| # Handles all data visualization logic for MudabbirAI | |
| import pandas as pd | |
| import plotly.graph_objects as go | |
| def create_progress_chart(log_data): | |
| """ | |
| Generates a Radar Chart comparing the initial draft scores vs. the final scores. | |
| """ | |
| if not log_data or "trace" not in log_data: | |
| return None | |
| # Filter for "attempt" steps to get the scores | |
| attempts = [step for step in log_data["trace"] if step["step_type"] == "attempt"] | |
| if not attempts: | |
| return None | |
| # Define the standard criteria | |
| categories = ["Novelty", "Usefulness_Feasibility", "Flexibility", "Elaboration", "Cultural_Appropriateness"] | |
| fig = go.Figure() | |
| for i, attempt in enumerate(attempts): | |
| scores = attempt.get("scores", {}) | |
| # Handle cases where scores might be missing (default to 0) | |
| values = [scores.get(cat, 0) for cat in categories] | |
| # Close the loop for radar chart (repeat first value at the end) | |
| values += [values[0]] | |
| radar_categories = categories + [categories[0]] | |
| name = f"Initial Draft" if i == 0 else f"Improved Draft (Loop {i})" | |
| color = "red" if i == 0 else "green" | |
| fig.add_trace(go.Scatterpolar( | |
| r=values, | |
| theta=radar_categories, | |
| fill='toself', | |
| name=name, | |
| line_color=color | |
| )) | |
| fig.update_layout( | |
| polar=dict( | |
| radialaxis=dict( | |
| visible=True, | |
| range=[0, 5] # Scores are always 0-5 | |
| )), | |
| showlegend=True, | |
| title="Evolution of Solution Quality" | |
| ) | |
| return fig | |
| def create_calibration_table(log_data): | |
| """ | |
| Generates a Pandas DataFrame showing the 'Audition Scores' for the calibration phase. | |
| """ | |
| if not log_data or "trace" not in log_data: | |
| return None | |
| # Find the calibration step in the log | |
| calibration_step = next((step for step in log_data["trace"] if step["step_type"] == "calibration"), None) | |
| # If no calibration happened (e.g. Single Agent mode), return None | |
| if not calibration_step or "details" not in calibration_step: | |
| return None | |
| # details is a list of dicts: {'role': 'Plant', 'llm': 'Gemini', 'score': {...}} | |
| details = calibration_step["details"] | |
| data = [] | |
| for item in details: | |
| role = item["role"] | |
| model = item["llm"] | |
| # The 'score' field contains the full evaluation object. | |
| # We need to extract the specific numeric score relevant to that Role. | |
| # Plant -> Novelty, Implementer -> Feasibility, Monitor -> Cultural | |
| score_data = item.get("score", {}) | |
| score = 0 | |
| if isinstance(score_data, dict): | |
| if role == "Plant": | |
| score = score_data.get("Novelty", {}).get("score", 0) | |
| elif role == "Implementer": | |
| score = score_data.get("Usefulness_Feasibility", {}).get("score", 0) | |
| elif role == "Monitor": | |
| score = score_data.get("Cultural_Appropriateness", {}).get("score", 0) | |
| data.append({"Role": role, "Model": model, "Score": score}) | |
| if not data: | |
| return None | |
| df = pd.DataFrame(data) | |
| # Pivot the table: Rows = Roles, Columns = Models, Values = Scores | |
| # This creates a nice comparison matrix | |
| pivot_df = df.pivot(index="Role", columns="Model", values="Score").reset_index() | |
| return pivot_df |