p3: map Brave LLM Context; RRF merge; per-source no_rerank

Live llm/context hits live in grounding.generic plus a URL-keyed
sources map, not a sources array. Fan-in uses reciprocal-rank fusion
instead of cosine. no_rerank keeps that source's own order as a prefix.
This commit is contained in:
2026-09-23 16:02:21 -07:00
parent eb4e46d036
commit b6e1cdf825
10 changed files with 264 additions and 58 deletions
+18 -18
View File
@@ -112,12 +112,14 @@ the shared fan-in. This is the Hermes SearXNG provider's request (`plugins/web/s
### 3.2 Brave LLM Context
PLAN §2, verified earlier: `GET /res/v1/llm/context?q=…` with `BRAVE_API_KEY` from
PLAN §2: `GET /res/v1/llm/context?q=…` with `BRAVE_API_KEY` from
`/var/lib/sift/secret.env` (0640 root:sift). **Do not read SearXNG's secret.env.**
Header `X-Subscription-Token`. Map result URLs and snippets from the live JSON
(`sources` and any URL-bearing fields). Do **not** assume a model-written
`grounding` answer exists — confirm against a live response before dropping or
keeping any field that is not a URL/title/snippet.
Header `X-Subscription-Token`. Live response (Brave docs + Open WebUI #24120):
hits are `grounding.generic[]` (`url`, `title`, `snippets[]`); top-level `sources`
is a URL-keyed metadata map, not a result array. Map generic first, join
`snippets`, then URL keys in `sources` for anything generic missed. Do **not**
treat a model-written `grounding` string as a snippet. Fixture:
`tests/testdata/brave_llm_context.json`.
This is **not** Brave Web Search (`/res/v1/web/search`). SearXNG already runs `braveapi`
as an engine; doubling that is wasted spend.
@@ -148,25 +150,23 @@ placeholder line the same way (empty, on-box fill).
dropped, trailing slash dropped on the path, `www.` left as-is (different sites). First
snippet wins; `source` becomes the first source that produced it; later sources only
affect rerank input if they brought a longer snippet (keep the longer one).
5. Rerank (§5) unless `rerank: false` or Dixie cannot take the call.
5. Merge: reciprocal-rank fusion across source lists unless `rerank: false`.
A source with `no_rerank = true` keeps its own order as a prefix (first-source
wins on URL). Cosine/honcho-embed is not used for search.
6. Truncate to `k` (native) or `limit` (`/v2/search`, default 5, max 20).
7. Store in the search cache **only if** every attempted source succeeded and
rerank did not fall back. A timeout or fallback must not pin a partial result
for the rest of the hour (skip the write, or use a short TTL such as 2 m — skip
is the default). Return.
7. Store in the search cache **only if** every attempted source succeeded.
A timeout must not pin a partial result for the rest of the hour.
Search **never GETs a result URL**. Agents `sift fetch` those through the P1 guard.
## 5. Rerank and Dixie
## 5. Merge (RRF)
Embed the query and each remaining snippet with `honcho-embed` (same engine, same
`dixie.max_inflight` FIFO as digest). Cosine similarity → `score`. Restore nothing to
source order except on fallback.
Fan-in uses reciprocal-rank fusion (`1/(60+rank)`) over per-source lists. Search
does not call `honcho-embed`; Dixie saturation cannot fail a search.
**Dixie saturation must not fail a search:** if the embed permit cannot be had within
`dixie.queue_wait`, or embed errors, or the queue is full → keep source-fan-in order
(SearXNG, then Brave, then Tavily, then original rank inside a source), warning
`rerank fell back: <reason>`. Never call chat/digest for search in P3.
`[search.tavily] no_rerank = true` keeps Tavily's own order at the front of the
result list; remaining sources still RRF. `rerank = false` skips RRF and keeps
source-fan-in order (SearXNG, then Brave, then Tavily).
## 6. Guard boundary (SSRF)