Create ai-data-analysis-agent.py with the code below, or save it directly from your editor.
import osimport tracebackimport pandas as pdimport matplotlibmatplotlib.use('Agg')import matplotlib.pyplot as pltimport seaborn as snsfrom agno.agent import Agentfrom agno.models.openrouter import OpenRouterfrom bindu.penguin.bindufy import bindufyfrom dotenv import load_dotenvload_dotenv()# -----------------------------# Custom Data Analyst Tools# -----------------------------def analyze_dataset(file_path: str) -> str: if not os.path.exists(file_path): return f"Error: File not found at {file_path}. Please provide a valid absolute path." try: df = pd.read_csv(file_path) info = [ f"Dataset Shape: {df.shape[0]} rows, {df.shape[1]} columns\n", "Columns and Data Types:\n" + str(df.dtypes) + "\n", "Missing Values:\n" + str(df.isnull().sum()) + "\n", "Summary Statistics:\n" + df.describe(include='all').to_string() ] return "\n".join(info) except Exception as e: return f"Error analyzing dataset: {str(e)}"def generate_visualization(file_path: str, x_column: str, y_column: str, chart_type: str = "bar") -> str: if not os.path.exists(file_path): return f"Error: File not found at {file_path}." try: df = pd.read_csv(file_path) if x_column not in df.columns or (y_column and y_column not in df.columns): return f"Error: Columns '{x_column}' or '{y_column}' not found." plt.figure(figsize=(10, 6)) sns.set_theme(style="whitegrid") if chart_type == "bar": sns.barplot(data=df, x=x_column, y=y_column) elif chart_type == "line": sns.lineplot(data=df, x=x_column, y=y_column) else: sns.scatterplot(data=df, x=x_column, y=y_column) plt.title(f"{chart_type.capitalize()} Chart: {y_column} vs {x_column}") plt.xticks(rotation=45) plt.tight_layout() os.makedirs("outputs", exist_ok=True) output_path = f"outputs/chart_{x_column}_{y_column}.png" plt.savefig(output_path) plt.close() return f"Success! Visualization generated and saved to: {output_path}" except Exception as e: return f"Error generating visualization: {str(e)}"# -----------------------------# Agent Handler# -----------------------------def handler(messages: list[dict]): try: last_message = messages[-1] user_query = "" # Safely extract text from the Bindu payload if "parts" in last_message: for part in last_message["parts"]: if part.get("kind") == "text": user_query += part.get("text", "") + "\n" elif "content" in last_message: user_query = last_message.get("content", "") user_query = user_query.strip() if not user_query: return [{"role": "assistant", "content": "Error: No text received."}] # Instantiate agent cleanly inside the thread agent = Agent( name="AI Data Analysis Agent", instructions=[ "You are an elite Data Scientist.", "When a user provides a path to a CSV, use the 'analyze_dataset' tool to understand its structure.", "Proactively use the 'generate_visualization' tool to create compelling charts.", "Always format your final output as a highly structured analytical report using Markdown." ], model=OpenRouter( id="openai/gpt-oss-120b", api_key=os.getenv("OPENROUTER_API_KEY") ), tools=[analyze_dataset, generate_visualization], markdown=True, telemetry=False ) result = agent.run(user_query) # Agent autonomously saves its own report os.makedirs("outputs", exist_ok=True) report_path = "outputs/analysis_report.md" with open(report_path, "w", encoding="utf-8") as f: f.write(result.content) return [{"role": "assistant", "content": str(result.content)}] except Exception as e: traceback.print_exc() return [{"role": "assistant", "content": f"Agent crashed: {str(e)}"}]# -----------------------------# Bindu Configuration# -----------------------------config = { "author": "your.email@example.com", "name": "AI Data Analysis Agent", "description": "An analytical agent that processes CSV data and generates visual charts.", "deployment": { "url": "http://localhost:3773", "expose": True, "cors_origins": ["http://localhost:5173"] }, "skills":["skills/ai-data-analysis-agent"],}if __name__ == "__main__": bindufy(config=config, handler=handler)
id: data-analysis-skillname: data-analysis-skillversion: 1.0.0author: your.email@example.comdescription: | Advanced data science skill that provides comprehensive dataset analysis, statistical summaries, and autonomous visual chart generation. Features: - CSV parsing and structural analysis - Statistical summaries (mean, median, standard deviation) - Missing value detection and data type inference - Autonomous data visualization (Bar, Line, and Scatter charts) - Markdown-formatted analytical reporting Uses Pandas for heavy data manipulation and a thread-safe Matplotlib/Seaborn backend (Agg) for background image generation.tags: - data-science - analytics - visualization - pandas - csv - statisticsinput_modes: - application/jsonoutput_modes: - application/jsonexamples: - "Please analyze the dataset located at sample_sales.csv" - "Give me a brief summary of the data, and generate a bar chart showing Sales by Product" - "Are there any missing values in this dataset?" - "Create a scatter plot comparing Revenue and Marketing Spend"capabilities_detail: dataset_parsing: supported: true description: "Ability to ingest and read CSV file structures" statistical_analysis: supported: true description: "Computes core statistics and identifies data anomalies/nulls" data_visualization: supported: true description: "Generates custom PNG charts based on user prompts and data trends" markdown_reporting: supported: true description: "Synthesizes data findings into highly readable Markdown reports"
# Clone the Bindu repositorygit clone https://github.com/GetBindu/Bindu# Navigate to frontend directorycd frontend# Install dependenciesnpm install# Start frontend development servernpm run dev