Download src/t2s/serving/audit.py from Ashoksainibadu/text2sql-assistant: direct link, hf CLI and curl.
- Browser
- Download file 3.84 kB
-
https://huggingface.co/spaces/Ashoksainibadu/text2sql-assistant/resolve/main/src/t2s/serving/audit.py
- Command line
-
hf download hf://spaces/Ashoksainibadu/text2sql-assistant/src/t2s/serving/audit.py
-
curl -L -o audit.py https://huggingface.co/spaces/Ashoksainibadu/text2sql-assistant/resolve/main/src/t2s/serving/audit.py
3.84 kB
| """Audit logger for recording text-to-SQL API requests and safety verdicts.""" | |
| import hashlib | |
| import json | |
| import os | |
| import sqlite3 | |
| import time | |
| from pathlib import Path | |
| from typing import Optional | |
| class AuditLogger: | |
| def __init__(self, db_path: Optional[str] = None) -> None: | |
| target_path = db_path or os.getenv("AUDIT_DB_PATH", "reports/audit_log.db") | |
| self.db_path = Path(target_path) | |
| try: | |
| self.db_path.parent.mkdir(parents=True, exist_ok=True) | |
| self._init_db() | |
| except (PermissionError, OSError): | |
| # Fallback for read-only containers / Hugging Face Spaces | |
| fallback_dir = Path("/tmp") if Path("/tmp").exists() else Path.home() | |
| self.db_path = fallback_dir / "audit_log.db" | |
| self.db_path.parent.mkdir(parents=True, exist_ok=True) | |
| self._init_db() | |
| def _init_db(self) -> None: | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| cursor.execute( | |
| """ | |
| CREATE TABLE IF NOT EXISTS audit_logs ( | |
| request_id TEXT PRIMARY KEY, | |
| timestamp REAL, | |
| api_key_hash TEXT, | |
| db_id TEXT, | |
| question TEXT, | |
| generated_sql TEXT, | |
| allowed INTEGER, | |
| reasons TEXT, | |
| row_count INTEGER, | |
| retried INTEGER, | |
| execution_time_ms REAL, | |
| model_version TEXT | |
| ); | |
| """ | |
| ) | |
| cursor.execute( | |
| """ | |
| CREATE TABLE IF NOT EXISTS user_feedback ( | |
| request_id TEXT PRIMARY KEY, | |
| timestamp REAL, | |
| rating INTEGER, | |
| comment TEXT | |
| ); | |
| """ | |
| ) | |
| conn.commit() | |
| conn.close() | |
| def log_query( | |
| self, | |
| request_id: str, | |
| api_key: str, | |
| db_id: str, | |
| question: str, | |
| generated_sql: str, | |
| allowed: bool, | |
| reasons: list, | |
| row_count: int, | |
| retried: bool, | |
| execution_time_ms: float, | |
| model_version: str = "Qwen2.5-Coder-3B-QLoRA", | |
| ) -> None: | |
| api_key_hash = hashlib.sha256(api_key.encode("utf-8")).hexdigest()[:16] | |
| # Redaction: truncate question and record hash to prevent credential leakage in logs | |
| sanitized_question = (question[:97] + "...") if len(question) > 100 else question | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| cursor.execute( | |
| """ | |
| INSERT OR REPLACE INTO audit_logs ( | |
| request_id, timestamp, api_key_hash, db_id, question, | |
| generated_sql, allowed, reasons, row_count, retried, | |
| execution_time_ms, model_version | |
| ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); | |
| """, | |
| ( | |
| request_id, | |
| time.time(), | |
| api_key_hash, | |
| db_id, | |
| sanitized_question, | |
| generated_sql, | |
| 1 if allowed else 0, | |
| json.dumps(reasons), | |
| row_count, | |
| 1 if retried else 0, | |
| execution_time_ms, | |
| model_version, | |
| ), | |
| ) | |
| conn.commit() | |
| conn.close() | |
| def log_feedback(self, request_id: str, rating: int, comment: Optional[str] = None) -> None: | |
| conn = sqlite3.connect(self.db_path) | |
| cursor = conn.cursor() | |
| cursor.execute( | |
| """ | |
| INSERT OR REPLACE INTO user_feedback (request_id, timestamp, rating, comment) | |
| VALUES (?, ?, ?, ?); | |
| """, | |
| (request_id, time.time(), rating, comment or ""), | |
| ) | |
| conn.commit() | |
| conn.close() | |
| default_audit_logger = AuditLogger() | |