79893d646b
Two things that were each half-done. The prompts handed the model copyable examples. chatSystemPrompt lost its openers this morning and the "Я подумала, что" tic went with them, but "не забыл ли я" appeared in its place: the removed example had been suppressing the masculine self-reference by accident. Two predicatives are not enough signal, so the rule is now stated as morphology (-ла) rather than as a pair of words — a suffix rule generalises where an example only gets copied. querySystemPrompt had the same defect and gets the same treatment; its "вот что я нашла: " opener is deliberate and stays. internal/kiwix had no caller. actions_query.go said "once internal/kiwix is wired into this chain" and that never happened. It is wired now, between the notes pass and the web source: everything of his answers first, and only what is left over is looked up. Off unless a `kiwix` block names a server and a book. Reading the search snippet does not work. Kiwix builds it from wherever the keyword matched, which on Wikipedia is the navigation box at the foot of the page — the first version of this answered "что такое фотосинтез?" by reciting "Ecological economics Ecological footprint Ecological forecasting …". Client grows an Article method; the head of the article is the lead paragraph, which is the definition the snippet was meant to be. Verified on the box: the same question now answers correctly off the ZIM. Only the rewritten query leaves the process. A test asserts it: a turn carrying a stored note must not put that note in the search string. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TrVSBKe3RFDF4fGYKWYQnX
55 lines
1.8 KiB
Go
55 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/kami/maven/internal/config"
|
|
"github.com/kami/maven/internal/kiwix"
|
|
"github.com/kami/maven/internal/llm"
|
|
)
|
|
|
|
// kiwixWiring — the offline encyclopedia, assembled. nil ⇒ off, which is the
|
|
// default: the query chain simply has no ZIM source.
|
|
//
|
|
// The rewriter is separately optional. Searching without one is legal and
|
|
// mostly useless against English ZIMs, but it is the honest degraded mode when
|
|
// there is no llama-server to rewrite with, and it is what `rewrite: false`
|
|
// asks for.
|
|
type kiwixWiring struct {
|
|
client *kiwix.Client
|
|
rewriter *kiwix.Rewriter // nil ⇒ the question is searched verbatim
|
|
book string
|
|
max int
|
|
runes int
|
|
}
|
|
|
|
// wireKiwix builds the ZIM reader from the `kiwix` block, or returns nil when
|
|
// there is none. config.Normalise has already dropped a block with no URL and
|
|
// filled the two size defaults, so this does no validation of its own.
|
|
//
|
|
// The llm client is the phraser's swap-aware one (llmClientFor), so a model
|
|
// swap re-points the rewriter with everything else. A nil client means there is
|
|
// no resident model at all; that degrades the rewriter, not the source.
|
|
func wireKiwix(cfg *config.Config, c *llm.Client) *kiwixWiring {
|
|
if cfg.Kiwix == nil {
|
|
return nil
|
|
}
|
|
kc := cfg.Kiwix
|
|
w := &kiwixWiring{
|
|
client: kiwix.New(kc.URL),
|
|
book: kc.Book,
|
|
max: kc.MaxResults,
|
|
runes: kc.SnippetRunes,
|
|
}
|
|
switch {
|
|
case !kc.RewriteEnabled():
|
|
log.Printf("voice: kiwix at %s (book %q, query rewriting off by config)", kc.URL, kc.Book)
|
|
case c == nil:
|
|
log.Printf("voice: kiwix at %s (book %q, no llama-server: searching questions verbatim)", kc.URL, kc.Book)
|
|
default:
|
|
w.rewriter = kiwix.NewRewriter(c)
|
|
log.Printf("voice: kiwix at %s (book %q)", kc.URL, kc.Book)
|
|
}
|
|
return w
|
|
}
|