feat(agent): strip raw tool-scaffolding from streamed answers — deterministic filter with one bounded recovery
This commit is contained in:
+25
-5
@@ -30,7 +30,19 @@ Agent tools (phase 37; phase 70: the copy teaches the harness-aligned
|
||||
may extend its context through the three server-side tools (round-
|
||||
capped, see :mod:`app.rag.agent`; the cap is the bound and this section
|
||||
does not re-state it, phase 45). The LOW/deflection prompt never
|
||||
carries it and stays byte-identical to the pre-phase text.
|
||||
carries it (phase 71: the LOW prompt's only addition is the
|
||||
plain-text line below — it still has no ``<tools>`` section).
|
||||
|
||||
Deflection plain-text line (phase 71, owner-permitted 2026-09-03):
|
||||
the otherwise-locked ``LOW`` prompt gains exactly one instruction
|
||||
line — "Reply in plain text only — you have no tools in this mode."
|
||||
— appended to the ``DEFLECT_MODE`` body: a deflected turn offers no
|
||||
tools, so any tool markup there is always wrong, and the line closes
|
||||
the door at the prompt (the deterministic filter + one bounded
|
||||
recovery in :mod:`app.rag.scaffolding` / :mod:`app.rag.agent` is the
|
||||
backstop). The ``DEFLECT_MODE`` marker and everything else in the
|
||||
prompt stay put — the E2E mock LLM keys on the marker's *presence*,
|
||||
not the wording, so that contract is unchanged.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -83,9 +95,10 @@ _KB_INTRO = (
|
||||
#: not re-state it, phase 45). Appended after the mode body
|
||||
#: (``<documents>``), so the instructions are the last thing the model
|
||||
#: reads. The LOW/deflection prompt never carries it — a deflection has
|
||||
#: no grounded context to extend — and stays byte-identical to the
|
||||
#: pre-phase text. The E2E mock keys off the ``<tools>`` marker's
|
||||
#: *presence*, not this wording.
|
||||
#: no grounded context to extend (phase 71: the LOW prompt's only
|
||||
#: addition is the plain-text line in :func:`build_deflect_prompt`).
|
||||
#: The E2E mock keys off the ``<tools>`` marker's *presence*, not this
|
||||
#: wording.
|
||||
TOOLS_SECTION: str = (
|
||||
"<tools>\n"
|
||||
"You may extend your context with three tools. `ls` lists the "
|
||||
@@ -224,7 +237,10 @@ def build_deflect_prompt(
|
||||
|
||||
Section order (phase 31): ``<relevance>`` → ``<knowledge_base>`` →
|
||||
``<tuning>`` → ``DEFLECT_MODE`` body; empty steering/overview omit
|
||||
their section, keeping the prompt byte-identical to the pre-phase text.
|
||||
their section, keeping the prompt byte-identical to the pre-phase
|
||||
text. The body ends with the phase-71 plain-text line (owner-
|
||||
permitted 2026-09-03 — the LOW prompt's only change): a deflected
|
||||
turn offers no tools, so any tool markup there is always wrong.
|
||||
"""
|
||||
weak = "\n".join(f"- {t}" for t in titles) if titles else "(nothing close at all)"
|
||||
mid = "\n".join(
|
||||
@@ -239,5 +255,9 @@ def build_deflect_prompt(
|
||||
+ "DEFLECT_MODE: retrieval was weak — the titles below are the closest "
|
||||
"your notes come to the question. They are titles only; do not pretend "
|
||||
"they answer it. Use them to propose 2-3 alternative questions.\n"
|
||||
# Phase 71 (owner-permitted 2026-09-03): the one plain-text line
|
||||
# — prevention at the prompt. The E2E mock keys on the
|
||||
# DEFLECT_MODE marker's presence, so appending is safe.
|
||||
"Reply in plain text only — you have no tools in this mode.\n"
|
||||
+ weak
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user