|
|
|
@@ -38,6 +38,11 @@ var fixtureJSON []byte
|
|
|
|
|
// other version rather than misreading a fixture and reporting a number.
|
|
|
|
|
const SchemaVersion = 1
|
|
|
|
|
|
|
|
|
|
// daemonTopK — how many candidates the read path asks for, mirroring
|
|
|
|
|
// memoryRecallWidth in cmd/mavend/actions_query.go. Kept in step so recall@3
|
|
|
|
|
// measures the same top-3 the daemon actually reads, not an arbitrary width.
|
|
|
|
|
const daemonTopK = 3
|
|
|
|
|
|
|
|
|
|
// StoredNote — one thing the user said once, as it lands in the semantic store.
|
|
|
|
|
// Kind is "note" or "fact"; both share the vector index (see
|
|
|
|
|
// cmd/mavend/recall.go), so a fact can legitimately win a recall.
|
|
|
|
@@ -267,8 +272,9 @@ type TagStat struct{ Passed, Total int }
|
|
|
|
|
// Recall1 — fraction of answerable cases whose wanted note ranked first.
|
|
|
|
|
func (r Report) Recall1() float64 { return ratio(r.Rank1, r.Answerable) }
|
|
|
|
|
|
|
|
|
|
// Recall3 — same, in the top three. The daemon asks for 3 (voice.go), so this
|
|
|
|
|
// is the ceiling a better gate or a reranker could reach.
|
|
|
|
|
// Recall3 — same, in the top three. The daemon asks for daemonTopK candidates
|
|
|
|
|
// (mirroring memoryRecallWidth in voice.go's caller), so this is the ceiling a
|
|
|
|
|
// better gate or a reranker could reach.
|
|
|
|
|
func (r Report) Recall3() float64 { return ratio(r.Rank3, r.Answerable) }
|
|
|
|
|
|
|
|
|
|
// Answered — fraction of answerable cases the daemon would actually answer
|
|
|
|
@@ -399,7 +405,7 @@ func scoreCase(ctx context.Context, emb router.Embedder, newStore NewStore, minS
|
|
|
|
|
o.Reasons = []string{fmt.Sprintf("embed query: %v", err)}
|
|
|
|
|
return o, nil
|
|
|
|
|
}
|
|
|
|
|
hits, err := st.Search(ctx, qvec, 3)
|
|
|
|
|
hits, err := st.Search(ctx, qvec, daemonTopK)
|
|
|
|
|
o.Latency = time.Since(start)
|
|
|
|
|
if err != nil {
|
|
|
|
|
o.Err = err
|
|
|
|
@@ -455,14 +461,13 @@ func rankNote(inTop3 bool) string {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// bestRecall mirrors cmd/mavend/recall.go — the gate the daemon actually
|
|
|
|
|
// applies to a memory hit. Duplicated rather than imported because package main
|
|
|
|
|
// is not importable; recalleval_test.go asserts the two agree in behaviour.
|
|
|
|
|
// The daemon returns the whole hit (a note and a fact are said differently);
|
|
|
|
|
// the harness only scores what came back, so it keeps returning the text.
|
|
|
|
|
// bestRecall mirrors the daemon's gate in cmd/mavend/recall.go, including the
|
|
|
|
|
// topic veto added for #470: a score that clears the gate still has to be
|
|
|
|
|
// about what he asked. Keep the two in step — a fixture that measures a
|
|
|
|
|
// weaker gate than the daemon runs flatters it.
|
|
|
|
|
// applies to a memory hit, including the topic veto added for #470: a score
|
|
|
|
|
// that clears the gate still has to be about what he asked. Duplicated rather
|
|
|
|
|
// than imported because package main is not importable; recalleval_test.go
|
|
|
|
|
// asserts the two agree in behaviour, so a weaker gate here than the daemon
|
|
|
|
|
// runs cannot flatter the score. The daemon returns the whole hit (a note and
|
|
|
|
|
// a fact are said differently); the harness only scores what came back, so it
|
|
|
|
|
// keeps returning the text.
|
|
|
|
|
func bestRecall(query string, results []memory.Result, minScore, minMargin float64) string {
|
|
|
|
|
if !memory.Confident(results, minScore, minMargin) {
|
|
|
|
|
return ""
|
|
|
|
|