""" NeoSyn: AI-Powered Synthetic Data & Insights This Gradio app hosts multiple MCP tools for different databases (sales, customers, products, transactions), and allows users to chat naturally for generating synthetic data, visualizing insights, or fetching summaries. All interactions are stored in ChromaDB memory. Author: Saivivek Katkuri Date: June 2025 """ import gradio as gr import os from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOpenAI from db_connector import fetch_table_data from data_processor import generate_synthetic_data from plotly_tools import generate_plot # Setup ChromaDB for chat memory (local storage) memory = Chroma(persist_directory="./chroma_memory") # Define database paths DB_PATHS = { "sales": "sales.db", "customers": "customers.db", "products": "products.db", "transactions": "transactions.db" } # Core function to handle queries def process_query(user_query, user_id): try: query_lower = user_query.lower() response = "" # Generate synthetic data if "generate" in query_lower and "records" in query_lower: for db_name, db_path in DB_PATHS.items(): if db_name in query_lower: table_name = db_name df = fetch_table_data(db_path, table_name) num = int(''.join([c for c in query_lower if c.isdigit()]) or 10) synthetic_df = generate_synthetic_data(df, num) file_path = f"generated/{db_name}_synthetic.csv" synthetic_df.to_csv(file_path, index=False) response = f"✅ Generated {num} synthetic records for {db_name}. [Download CSV]({file_path})" memory.add_texts([f"{user_id}: {response}"]) return response # Generate plot elif "plot" in query_lower or "distribution" in query_lower or "graph" in query_lower: for db_name, db_path in DB_PATHS.items(): if db_name in query_lower: desc, html_path, png_path = generate_plot(user_query, db_path) response = f"{desc} [View Plot (HTML)]({html_path}) or [Download PNG]({png_path})" memory.add_texts([f"{user_id}: {response}"]) return response # Fetch table summary else: for db_name, db_path in DB_PATHS.items(): if db_name in query_lower: df = fetch_table_data(db_path, db_name) summary = f"📊 {db_name.upper()} Data Summary:\n{df.describe().to_string()}" response = summary memory.add_texts([f"{user_id}: {response}"]) return response response = "❓ Sorry, I couldn't understand. Please specify the table or ask for synthetic data or plots." memory.add_texts([f"{user_id}: {response}"]) return response except Exception as e: return f"❌ Error: {str(e)}" # Gradio ChatInterface with gr.Blocks() as demo: gr.Markdown("# NeoSyn: AI-Powered Synthetic Data & Insights") gr.Markdown("Chat naturally to generate synthetic data, get summaries, or plots from sales, customers, products, or transactions.") chat = gr.ChatInterface( fn=process_query, chatbot=gr.Chatbot(type='messages'), # Use OpenAI-style messages format additional_inputs=[gr.Textbox(label="User ID (optional)", value="default_user")], title="NeoSyn Chat", description="Ask me to generate synthetic data, get insights, or plots!" ) if __name__ == "__main__": demo.queue().launch()