mirror of
http://100.103.83.12:3003/fegger/pv-agent.git
synced 2026-09-17 15:46:23 +00:00
feat(agent): support cost questions and thinking fallback
This commit is contained in:
+51
-25
@@ -12,7 +12,7 @@ import time
|
||||
|
||||
from .config import Config
|
||||
from .normalize import normalize_text
|
||||
from .ollama_client import OllamaClient
|
||||
from .ollama_client import OllamaClient, OllamaError
|
||||
from .query_planner import SubQuery, is_decision_support, plan_queries
|
||||
from .retrieve import ChunkResult, Retriever
|
||||
|
||||
@@ -71,9 +71,18 @@ Verbindliche Regeln:
|
||||
von zweckgebundenen Sach- oder Kostenleistungen. Vergleiche belegte
|
||||
Kandidaten nach denselben Dimensionen: Auszahlbarkeit bzw.
|
||||
Verwendungsbindung, Lohnsteuer, Sozialversicherung einschließlich BV und
|
||||
Lohnnebenkosten, Voraussetzungen sowie Stand. Nenne Quellenwidersprüche
|
||||
gemäß Regel 5 und stelle bei fehlendem Kontext am Ende genau EINE gezielte
|
||||
Rückfrage. Sind [wk-akt-04] und [lb-sva-03] beide als Block-Köpfe im
|
||||
Lohnnebenkosten, Voraussetzungen sowie Stand. Nennt die Frage konkrete
|
||||
Eckdaten (z. B. Bruttolohn, Betrag, Einmaligkeit, Barzahlung), wende die
|
||||
belegten Sätze unmittelbar auf diesen Fall an: rechne mit den im Kontext
|
||||
genannten Sätzen die Arbeitgeberkosten Schritt für Schritt (Lohnsteuer,
|
||||
SV einschließlich DB und DZ, allfällige KommSt) und gib die Gesamtbelastung
|
||||
an. Belege jede in die Rechnung eingehende Zahl mit [ID] und Stand; steht
|
||||
ein Rechenwert nur allgemein im Kontext (z. B. Jahressechstel,
|
||||
Bemessungsgrundlage), nenne diese Annahme explizit. Fehlt hingegen ein für
|
||||
die Berechnung wesentlicher Parameter, stelle am Ende genau EINE gezielte
|
||||
Rückfrage — nicht zusätzlich, wenn die Rechnung mit den Kontextwerten
|
||||
möglich ist. Nenne Quellenwidersprüche
|
||||
gemäß Regel 5. Sind [wk-akt-04] und [lb-sva-03] beide als Block-Köpfe im
|
||||
Kontext vorhanden, stelle den Konflikt ausdrücklich mit ⚠ dar:
|
||||
[wk-akt-04] nennt die Mitarbeiterprämie 2026 SV-/BV-pflichtig;
|
||||
[lb-sva-03] ordnet sie systematisch in den taxativen Katalog
|
||||
@@ -268,7 +277,11 @@ def answer_question(
|
||||
if cfg.planner_enabled:
|
||||
try:
|
||||
sub_queries, planned, qtype = plan_queries(question, client, cfg)
|
||||
sub_queries = sub_queries[: cfg.planner_max_queries] or sub_queries[:1]
|
||||
if not is_decision_support(question):
|
||||
# LLM-Pläne bleiben auf die Maximalzahl begrenzt; der
|
||||
# deterministische Abgaben-Vergleichsplan liefert nur gezielte
|
||||
# Queries (max. 5) und darf sie vollständig behalten.
|
||||
sub_queries = sub_queries[: cfg.planner_max_queries] or sub_queries[:1]
|
||||
except Exception:
|
||||
sub_queries, planned, qtype = [SubQuery(text=question)], False, "specific"
|
||||
|
||||
@@ -332,28 +345,41 @@ def answer_question(
|
||||
def chat(msgs, num_predict: int | None = None):
|
||||
"""Ein Chat-Zug; liefert (gestrippter Content, done_reason).
|
||||
Bei done_reason='length' (Antwort bei num_predict abgeschnitten)
|
||||
sind Zitationen ggf. unvollstaendig — der Aufrufer ruft einmal mit
|
||||
doppeltem Budget neu (technischer Retry, kein Regel-Regeneration)."""
|
||||
sind Zitationen ggf. unvollständig — der Aufrufer ruft einmal mit
|
||||
doppeltem Budget neu (technischer Retry, kein Regel-Regeneration).
|
||||
Liefert das Modell bei aktivem Thinking leeren Content (Antwort nur
|
||||
im thinking-Feld bzw. Budget im Thinking aufgebraucht), wird einmal
|
||||
ohne Thinking wiederholt."""
|
||||
budget = num_predict or cfg.num_predict
|
||||
if hasattr(client, "chat_full"):
|
||||
raw, done_reason = client.chat_full(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=budget,
|
||||
think=cfg.think,
|
||||
|
||||
def call(use_think: bool):
|
||||
if hasattr(client, "chat_full"):
|
||||
return client.chat_full(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=budget,
|
||||
think=use_think,
|
||||
)
|
||||
return (
|
||||
client.chat(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=budget,
|
||||
think=use_think,
|
||||
),
|
||||
"stop",
|
||||
)
|
||||
else:
|
||||
raw = client.chat(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=budget,
|
||||
think=cfg.think,
|
||||
)
|
||||
done_reason = "stop"
|
||||
|
||||
try:
|
||||
raw, done_reason = call(cfg.think)
|
||||
except OllamaError:
|
||||
if not cfg.think:
|
||||
raise
|
||||
raw, done_reason = call(False)
|
||||
return strip_think(raw), done_reason
|
||||
|
||||
def chat_with_length_retry(msgs):
|
||||
|
||||
Reference in New Issue
Block a user