From 60580fd67ece3877e7dd660ac9a8e1b009636115 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 11 Jul 2026 23:59:31 +0200 Subject: [PATCH] =?UTF-8?q?refactor(brain):=20local=20wieder=20tool-los=20?= =?UTF-8?q?(B1a)=20=E2=80=94=208B=20nur=20noch=20Reden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B1b hatte dem 8B run_*/web_search-Tools gegeben. Das war die Wurzel von BEIDEM: (1) ein 8B ist ein unzuverlaessiger Tool-Caller und erfindet lieber eine plausible Antwort ('der Song ist X') statt das Tool zu rufen → halo; (2) das zwang zu per-Skill-Guards (skaliert nicht). Fix ohne eine einzige per-Skill-Zeile: - Local: tools=[] — kann kein Skill-Ergebnis mehr faelschen. - Router: _LIVE_HINTS schickt alles mit aktueller Grundwahrheit (Wetter/News/Uhrzeit/Musik/Preise/Timer/…) VORAB an Claude, nicht erst nach einem gescheiterten Local-Versuch (kein Doppel-Zahlen). Topic-Ebene, nicht per-Skill — ein neuer Skill braucht hier keine Zeile. - Prompt: _AWARENESS sagt local explizit, dass es tool-los ist und fuer Live/Aktion eskaliert. Arbeitsteilung: Fast-Path (Regex→Skill, deterministisch, 0 halo) fuer Befehle · Local (tool-los) fuers Reden · Claude fuer alles mit Tool/Fakt/ Gedaechtnis/Urteil. Co-Authored-By: Claude Opus 4.8 --- aria-brain/agent.py | 9 ++++++++- aria-brain/router.py | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/aria-brain/agent.py b/aria-brain/agent.py index 17d339d..85b78b5 100644 --- a/aria-brain/agent.py +++ b/aria-brain/agent.py @@ -1418,7 +1418,14 @@ class Agent: self._local_ran_skill = False local_only = bool(cfg.get("localOnly")) local_model = cfg.get("localLlmModel") or "qwen3-8b" # B0.5: llama-swap-Key - tools = self._build_local_tools() # B1b: kuratierte Tools + # B1a-Rueckbau (bewusst): local ist TOOL-LOS — nur reines Reden. Ein 8B + # ist ein unzuverlaessiger Tool-Caller: mit Werkzeug in der Hand erfindet + # er lieber eine plausible Antwort ('der Song ist X'), statt das Tool zu + # rufen — das war die Halo-Quelle UND zwang zu per-Skill-Guards. Ohne + # Tools KANN er kein Skill-Ergebnis faelschen. Alles mit Grundwahrheit + # (Fakt/Live-Zustand/Gedaechtnis/Aktion) gehoert an Claude (Router-Gate + # vorab) oder an den deterministischen Fast-Path — nicht an den 8B. + tools = [] sys_prompt = router_mod.build_local_system_prompt(IDENTITY_ANCHOR, has_tools=bool(tools)) diff --git a/aria-brain/router.py b/aria-brain/router.py index f626ffd..958074b 100644 --- a/aria-brain/router.py +++ b/aria-brain/router.py @@ -75,6 +75,26 @@ _TOOL_HINTS = re.compile( re.IGNORECASE, ) +# LIVE-/DYNAMISCH-Marker → Claude. Seit dem B1a-Rueckbau ist local TOOL-LOS +# (nur Reden), kann also nichts nachschlagen. Alles was aktuelle Grundwahrheit +# braucht — Wetter, News, Uhrzeit/Datum, Musik-/Spotify-Zustand, Preise/Kurse, +# Verkehr, Oeffnungszeiten — kann ein 8B nicht wissen und wuerde es erfinden. +# Darum vorab an Claude (der ruft das Tool). Das ist TOPIC-Ebene, nicht per-Skill: +# ein neuer Skill braucht hier keine Zeile — er faellt unter „braucht Grundwahrheit". +_LIVE_HINTS = re.compile( + r"\b(wetter|temperatur|regne\w*|schneit|grad draussen|" + r"news|nachrichten|schlagzeile\w*|" + r"uhrzeit|wie spaet|wie spät|welcher tag|welches datum|wochentag|" + r"spotify|musik|lied|song|playlist|lautstaerke|lautstärke|" + r"laeuft gerade|läuft gerade|spiele? (ab|weiter|die|den|das)|naechst\w*|nächst\w*|" + r"ueberspring\w*|überspring\w*|skip\w*|pausier\w*|" + r"timer|wecker|weck mich|erinner\w*|" + r"preis|kurs|aktie|wechselkurs|bitcoin|" + r"stau|verkehr|zugverbindung|bahn|abfahrt|" + r"oeffnungszeit\w*|öffnungszeit\w*|geoeffnet|geöffnet|hat .* auf)\b", + re.IGNORECASE, +) + # Technik-/Tiefe-Marker → Claude (lokales 8B soll das nicht raten). _HARD_HINTS = re.compile( r"```|" # Codeblock @@ -126,6 +146,8 @@ def should_try_local(user_message: str, cfg: dict) -> bool: return False if _TOOL_HINTS.search(msg): return False + if _LIVE_HINTS.search(msg): + return False if _HARD_HINTS.search(msg): return False return True @@ -138,10 +160,16 @@ def should_try_local(user_message: str, cfg: dict) -> bool: # kein volles Memory (B1a). # Was das lokale Tier NICHT selbst kann → dafuer eskaliert es an Claude. +# Seit dem B1a-Rueckbau hat local KEINE Werkzeuge mehr: es kann nichts +# nachschlagen und nichts steuern. Alles was aktuelle Grundwahrheit oder eine +# Aktion braucht, gehoert ans grosse Modell. _AWARENESS = ( - "Nur das grosse Modell (nicht du im Schnell-Modus) kann: Bilder generieren, " - "Skills bauen/aendern, Projekte & OAuth verwalten, ins Gedaechtnis SCHREIBEN, " - "sowie tiefe/technische Analysen und langen Code." + "Du hast im Schnell-Modus KEINE Werkzeuge — du kannst nichts nachschlagen und " + "nichts steuern. Nur das grosse Modell kann: aktuelle Infos holen (Wetter, " + "News, Uhrzeit, Preise), Musik/Spotify steuern oder den laufenden Song " + "nennen, Timer setzen, Bilder generieren, Skills bauen/aendern, Projekte & " + "OAuth verwalten, ins Gedaechtnis schreiben, sowie tiefe/technische Analysen " + "und langen Code. Fuer ALL das eskalierst du." )