FabIndy's picture
Improve AI summary UX and tighten prompt to prevent truncation
845e1f0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
qa.py — QA + SUMMARY via Groq uniquement (pas de LLM local)
- Pas de fallback llama.cpp (trop lent).
- Si GROQ_API_KEY n'est pas défini, on lève une erreur explicite.
"""
from __future__ import annotations
import os
from dataclasses import dataclass
from typing import List, Dict
from src.resources import generate_chat, is_groq_enabled
# ==================== CONFIG ====================
@dataclass(frozen=True)
class QAConfig:
qa_top_k_final: int = int(os.environ.get("QA_TOP_K_FINAL", "2"))
qa_doc_max_chars: int = int(os.environ.get("QA_DOC_MAX_CHARS", "700"))
qa_max_tokens: int = int(os.environ.get("QA_MAX_TOKENS", "220"))
qa_temperature: float = float(os.environ.get("QA_TEMPERATURE", "0.1"))
# ==================== TEXT UTILS ====================
def truncate_text(s: str, n: int) -> str:
if not s:
return ""
s = s.strip()
return s if len(s) <= n else s[:n].rstrip() + "\n[...]\n"
# ==================== PROMPTS ====================
def build_qa_prompt_fast(question: str, context: str, sources: List[str]) -> str:
src = ", ".join(sources) if sources else "N/A"
return f"""Tu es un assistant juridique francophone. Tu aides à comprendre le Code de l'éducation (France).
RÈGLES STRICTES :
- Réponds uniquement en français.
- Appuie-toi en priorité sur le CONTEXTE fourni.
- Si l'information n'est pas dans le contexte, dis-le explicitement.
- Réponse courte et pratique (6 à 10 phrases maximum).
- Ne cite pas de sources externes (sites, lois non fournies, jurisprudence, etc.).
QUESTION :
{question}
CONTEXTE :
{context}
Termine par une ligne :
Sources (articles) : {src}
"""
def build_summary_prompt(article_id: str, article_text: str) -> str:
return f"""Tu es un assistant juridique francophone.
LANGUE : réponds uniquement en français.
TÂCHE : résumer fidèlement un article du Code de l'éducation à partir du texte fourni.
RÈGLES STRICTES :
- N'invente rien. Si une information n'est pas dans le texte, ne l'ajoute pas.
- 4 puces maximum.
- 1 seule phrase courte par puce.
- Chaque puce ≤ 12 mots.
- Ne pas numéroter. Ne pas écrire "Puce 1", "Puce 2".
- Commence chaque ligne par "- ".
- 45 mots maximum au total.
- Ne rien écrire en dehors des puces.
ARTICLE {article_id} (texte / extraits fournis) :
{article_text}
"""
# ==================== GENERATION (GROQ ONLY) ====================
def llm_generate_qa(prompt: str, cfg: QAConfig | None = None) -> str:
"""
Génération via Groq uniquement.
"""
if not is_groq_enabled():
raise RuntimeError(
"Groq n'est pas configuré : variable GROQ_API_KEY manquante. "
"Ajoute GROQ_API_KEY (et optionnellement GROQ_MODEL) dans l'environnement."
)
cfg = cfg or QAConfig()
messages: List[Dict[str, str]] = [{"role": "user", "content": prompt}]
return generate_chat(
messages,
max_tokens=cfg.qa_max_tokens,
temperature=cfg.qa_temperature,
)