diff --git a/app/routes/api_bp.py b/app/routes/api_bp.py index 81269c3..340d094 100644 --- a/app/routes/api_bp.py +++ b/app/routes/api_bp.py @@ -1,9 +1,10 @@ -"""API blueprint — groups, documents, supplements, sync, cleanup, spec-current.""" +"""API blueprint — groups, documents, supplements, sync, cleanup, spec-current, chat.""" from flask import Blueprint, request, jsonify from app.db import documents, supplements, spec_current from app.db.connection import execute, query from app.services.grouping import group_documents, apply_groups -from app.config import API_KEY +from app.config import API_KEY, LLM_URL, LLM_KEY, LLM_MODEL +import httpx api_bp = Blueprint("api", __name__) @@ -133,6 +134,53 @@ def api_spec_current(): return jsonify(ok=True, rows=rows) +# ── Chat (совместимость с Lucee /chat.cfm) ────────────────────── + +@api_bp.route("/chat", methods=["POST"]) +@api_bp.route("/chat.cfm", methods=["POST"]) +def chat(): + """Чат с LLM по данным спецификации. Совместим с Lucee-форматом ответа.""" + contract_id = request.args.get("contract_id", "") + question = request.form.get("question", "") + if not contract_id or not question: + return jsonify(OK=False, ERROR="contract_id and question required") + + rows = spec_current.list_by_contract(contract_id) + if not rows: + return jsonify(OK=True, ANSWER="Нет данных. Сначала запустите сравнение.") + + ctx = "\n".join( + f"{r.get('name','')} | цена={r.get('price')} | объём={r.get('qty')} | " + f"сумма={r.get('sum')} | начало={r.get('date_start')}" + for r in rows + ) + prompt = ( + f"Ты — анализатор договоров. Данные:\n{ctx}\n\n" + f"Вопрос: {question}\nОтветь кратко, только по данным." + ) + + try: + with httpx.Client(http2=True, timeout=120) as client: + resp = client.post( + LLM_URL, + json={ + "model": LLM_MODEL, + "messages": [{"role": "user", "content": prompt}], + "max_tokens": 1000, + "temperature": 0.1, + }, + headers={ + "Authorization": f"Bearer {LLM_KEY}", + "Content-Type": "application/json", + }, + ) + resp.raise_for_status() + answer = resp.json()["choices"][0]["message"]["content"] + return jsonify(OK=True, ANSWER=answer) + except Exception as e: + return jsonify(OK=False, ERROR=f"LLM error: {e}") + + # ── Cleanup (требует API-ключ) ──────────────────────────────────── @api_bp.route("/api/cleanup", methods=["POST"])