Spaces:
Running
Running
Commit Β·
f97b9fe
1
Parent(s): 1b50825
fix: strip trailing semicolons from LLM-generated SQL and add SQL-route fallback
Browse filesTwo bugs prevented SQL retrieval from working:
1. LLMs append trailing semicolons to SQL (~90%% of the time).
_validate_sql() rejected these as potential injection attacks.
Fix: rstrip(';') before validation (internal semicolons still blocked).
2. When route=sql and the LLM SQL query failed, the keyword-based
SQL fallback never triggered (condition excluded route=sql).
Fix: expanded fallback to build fresh keyword query for route=sql.
Verified end-to-end: China PTS scores now returns 49 rows (was 0).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- src/retriever.py +23 -6
- src/sql_retriever.py +5 -0
src/retriever.py
CHANGED
|
@@ -259,12 +259,29 @@ def retrieve(
|
|
| 259 |
if route in ("vector", "both") or (route == "sql" and not sql_rows):
|
| 260 |
db_results = retrieve_from_vectordb(query, cfg)
|
| 261 |
|
| 262 |
-
# ββ Fallback:
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
# ββ Web search βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 270 |
web_enabled = cfg.get("web_search", {}).get("enabled", False)
|
|
|
|
| 259 |
if route in ("vector", "both") or (route == "sql" and not sql_rows):
|
| 260 |
db_results = retrieve_from_vectordb(query, cfg)
|
| 261 |
|
| 262 |
+
# ββ Fallback: try keyword-based SQL when primary path returned nothing β
|
| 263 |
+
# - route "vector"/"both": vector found nothing β try SQL keyword search
|
| 264 |
+
# - route "sql": LLM SQL query failed β try SQL keyword search as last resort
|
| 265 |
+
sql_fallback_needed = (
|
| 266 |
+
sql_enabled
|
| 267 |
+
and not sql_rows
|
| 268 |
+
and (
|
| 269 |
+
(route in ("vector", "both") and not db_results)
|
| 270 |
+
or route == "sql"
|
| 271 |
+
)
|
| 272 |
+
)
|
| 273 |
+
if sql_fallback_needed:
|
| 274 |
+
if route == "sql":
|
| 275 |
+
# LLM-generated sql_query already failed; build a fresh keyword query
|
| 276 |
+
fallback_query = _build_fallback_sql_query(query, cfg)
|
| 277 |
+
if fallback_query:
|
| 278 |
+
sql_rows, sql_context = _run_sql_retrieval(fallback_query, cfg)
|
| 279 |
+
else:
|
| 280 |
+
# route is "vector" or "both" β existing fallback logic
|
| 281 |
+
if not sql_query:
|
| 282 |
+
sql_query = _build_fallback_sql_query(query, cfg)
|
| 283 |
+
if sql_query:
|
| 284 |
+
sql_rows, sql_context = _run_sql_retrieval(sql_query, cfg)
|
| 285 |
|
| 286 |
# ββ Web search βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 287 |
web_enabled = cfg.get("web_search", {}).get("enabled", False)
|
src/sql_retriever.py
CHANGED
|
@@ -73,6 +73,11 @@ def execute_sql_query(sql_query: str, cfg: dict) -> list[dict]:
|
|
| 73 |
# Strip comments before validation AND execution
|
| 74 |
sql_query = _strip_sql_comments(sql_query).strip()
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
if not _validate_sql(sql_query):
|
| 77 |
return []
|
| 78 |
|
|
|
|
| 73 |
# Strip comments before validation AND execution
|
| 74 |
sql_query = _strip_sql_comments(sql_query).strip()
|
| 75 |
|
| 76 |
+
# Strip trailing semicolons β LLMs add them ~90% of the time.
|
| 77 |
+
# Must happen AFTER comment removal but BEFORE validation, so that
|
| 78 |
+
# _validate_sql() still rejects internal semicolons (statement chaining).
|
| 79 |
+
sql_query = sql_query.rstrip(";").rstrip()
|
| 80 |
+
|
| 81 |
if not _validate_sql(sql_query):
|
| 82 |
return []
|
| 83 |
|