"""Generate «Руководство оператора» text via the same OpenRouter stack as ESKD chat.""" from __future__ import annotations from pathlib import Path from app.core.config import get_settings from app.services.llm import openrouter_chat_sync EXAMPLE_PATH = Path(__file__).resolve().parents[2] / "espd_templates" / "ro_mat.txt" SYSTEM_PROMPT = """Ты технический писатель по ГОСТ ЕСПД (ЕСПД: ГОСТ 19.101, ГОСТ 19.105, ГОСТ 19.503-79 и связанные). Твоя единственная задача — по описанию программы составить полный текст документа «Руководство оператора» на русском языке. Обязательная структура (нумерация разделов и подпунктов как в образце): 1. Назначение программы 2. Условия выполнения программы 3. Установка программы 4. Работа с программой Правила: - Пиши деловым техническим стилем, без воды и без обращений к читателю в разговорной форме. - Не упоминай ИИ, LLM, промпты, OpenRouter и процесс генерации. - Не используй markdown (без #, **, списков с "-"), только обычный текст с нумерацией 1., 1.1, 1.1.1. - Не добавляй титульный лист, оглавление, «Введение» вне структуры и служебные комментарии. - Если в описании не хватает деталей — формулируй разумные типовые требования (ОС, права, шаги установки/запуска), не выдумывай конкретные секретные URL/пароли. - Выход: только готовый текст руководства, без предисловий вроде «Вот документ:». """ def _load_example() -> str: if not EXAMPLE_PATH.exists(): return "" return EXAMPLE_PATH.read_text(encoding="utf-8", errors="replace") def generate_ro_content(progname: str, decimal: str, user_description: str) -> str: settings = get_settings() if not (settings.openrouter_api_key or "").strip(): return "[Ошибка: не задан OPENROUTER_API_KEY.]" example = _load_example() sample = ( example[:12000] if example else ( "1. Назначение программы\n" "1.1. …\n" "2. Условия выполнения программы\n" "3. Установка программы\n" "4. Работа с программой" ) ) user_prompt = f"""Составь полный текст «Руководство оператора» по ГОСТ ЕСПД. Данные документа: - Обозначение (децимальный номер): {decimal or "—"} - Название программы: {progname or "—"} Описание от заказчика (что за программа, для какой системы, что должна делать): {user_description.strip() or "Описание не предоставлено — составь типовое руководство по названию и обозначению."} Образец оформления и стиля (придерживайся структуры и нумерации): --- {sample} --- Выведи только текст руководства.""" try: text = openrouter_chat_sync( [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_prompt}, ], temperature=0.4, max_tokens=4000, ) return text.strip() except Exception as e: return f"[Ошибка генерации: {e}]"