Skip to content

Commit 25beddf

Browse files
authored
Merge pull request #23 from PennChopMicrobiomeProgram/codex/plan-implementation-for-natural-language-query-feature
Add natural language query endpoint
2 parents 09bf320 + 51bd7cb commit 25beddf

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

app/app.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from sqlalchemy import text
2727
from sqlalchemy import select
2828
from app.datatables import datatables_response, init_app, query_columns
29+
from app.nl_query import run_nl_query
2930
from werkzeug.middleware.proxy_fix import ProxyFix
3031

3132

@@ -218,6 +219,19 @@ def api_query():
218219
return {"error": "Query execution failed"}, 500
219220

220221

222+
@app.route("/api/nl_query", methods=["POST"])
223+
def api_nl_query():
224+
"""Translate a natural language question into SQL and execute it."""
225+
question = request.form.get("query")
226+
if not question:
227+
return {"error": "No query provided"}, 400
228+
try:
229+
return run_nl_query(db.session, question), 200
230+
except Exception as e:
231+
print(f"Error executing NL query: {e}")
232+
return {"error": "Query execution failed"}, 500
233+
234+
221235
@app.route("/api", methods=["POST"])
222236
def api():
223237
try:

app/nl_query.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Utility functions for natural language to SQL queries."""
2+
3+
from typing import Dict, List
4+
5+
from sqlalchemy import text
6+
from sqlalchemy.orm import Session
7+
8+
9+
def _to_sql(question: str) -> str:
10+
"""Naively convert a natural language question to SQL.
11+
12+
This is a placeholder implementation meant to demonstrate how the
13+
translation could be structured. Only a very small set of questions is
14+
supported.
15+
"""
16+
17+
q = question.lower()
18+
if "how many isolates" in q:
19+
return "SELECT COUNT(*) AS count FROM isolates"
20+
raise ValueError("Unsupported question")
21+
22+
23+
def run_nl_query(session: Session, question: str) -> Dict[str, List[Dict[str, int]]]:
24+
"""Execute a natural language query against the database."""
25+
26+
sql = _to_sql(question)
27+
result = session.execute(text(sql)).fetchall()
28+
return {"sql": sql, "result": [dict(row._mapping) for row in result]}

tests/test_api.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ def test_query_api(client):
6464
data = resp.get_json()
6565
assert data["recordsTotal"] == 1
6666
assert data["data"][0]["one"] == 1
67+
68+
69+
def test_nl_query_api(client):
70+
resp = client.post("/api/nl_query", data={"query": "How many isolates are there?"})
71+
assert resp.status_code == 200
72+
data = resp.get_json()
73+
assert data["sql"] == "SELECT COUNT(*) AS count FROM isolates"
74+
assert data["result"][0]["count"] == 0

0 commit comments

Comments
 (0)