49 lines
2.6 KiB
Python
49 lines
2.6 KiB
Python
"""Production answer path: retrieval -> model selection -> guard -> rendered text."""
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from pathlib import Path
|
|
|
|
from tools.rag.common import DB_FILE
|
|
from tools.rag.rag_utils import build_rag_context
|
|
from tools.rag.llm_context import compact_rag_payload
|
|
from tools.graphrag.graph_search import search_graph
|
|
from tools.answer_evaluation.graph_context import graph_context
|
|
from tools.answer_evaluation.checked_generation import generate_checked_answer
|
|
from tools.answer_evaluation.verified_rag import generate_verified_rag
|
|
from tools.answers.model_client import complete_with_configured_model
|
|
|
|
_capacity = threading.BoundedSemaphore(2)
|
|
|
|
|
|
def deliver_answer(question: str, *, engine: str = 'rag', limit: int = 5,
|
|
complete=None, db_file: Path = DB_FILE, include_diagnostics: bool = False) -> dict:
|
|
if not _capacity.acquire(blocking=False):
|
|
return {'status': 'error', 'reason': 'answer_capacity_exceeded',
|
|
'accepted_for_delivery': False, 'answer': 'Agent práve spracúva iné odpovede. Skúste to o chvíľu.'}
|
|
try:
|
|
model = complete or complete_with_configured_model
|
|
if engine == 'rag':
|
|
retrieved = compact_rag_payload(build_rag_context(db_file, question, limit=limit))
|
|
result = generate_verified_rag(question, retrieved, model)
|
|
context = retrieved
|
|
elif engine == 'graphrag':
|
|
context = graph_context(search_graph(question))
|
|
prompt = (Path(__file__).resolve().parents[1] / 'answer_evaluation/graph_answer_prompt.txt').read_text()
|
|
generated = generate_checked_answer(question, context, prompt, model)
|
|
if generated.get('accepted_for_delivery'):
|
|
result = {**generated['answer'], 'accepted_for_delivery': True, 'reason': None,
|
|
'index_version': context.get('index_version'), 'complete': context.get('complete'),
|
|
'truncated': context.get('truncated'), 'truncation_reasons': context.get('truncation_reasons'),
|
|
'attempts': generated['attempts']}
|
|
else:
|
|
result = {'status': 'error', 'reason': 'answer_rejected', 'accepted_for_delivery': False,
|
|
'answer': 'Odpoveď neprešla kontrolou podkladov; neoverené údaje sa nezobrazia.',
|
|
'index_version': context.get('index_version'), 'attempts': generated['attempts']}
|
|
else:
|
|
raise ValueError('Unsupported answer engine')
|
|
return {**result, 'engine': engine,
|
|
**({'retrieval_context': context} if include_diagnostics else {})}
|
|
finally:
|
|
_capacity.release()
|