The old model was a symmetric paraphrase model, so it scored "do these look alike" instead of "does this note answer this question". Also fixes the file mismatch: the Makefile, the deploy config and both evals now all name the same quantized file, and the quantized one is what gets measured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
This commit is contained in:
@@ -117,18 +117,40 @@ type cachingEmbedder struct {
|
||||
seen map[string][]float32
|
||||
}
|
||||
|
||||
var _ router.AsymmetricEmbedder = (*cachingEmbedder)(nil)
|
||||
|
||||
func (c *cachingEmbedder) Dim() int { return c.inner.Dim() }
|
||||
func (c *cachingEmbedder) Close() error { return nil } // the caller owns inner
|
||||
|
||||
func (c *cachingEmbedder) Embed(ctx context.Context, text string) ([]float32, error) {
|
||||
if v, ok := c.seen[text]; ok {
|
||||
return c.cached(ctx, "embed:"+text, func() ([]float32, error) {
|
||||
return c.inner.Embed(ctx, text)
|
||||
})
|
||||
}
|
||||
|
||||
// The two sides of an asymmetric embedder give different vectors for the same
|
||||
// string, so the cache key has to say which side asked.
|
||||
func (c *cachingEmbedder) EmbedQuery(ctx context.Context, text string) ([]float32, error) {
|
||||
return c.cached(ctx, "query:"+text, func() ([]float32, error) {
|
||||
return router.EmbedQuery(ctx, c.inner, text)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *cachingEmbedder) EmbedPassage(ctx context.Context, text string) ([]float32, error) {
|
||||
return c.cached(ctx, "passage:"+text, func() ([]float32, error) {
|
||||
return router.EmbedPassage(ctx, c.inner, text)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *cachingEmbedder) cached(_ context.Context, key string, embed func() ([]float32, error)) ([]float32, error) {
|
||||
if v, ok := c.seen[key]; ok {
|
||||
return v, nil
|
||||
}
|
||||
v, err := c.inner.Embed(ctx, text)
|
||||
v, err := embed()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.seen[text] = v
|
||||
c.seen[key] = v
|
||||
return v, nil
|
||||
}
|
||||
|
||||
@@ -305,7 +327,7 @@ func scoreCase(ctx context.Context, emb router.Embedder, newStore NewStore, minS
|
||||
|
||||
all := append(append([]StoredNote(nil), c.Notes...), filler...)
|
||||
for _, n := range all {
|
||||
vec, err := emb.Embed(ctx, n.Text)
|
||||
vec, err := router.EmbedPassage(ctx, emb, n.Text)
|
||||
if err != nil {
|
||||
return Outcome{}, fmt.Errorf("%s: embed note %s: %w", c.ID, n.ID, err)
|
||||
}
|
||||
@@ -317,7 +339,7 @@ func scoreCase(ctx context.Context, emb router.Embedder, newStore NewStore, minS
|
||||
|
||||
o := Outcome{Case: c}
|
||||
start := time.Now()
|
||||
qvec, err := emb.Embed(ctx, c.Query)
|
||||
qvec, err := router.EmbedQuery(ctx, emb, c.Query)
|
||||
if err != nil {
|
||||
o.Latency = time.Since(start)
|
||||
o.Err = err
|
||||
|
||||
@@ -246,8 +246,8 @@ func TestONNXRecall(t *testing.T) {
|
||||
if lib == "" {
|
||||
t.Skip("MAVEN_ONNX_LIB unset — see AGENTS.md § Embedder model for intent routing")
|
||||
}
|
||||
model := filepath.Join("../../..", "models/embedder/model.onnx")
|
||||
tok := filepath.Join("../../..", "models/embedder/tokenizer.json")
|
||||
model := filepath.Join("../../..", "models/embedder/multilingual-e5-small/model_quantized.onnx")
|
||||
tok := filepath.Join("../../..", "models/embedder/multilingual-e5-small/tokenizer.json")
|
||||
for _, p := range []string{lib, model, tok} {
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
t.Skipf("missing %s: %v", p, err)
|
||||
|
||||
Reference in New Issue
Block a user