#!/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, )