feat(consume): several sub-questions in one call, merged by the product
C2. `consume.build_multi_payload` takes two or more questions, reads the bundle ONCE (`bm25.prepare` builds the index a question does not depend on), ranks and cuts each sub-question exactly as `build_payload` would alone, and interleaves the deliveries: first excerpt of each sub-question in turn, then the second, a concept already taken skipped, cut at the same `k` and `limit` one question gets -- so asking four times does not buy a payload four times the size. Chose round-robin, not a merge by score, because two questions' BM25 totals are not on one scale: a merge by score would let the wordiest sub-question take every place. It is the rule the search gate measured with before the product had it, moved unchanged. Shape, and only for two or more questions (one question is `build_payload`'s payload byte for byte): - `questions` replaces `question`; - every excerpt carries `subquestions`, the indices of every sub-question whose own delivery named it, the one whose text (passage) it carries first; - `coverage` holds one block per sub-question (the single shape plus its `question`, `unanswered_in_payload` read against what the reader receives), `weak_subquestions`, and `weak` true only when EVERY sub-question is weak; - `withheld` is every concept the merge did not deliver: `below_k` where a sub-question delivered it and the merge's cut did not, otherwise the rule of the sub-question that ranked it best. `nearest` walks the rankings in the delivery's turn order. The contract checker accepts it with 0 findings. `okf consume --question A --question B` and `okf_ask` with `questions` (both forms at once is `question_ambiguous`) reach it. A reservation or a fusion widening acts on ONE cut and is refused with several questions (`subquestions_flag_conflict`). The search gate's series (e) and (f) now ask ONE call with every sub-question; the gate's own merge is gone. Sets and thresholds untouched. The gate's table for this commit is kept in local state. Suite on a clean tree after `git add`: 2411 passed, 2 skipped, 4 xfailed. ruff, ruff format, mypy --strict clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7982dad846
commit
80aac93b8f
6 changed files with 918 additions and 173 deletions
11
README.md
11
README.md
|
|
@ -835,6 +835,17 @@ its rule in the open, not a verdict: the reader rephrases in the bundle's own
|
|||
words, and if it stays weak, says the bundle does not cover the question. Words
|
||||
that only frame a question (`how often`, `hva står i`) are not topic words.
|
||||
|
||||
**Several sub-questions in one call.** A broad question is asked best as two
|
||||
to four narrow ones in the bundle's own words: `okf consume ./bundle --question
|
||||
"first" --question "second"`, or `okf_ask` with `questions`. The bundle is read
|
||||
once, each sub-question is ranked and cut as it would be alone, and the
|
||||
deliveries are interleaved — first excerpt of each in turn, then the second,
|
||||
duplicates dropped — under the same `--k` and `--limit` one question gets. The
|
||||
payload then carries `questions` instead of `question`, every excerpt names the
|
||||
`subquestions` it answered, and `coverage` has one block per sub-question, with
|
||||
`weak` true only when every sub-question is weak. One question gives exactly
|
||||
the payload it always did.
|
||||
|
||||
`--cost-vocabulary` is off by default and widens one question class: it lets a
|
||||
declared list of cost/price/quantity terms bridge a question and a document that
|
||||
name money with different words. The gate is the question — one naming no such
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue