Skip to content

feat(tools): the follow-up rate, measured on the user's own conversation - #882

Open
green-dalii wants to merge 2 commits into
mainfrom
feat/followup-rate-from-real-history
Open

green-dalii wants to merge 2 commits into
mainfrom
feat/followup-rate-from-real-history

Conversation

@green-dalii

Copy link
Copy Markdown
Member

The conversation harness measures a constructed follow-up: the question names nothing at all (那它呢?), so "no history answers it" is close to built in. That proves the history can carry a follow-up. It does not say how many real follow-ups there are — and the design decision that depends on that number, how much the retrieval should weight the history, was being made without it.

The number is free data. The plugin already stores the user's own conversation in data.json under queryHistory. This tool reads it, counts, and prints. No model call, no network, nothing leaves the machine.

The classifier reuses the harness's own shape — the production lexMatchByTitleAndAliases plus nameTierCoverage over the top hit — so two tools cannot disagree about what "names nothing" means.

First measurement, 7 user turns from the production vault: 2 follow-ups (29 %).

# classified coverage name-tier hits user turn
1 follow-up 0.349 154 什么是COT?它为什么能提高模型能力?
2 self-sufficient 1.000 29 也就是说是不是用token换智力?
3 follow-up 0.000 0 最早是怎么发现这个功能的?
4 self-sufficient 1.000 3 DSA和DSA2有什么区别?
5 self-sufficient 0.500 7 CSA和CSA2的区别是什么?
6 self-sufficient 1.000 102 为我介绍Deepseek公司
7 self-sufficient 1.000 33 简要介绍Kimi公司

The statistic is imprecise in a way the output has to show. Turn 2 is a colloquial follow-up (也就是说 = "so you mean"), and the classifier calls it self-sufficient with coverage 1.000 because token appears in some page's title. That is the same defect a coverage gate would have had: the number measures whether the question carries an aspect word, not whether it names its own topic. So the printed rate is a lower bound — 29 % by the statistic, 29–43 % by reading the same seven turns — and the per-turn table is there so a reader can correct it.

Why that matters beyond bookkeeping. The weighted history arm breaks even against dropping the history entirely at a 9.8 % follow-up share on the derived family and 33.9 % on the hand-written one. A real share of 29–43 % sits at or above that band, so the weighting's benefit is marginal if the rate is near the top of its plausible range. This tool is what turns that from an assumption into a number someone can check.

n = 7. The plugin keeps only the latest conversation (maxConversationHistory). A real rate needs accumulation, and that would be a product change — a local counter appending one line per user turn — which this PR deliberately does not make.

Gate 1: lint 0, tsc 0. No production code is touched.

The conversation harness measures a CONSTRUCTED follow-up: the question names
nothing at all, so "no history answers it" is close to built in. That proves
the history can carry a follow-up. It does not say how many real follow-ups
there are, and the design decision that depends on that number — how much the
retrieval should weight the history — was being made without it.

The number is free data. The plugin already stores the user's own conversation
in `data.json` under `queryHistory`, so this reads it, counts, and prints. No
model call, no network, nothing leaves the machine.

The classifier is the harness's own shape — the production
`lexMatchByTitleAndAliases` plus `nameTierCoverage` over the top hit — so two
tools cannot disagree about what "names nothing" means.

**And it is imprecise in a way the output has to show.** On the production
vault it classifies 「也就是说是不是用token换智力?」 as self-sufficient with
coverage 1.000, because `token` appears in some page's title. That is the same
defect a coverage gate would have had: the number measures whether the question
carries an aspect word, not whether it names its own topic. So the rate is a
lower bound, and the per-turn table is printed so a reader can correct it — 29 %
by the statistic, 29-43 % by reading the same seven turns.

First measurement, 7 user turns from the production vault: 2 follow-ups. n is
small because the plugin keeps only the latest conversation. A real rate needs
accumulation, and that would be a product change: a local counter that appends
one line per user turn, so a user can hand over the numbers without sending
anything anywhere.
Two corrections to the same tool, both the same defect: a statement that was
stronger than what the code does.

One, the header claimed the harness and this tool "cannot disagree about what
'names nothing' means". They agree on the predicate and disagree on the corpus.
The harness loads page bodies; this tool is given a `wiki` directory and reads
only `index.md`. `nameTierCoverage` skips a term whose document frequency is 0
from BOTH the numerator and the denominator, so a term that appears only in a
body is absent here and counted there. The comment now says that, with the
direction: coverage here is the higher of the two, so a question looks
self-sufficient, so this rate is the lower of the two. That is a second,
independent reason the number is a floor.

Two, a missing `queryHistory` field and an empty history both printed one line
and both exited 0. A caller cannot branch on a message, and "the argument is the
wrong file" is not the same answer as "the measurement ran and found nothing".
A missing field now exits 1 and names the field; an empty history still exits 0.

Verified by running it, not by reading it:

    {"other":1}        -> exit 1, "no queryHistory field in ... is this t..."
    {"queryHistory":[]} -> exit 0, "no user turns in queryHistory"

Also rebased onto current main, because #890 changed the dependency set and this
branch predated it, which fails two third-party-notice tests locally.
@green-dalii
green-dalii force-pushed the feat/followup-rate-from-real-history branch from 6398244 to 078585d Compare October 25, 2026 02:51
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