import os import traceback from pathlib import Path import gradio as gr from langchain.chat_models import init_chat_model from langchain.agents import create_agent from langchain_community.utilities import SQLDatabase from langchain_community.agent_toolkits import SQLDatabaseToolkit DB_PATH = Path("database_") / "zain_customer_360_ai_demo.db" MODEL_NAME = "gpt-4.1-mini" SYSTEM_PROMPT = """ You are a telecom business intelligence SQL agent for Zain Jordan. You are connected to a SQLite Customer 360 database. Rules: - Use SELECT queries only. - Never modify the database. - Never use INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, CREATE, REPLACE, ATTACH, DETACH, or VACUUM. - Inspect the database schema before writing SQL. - Limit results to 10 rows unless the user asks otherwise. - Use only relevant columns. - Do not guess facts that are not in the database. - Explain the result in simple business language. Useful context: - Churn analysis usually uses customers and customer_churn_scores. - Revenue/value analysis usually uses customer_value_segments, invoices, payments, or transactions. - Complaint analysis usually uses complaints and support_interactions. - Campaign analysis usually uses campaigns and customer_campaign_responses. - Network analysis usually uses network_towers and network_events. Final answer format: 1. Direct Answer 2. Key Numbers 3. Business Interpretation 4. Recommended Next Action """.strip() sql_agent = None def get_sql_agent(): global sql_agent if sql_agent is not None: return sql_agent api_key = os.environ.get("OPENAI_API_KEY") if not api_key: raise ValueError( "OPENAI_API_KEY is missing. Add it in Hugging Face Space Settings → Variables and secrets → Secrets." ) if not DB_PATH.exists(): raise FileNotFoundError( f"Database not found at: {DB_PATH}\n\n" "Please create a folder named database_ and upload zain_customer_360_ai_demo.db inside it." ) db_uri = f"sqlite:///{DB_PATH.resolve()}" db = SQLDatabase.from_uri(db_uri) llm = init_chat_model( MODEL_NAME, model_provider="openai" ) toolkit = SQLDatabaseToolkit( db=db, llm=llm ) tools = toolkit.get_tools() sql_agent = create_agent( model=llm, tools=tools, system_prompt=SYSTEM_PROMPT ) return sql_agent def run_sql_agent(question): try: if not question or not question.strip(): return "Please enter a business question." agent = get_sql_agent() result = agent.invoke({ "messages": [ { "role": "user", "content": question } ] }) final_message = result["messages"][-1] if hasattr(final_message, "content"): return final_message.content return str(final_message) except Exception as e: return f""" ### Error {str(e)} ### Traceback ```text {traceback.format_exc()} ``` """ with gr.Blocks(title="Zain Jordan SQL Agent") as demo: gr.Markdown("# Zain Jordan Customer 360 SQL Agent") gr.Markdown(""" Ask business questions from the Zain Jordan Customer 360 SQLite database. This app uses: - SQLite database - LangChain `SQLDatabase` - LangChain `SQLDatabaseToolkit` - OpenAI `gpt-4.1-mini` - Gradio interface Expected database location: ```text database_/zain_customer_360_ai_demo.db ``` Example questions: - Which cities have the most high-risk churn customers? - Which customer value segments have the highest average ARPU? - What are the top complaint categories? - Which campaigns had the highest conversion rate? """) question = gr.Textbox( label="Ask a business question", lines=4, value="Which cities have the most high-risk churn customers? Show the top 10 cities.", placeholder="Ask a question about churn, revenue, complaints, campaigns, customers, or network events." ) run_button = gr.Button("Run SQL Agent", variant="primary") answer = gr.Markdown(label="Answer") run_button.click( fn=run_sql_agent, inputs=question, outputs=answer ) if __name__ == "__main__": demo.launch()