refactor(local-llm): generische Tool-Fehler-Eskalation statt per-Skill-Router-Code
Stefan-Punkt: der 'auf <Geraet>'-Router-Patch war ein per-Fall-Band-Aid, das
nicht skaliert (naechster Skill mit komplexer API → wieder patchen). Besser:
das LLM merkt es selbst.
- Router-Hardcoding zurueckgenommen (kein 'auf Geraet'→Claude mehr).
- GENERAL: im lokalen Tool-Loop → scheitert ein Tool-Call (Ergebnis beginnt mit
'FEHLER'), uebernimmt Claude. Gilt fuer JEDEN Skill, kein per-Fall-Wissen im
Router. Lokal probiert, bei Fehler eskaliert.
- skill_create-Anleitung: SEMANTISCH bauen — Skills bieten klare Operationen als
args (action/device_name), NICHT rohe {path,method,body}-Durchreichung. Das
args-Schema ist die 'Bedienungsanleitung', die das LLM sieht (die haben wir
also schon — sie muss nur semantisch sein). Was das LLM sonst raten muesste
(Endpunkte/IDs/Payload) gehoert INS Skill.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -150,6 +150,17 @@ META_TOOLS = [
|
||||
"Stefan sich alle 60min manuell neu einloggen.\n"
|
||||
" - Bei konfigurierbaren Werten (User-IDs, Endpoints, Defaults): "
|
||||
"ueber `config_schema` deklarieren, NICHT hardcoden.\n\n"
|
||||
"SEMANTISCH BAUEN (wichtig fuer Zuverlaessigkeit!): Ein Skill soll "
|
||||
"KLARE Operationen als args anbieten, NICHT die rohe API "
|
||||
"durchreichen. Schlecht: args = {path, method, body} — dann muss das "
|
||||
"aufrufende LLM die ganze fremde API selbst kennen und baut bei "
|
||||
"komplexen Faellen (z.B. Geraete-Transfer) falsche Calls. Gut: args "
|
||||
"= {action: 'play'|'pause'|'next'|'play_on_device', device_name?: str} "
|
||||
"— der Skill-Code loest intern auf (Geraet-Name → ID, richtiger "
|
||||
"Endpoint) und kapselt die API. Faustregel: Was das LLM sonst RATEN "
|
||||
"muesste (Endpunkte, IDs, Payload-Struktur), gehoert INS Skill. Das "
|
||||
"`args`-Schema ist die Bedienungsanleitung, die das LLM sieht — mach "
|
||||
"sie semantisch und selbsterklaerend.\n\n"
|
||||
"HARTE REGEL — IMMER Skill anlegen wenn: die Loesung erfordert eine "
|
||||
"pip-Library. Sonst muesste der Install bei jedem Container-Restart "
|
||||
"neu laufen (Brain hat keinen persistenten State ausser /data/skills/).\n\n"
|
||||
@@ -1186,6 +1197,7 @@ class Agent:
|
||||
messages.append({"role": "assistant",
|
||||
"content": res.get("content") or "",
|
||||
"tool_calls": tcs})
|
||||
had_error = False
|
||||
for tc in tcs:
|
||||
fn = tc.get("function") or {}
|
||||
tname = fn.get("name") or ""
|
||||
@@ -1196,10 +1208,20 @@ class Agent:
|
||||
logger.info("[router] lokal Tool-Call: %s(%s)", tname,
|
||||
", ".join(targs.keys()))
|
||||
tresult = self._dispatch_tool(tname, targs)
|
||||
if (tresult or "").strip().startswith("FEHLER"):
|
||||
had_error = True
|
||||
messages.append({"role": "tool",
|
||||
"tool_call_id": tc.get("id") or "",
|
||||
"name": tname,
|
||||
"content": (tresult or "")[:6000]})
|
||||
# GENERAL (kein per-Skill-Code): scheitert ein Tool-Call, macht
|
||||
# das grosse Modell weiter — es baut komplexe/rohe API-Calls
|
||||
# zuverlaessiger und behandelt Fehler besser. So muss der Router
|
||||
# NICHT wissen, welche Skill-Aufrufe "schwer" sind; das lokale
|
||||
# Tier probiert, und bei Fehler uebernimmt Claude.
|
||||
if had_error and not local_only:
|
||||
logger.info("[router] lokaler Tool-Fehler → Claude uebernimmt")
|
||||
return None
|
||||
continue # naechste Runde mit Tool-Ergebnissen
|
||||
final = (res.get("content") or "").strip()
|
||||
break
|
||||
|
||||
@@ -67,11 +67,7 @@ _TOOL_HINTS = re.compile(
|
||||
r"skill|projekt|oauth|"
|
||||
r"licht|lampe|steckdose|rollade|heizung|"
|
||||
r"kalender|termin|"
|
||||
r"maild?|e-?mail|nachricht schreiben)\b|"
|
||||
# Geraete-gezieltes Spotify-Abspielen = komplexer Transfer-Flow (Geraete
|
||||
# abfragen -> Name->ID -> richtiger Endpoint). Das 8B fummelt das -> Claude.
|
||||
r"(abspiel|spielen|play|weiter|wechsel|übertrag|transfer).{0,15}\bauf\b|"
|
||||
r"\bauf\s+(android|handy|smartphone|desktop|duffy|firetv|tv|dem\s+\w+|mein)",
|
||||
r"maild?|e-?mail|nachricht schreiben)\b",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user