| """PromptBuilder — формирование chat-template input для модели. |
| |
| Соответствует разделу 2.4 пояснительной записки. Один и тот же билдер |
| используется при обучении (формирование SFT-примеров) и при инференсе |
| (формирование запроса к загруженной модели), что гарантирует совпадение |
| формата train- и inference-time промптов. |
| |
| Помимо схемы и вопроса, билдер опционально принимает BusinessVocabulary |
| (раздел 3.6 ВКР). Бизнес-термины подмешиваются в системное сообщение, |
| а не конкатенируются к пользовательскому вопросу — это согласуется с |
| тем, как современные instruction-tuned модели интерпретируют роли |
| сообщений в chat-template. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from typing import TYPE_CHECKING |
|
|
| if TYPE_CHECKING: |
| from src.business.vocabulary import BusinessVocabulary |
|
|
|
|
| BASE_SYSTEM_PROMPT = ( |
| "Ты — ассистент, который преобразует вопросы на русском языке в корректные SQL-запросы. " |
| "Тебе даётся схема базы данных в виде CREATE TABLE statements и пример нескольких строк. " |
| "Сгенерируй один SQL-запрос, который отвечает на вопрос пользователя. " |
| "Возвращай ТОЛЬКО SQL без объяснений, без markdown, без префиксов." |
| ) |
|
|
|
|
| def build_user_message(schema: str, question: str) -> str: |
| """Пользовательская часть промпта в формате ``### Schema / ### Question / ### SQL:``.""" |
| return f"### Schema:\n{schema}\n\n### Question:\n{question}\n\n### SQL:\n" |
|
|
|
|
| def build_system_message(vocabulary: "BusinessVocabulary | None" = None) -> str: |
| """Собирает системное сообщение. |
| |
| Если передан непустой бизнес-словарь, к базовому промпту добавляется |
| блок с определениями терминов, фильтрами и правилами компании. Это |
| позволяет адаптировать систему к терминологии конкретной организации |
| без повторного дообучения модели. |
| """ |
| if vocabulary is None or not vocabulary: |
| return BASE_SYSTEM_PROMPT |
| context = vocabulary.render_system_context() |
| if not context: |
| return BASE_SYSTEM_PROMPT |
| return BASE_SYSTEM_PROMPT + "\n\n" + context |
|
|
|
|
| def build_chat_messages( |
| schema: str, |
| question: str, |
| vocabulary: "BusinessVocabulary | None" = None, |
| ) -> list[dict]: |
| """Сообщения для ``tokenizer.apply_chat_template``. |
| |
| Параметры |
| --------- |
| schema : str |
| Текстовое представление схемы (CREATE TABLE + sample rows). |
| question : str |
| Вопрос пользователя на русском языке. |
| vocabulary : BusinessVocabulary, optional |
| Бизнес-словарь компании. Если передан — добавляется в системное |
| сообщение, не нарушая структуры пользовательской реплики. |
| """ |
| return [ |
| {"role": "system", "content": build_system_message(vocabulary)}, |
| {"role": "user", "content": build_user_message(schema, question)}, |
| ] |
|
|
|
|
| def build_training_example( |
| schema: str, |
| question: str, |
| sql: str, |
| vocabulary: "BusinessVocabulary | None" = None, |
| ) -> list[dict]: |
| """Полный диалог с эталонной репликой ассистента для Supervised |
| Fine-Tuning (раздел 2.4 ВКР). |
| """ |
| msgs = build_chat_messages(schema, question, vocabulary) |
| msgs.append({"role": "assistant", "content": sql.strip()}) |
| return msgs |
|
|
|
|
| |
| |
| SYSTEM_PROMPT = BASE_SYSTEM_PROMPT |
|
|