LIANJie-Jason Claude Opus 4.6 commited on
Commit
8529300
·
1 Parent(s): 203c044

feat: update prompts for SQL routing, CHUNK-SQL IDs, and schema injection

Browse files
Files changed (2) hide show
  1. src/prompts.py +37 -2
  2. tests/test_prompts.py +29 -0
src/prompts.py CHANGED
@@ -40,7 +40,7 @@ REFERENCE LIST FORMAT
40
  ---------------------------------------------------------------------
41
  At the end of every response, include a "References" section.
42
 
43
- IMPORTANT: Do NOT use chunk IDs (CHUNK-LOCAL-001, CHUNK-WEB-001, etc.)
44
  in the reference list. Extract the ACTUAL file name, path, and page
45
  number from the "From:" and "Path:" lines in the context.
46
 
@@ -100,7 +100,7 @@ Run through this 9-point verification checklist and report results:
100
  3. Are there any claims that appear fabricated or hallucinated?
101
  4. Are direct quotes accurately reproduced from the context?
102
  5. Does the References section exist and list all cited sources?
103
- 6. Is the source priority respected (CHUNK-LOCAL > CHUNK-WEB)?
104
  7. Are any phrase-level flags confirmed as hallucinations?
105
  8. Do similarity flags indicate unsupported semantic drift?
106
  9. Is the response length proportional to the available evidence?
@@ -148,6 +148,7 @@ RULES for CLARIFY:
148
  - Do NOT ask for clarification on clear questions -- even if they are broad
149
  - A broad question is NOT the same as an ambiguous question
150
 
 
151
  CONVERSATION HISTORY:
152
  {history}
153
 
@@ -156,16 +157,41 @@ USER'S QUESTION: {query}
156
  Respond in JSON:
157
  {{
158
  "action": "search" or "clarify",
 
159
  "search_query": "keyword-optimized query for vector search (only if action is search)",
160
  "display_query": "clear natural-language question for the AI to answer (only if action is search)",
 
161
  "clarification_question": "question to ask (only if action is clarify)",
162
  "reasoning": "one sentence explaining your choice"
163
  }}
164
  """
165
 
166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  def build_query_understanding_prompt(
168
  query: str, domain: str, history: list[dict],
 
169
  ) -> str:
170
  """Build the query understanding prompt for pre-retrieval reformulation.
171
 
@@ -173,6 +199,7 @@ def build_query_understanding_prompt(
173
  query: The user's raw question.
174
  domain: Knowledge domain from config.
175
  history: Recent conversation messages for context resolution.
 
176
 
177
  Returns:
178
  Formatted query understanding prompt string.
@@ -190,10 +217,18 @@ def build_query_understanding_prompt(
190
  else:
191
  history_str = "(No prior conversation)"
192
 
 
 
 
 
 
 
 
193
  return QUERY_UNDERSTANDING_PROMPT_TEMPLATE.format(
194
  domain=domain,
195
  history=_escape_braces(history_str),
196
  query=_escape_braces(query),
 
197
  )
198
 
199
 
 
40
  ---------------------------------------------------------------------
41
  At the end of every response, include a "References" section.
42
 
43
+ IMPORTANT: Do NOT use chunk IDs (CHUNK-LOCAL-001, CHUNK-SQL-001, CHUNK-WEB-001, etc.)
44
  in the reference list. Extract the ACTUAL file name, path, and page
45
  number from the "From:" and "Path:" lines in the context.
46
 
 
100
  3. Are there any claims that appear fabricated or hallucinated?
101
  4. Are direct quotes accurately reproduced from the context?
102
  5. Does the References section exist and list all cited sources?
103
+ 6. Is the source priority respected (CHUNK-LOCAL = CHUNK-SQL > CHUNK-WEB)?
104
  7. Are any phrase-level flags confirmed as hallucinations?
105
  8. Do similarity flags indicate unsupported semantic drift?
106
  9. Is the response length proportional to the available evidence?
 
148
  - Do NOT ask for clarification on clear questions -- even if they are broad
149
  - A broad question is NOT the same as an ambiguous question
150
 
151
+ {sql_routing_block}
152
  CONVERSATION HISTORY:
153
  {history}
154
 
 
157
  Respond in JSON:
158
  {{
159
  "action": "search" or "clarify",
160
+ "route": "vector" or "sql" or "both",
161
  "search_query": "keyword-optimized query for vector search (only if action is search)",
162
  "display_query": "clear natural-language question for the AI to answer (only if action is search)",
163
+ "sql_query": "SQLite SELECT query (only when route is sql or both)",
164
  "clarification_question": "question to ask (only if action is clarify)",
165
  "reasoning": "one sentence explaining your choice"
166
  }}
167
  """
168
 
169
 
170
+ _SQL_ROUTING_INSTRUCTIONS = """\
171
+ SQL ROUTING:
172
+ You have access to structured SQL tables in addition to vector search.
173
+ When choosing a route:
174
+ - "sql" — for data lookups, filtering, aggregation, counting, comparisons
175
+ (e.g., "PTS scores for China", "how many countries", "average GDP")
176
+ - "vector" — for conceptual, definitional, or methodology questions
177
+ (e.g., "what does PTS measure?", "explain the methodology")
178
+ - "both" — for mixed questions combining concepts with data
179
+ (e.g., "explain PTS methodology and show China's scores")
180
+
181
+ IMPORTANT: If the user asks about data summarization, counting, averaging,
182
+ filtering, or any question that requires looking at dataset rows, ALWAYS
183
+ set route to "sql" or "both".
184
+
185
+ When route is "sql" or "both", also provide a valid SQLite SELECT query
186
+ in the "sql_query" field. Use only table/column names from the schema below.
187
+
188
+ {schema_text}
189
+ """
190
+
191
+
192
  def build_query_understanding_prompt(
193
  query: str, domain: str, history: list[dict],
194
+ sql_schema_summary: str = "",
195
  ) -> str:
196
  """Build the query understanding prompt for pre-retrieval reformulation.
197
 
 
199
  query: The user's raw question.
200
  domain: Knowledge domain from config.
201
  history: Recent conversation messages for context resolution.
202
+ sql_schema_summary: Compact SQL schema summary (empty if no tables).
203
 
204
  Returns:
205
  Formatted query understanding prompt string.
 
217
  else:
218
  history_str = "(No prior conversation)"
219
 
220
+ if sql_schema_summary:
221
+ sql_routing_block = _escape_braces(
222
+ _SQL_ROUTING_INSTRUCTIONS.format(schema_text=sql_schema_summary)
223
+ )
224
+ else:
225
+ sql_routing_block = ""
226
+
227
  return QUERY_UNDERSTANDING_PROMPT_TEMPLATE.format(
228
  domain=domain,
229
  history=_escape_braces(history_str),
230
  query=_escape_braces(query),
231
+ sql_routing_block=sql_routing_block,
232
  )
233
 
234
 
tests/test_prompts.py CHANGED
@@ -80,3 +80,32 @@ def test_build_verification_prompt_with_curly_braces():
80
  assert "{result}" in prompt
81
  assert "{raw_value}" in prompt
82
  assert "{braces}" in prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  assert "{result}" in prompt
81
  assert "{raw_value}" in prompt
82
  assert "{braces}" in prompt
83
+
84
+
85
+ def test_qu_prompt_includes_schema_when_provided():
86
+ from src.prompts import build_query_understanding_prompt
87
+ schema_summary = "Available SQL tables:\n- t (100 rows): x (TEXT)"
88
+ prompt = build_query_understanding_prompt(
89
+ "test query", "research", [], sql_schema_summary=schema_summary,
90
+ )
91
+ assert "Available SQL tables" in prompt
92
+ assert "route" in prompt
93
+ assert "sql_query" in prompt
94
+
95
+
96
+ def test_qu_prompt_no_schema_no_sql_fields():
97
+ from src.prompts import build_query_understanding_prompt
98
+ prompt = build_query_understanding_prompt("test query", "research", [])
99
+ assert "Available SQL tables" not in prompt
100
+
101
+
102
+ def test_system_prompt_mentions_chunk_sql():
103
+ from src.prompts import build_prompt
104
+ prompt = build_prompt("context", "Bot", "research")
105
+ assert "CHUNK-SQL" in prompt
106
+
107
+
108
+ def test_verification_prompt_sql_priority():
109
+ from src.prompts import build_verification_prompt
110
+ prompt = build_verification_prompt("resp", "ctx", [], [])
111
+ assert "CHUNK-SQL" in prompt