Compare commits
2 Commits
14d29724f1
...
eada1a829b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eada1a829b | ||
|
|
1c500328d1 |
@@ -27,6 +27,19 @@ def record_sql_audit(query, success, error_message=None):
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Failed to record SQL audit: {e}")
|
||||
|
||||
def record_llm_audit(prompt, response, model, success, error_message=None):
|
||||
"""Records an LLM interaction in the audit table."""
|
||||
try:
|
||||
person_id = getattr(current_user, 'id', None)
|
||||
ip_address = get_client_ip()
|
||||
sql = """
|
||||
INSERT INTO llm_audit (person_id, prompt, response, model, ip_address, success, error_message)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
db.execute(sql, [person_id, prompt, response, model, ip_address, success, error_message], commit=True)
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Failed to record LLM audit: {e}")
|
||||
|
||||
def _execute_sql(query):
|
||||
"""Executes arbitrary SQL query, returning results, columns, and error."""
|
||||
results, columns, error = None, [], None
|
||||
@@ -76,10 +89,11 @@ def _generate_sql_from_natural_language(natural_query):
|
||||
api_url = f"https://generativelanguage.googleapis.com/v1beta/models/{gemni_model}:generateContent?key={api_key}"
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
prompt = natural_query
|
||||
try:
|
||||
# Get and format schema
|
||||
schema_info = _get_schema_info()
|
||||
schema_string = _generate_create_script(schema_info)
|
||||
schema_info = db.schema.get_schema_info()
|
||||
schema_string = db.schema.generate_create_script(schema_info)
|
||||
|
||||
prompt = f"""Given the following database schema:
|
||||
```sql
|
||||
@@ -128,14 +142,20 @@ Return ONLY the SQL query, without any explanation or surrounding text/markdown.
|
||||
filtered_lines = [line for line in sql_lines if not line.strip().startswith('--')]
|
||||
final_sql = "\n".join(filtered_lines).strip()
|
||||
|
||||
return final_sql, None
|
||||
generated_sql, error = final_sql, None
|
||||
record_llm_audit(prompt, generated_sql, gemni_model, True)
|
||||
return generated_sql, error
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
current_app.logger.error(f"Gemini API request error: {e}")
|
||||
return None, f"Error communicating with API: {e}"
|
||||
error_msg = f"Error communicating with API: {e}"
|
||||
record_llm_audit(prompt, None, gemni_model, False, error_msg)
|
||||
return None, error_msg
|
||||
except (KeyError, IndexError, Exception) as e:
|
||||
current_app.logger.error(f"Error processing Gemini API response: {e} - Response: {response_data if 'response_data' in locals() else 'N/A'}")
|
||||
return None, f"Error processing API response: {e}"
|
||||
error_msg = f"Error processing API response: {e}"
|
||||
record_llm_audit(prompt, None, gemni_model, False, error_msg)
|
||||
return None, error_msg
|
||||
|
||||
|
||||
# --- Routes ---
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 199 KiB |
@@ -32,8 +32,8 @@
|
||||
class="flex-grow p-2 border border-gray-300 rounded-l-md shadow-sm focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
||||
placeholder="e.g., 'Show me the number of workouts per person'">
|
||||
<button type="button" hx-post="{{ url_for('sql_explorer.generate_sql') }}"
|
||||
hx-include="[name='natural_query']" hx-target="#query" hx-swap="innerHTML"
|
||||
hx-indicator="#sql-spinner"
|
||||
hx-include="[name='natural_query']" hx-indicator="#sql-spinner" hx-swap="none"
|
||||
_="on htmx:afterRequest set #query.value to detail.xhr.responseText then send input to #query"
|
||||
class="bg-purple-600 text-white p-2.5 rounded-r-md hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-opacity-50 inline-flex items-center">
|
||||
Generate SQL
|
||||
<span id="sql-spinner" class="htmx-indicator ml-2">
|
||||
|
||||
Reference in New Issue
Block a user