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()