1f38e71d1a
Verification, as the task asked. Drove что такое фотосинтез through /api/chat with the search reachable, with the container stopped, and with the host blackholed. Kiwix claims the turn in both failure cases, and a stopped container costs nothing: DNS fails and the ZIM answers inside the same second. The blackhole is the case that hurts. The search waited its full 8-second budget before the ZIM was asked and the turn took 15.4s against 3.5, which he sits through with nothing being said. So the connect phase alone is now capped at 1.5s. A reachable instance that is merely slow keeps the whole budget, because it is fanning out to real engines. The RU Wikipedia ZIM is on the box (owner moved it into the kiwix zims dir), and kiwix-serve picked it up. A Cyrillic question now searches book_ru verbatim and skips the RU->EN rewrite: that rewriter is the workaround for an English book, and against a Russian one it is a translation of his own words back at him. Catalog names come from the filename, not the <name> field — books.name=wikipedia_ru_all returns nothing. Measurement in docs/evals/2026-08-05-kiwix-offline-fallback.md. The RU book answering a driven turn needs a rebuild and is not verified yet.
63 lines
2.1 KiB
Go
63 lines
2.1 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
|
|
// bookRU — searched instead of book when the question is Cyrillic, and
|
|
// searched verbatim because it is in his language already (V-508). Empty ⇒
|
|
// every question goes to book.
|
|
bookRU 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,
|
|
bookRU: kc.BookRU,
|
|
max: kc.MaxResults,
|
|
runes: kc.SnippetRunes,
|
|
}
|
|
if kc.BookRU != "" {
|
|
log.Printf("voice: kiwix: russian questions read %q verbatim", kc.BookRU)
|
|
}
|
|
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
|
|
}
|