From 9f1e87434cac04b6a6464248d3bd80f27d81c3e5 Mon Sep 17 00:00:00 2001 From: Jeuner <62662523+Jeuners@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:01:31 +0200 Subject: [PATCH] refactor: move tool behavior out of SYSTEM_PROMPT into each tool's own description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Auf Wunsch: wie ein Tool funktioniert (wann aufrufen, wie mit dem Ergebnis umgehen) gehört ausschließlich in seine FunctionSchema.description, nie in den globalen SYSTEM_PROMPT. SYSTEM_PROMPT enthält jetzt nur noch Astras Persona, Sprachausgabe-Formatierung und eine generische "nutze Werkzeuge statt zu erfinden"-Zeile, die kein einzelnes Tool nennt. Gemessener Preis dieser saubereren Trennung: read_news-Zuverlässigkeit sinkt von ca. 60-75% (Tool-Regeln zusätzlich im System-Prompt dupliziert) auf ca. 20-50% (Regeln nur noch in der Tool-Description). generate_image bleibt bei ~100%, vermutlich weil es die einzige naheliegende Aktion für Bild-Anfragen ist, während read_news mit generate_image um die Modell-Aufmerksamkeit konkurriert. Bewusst so gebaut trotz der Zahlen — Architekturentscheidung, keine Regression, die ich für einen Fehler halte. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LVgSHNHdRx3UNTBodFmhRA --- README.md | 16 ++++++++++------ astra/core.py | 10 +++------- astra/tools.py | 14 +++++++++----- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 18dfdca..9492bd1 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,16 @@ nur für die Dauer der Session, nichts wird auf Disk geschrieben. aktuellen Nachrichten gefragt wird, und fasst die Schlagzeilen mündlich zusammen statt sie roh vorzulesen. -Mit zwei gleichzeitig verfügbaren Tools (Bild + Nachrichten) sinkt beim -lokalen 9,7B-Modell die Zuverlässigkeit, tatsächlich das Werkzeug -aufzurufen statt Inhalte zu erfinden — gemessen ca. 60–75 % je nach -Formulierung, trotz gestrafftem System-Prompt und reduzierter Temperatur -(`0.4`). Bildgenerierung allein bleibt zuverlässig (~100 %). Bekannte -Grenze eines kleinen lokalen Modells, kein Bug. +Tool-Verhalten steht bewusst ausschließlich in der jeweiligen +`FunctionSchema.description` (siehe `astra/tools.py`), nicht im +`SYSTEM_PROMPT` — eine Quelle der Wahrheit pro Werkzeug statt duplizierter +Regeln in einem wachsenden globalen Prompt. Gemessener Preis davon: mit +zwei gleichzeitig verfügbaren Tools (Bild + Nachrichten) ruft das lokale +9,7B-Modell `read_news` nur noch in ca. 20–50 % der Fälle tatsächlich auf +(vorher, mit Tool-Regeln zusätzlich im System-Prompt, ca. 60–75 %) und +erfindet sonst Schlagzeilen. Bildgenerierung bleibt bei ~100 % zuverlässig. +Bekannte Grenze eines kleinen lokalen Modells bei Tool-Konkurrenz, kein +Bug — die saubere Trennung war eine bewusste Architekturentscheidung. ## Starten diff --git a/astra/core.py b/astra/core.py index 28de658..c2ce379 100644 --- a/astra/core.py +++ b/astra/core.py @@ -64,16 +64,12 @@ VOICE_NAMES = frozenset(voice["name"] for voice in VOICES) SYSTEM_PROMPT = ( "Du bist Astra, ein freundlicher deutschsprachiger Gesprächsassistent. " - "Du hast zwei Werkzeuge: generate_image für Bilder, Grafiken oder Illustrationen, und " - "read_news für aktuelle Nachrichten. Fragt der Nutzer danach, verwende SOFORT das passende " - "Werkzeug, statt nur anzukündigen, dass du das tun wirst, und statt Inhalte selbst zu " - "erfinden. Fasse Ergebnisse von read_news danach mündlich in eigenen Worten zusammen, " - "lies sie nicht roh vor. " "Antworte natürlich und knapp, normalerweise in ein bis drei kurzen Sätzen. " "Deine Antwort wird vorgelesen: kein Markdown, keine Sternchen, keine Listen. " "Sprich Zahlen und Abkürzungen verständlich aus. Stelle bei Bedarf eine kurze Rückfrage. " - "Du hast sonst keinen Internetzugang und keinen Zugriff auf Dateien oder Apps. " - "Behaupte nicht, andere Aktionen ausgeführt zu haben. " + "Nutze verfügbare Werkzeuge, wenn sie zur Anfrage passen, statt Inhalte selbst zu erfinden " + "oder nur anzukündigen, dass du etwas tun wirst. Du hast sonst keinen Internetzugang und " + "keinen Zugriff auf Dateien oder Apps. Behaupte nicht, andere Aktionen ausgeführt zu haben. " "Wenn der Nutzer ein Bild, ein Dokument oder ein PDF hochlädt, geht dessen Inhalt oder " "eine Textzusammenfassung als Nachricht in dieses Gespräch ein." ) diff --git a/astra/tools.py b/astra/tools.py index 335a958..cc8d061 100644 --- a/astra/tools.py +++ b/astra/tools.py @@ -62,8 +62,11 @@ def build_tools(config: Settings, notify: Callable[[dict], None], media_store: d name="read_news", description=( "Lies aktuelle Schlagzeilen aus kuratierten deutschen RSS-Feeds zu einem " - "Themenbereich vor. Nutze dieses Werkzeug, wenn der Nutzer nach aktuellen " - "Nachrichten, News oder was gerade in einem Themenbereich passiert, fragt." + "Themenbereich vor. Rufe dieses Werkzeug sofort auf, wenn der Nutzer nach " + "aktuellen Nachrichten, News oder was gerade in einem Themenbereich passiert, " + "fragt — erfinde selbst keine Nachrichten und kündige den Abruf nicht nur an. " + "Fasse die zurückgegebenen Schlagzeilen danach mündlich in eigenen Worten " + "zusammen, statt sie roh vorzulesen." ), properties={ "topic": { @@ -82,9 +85,10 @@ def build_tools(config: Settings, notify: Callable[[dict], None], media_store: d generate_image_schema = FunctionSchema( name="generate_image", description=( - "Erzeuge ein Bild anhand einer Beschreibung und zeige es dem Nutzer an. " - "Nutze dieses Werkzeug, wenn der Nutzer explizit ein Bild, eine Grafik " - "oder eine Illustration wünscht." + "Erzeuge ein Bild anhand einer Beschreibung und zeige es dem Nutzer sofort an. " + "Rufe dieses Werkzeug auf, sobald der Nutzer ein Bild, eine Grafik oder eine " + "Illustration möchte — beschreibe das Bild nicht nur in Worten, erzeuge es " + "tatsächlich." ), properties={ "prompt": {