Будівництво HyperQuery: Інтерфейс природної мови для SQL баз даних

Як я створив генератор SQL запитів на основі ШІ за допомогою FastAPI та Groq

pic

Вступ

В еру розробки з підтримкою ШІ, поєднання природної мови та технічних систем відкриває нові можливості. У цій статті ми розглянемо HyperQuery, систему, яка перетворює прості питання англійською мовою на SQL запити за допомогою великих мовних моделей (LLM), виконує їх проти бази даних і виводить результати через веб-інтерфейс.

Архітектура системи

pic

Основні компоненти системи та потік даних

Основні компоненти:

  1. Обробка природної мови: Модель Llama3-70B від Groq
  2. Backend: FastAPI + SQLite + Pydantic
  3. Frontend: Vanilla HTML/CSS/JS
  4. Конвеєр запитів: AI → SQL → Виконання → HTML

Ключові технічні компоненти

1. Генерація SQL за допомогою ШІ

services/query_service.py

class QueryService:  
 def generate_sql(self, user_query: str) -> SQLResponse:  
 response = self.client.chat.completions.create(  
 model="llama3-70b-8192",  
 messages=[  
 {"role": "system", "content": self.base_prompt},  
 {"role": "user", "content": f"Query: {user_query}\nSQL:"}  
 ],  
 response_model=SQLResponse,  
 temperature=0.1  
 )  
 return self._validate_sql(response.sql)

Файл query_service.py є "мозком" HyperQuery. Він використовує модель Llama3-70B від Groq для перетворення запитів на природній мові в SQL. Метод generate_sql відправляє запит користувача до LLM, який генерує SQL на основі схеми бази даних. Метод _validate_sql перевіряє, чи є згенерований SQL безпечним і правильним, розширюючи SELECT * на конкретні назви стовпців і забезпечуючи синтаксис, специфічний для SQLite. Цей компонент також забезпечує генерацію запитів з урахуванням схеми, гарантуючи, що SQL відповідає структурі бази даних.

2. Керування підключеннями до бази даних

database/connector.py

class DatabaseConnector:  
 @contextmanager  
 def get_connection(self):  
 conn = sqlite3.connect(  
 settings.DATABASE_PATH,  
 detect_types=sqlite3.PARSE_DECLTYPES,  
 check_same_thread=False  
 )  
 sqlite3.register_converter('timestamp', convert_timestamp)  
 conn.row_factory = sqlite3.Row  
 yield conn  
 conn.close()  
def execute_safe_query(self, query: str):  
 # Only allows SELECT/PRAGMA queries  
 if not query.upper().startswith(tuple(settings.ALLOWED_OPERATIONS)):  
 raise ValueError("Unauthorized query type")

Файл connector.py керує всіма взаємодіями з базою даних. Він використовує модуль Python sqlite3 для створення та управління підключеннями, забезпечуючи безпеку потоків через check_same_thread=False. Метод get_connection надає контекстний менеджер для підключень до бази даних, а метод execute_safe_query забезпечує виконання лише запитів для читання (SELECT і PRAGMA). Цей файл також обробляє конвертацію часових міток, підтримуючи кілька форматів дати та часу, щоб уникнути помилок під час розбору.

3. Динамічне управління схемою

database/schema_manager.py

class SchemaManager:  
 def get_schema_prompt(self):  
 tables = self.db.execute_safe_query(  
 "SELECT name FROM sqlite_master WHERE type='table'"  
 )  
 schema = {}  
 for table in tables:  
 columns = self.db.execute_safe_query(  
 f"PRAGMA table_info({table['name']})"  
 )  
 schema[table['name']] = [col['name'] for col in columns]  
 return schema

Файл schema_manager.py динамічно отримує схему бази даних, включаючи таблиці та стовпці, за допомогою команди PRAGMA table_info в SQLite. Ця схема потім форматуються в запит для LLM, що дає можливість генерувати точні SQL запити. Динамічне отримання схеми гарантує, що HyperQuery завжди працює з останньою структурою бази даних, навіть якщо таблиці чи стовпці додаються чи змінюються.

4.

Рендеринг результатів

services/html_generator.py

class HTMLGenerator:  
 @staticmethod  
 def generate_table(data: List[Dict], columns: List[str]):  
 return f"""  

{"".join(f"" for col in columns)}{"".join(    f"{''.join(f'' for col in columns)}"    for row in data    )}
{col}    {row[col]}    
    """ 

Файл html_generator.py перетворює результати запитів на HTML таблиці. Він динамічно генерує заголовки таблиць на основі стовпців, що повертаються запитом, і заповнює рядки даними. Цей компонент також обробляє крайні випадки, такі як порожні результати або відсутні стовпці, забезпечуючи постійну взаємодію з користувачем. Сформований HTML є адаптивним і оформлений сучасним CSS для елегантного вигляду.

5. Backend API

backend/main.py

@app.post("/api/query")   
async def handle_query(payload: Dict):    
    try:    
        user_query = payload.get("query", "")    
        sql_response = query_service.generate_sql(user_query)    
        results, columns = db.execute_safe_query(sql_response.sql)    
        return {    
            "sql": sql_response.sql,    
            "html": html_gen.generate_table(results, columns),    
            "columns": columns,    
            "row_count": len(results)    
        }    
    except Exception as e:    
        raise HTTPException(status_code=500, detail=str(e)) 

Пояснення:
Файл main.py є точкою входу для backend FastAPI. Він надає кінцеву точку /api/query, яка приймає запити на природній мові, генерує SQL, виконує його та повертає результати у вигляді HTML. Цей файл організовує взаємодію між сервісом запитів, підключенням до бази даних і генератором HTML. Він також обробляє помилки коректно, надаючи користувачеві змістовний зворотний зв'язок.

Висновок

HyperQuery демонструє, як сучасні можливості ШІ можуть спростити взаємодію з базами даних, одночасно зберігаючи безпеку та продуктивність. Поєднуючи LLM з традиційними базами даних, ми створюємо мости між природною мовою та структурованими даними — важливий крок до більш доступної аналітики даних.

GitHub Репозиторій: https://github.com/iamAliAsgharKhan/HyperQuery

Про автора
Ali Asghar — розробник повного стеку та консультант з ШІ, захоплений створенням мостів між природною мовою та технічними системами. Підключайтеся в LinkedIn і Twitter для отримання більше статей про розробку з підтримкою ШІ.

Перекладено з: Building HyperQuery: A Natural Language Interface for SQL Databases

Leave a Reply

Your email address will not be published. Required fields are marked *