dvwn commited on
Commit
dc6fe88
·
1 Parent(s): 5ac1ec2

Update SQL agent > src/nl2sql/sql_agent.py

Browse files

1. Act as a bridge connect the db_manager and hf_engine.
2. Utilize PromptTemplate to instruct LLM on its persona.

src/database/__pycache__/db_manager.cpython-313.pyc CHANGED
Binary files a/src/database/__pycache__/db_manager.cpython-313.pyc and b/src/database/__pycache__/db_manager.cpython-313.pyc differ
 
src/nl2sql/sql_agent.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Path: src/nl2sql/sql_agent.py
2
+ # SQL Agent for handling NL2SQL conversion
3
+ from src.database.db_manager import get_db_connection, get_schema_context
4
+ from langchain_core.prompts import PromptTemplate
5
+ from src.nl2sql.hf_engine import get_llm
6
+
7
+ # Craft the Prompt Template to instruct LLM on its persona
8
+ SQL_PROMPT_TEMPLATE = """You are an expert SQLite developer.
9
+ Your task is to write a syntactically correct SQLite query to answer the user's question based strictly on the provided database schema.
10
+ Return ONLY the raw SQL query.
11
+ Do not include any explanations, markdown formatting, or code blocks.
12
+
13
+ Schema Context:
14
+ {schema}
15
+
16
+ User Question:
17
+ {question}
18
+
19
+ SQL Query:"""
20
+
21
+ prompt_template = PromptTemplate(
22
+ input_variables = ["schema", "question"],
23
+ template = SQL_PROMPT_TEMPLATE
24
+ )
25
+
26
+ # Clean the output
27
+ def clean_sql(raw_sql: str) -> str:
28
+ """
29
+ Utility to strip markdown formatting if the LLM hallucinated code blocks.
30
+ Ensure the raw string can be directly executed by the SQLite cursor.
31
+ """
32
+ cleaned = raw_sql.strip()
33
+ if cleaned.startswith("```sql"):
34
+ cleaned = cleaned[6:]
35
+ elif cleaned.startswith("```"):
36
+ cleaned = cleaned[3:]
37
+
38
+ if cleaned.endswith("```"):
39
+ cleaned = cleaned[:-3]
40
+
41
+ return cleaned.strip()
42
+
43
+ # Function to handle NL2SQL conversion
44
+ def nl2sql_agent(user_question: str) -> dict:
45
+ """
46
+ Complete flow execution:
47
+ Get Schema context -> Generate SQL query -> Execute SQL query -> Return results
48
+ """
49
+ # Fetch database schema context using RAG
50
+ print(f"Fetching RAG schema context for: '{user_question}'...")
51
+ schema = get_schema_context(question = user_question)
52
+
53
+ # Generate SQL query using the schema context and user question
54
+ print("Generating SQL query via LLM...")
55
+ llm = get_llm()
56
+
57
+ # LangChain Pipeline: Pipe prompt into LLM
58
+ chain = prompt_template | llm
59
+ raw_response = chain.invoke({
60
+ "schema": schema,
61
+ "question": user_question
62
+ })
63
+
64
+ # Parse & clean the generated SQL query
65
+ generated_sql = clean_sql(raw_response)
66
+ print(f"Generated SQL: \n{generated_sql}")
67
+
68
+ # Execute the generated SQL query and fetch results
69
+ connection = get_db_connection()
70
+ if not connection:
71
+ return {
72
+ "query": generated_sql,
73
+ "error": "Could not establish database connection",
74
+ "status": "failed"
75
+ }
76
+
77
+ try:
78
+ cursor = connection.cursor()
79
+ cursor.execute(generated_sql)
80
+ results = cursor.fetchall()
81
+ return {
82
+ "query": generated_sql,
83
+ "results": results,
84
+ "status": "success"
85
+ }
86
+ except Exception as e:
87
+ return {
88
+ "query": generated_sql,
89
+ "error": str(e),
90
+ "status": f"error executing SQL: {e}"
91
+ }
92
+ finally:
93
+ connection.close()
94
+
95
+ # Local Test block
96
+ if __name__ == "__main__":
97
+ from dotenv import load_dotenv
98
+ load_dotenv()
99
+
100
+ test_question = "How many employees are there in the Employee table?"
101
+
102
+ print("------Starting NL2SQL Agent Test------")
103
+ result = nl2sql_agent(test_question)
104
+
105
+ print("------Final Output------")
106
+ for key, value in result.items():
107
+ print(f"{key.capitalize()}: {value}")