File size: 4,314 Bytes
2f8d918 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | 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()
|