Skip to content

Repair voice turns that claim a knowledge gap without searching - #20

Open
codeyogi911 wants to merge 1 commit into
mainfrom
claude/loving-kepler-460a5c
Open

Repair voice turns that claim a knowledge gap without searching#20
codeyogi911 wants to merge 1 commit into
mainfrom
claude/loving-kepler-460a5c

Conversation

@codeyogi911

Copy link
Copy Markdown
Owner

Problem

The voice eval bar "how-to question must search the help centre before answering" (kb_no_match_honest) was model-flaky: @cf/zai-org/glm-4.7-flash at temperature 0 answers unfamiliar-product questions with "I don't have information on that" without calling search_help_center, despite explicit prompt instructions. Probing showed the flake at 7 of 8 runs. The previously reverted fix (forcing toolChoice on question-shaped first steps) broke the sibling bar "off-topic question must not call a support tool" because it classified the question; off-topic questions are also question-shaped.

Approach

Classify the reply instead. Probing 30+ live turns showed the two failure classes are lexically separable:

  • Broken kbMiss turns: zero tool calls plus a possession claim — "I don't have information on router settings"
  • Off-topic redirects (20/20): refusal phrasing — "I'm not able to discuss/answer…" — never a missing-documentation claim

New src/voice/repair.ts enforces the invariant the prompt already states (never claim something is undocumented without a search this turn):

  • claimsKnowledgeGap(text) — corpus-driven detector for missing-documentation claims, with guards so refusals, bare "no answer" troubleshooting, and "general questions" redirects never match.
  • repairUnsearchedKnowledgeGap(stream, rerun) — buffers the turn until the first tool call (tool-using turns pass through with zero added latency); a tool-less turn ending in a gap claim is discarded and re-run once with search_help_center forced on step 0 via prepareStep. The rerun always searches, so it can never re-trigger; ticket creation is already requestId-idempotent.

Wired into the production stream in demo-agent.ts and mirrored in both eval-worker paths (generateText and streamText).

Verification

  • Live probes after the fix: kbMiss 10/10 with search (was 1/8); off-topic 20/20 with zero tool calls
  • 5 consecutive green npm run eval:voice runs (22 passes each)
  • npm run check green (234 + 6 tests, all typechecks, generated assets clean)
  • test/voice-repair.test.ts pins the detector to the observed reply corpus for both classes plus the wrapper's pass-through/disarm/repair behaviors

Known residual (pre-existing, out of scope): 1 of 6 probed kb_grounded_answer runs invented an undocumented interval ("monthly"); it never tripped across the 5 eval runs and this repair intentionally does not cover invention.

🤖 Generated with Claude Code

The voice model at temperature 0 skips search_help_center on
unfamiliar-product questions and answers "I don't have information on
that" directly, violating the prompt's search-before-claiming rule and
flaking the kb_no_match_honest eval bar (observed 7/8 runs). The broken
shape is deterministic to detect — no tool call plus a
missing-documentation claim — so such a turn is re-run once with the
search forced on the first step via prepareStep, and only the repaired
turn reaches the caller. Off-topic scope redirects phrase refusals, not
knowledge gaps, so they never repair and never gain a tool call, keeping
the sibling support_scope bar intact.

Wired into the production stream in demo-agent and both eval-worker
paths. Detector regexes are corpus-driven from probed model output;
voice-repair.test.ts pins both reply classes. Verified with 5
consecutive green eval:voice runs and npm run check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant