Download Backend/tools/query_tool.py from Mey-agen/MVP: direct link, hf CLI and curl.
- Browser
- Download file 3.61 kB
-
https://huggingface.co/spaces/Mey-agen/MVP/resolve/main/Backend/tools/query_tool.py
- Command line
-
hf download hf://spaces/Mey-agen/MVP/Backend/tools/query_tool.py
-
curl -L -o query_tool.py https://huggingface.co/spaces/Mey-agen/MVP/resolve/main/Backend/tools/query_tool.py
3.61 kB
| import os | |
| import sys | |
| from pathlib import Path | |
| # Ensure Backend directory is in sys.path and root .env is loaded | |
| BACKEND_DIR = Path(__file__).resolve().parent.parent | |
| if str(BACKEND_DIR) not in sys.path: | |
| sys.path.insert(0, str(BACKEND_DIR)) | |
| import config | |
| from pydantic import BaseModel | |
| from litellm import completion | |
| from database.database import execute_query | |
| # Simplified schema reference for the LLM context | |
| DB_SCHEMA = """ | |
| CREATE TABLE customers (id INTEGER PRIMARY KEY, first_name TEXT, last_name TEXT, email TEXT, created_at TIMESTAMP); | |
| CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, product_name TEXT, amount REAL, status TEXT, order_date TIMESTAMP, FOREIGN KEY (customer_id) REFERENCES customers(id)); | |
| """ | |
| class QueryToolParams(BaseModel): | |
| natural_language_query: str | |
| def run_query_tool(params: dict) -> str: | |
| """Translates NL to SQL, validates it, and executes it against the database.""" | |
| try: | |
| tool_config = QueryToolParams(**params) | |
| except Exception as e: | |
| return f"Error parsing parameters: {e}" | |
| prompt = f"""You are an expert SQL assistant. Convert the following natural language query into a raw SQL SELECT statement. | |
| Schema: | |
| {DB_SCHEMA} | |
| Query: {tool_config.natural_language_query} | |
| Return ONLY the SQL string, without markdown formatting or code blocks. | |
| """ | |
| try: | |
| model_name = config.get_llm_model() | |
| api_key = config.get_api_key() | |
| completion_kwargs = { | |
| "model": model_name, | |
| "messages": [{"role": "user", "content": prompt}], | |
| "temperature": 0 | |
| } | |
| if api_key: | |
| completion_kwargs["api_key"] = api_key | |
| response = completion(**completion_kwargs) | |
| message = response.choices[0].message | |
| sql_query = (message.content or getattr(message, "reasoning_content", "") or "").strip() | |
| except Exception as e: | |
| return f"Query Tool Error: {str(e)}" | |
| try: | |
| import re | |
| # If output contains markdown code block, extract it | |
| code_block_match = re.search(r"```(?:sql)?\s*([\s\S]*?)\s*```", sql_query, re.IGNORECASE) | |
| if code_block_match: | |
| sql_query = code_block_match.group(1).strip() | |
| elif not sql_query.upper().startswith("SELECT"): | |
| # If wrapped in reasoning text, extract the SELECT statement | |
| select_match = re.search(r"(SELECT\s+[\s\S]+?)(?:;|\n\n|$)", sql_query, re.IGNORECASE) | |
| if select_match: | |
| sql_query = select_match.group(1).strip() | |
| if sql_query.startswith("```sql"): | |
| sql_query = sql_query.replace("```sql", "", 1) | |
| if sql_query.endswith("```"): | |
| sql_query = sql_query[::-1].replace("```", "", 1)[::-1] | |
| elif sql_query.startswith("```"): | |
| sql_query = sql_query.replace("```", "", 1) | |
| if sql_query.endswith("```"): | |
| sql_query = sql_query[::-1].replace("```", "", 1)[::-1] | |
| sql_query = sql_query.strip() | |
| # Simple read-only check since safety module is removed | |
| if not sql_query.upper().startswith("SELECT"): | |
| return "Safety Violation: Only SELECT queries are allowed." | |
| if "LIMIT" not in sql_query.upper(): | |
| sql_query = sql_query.rstrip(";") + " LIMIT 50;" | |
| rows = execute_query(sql_query) | |
| if not rows: | |
| return f"Executed `{sql_query}`: No results found." | |
| return f"Executed `{sql_query}`:\n" + str(rows) | |
| except Exception as e: | |
| return f"Query Tool Error: {str(e)}" | |