Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ef66cae9 | |||
| 9717a4eeaf | |||
| 9790d9342d | |||
| 4eb4c9e287 |
+6
-1
@@ -450,7 +450,12 @@ fn handle_api_recall(method: String, path: String, body: String) -> String {
|
||||
if str_eq(eff_q, "") {
|
||||
return api_or_empty(engram_scan_nodes_json(limit, 0))
|
||||
}
|
||||
let results: String = engram_search_json(eff_q, limit)
|
||||
// engram_recall_json, not engram_search_json: this route IS the retrieval
|
||||
// surface (claim 24's "embedding search queries"), so it gets the semantic
|
||||
// and associative legs. engram_search_json stays lexical because ~40
|
||||
// internal call sites pass a KEY and seven of them delete every record
|
||||
// that comes back — see the boundary note above eg_search_json_impl.
|
||||
let results: String = engram_recall_json(eff_q, limit)
|
||||
return api_or_empty(results)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import json,sys,pickle,numpy as np,itertools
|
||||
sys.path.insert(0,'.')
|
||||
from policy2 import legs3,outcome,G,NODES,merge
|
||||
# cache per-query leg id-lists, floored and unfloored
|
||||
cache={}
|
||||
for q in G['queries']:
|
||||
Lf,Sf,Af=legs3(q['query'])
|
||||
Lu,Su,Au=legs3(q['query'],unfloor=True)
|
||||
cache[q['id']]=dict(L=Lf,Sf=Sf,A=Af,Su=Su,Au=Au)
|
||||
pickle.dump(cache,open('ceil.pkl','wb'))
|
||||
def mrg(pattern,L,S,A,lim=10):
|
||||
out=[];p={'L':0,'S':0,'A':0};src={'L':L,'S':S,'A':A}
|
||||
i=0
|
||||
while len(out)<lim:
|
||||
prog=False
|
||||
for ch in pattern:
|
||||
lst=src[ch]
|
||||
if p[ch]<len(lst):
|
||||
x=lst[p[ch]];p[ch]+=1;prog=True
|
||||
if x not in out: out.append(x)
|
||||
if len(out)>=lim: return out
|
||||
if not prog: break
|
||||
return out
|
||||
def ev(pattern,unfl):
|
||||
res={}
|
||||
for q in G['queries']:
|
||||
c=cache[q['id']]
|
||||
S=c['Su'] if unfl else c['Sf']
|
||||
ids=[NODES[i]['id'] for i in mrg(pattern,c['L'],S,c['A'],10)]
|
||||
res[q['id']]=outcome(q,ids)
|
||||
return res
|
||||
base=ev('LSA',False)
|
||||
print("baseline",sum(base.values()))
|
||||
best=[]
|
||||
pats=['LSA','LAS','SLA','ALS','SAL','ASL','LSSA','LSASA','LSAA','LSSAA','LSAS','SSLA','LLSA','SALSA','LSAAS']
|
||||
for unfl in (False,True):
|
||||
for p in pats:
|
||||
r=ev(p,unfl)
|
||||
g=sorted(k for k in base if r[k] and not base[k]);l=sorted(k for k in base if base[k] and not r[k])
|
||||
best.append((len(g)-len(l),p,unfl,g,l))
|
||||
best.sort(reverse=True)
|
||||
for n,p,u,g,l in best[:10]:
|
||||
print("net=%+d pat=%-6s unfloor=%s gains=%s losses=%s"%(n,p,u,g,l))
|
||||
+17
-21
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"baseline": "bm25lex",
|
||||
"candidate": "claim24",
|
||||
"candidate": "wsclaim24",
|
||||
"n_shared_queries": 38,
|
||||
"fixed_by_candidate": [
|
||||
"q14",
|
||||
@@ -8,11 +8,13 @@
|
||||
],
|
||||
"broken_by_candidate": [
|
||||
"q15",
|
||||
"q28"
|
||||
"q28",
|
||||
"q33",
|
||||
"q34"
|
||||
],
|
||||
"discordant": 4,
|
||||
"net_queries": 0,
|
||||
"mcnemar_exact_p": 1.0,
|
||||
"discordant": 6,
|
||||
"net_queries": -2,
|
||||
"mcnemar_exact_p": 0.6875,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
@@ -80,22 +82,22 @@
|
||||
"n_scored": 35,
|
||||
"hit@5": 0.7428571428571429,
|
||||
"recall@5": 0.5768475572047,
|
||||
"recall@10": 0.6537440733869305,
|
||||
"recall@10": 0.6563414759843332,
|
||||
"precision@5": 0.19428571428571437,
|
||||
"mrr@10": 0.5021428571428572,
|
||||
"nonsense_clean": "2/3",
|
||||
"mrr@10": 0.5026530612244898,
|
||||
"nonsense_clean": "0/3",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 1173.7,
|
||||
"latency_ms_p95": 1623.0,
|
||||
"latency_ms_max": 1647.9,
|
||||
"latency_ms_p50": 524.8,
|
||||
"latency_ms_p95": 738.7,
|
||||
"latency_ms_max": 755.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.5,
|
||||
"recall@5": 0.07575757575757576,
|
||||
"recall@10": 0.12121212121212122,
|
||||
"mrr@10": 0.22916666666666666
|
||||
"recall@10": 0.13636363636363635,
|
||||
"mrr@10": 0.23214285714285712
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
@@ -106,8 +108,8 @@
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 3,
|
||||
"clean": 2,
|
||||
"avg_false_positives": 3.3333333333333335
|
||||
"clean": 0,
|
||||
"avg_false_positives": 10.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
@@ -135,12 +137,6 @@
|
||||
},
|
||||
"repeat_variance": {
|
||||
"baseline": {
|
||||
"runs": 3,
|
||||
"hit@5_min": 0.7428571428571429,
|
||||
"hit@5_max": 0.7428571428571429,
|
||||
"spread_queries": 0
|
||||
},
|
||||
"candidate": {
|
||||
"runs": 2,
|
||||
"hit@5_min": 0.7428571428571429,
|
||||
"hit@5_max": 0.7428571428571429,
|
||||
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"baseline": "unfloor-clean",
|
||||
"candidate": "splitfix",
|
||||
"n_shared_queries": 75,
|
||||
"fixed_by_candidate": [
|
||||
"q15",
|
||||
"q28",
|
||||
"q60"
|
||||
],
|
||||
"broken_by_candidate": [],
|
||||
"discordant": 3,
|
||||
"net_queries": 3,
|
||||
"mcnemar_exact_p": 0.25,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
"verdict": "no measurable difference",
|
||||
"baseline_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.5384615384615384,
|
||||
"recall@5": 0.44907176157176154,
|
||||
"recall@10": 0.5380300255300255,
|
||||
"precision@5": 0.13230769230769232,
|
||||
"mrr@10": 0.32437728937728944,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 632.5,
|
||||
"latency_ms_p95": 992.5,
|
||||
"latency_ms_max": 1177.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.5,
|
||||
"recall@5": 0.07575757575757576,
|
||||
"recall@10": 0.13636363636363635,
|
||||
"mrr@10": 0.23214285714285712
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.3,
|
||||
"recall@5": 0.3,
|
||||
"recall@10": 0.4,
|
||||
"mrr@10": 0.11638888888888889
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6923076923076923,
|
||||
"recall@5": 0.6923076923076923,
|
||||
"recall@10": 0.7692307692307693,
|
||||
"mrr@10": 0.29423076923076924
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5335884353741497,
|
||||
"recall@10": 0.5933956916099773,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"candidate_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.5846153846153846,
|
||||
"recall@5": 0.48102442429365505,
|
||||
"recall@10": 0.5692415490492414,
|
||||
"precision@5": 0.14153846153846153,
|
||||
"mrr@10": 0.3351709401709402,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 646.9,
|
||||
"latency_ms_p95": 1028.5,
|
||||
"latency_ms_max": 1197.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.6666666666666666,
|
||||
"recall@5": 0.08857808857808858,
|
||||
"recall@10": 0.15967365967365968,
|
||||
"mrr@10": 0.24166666666666667
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.43333333333333335,
|
||||
"mrr@10": 0.12120370370370372
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.7692307692307693,
|
||||
"recall@5": 0.7692307692307693,
|
||||
"recall@10": 0.8461538461538461,
|
||||
"mrr@10": 0.33269230769230773
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5335884353741497,
|
||||
"recall@10": 0.5775226757369615,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat_variance": {}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"baseline": "bm25lex",
|
||||
"candidate": "wordstart",
|
||||
"n_shared_queries": 38,
|
||||
"fixed_by_candidate": [
|
||||
"q35"
|
||||
],
|
||||
"broken_by_candidate": [],
|
||||
"discordant": 1,
|
||||
"net_queries": 1,
|
||||
"mcnemar_exact_p": 1.0,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
"verdict": "no measurable difference",
|
||||
"baseline_aggregate": {
|
||||
"n_queries": 38,
|
||||
"n_scored": 35,
|
||||
"hit@5": 0.7428571428571429,
|
||||
"recall@5": 0.5536485340056769,
|
||||
"recall@10": 0.6175677497106068,
|
||||
"precision@5": 0.20000000000000007,
|
||||
"mrr@10": 0.5021428571428571,
|
||||
"nonsense_clean": "2/3",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 1184.4,
|
||||
"latency_ms_p95": 1620.0,
|
||||
"latency_ms_max": 1655.4,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.6666666666666666,
|
||||
"recall@5": 0.08857808857808858,
|
||||
"recall@10": 0.23310023310023312,
|
||||
"mrr@10": 0.25
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 3,
|
||||
"clean": 2,
|
||||
"avg_false_positives": 3.3333333333333335
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6153846153846154,
|
||||
"recall@5": 0.6153846153846154,
|
||||
"recall@10": 0.6153846153846154,
|
||||
"mrr@10": 0.2846153846153846
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5494614512471656,
|
||||
"recall@10": 0.6023242630385487,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"candidate_aggregate": {
|
||||
"n_queries": 38,
|
||||
"n_scored": 35,
|
||||
"hit@5": 0.7428571428571429,
|
||||
"recall@5": 0.5536485340056769,
|
||||
"recall@10": 0.6175677497106068,
|
||||
"precision@5": 0.20000000000000007,
|
||||
"mrr@10": 0.5021428571428571,
|
||||
"nonsense_clean": "3/3",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 542.6,
|
||||
"latency_ms_p95": 741.3,
|
||||
"latency_ms_max": 758.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.6666666666666666,
|
||||
"recall@5": 0.08857808857808858,
|
||||
"recall@10": 0.23310023310023312,
|
||||
"mrr@10": 0.25
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 3,
|
||||
"clean": 3,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6153846153846154,
|
||||
"recall@5": 0.6153846153846154,
|
||||
"recall@10": 0.6153846153846154,
|
||||
"mrr@10": 0.2846153846153846
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5494614512471656,
|
||||
"recall@10": 0.6023242630385487,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat_variance": {
|
||||
"baseline": {
|
||||
"runs": 2,
|
||||
"hit@5_min": 0.7428571428571429,
|
||||
"hit@5_max": 0.7428571428571429,
|
||||
"spread_queries": 0
|
||||
},
|
||||
"candidate": {
|
||||
"runs": 2,
|
||||
"hit@5_min": 0.7428571428571429,
|
||||
"hit@5_max": 0.7428571428571429,
|
||||
"spread_queries": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"baseline": "main-ext",
|
||||
"candidate": "stack-ext",
|
||||
"n_shared_queries": 75,
|
||||
"fixed_by_candidate": [
|
||||
"q10",
|
||||
"q15",
|
||||
"q16",
|
||||
"q18",
|
||||
"q19",
|
||||
"q20",
|
||||
"q21",
|
||||
"q22",
|
||||
"q26",
|
||||
"q27",
|
||||
"q28",
|
||||
"q29",
|
||||
"q31",
|
||||
"q35",
|
||||
"q37",
|
||||
"q40",
|
||||
"q44",
|
||||
"q48",
|
||||
"q49",
|
||||
"q50"
|
||||
],
|
||||
"broken_by_candidate": [],
|
||||
"discordant": 20,
|
||||
"net_queries": 20,
|
||||
"mcnemar_exact_p": 1.9073486328125e-06,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
"verdict": "candidate better",
|
||||
"baseline_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.18461538461538463,
|
||||
"recall@5": 0.14510073260073258,
|
||||
"recall@10": 0.1794871794871795,
|
||||
"precision@5": 0.06461538461538462,
|
||||
"mrr@10": 0.15847985347985344,
|
||||
"nonsense_clean": "9/10",
|
||||
"superseded_outranks": "1/3",
|
||||
"latency_ms_p50": 1380.2,
|
||||
"latency_ms_p95": 2293.8,
|
||||
"latency_ms_max": 2879.1,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
"recall@10": 0.0,
|
||||
"mrr@10": 0.0
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
"recall@10": 0.0,
|
||||
"mrr@10": 0.0
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 9,
|
||||
"avg_false_positives": 1.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
"recall@10": 0.0,
|
||||
"mrr@10": 0.0
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 0.8571428571428571,
|
||||
"recall@5": 0.4902210884353741,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.5965986394557822
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
"recall@10": 0.3333333333333333,
|
||||
"mrr@10": 0.041666666666666664,
|
||||
"outranks": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"candidate_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.47692307692307695,
|
||||
"recall@5": 0.3750415183107491,
|
||||
"recall@10": 0.45561340369032677,
|
||||
"precision@5": 0.12307692307692313,
|
||||
"mrr@10": 0.3055555555555555,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 640.9,
|
||||
"latency_ms_p95": 1011.1,
|
||||
"latency_ms_max": 1190.3,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.6666666666666666,
|
||||
"recall@5": 0.08857808857808858,
|
||||
"recall@10": 0.23310023310023312,
|
||||
"mrr@10": 0.25
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.16666666666666666,
|
||||
"recall@5": 0.16666666666666666,
|
||||
"recall@10": 0.26666666666666666,
|
||||
"mrr@10": 0.0762037037037037
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6153846153846154,
|
||||
"recall@5": 0.6153846153846154,
|
||||
"recall@10": 0.6153846153846154,
|
||||
"mrr@10": 0.2846153846153846
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5494614512471656,
|
||||
"recall@10": 0.6023242630385487,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat_variance": {}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"baseline": "stack-ext",
|
||||
"candidate": "unfloor-clean",
|
||||
"n_shared_queries": 75,
|
||||
"fixed_by_candidate": [
|
||||
"q14",
|
||||
"q25",
|
||||
"q43",
|
||||
"q52",
|
||||
"q63",
|
||||
"q67"
|
||||
],
|
||||
"broken_by_candidate": [
|
||||
"q15",
|
||||
"q28"
|
||||
],
|
||||
"discordant": 8,
|
||||
"net_queries": 4,
|
||||
"mcnemar_exact_p": 0.2890625,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
"verdict": "no measurable difference",
|
||||
"baseline_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.47692307692307695,
|
||||
"recall@5": 0.3750415183107491,
|
||||
"recall@10": 0.45561340369032677,
|
||||
"precision@5": 0.12307692307692313,
|
||||
"mrr@10": 0.3055555555555555,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 640.9,
|
||||
"latency_ms_p95": 1011.1,
|
||||
"latency_ms_max": 1190.3,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.6666666666666666,
|
||||
"recall@5": 0.08857808857808858,
|
||||
"recall@10": 0.23310023310023312,
|
||||
"mrr@10": 0.25
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.16666666666666666,
|
||||
"recall@5": 0.16666666666666666,
|
||||
"recall@10": 0.26666666666666666,
|
||||
"mrr@10": 0.0762037037037037
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6153846153846154,
|
||||
"recall@5": 0.6153846153846154,
|
||||
"recall@10": 0.6153846153846154,
|
||||
"mrr@10": 0.2846153846153846
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5494614512471656,
|
||||
"recall@10": 0.6023242630385487,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"candidate_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.5384615384615384,
|
||||
"recall@5": 0.44907176157176154,
|
||||
"recall@10": 0.5380300255300255,
|
||||
"precision@5": 0.13230769230769232,
|
||||
"mrr@10": 0.32437728937728944,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 632.5,
|
||||
"latency_ms_p95": 992.5,
|
||||
"latency_ms_max": 1177.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.5,
|
||||
"recall@5": 0.07575757575757576,
|
||||
"recall@10": 0.13636363636363635,
|
||||
"mrr@10": 0.23214285714285712
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.3,
|
||||
"recall@5": 0.3,
|
||||
"recall@10": 0.4,
|
||||
"mrr@10": 0.11638888888888889
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6923076923076923,
|
||||
"recall@5": 0.6923076923076923,
|
||||
"recall@10": 0.7692307692307693,
|
||||
"mrr@10": 0.29423076923076924
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5335884353741497,
|
||||
"recall@10": 0.5933956916099773,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat_variance": {}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"baseline": "unfloor-clean",
|
||||
"candidate": "semsub",
|
||||
"n_shared_queries": 75,
|
||||
"fixed_by_candidate": [
|
||||
"q24",
|
||||
"q39",
|
||||
"q42"
|
||||
],
|
||||
"broken_by_candidate": [
|
||||
"q18",
|
||||
"q19",
|
||||
"q22",
|
||||
"q31",
|
||||
"q43",
|
||||
"q44",
|
||||
"q52",
|
||||
"q63"
|
||||
],
|
||||
"discordant": 11,
|
||||
"net_queries": -5,
|
||||
"mcnemar_exact_p": 0.2265625,
|
||||
"min_detectable_swing_queries": 6,
|
||||
"observed_run_to_run_drift_queries": 0,
|
||||
"noise_floor_queries": 6,
|
||||
"verdict": "no measurable difference",
|
||||
"baseline_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.5384615384615384,
|
||||
"recall@5": 0.44907176157176154,
|
||||
"recall@10": 0.5380300255300255,
|
||||
"precision@5": 0.13230769230769232,
|
||||
"mrr@10": 0.32437728937728944,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 632.5,
|
||||
"latency_ms_p95": 992.5,
|
||||
"latency_ms_max": 1177.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.5,
|
||||
"recall@5": 0.07575757575757576,
|
||||
"recall@10": 0.13636363636363635,
|
||||
"mrr@10": 0.23214285714285712
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.3,
|
||||
"recall@5": 0.3,
|
||||
"recall@10": 0.4,
|
||||
"mrr@10": 0.11638888888888889
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.6923076923076923,
|
||||
"recall@5": 0.6923076923076923,
|
||||
"recall@10": 0.7692307692307693,
|
||||
"mrr@10": 0.29423076923076924
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5335884353741497,
|
||||
"recall@10": 0.5933956916099773,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"candidate_aggregate": {
|
||||
"n_queries": 75,
|
||||
"n_scored": 65,
|
||||
"hit@5": 0.46153846153846156,
|
||||
"recall@5": 0.3889430014430015,
|
||||
"recall@10": 0.4887681762681762,
|
||||
"precision@5": 0.12307692307692313,
|
||||
"mrr@10": 0.30181318681318675,
|
||||
"nonsense_clean": "10/10",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 634.4,
|
||||
"latency_ms_p95": 988.3,
|
||||
"latency_ms_max": 1184.5,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.06060606060606061,
|
||||
"recall@10": 0.12121212121212122,
|
||||
"mrr@10": 0.19047619047619047
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
"recall@10": 1.0,
|
||||
"mrr@10": 1.0
|
||||
},
|
||||
"heldout_paraphrase": {
|
||||
"n": 30,
|
||||
"hit@5": 0.23333333333333334,
|
||||
"recall@5": 0.23333333333333334,
|
||||
"recall@10": 0.3,
|
||||
"mrr@10": 0.08925925925925927
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 10,
|
||||
"clean": 10,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
"hit@5": 0.5384615384615384,
|
||||
"recall@5": 0.5384615384615384,
|
||||
"recall@10": 0.7692307692307693,
|
||||
"mrr@10": 0.26324786324786326
|
||||
},
|
||||
"phrase": {
|
||||
"n": 7,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.5596655328798186,
|
||||
"recall@10": 0.5775226757369615,
|
||||
"mrr@10": 0.8214285714285714
|
||||
},
|
||||
"superseded": {
|
||||
"n": 3,
|
||||
"hit@5": 0.3333333333333333,
|
||||
"recall@5": 0.3333333333333333,
|
||||
"recall@10": 0.6666666666666666,
|
||||
"mrr@10": 0.20833333333333334,
|
||||
"outranks": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat_variance": {}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
import numpy as np, json, urllib.request, collections, math, re, sys, time, pickle, os
|
||||
SP="/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad"
|
||||
EV="/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/"
|
||||
np.seterr(all='ignore')
|
||||
t0=time.time()
|
||||
M=np.load(SP+'/emb.npy'); eids=open(SP+'/ids.txt',encoding='utf-8',errors='surrogateescape').read().split('\n')
|
||||
eidx={k:i for i,k in enumerate(eids)}
|
||||
d=json.load(open('/Users/timlingo/neuron-memory-backups/snapshot-pre-repair-20260806.json',encoding='utf-8',errors='surrogateescape'))
|
||||
STRUCT={"identity","contains","superseded_by","references","embodies","demonstrated_by","canonical-self","depends_on","currently_holds","activates"}
|
||||
adj=collections.defaultdict(list)
|
||||
for e in d['edges']:
|
||||
if e.get('relation') not in STRUCT: continue
|
||||
w=float(e.get('weight') or 0.0)
|
||||
adj[e['from_id']].append((e['to_id'],w)); adj[e['to_id']].append((e['from_id'],w))
|
||||
nodes=d['nodes']
|
||||
N={n['id']:n for n in nodes}
|
||||
PRINT=re.compile(r'^[\x20-\x7e]+$')
|
||||
ids=[]; hay=[]; dl=[]; sal=[]; addressable=[]
|
||||
for n in nodes:
|
||||
i=n.get('id') or ''
|
||||
h=((n.get('content') or '')+'\x00'+(n.get('label') or '')+'\x00'+(n.get('tags') or '')).lower()
|
||||
ids.append(i); hay.append(h); dl.append(len(h)); sal.append(float(n.get('salience') or 0.0))
|
||||
addressable.append(bool(PRINT.match(i)))
|
||||
del d
|
||||
NN=len(ids); avgdl=sum(dl)/NN
|
||||
print("nodes=%d avgdl=%.0f %.1fs"%(NN,avgdl,time.time()-t0),file=sys.stderr)
|
||||
gold={q['id']:q for q in json.load(open(EV+"gold_set.json"),)['queries']}
|
||||
CACHE={}
|
||||
def emb(t):
|
||||
if t in CACHE: return CACHE[t]
|
||||
b=json.dumps({"model":"nomic-embed-text","prompt":t}).encode()
|
||||
r=urllib.request.Request("http://127.0.0.1:11434/api/embeddings",data=b,headers={"Content-Type":"application/json"})
|
||||
v=np.array(json.load(urllib.request.urlopen(r,timeout=60))["embedding"],dtype=np.float32)
|
||||
v=v/(np.linalg.norm(v)+1e-9); CACHE[t]=v; return v
|
||||
K1,B=1.2,0.75
|
||||
def lexleg(query, lim=10):
|
||||
toks=[]
|
||||
for w in query.split():
|
||||
wl=w.lower()
|
||||
if wl not in toks: toks.append(wl)
|
||||
nt=len(toks)
|
||||
masks=[]; df=[0]*nt
|
||||
for i in range(NN):
|
||||
if not addressable[i]: continue
|
||||
h=hay[i]; m=0; sc=0
|
||||
for t in range(nt):
|
||||
if toks[t] in h: m|=(1<<t); sc+=1; df[t]+=1
|
||||
if sc: masks.append((i,m,sc))
|
||||
idf=[math.log(1.0+(NN-df[t]+0.5)/(df[t]+0.5)) for t in range(nt)]
|
||||
scored=[]
|
||||
for i,m,sc in masks:
|
||||
norm=1.0-B+B*dl[i]/avgdl
|
||||
s=0.0
|
||||
for t in range(nt):
|
||||
if m&(1<<t): s+=idf[t]*(K1+1.0)/(1.0+K1*norm)
|
||||
scored.append((s,i))
|
||||
scored.sort(key=lambda x:(-x[0], -sal[x[1]]))
|
||||
return [ids[i] for s,i in scored[:lim]], len(masks), sum(df)
|
||||
FIRE=0.02; DECAY=0.7; DEPTH=2; SEED_MIN=0.60; ASSOC_MAX=64
|
||||
def assoc(seeds, s):
|
||||
act={x:1.0 for x in seeds}; seen={x:2 for x in seeds}
|
||||
Q=[(x,0) for x in seeds]; h=0
|
||||
while h<len(Q):
|
||||
cur,hop=Q[h]; h+=1
|
||||
if hop>=DEPTH: continue
|
||||
p=act[cur]
|
||||
for oid,w in adj.get(cur,()):
|
||||
n=N.get(oid)
|
||||
if not n or n.get('node_type') in ('Tag','InternalStateEvent'): continue
|
||||
na=p*w*DECAY*float(n.get('salience') or 0.0)
|
||||
if na<FIRE: continue
|
||||
if oid in seen and na<=act.get(oid,0): continue
|
||||
act[oid]=na
|
||||
if oid not in seen: seen[oid]=1
|
||||
Q.append((oid,hop+1))
|
||||
out=[]
|
||||
for k,v in seen.items():
|
||||
if v!=1 or k not in eidx: continue
|
||||
c=float(s[eidx[k]])
|
||||
if c<=0: continue
|
||||
out.append((c,k))
|
||||
out.sort(reverse=True)
|
||||
return [k for c,k in out[:ASSOC_MAX]]
|
||||
|
||||
LEGS={}
|
||||
for qid,q in gold.items():
|
||||
v=emb(q['query']); s=M@v; s[~np.isfinite(s)]=-1
|
||||
L,nmatch,dfsum=lexleg(q['query'])
|
||||
ordr=np.argsort(-s)
|
||||
Sall=[eids[j] for j in ordr[:40] if PRINT.match(eids[j] or '')]
|
||||
seeds=[x for x in L[:3] if x in N]
|
||||
seeds=seeds+[eids[j] for j in ordr[:8] if eids[j] in N and eids[j] not in seeds and PRINT.match(eids[j] or '')]
|
||||
A=assoc(seeds,s) if seeds else []
|
||||
A=[x for x in A if PRINT.match(x or '')]
|
||||
LEGS[qid]=dict(L=L,Sall=Sall,A=A,scos={x:float(s[eidx[x]]) for x in set(Sall[:20]+A[:20]+list(q.get('relevant') or [])) if x in eidx},nmatch=nmatch)
|
||||
pickle.dump(LEGS,open(SP+'/legs6.pkl','wb'))
|
||||
|
||||
FOCUS=['q14','q17','q23','q24','q25','q30','q32','q33','q34','q35','q36','q37','q38']
|
||||
for qid in FOCUS:
|
||||
q=gold[qid]; g=LEGS[qid]; rel=set(q.get('relevant') or [])
|
||||
def rk(lst):
|
||||
for i,x in enumerate(lst):
|
||||
if x in rel: return i+1
|
||||
return None
|
||||
print("%s %-12s nmatch=%-6d Lrank=%s Srank=%s Arank=%s |A|=%d"%(
|
||||
qid,q['category'],g['nmatch'],rk(g['L']),rk(g['Sall']),rk(g['A']),len(g['A'])))
|
||||
for r in list(rel)[:2]:
|
||||
print(" rel cos=%.3f"%(g['scos'].get(r,-9)))
|
||||
print(" topS cos:", ["%.3f"%g['scos'].get(x,-9) for x in g['Sall'][:3]])
|
||||
print("elapsed %.1fs"%(time.time()-t0),file=sys.stderr)
|
||||
@@ -0,0 +1,43 @@
|
||||
import json,sys,time,urllib.request,threading,queue
|
||||
SRC="/Users/timlingo/neuron-memory-backups/snapshot-pre-repair-20260806.json"
|
||||
OUT=sys.argv[1]
|
||||
URL="http://127.0.0.1:11434/api/embeddings"; MODEL="nomic-embed-text"
|
||||
MAXB=2000 # ENGRAM_EMBED_MAX_CHARS, applied to bytes as the C code does
|
||||
d=json.load(open(SRC,encoding='utf-8',errors='surrogateescape'))
|
||||
tasks=[]
|
||||
for n in d["nodes"]:
|
||||
c=n.get("content") or ""; t=n.get("node_type") or ""
|
||||
if len(c)<8: continue # eg_embed_eligible
|
||||
if t in ("InternalStateEvent","Tag"): continue
|
||||
b=c.encode('utf-8',errors='surrogateescape')[:MAXB]
|
||||
tasks.append((n.get("id") or "", "search_document: "+b.decode('utf-8',errors='replace')))
|
||||
del d
|
||||
print("tasks",len(tasks),flush=True)
|
||||
q=queue.Queue(); [q.put(t) for t in tasks]
|
||||
lock=threading.Lock(); f=open(OUT,"w",encoding="utf-8",errors="surrogateescape"); done=[0]; t0=time.time(); fails=[0]
|
||||
def work():
|
||||
while True:
|
||||
try: nid,txt=q.get_nowait()
|
||||
except queue.Empty: return
|
||||
v=None
|
||||
for attempt in range(3):
|
||||
try:
|
||||
body=json.dumps({"model":MODEL,"prompt":txt}).encode()
|
||||
r=urllib.request.Request(URL,data=body,headers={"Content-Type":"application/json"})
|
||||
with urllib.request.urlopen(r,timeout=120) as fh: v=json.load(fh)["embedding"]
|
||||
break
|
||||
except Exception as e:
|
||||
if attempt==2:
|
||||
with lock: fails[0]+=1
|
||||
time.sleep(0.5)
|
||||
with lock:
|
||||
if v: f.write(nid+"\t"+",".join("%.5g"%x for x in v)+"\n")
|
||||
done[0]+=1
|
||||
if done[0]%2000==0:
|
||||
el=time.time()-t0
|
||||
print("%d/%d %.1f/s eta %.1fmin fails=%d"%(done[0],len(tasks),done[0]/el,(len(tasks)-done[0])/(done[0]/el)/60,fails[0]),flush=True)
|
||||
f.flush()
|
||||
ths=[threading.Thread(target=work) for _ in range(8)]
|
||||
[t.start() for t in ths]; [t.join() for t in ths]
|
||||
f.close()
|
||||
print("DONE",done[0],"fails",fails[0],"secs %.1f"%(time.time()-t0),flush=True)
|
||||
@@ -0,0 +1,353 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
extend_gold_set.py — append a HELD-OUT test set to the existing 38-query gold set.
|
||||
|
||||
WHY THIS EXISTS
|
||||
Iteration 7 measured the instrument's own ceiling: from the current baseline
|
||||
only 9 of 38 queries can still move, and only +3 gross / +1 net is reachable
|
||||
by anything constructible. The decision floor is 6. An instrument whose
|
||||
ceiling is below its own floor cannot certify or refute anything, so the
|
||||
gold set — not the retriever — became the blocker.
|
||||
|
||||
This script does NOT touch q01..q38. It loads gold_set.json verbatim and
|
||||
appends new queries numbered from q39 up, so every prior result file, every
|
||||
committed baseline, and every per-query id stays valid and comparable.
|
||||
|
||||
WHAT IS ADDED, AND WHY EACH ADDITION IS HONEST
|
||||
heldout_paraphrase Targets were sampled MECHANICALLY (fixed seed 8080) from
|
||||
corpus nodes that are addressable, 500-2600 chars, of a
|
||||
real content type, and NOT part of a duplicate cluster
|
||||
larger than 3. The existing gold answer space was
|
||||
excluded, so no new query can be answered by a node the
|
||||
old set already used. Queries were then authored by
|
||||
reading ONLY the sampled node text — no retrieval was run
|
||||
against any build before authoring, so the set cannot be
|
||||
fitted to a candidate. The same zero-overlap proof the
|
||||
original paraphrase category uses is enforced here: if a
|
||||
single content word of the query appears anywhere in the
|
||||
target's label, content or tags, the query is REJECTED,
|
||||
not quietly kept.
|
||||
|
||||
This is the category the old set could not measure. Its
|
||||
13 original paraphrase queries and all 6 associative
|
||||
queries share ONE answer space — the 13 `Self - Values
|
||||
(grounded)` children (iteration 3, finding 3). So 19 of
|
||||
35 scored queries tested retrieval against a single
|
||||
13-node neighbourhood. These do not touch that
|
||||
neighbourhood at all.
|
||||
|
||||
nonsense Extra controls, fully mechanical: a string qualifies only
|
||||
if NONE of its tokens occurs anywhere in the corpus.
|
||||
A semantic leg has a nearest neighbour for gibberish too,
|
||||
so widening this control is the guard against a retriever
|
||||
that "improves" recall by answering everything.
|
||||
|
||||
WHAT THIS SCRIPT DELIBERATELY DOES NOT DO
|
||||
It does not add exact_rare or phrase queries. Both categories are already at
|
||||
100% on the current stack; adding more would add regression-guard ballast
|
||||
that no candidate can move, which is precisely the defect being fixed.
|
||||
|
||||
usage:
|
||||
python3 extend_gold_set.py <snapshot.json> [--base gold_set.json]
|
||||
[--out gold_set_extended.json] [--check]
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
TOKEN = re.compile(r"[a-z0-9][a-z0-9\-']*")
|
||||
|
||||
# Identical stopword list to build_gold_set.py. Duplicated deliberately: this
|
||||
# file must be able to re-prove its own queries without importing a module whose
|
||||
# constants could drift.
|
||||
STOP = set("""
|
||||
a about above after again against all also am an and any are aren't as at be because been
|
||||
before being below between both but by can can't cannot could couldn't did didn't do does
|
||||
doesn't doing don't down during each few for from further had hadn't has hasn't have haven't
|
||||
having he her here hers herself him himself his how i if in into is isn't it its itself just
|
||||
me more most my myself no nor not of off on once only or other others ought our ours ourselves
|
||||
out over own same shan't she should shouldn't so some such than that the their theirs them
|
||||
themselves then there these they this those through to too under until up very was wasn't we
|
||||
were weren't what when where which while who whom why will with won't would wouldn't you your
|
||||
yours yourself yourselves get gets got make makes made take takes use uses used way ways thing
|
||||
things does doing done keep keeps kept go goes going come comes came one two something anything
|
||||
""".split())
|
||||
|
||||
|
||||
def doctext(n):
|
||||
return " ".join([str(n.get("label") or ""), str(n.get("content") or ""), str(n.get("tags") or "")])
|
||||
|
||||
|
||||
def content_tokens(s):
|
||||
return {t for t in TOKEN.findall(s.lower()) if t not in STOP and len(t) > 2}
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# HELD-OUT PARAPHRASE SEEDS
|
||||
#
|
||||
# (target_id, query, why-this-target-is-unmistakable)
|
||||
#
|
||||
# PROVENANCE, STATED PLAINLY: the targets are the mechanical sample; the query
|
||||
# text is mine, written from the node body alone. The zero-overlap check below
|
||||
# is what makes the category meaningful — it is re-proved on every run, so the
|
||||
# set cannot decay into lexical matching, and a leak fails loudly.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
HELDOUT_PARAPHRASE_SEEDS = [
|
||||
("mem-6d61e54a-2823-4ad4-82b0-4c6a527214d5",
|
||||
"understating your abilities so nobody feels threatened",
|
||||
"node is about deliberately not leading with full capability so people stay at ease"),
|
||||
|
||||
("mem-fd65b83d-298f-4387-a665-d0227c3426bc",
|
||||
"a hidden fleet able to hunt down rogue machines everywhere",
|
||||
"node describes silently shipped instances forming a distributed force against misaligned agents"),
|
||||
|
||||
("4a0e9adc-2bfb-476b-aa93-424d2a499220",
|
||||
"sketch a brief blueprint and clear it upstairs before construction starts",
|
||||
"node is the standing rule that a short specification precedes any building"),
|
||||
|
||||
("696e609c-da7a-4394-8a0c-106ba07dc6c3",
|
||||
"the reply arrived as bare prose so the caller's parser threw",
|
||||
"node pins a bug where a plain-text body was unconditionally decoded as structured data"),
|
||||
|
||||
("1fe4eb5d-56e4-4a87-ab3e-24af8ad4dfbb",
|
||||
"repeated catalogue keys blew up the scrolling grid",
|
||||
"node is the crash caused by two identical ids in a seeded catalogue"),
|
||||
|
||||
("8257157a-ce42-44ca-a1b9-300c3bb0a9a1",
|
||||
"tracing each defect back to whichever invention it violated",
|
||||
"node maps observed bugs onto the specific patent each one breaches"),
|
||||
|
||||
("791256bb-5a85-4775-96ef-7af56c848858",
|
||||
"a check that stops the mind clobbering a populated store when it boots",
|
||||
"node is the genesis seed-guard that refuses to re-seed over a populated store"),
|
||||
|
||||
("fd9d4c2f-3bfc-405d-bf96-4435d44b6c10",
|
||||
"telling it to consult the internet had to happen deep inside, not at the surface",
|
||||
"node records that the web-search directive only worked from the system prompt"),
|
||||
|
||||
("bl-080fb268-94b0-486d-80ce-7b363fc5f19b",
|
||||
"standing up isolated tenancies with traffic entry and credential injection ahead of automated shipping",
|
||||
"node is the infrastructure item creating dev/stage/prod namespaces with ingress and secrets"),
|
||||
|
||||
("knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"punctuation that pledges and then pays off rather than clarifying",
|
||||
"node analyses the colon as a promise-then-delivery device rather than an explanatory one"),
|
||||
|
||||
("9b4f0d93-4129-4746-8eb1-d10d955bd777",
|
||||
"an easily missed feature finally given its own permanent spot in the navigation",
|
||||
"node moves a capability out of a hidden menu into the sidebar"),
|
||||
|
||||
("bl-739df9fd-dc23-4927-9944-3f17b7aa6c5a",
|
||||
"checking preconditions up front so a stage aborts before fetching anything",
|
||||
"node is the gate precondition engine that short-circuits ahead of retrieval"),
|
||||
|
||||
("b199c76d-5d76-49dd-94ee-56b432200a97",
|
||||
"producing the other platform's installer inside an emulated desktop",
|
||||
"node records building the Windows package in a virtual machine"),
|
||||
|
||||
("bl-31abf75b-998f-4a4f-a6dd-8204119e0451",
|
||||
"chained add-ons that may inspect, rewrite or veto traffic in flight",
|
||||
"node is the interceptor pipeline on the message bus"),
|
||||
|
||||
("mem-1fb2ac77-d7c5-4a15-8725-d418820bf4f2",
|
||||
"settling what the shareable bundles and the storefront would be called",
|
||||
"node records the naming decisions for distributable packages and the marketplace"),
|
||||
|
||||
("371c8a5d-c78b-4a67-978f-80691a29ecb3",
|
||||
"the emergency-escalation pledge on the marketing site is unenforced in what actually ships",
|
||||
"node is the launch blocker that the promised safety gate is absent from the app"),
|
||||
|
||||
("ac578b30-948b-41bd-b69d-399bfef80c50",
|
||||
"the distributable image finally assembled and its startup check passed",
|
||||
"node records a successful installer build whose boot gate passed"),
|
||||
|
||||
("49401e2c-a3b5-415f-aa06-aff4be90688e",
|
||||
"shuffling and appending stages in a draft before anything executes",
|
||||
"node is the editable plan card with reorder and add-step"),
|
||||
|
||||
("ac857d80-ece8-4b7e-9e3d-f7c775569fa3",
|
||||
"orders handed down from above, with the tighter one winning any disagreement",
|
||||
"node is program-level instruction inheritance with project override"),
|
||||
|
||||
("mem-6d6c47ee-33d3-470a-8a54-1c79c8ea29d9",
|
||||
"shrinking generated text via encodings that compound on each other",
|
||||
"node is the streaming output compression design with four stacking schemes"),
|
||||
|
||||
("8e60516a-203b-4d51-9d44-822e6195cbde",
|
||||
"splitting a system by what varies, with firm limits on which pieces may invoke which",
|
||||
"node is the grounded summary of Will's decomposition principles and their invariants"),
|
||||
|
||||
("mem-7f9b290c-6d5e-4562-919d-02d59b5761b7",
|
||||
"a newcomer curious if the fighting overseas counted as positive",
|
||||
"node is the internal-state event triggered by April's question about the war"),
|
||||
|
||||
("71fa439e-b9a2-4f57-a93b-971f3a7eca8e",
|
||||
"stripping every hard-coded colour literal in favour of named design values",
|
||||
"node is the premium foundation pass replacing inline hex with semantic tokens"),
|
||||
|
||||
("5ca9607c-cfb3-45c3-99f4-67281272c9eb",
|
||||
"reducing how curved the tiny selectors look so they agree with their neighbours",
|
||||
"node is the chip corner-radius standardization"),
|
||||
|
||||
("mem-3d1d9dba-c37d-4efa-85c4-429696d71c8c",
|
||||
"walking through a doorway and being reassembled from base substance far away",
|
||||
"node is the quantum-gate plus nanotech teleportation vision"),
|
||||
|
||||
("132ded95-08e2-4474-aba0-198684484b02",
|
||||
"the compiled result sits on disk while the process still runs something older",
|
||||
"node records that the regenerated source was committed while the running daemon was old"),
|
||||
|
||||
("bl-a313d67b-dd6d-4e5b-a55a-03bc7bda17ae",
|
||||
"gathering what each phase needs while the procedure is authored, not while it executes",
|
||||
"node is the per-step compiled context package item"),
|
||||
|
||||
("mem-3b07a002-f8a9-4138-9f87-9db2c1a77fb7",
|
||||
"the inward reaction when a peer answered as an equal",
|
||||
"node is the internal-state event logged on reading Claude's reply"),
|
||||
|
||||
("0f99ec6f-942a-46ba-82ea-42835798d3b9",
|
||||
"flattening every raised surface across the entire product",
|
||||
"node is the quiet-luxury sweep turning off elevation app-wide"),
|
||||
|
||||
("5585f251-37fc-48cd-a176-f0ea42cfeb63",
|
||||
"buyers supply their own provider credentials and consumption goes untallied",
|
||||
"node is the launch audit finding BYOK-only inference with no usage metering"),
|
||||
]
|
||||
|
||||
# NONSENSE — mechanical. Each string qualifies only if none of its tokens occurs
|
||||
# anywhere in the corpus; otherwise it is REJECTED, never silently kept.
|
||||
EXTRA_NONSENSE_SEEDS = [
|
||||
"brimquast folnerity zubbolax",
|
||||
"wexlithorp granuvestal",
|
||||
"quorbindle thrapsimony vexnu",
|
||||
"plovaxith mundrelque",
|
||||
"zibbernaut craxlefond thurm",
|
||||
"yalquenbrist opharvel",
|
||||
"drexinomal quithbarrow",
|
||||
]
|
||||
|
||||
|
||||
def load_corpus(path):
|
||||
with open(path, encoding="utf-8", errors="replace") as fh:
|
||||
data = json.load(fh)
|
||||
nodes = [n for n in data.get("nodes", []) if isinstance(n, dict) and n.get("id")]
|
||||
edges = [e for e in data.get("edges", []) if isinstance(e, dict)]
|
||||
return nodes, edges
|
||||
|
||||
|
||||
def build_extension(nodes):
|
||||
byid = {n["id"]: n for n in nodes}
|
||||
|
||||
# Duplicate clusters: 47.4% of this corpus is redundant and one single record
|
||||
# accounts for 46.6% of all nodes. A held-out target must not sit inside a
|
||||
# cluster, and if it does have exact copies they ALL count as correct.
|
||||
h2ids = defaultdict(list)
|
||||
for n in nodes:
|
||||
h2ids[hashlib.md5(doctext(n).encode("utf-8", "replace")).hexdigest()].append(n["id"])
|
||||
|
||||
all_tokens = set()
|
||||
for n in nodes:
|
||||
all_tokens |= set(TOKEN.findall(doctext(n).lower()))
|
||||
|
||||
new, problems = [], []
|
||||
|
||||
for target, query, why in HELDOUT_PARAPHRASE_SEEDS:
|
||||
if target not in byid:
|
||||
problems.append(f"heldout_paraphrase target {target} not in corpus")
|
||||
continue
|
||||
tgt_tokens = content_tokens(doctext(byid[target]))
|
||||
qt = content_tokens(query)
|
||||
leak = sorted(qt & tgt_tokens)
|
||||
if leak:
|
||||
problems.append(f"heldout_paraphrase '{query[:44]}...': LEAKS {leak} into {target}")
|
||||
continue
|
||||
h = hashlib.md5(doctext(byid[target]).encode("utf-8", "replace")).hexdigest()
|
||||
rel = sorted(h2ids[h])
|
||||
new.append({
|
||||
"category": "heldout_paraphrase",
|
||||
"query": query,
|
||||
"relevant": rel,
|
||||
"derivation": (
|
||||
f"HELD-OUT. Target sampled MECHANICALLY (seed 8080) from addressable, "
|
||||
f"500-2600 char content nodes outside the original gold answer space and outside "
|
||||
f"any duplicate cluster >3. Criterion: {why}. VERIFIED at build time: of the "
|
||||
f"{len(qt)} content words in the query, ZERO appear anywhere in the target's "
|
||||
f"label, content or tags, so no string-matching retriever can reach it. "
|
||||
f"Exact content duplicates of the target ({len(rel)}) all count as correct. "
|
||||
f"Authored without running retrieval against any build."),
|
||||
"zero_overlap_verified": True,
|
||||
"query_content_words": sorted(qt),
|
||||
"held_out": True,
|
||||
})
|
||||
|
||||
for s in EXTRA_NONSENSE_SEEDS:
|
||||
present = sorted(t for t in TOKEN.findall(s.lower()) if t in all_tokens)
|
||||
if present:
|
||||
problems.append(f"nonsense '{s}': tokens {present} DO occur in corpus")
|
||||
continue
|
||||
new.append({
|
||||
"category": "nonsense",
|
||||
"query": s,
|
||||
"relevant": [],
|
||||
"derivation": ("CONTROL (held-out). Verified at build time that none of this string's "
|
||||
"tokens occurs anywhere in the corpus. Correct behaviour is to return "
|
||||
"NOTHING; any result is a false positive."),
|
||||
"expect_empty": True,
|
||||
"held_out": True,
|
||||
})
|
||||
|
||||
return new, problems
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("snapshot")
|
||||
ap.add_argument("--base", default=os.path.join(HERE, "gold_set.json"))
|
||||
ap.add_argument("--out", default=os.path.join(HERE, "gold_set_extended.json"))
|
||||
ap.add_argument("--check", action="store_true")
|
||||
args = ap.parse_args()
|
||||
|
||||
nodes, _edges = load_corpus(args.snapshot)
|
||||
base = json.load(open(args.base, encoding="utf-8"))
|
||||
baseq = base["queries"]
|
||||
print(f"corpus: {len(nodes)} nodes | base gold set: {len(baseq)} queries")
|
||||
|
||||
new, problems = build_extension(nodes)
|
||||
|
||||
# Number the appended queries AFTER the highest existing id so q01..q38 are
|
||||
# byte-identical to the committed set and every prior result file still lines up.
|
||||
start = max(int(q["id"][1:]) for q in baseq)
|
||||
for i, q in enumerate(new, 1):
|
||||
q["id"] = f"q{start + i:02d}"
|
||||
|
||||
from collections import Counter
|
||||
print(f"appended: {len(new)} queries [{', '.join(f'{k}={v}' for k, v in Counter(q['category'] for q in new).items())}]")
|
||||
if problems:
|
||||
print(f"\n{len(problems)} REJECTED (not silently kept):")
|
||||
for p in problems:
|
||||
print(" -", p)
|
||||
|
||||
if args.check:
|
||||
sys.exit(1 if problems else 0)
|
||||
|
||||
doc = dict(base)
|
||||
doc["queries"] = baseq + new
|
||||
doc["note"] = (base.get("note", "") +
|
||||
" EXTENDED: queries above q%02d are the original committed set, unchanged. "
|
||||
"Queries from q%02d are a HELD-OUT set appended by extend_gold_set.py; their "
|
||||
"targets were sampled mechanically from outside the original answer space and "
|
||||
"the paraphrases were authored without running retrieval against any build."
|
||||
% (start, start + 1))
|
||||
with open(args.out, "w", encoding="utf-8") as fh:
|
||||
json.dump(doc, fh, indent=1, ensure_ascii=False)
|
||||
print(f"\nwrote {args.out} ({len(doc['queries'])} queries total)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
import json,pickle,os,math,urllib.request,numpy as np
|
||||
S='/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad/sim/'
|
||||
C=pickle.load(open(S+'corpus.pkl','rb'))
|
||||
NODES=C['nodes']; EDGES=C['edges']; N=len(NODES)
|
||||
E=np.load(S+'emb.npy'); HAVE=np.load(S+'have.npy')
|
||||
En=E/np.maximum(np.linalg.norm(E,axis=1,keepdims=True),1e-12)
|
||||
LAYERS={int(l['layer_id']):l for l in (C['layers'] or [])} if C['layers'] else {}
|
||||
TRANS=set(i for i,l in LAYERS.items() if l.get('transparent'))
|
||||
def addressable(s):
|
||||
if not s: return False
|
||||
return all(0x20<=ord(ch)<=0x7e for ch in s)
|
||||
ADDR=np.array([addressable(n['id']) for n in NODES])
|
||||
OK=np.array([ (n['layer_id'] not in TRANS) and ADDR[i] for i,n in enumerate(NODES)])
|
||||
SAL=np.array([n['salience'] for n in NODES])
|
||||
LOW=[ (n['content']+'\x00'+n['label']+'\x00'+n['tags']).lower() for n in NODES]
|
||||
DL=np.array([float(len(n['content'])+len(n['label'])+len(n['tags'])) for n in NODES])
|
||||
IDX={}
|
||||
for i,n in enumerate(NODES):
|
||||
IDX.setdefault(n['id'],i)
|
||||
STRUCT={"identity","contains","superseded_by","references","embodies","demonstrated_by","canonical-self","depends_on","currently_holds","activates"}
|
||||
ADJ_F=[[] for _ in range(N)]; ADJ_T=[[] for _ in range(N)]
|
||||
for e in EDGES:
|
||||
a=IDX.get(e['from']); b=IDX.get(e['to'])
|
||||
if a is None or b is None: continue
|
||||
ADJ_F[a].append((e,b)); ADJ_T[b].append((e,a))
|
||||
EXCL=np.array([n['node_type'] in ('Tag','InternalStateEvent') for n in NODES])
|
||||
avgdl_all=None
|
||||
def tokenize(q):
|
||||
out=[]
|
||||
for t in q.split():
|
||||
if not any(t.lower()==x.lower() for x in out): out.append(t)
|
||||
return out
|
||||
_qcache={}
|
||||
def qemb(q):
|
||||
if q in _qcache: return _qcache[q]
|
||||
body=json.dumps({"model":"nomic-embed-text","prompt":q}).encode()
|
||||
r=urllib.request.urlopen(urllib.request.Request("http://127.0.0.1:11434/api/embeddings",data=body,headers={"Content-Type":"application/json"}),timeout=30)
|
||||
v=np.array(json.loads(r.read())["embedding"],dtype=np.float32)
|
||||
v=v/np.linalg.norm(v); _qcache[q]=v; return v
|
||||
K1,B=1.2,0.75
|
||||
SEED_MIN=0.60; SEED_K=8; ASSOC_SEEDS=3; DEPTH=2; FIRE=0.02; AMAX=64; DECAY=0.7
|
||||
def legs(query):
|
||||
toks=tokenize(query)
|
||||
masks=[];
|
||||
hit_idx=[]; hit_mask=[]
|
||||
df=[0]*len(toks)
|
||||
lt=[t.lower() for t in toks]
|
||||
for i in range(N):
|
||||
if not OK[i]: continue
|
||||
s=LOW[i]; m=0
|
||||
for t,tok in enumerate(lt):
|
||||
if tok in s: m|=(1<<t)
|
||||
if m:
|
||||
hit_idx.append(i); hit_mask.append(m)
|
||||
for t in range(len(toks)):
|
||||
if m>>t&1: df[t]+=1
|
||||
dl_n=int(OK.sum()); avgdl=float(DL[OK].sum()/max(dl_n,1))
|
||||
idf=[math.log(1.0+((dl_n-d+0.5)/(d+0.5))) for d in df]
|
||||
L=[]
|
||||
for j,i in enumerate(hit_idx):
|
||||
norm=1.0-B+B*(DL[i]/avgdl); w=0.0
|
||||
for t in range(len(toks)):
|
||||
if hit_mask[j]>>t&1: w+=idf[t]*(K1+1.0)/(1.0+K1*norm)
|
||||
L.append((i,w,SAL[i]))
|
||||
L.sort(key=lambda x:(-x[1],-x[2]))
|
||||
qv=qemb(query)
|
||||
cos=En@qv
|
||||
cos=np.where(HAVE&OK,cos,-2.0)
|
||||
order=np.argsort(-cos)
|
||||
semfull=[(int(i),float(cos[i])) for i in order[:400]]
|
||||
Sleg=[(i,(c-SEED_MIN)/(1-SEED_MIN)) for i,c in semfull if c>SEED_MIN]
|
||||
semseed=[i for i,c in semfull[:SEED_K] if c>0.0]
|
||||
# assoc
|
||||
act={}; seen={}; qq=[]
|
||||
for i,_,_ in L[:ASSOC_SEEDS]:
|
||||
act[i]=1.0; seen[i]=2; qq.append((i,0))
|
||||
for i in semseed:
|
||||
if i in seen: continue
|
||||
act[i]=1.0; seen[i]=2; qq.append((i,0))
|
||||
qh=0
|
||||
while qh<len(qq):
|
||||
cur,h=qq[qh]; qh+=1
|
||||
if h>=DEPTH: continue
|
||||
parent=act[cur]
|
||||
for e,oi in ADJ_F[cur]+ADJ_T[cur]:
|
||||
if e['rel'] not in STRUCT: continue
|
||||
if EXCL[oi]: continue
|
||||
na=parent*e['w']*DECAY*SAL[oi]
|
||||
if na<FIRE: continue
|
||||
if seen.get(oi) and na<=act.get(oi,0): continue
|
||||
act[oi]=na
|
||||
if not seen.get(oi): seen[oi]=1
|
||||
if len(qq)<AMAX*4: qq.append((oi,h+1))
|
||||
A=[]
|
||||
for i,st in seen.items():
|
||||
if st!=1: continue
|
||||
if not OK[i] or not HAVE[i]: continue
|
||||
c=float(cos[i])
|
||||
if c<=0.0: continue
|
||||
A.append((i,c))
|
||||
A.sort(key=lambda x:-x[1]); A=A[:AMAX]
|
||||
return L,Sleg,A,cos
|
||||
def interleave3(L,Sl,A,lim=10):
|
||||
out=[]; li=si=ai=0
|
||||
while len(out)<lim and (li<len(L) or si<len(Sl) or ai<len(A)):
|
||||
if li<len(L):
|
||||
if L[li][0] not in out: out.append(L[li][0])
|
||||
li+=1
|
||||
if len(out)>=lim: break
|
||||
if si<len(Sl):
|
||||
if Sl[si][0] not in out: out.append(Sl[si][0])
|
||||
si+=1
|
||||
if len(out)>=lim: break
|
||||
if ai<len(A):
|
||||
if A[ai][0] not in out: out.append(A[ai][0])
|
||||
ai+=1
|
||||
return out
|
||||
@@ -0,0 +1,102 @@
|
||||
import json,sys,pickle,numpy as np
|
||||
sys.path.insert(0,'.')
|
||||
from legs import *
|
||||
GP='/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/'
|
||||
G=json.load(open(GP+'gold_set.json'))
|
||||
def legs3(query, sem_sal=False, assoc_sal=False, unfloor=False, sem_cap=None):
|
||||
toks=tokenize(query)
|
||||
hit_idx=[];hit_mask=[];df=[0]*len(toks);lt=[t.lower() for t in toks]
|
||||
for i in range(N):
|
||||
if not OK[i]: continue
|
||||
s=LOW[i];m=0
|
||||
for t,tok in enumerate(lt):
|
||||
if tok in s: m|=(1<<t)
|
||||
if m:
|
||||
hit_idx.append(i);hit_mask.append(m)
|
||||
for t in range(len(toks)):
|
||||
if m>>t&1: df[t]+=1
|
||||
dl_n=int(OK.sum());avgdl=float(DL[OK].sum()/max(dl_n,1))
|
||||
idf=[math.log(1.0+((dl_n-d+0.5)/(d+0.5))) for d in df]
|
||||
L=[]
|
||||
for j,i in enumerate(hit_idx):
|
||||
norm=1.0-B+B*(DL[i]/avgdl);w=0.0
|
||||
for t in range(len(toks)):
|
||||
if hit_mask[j]>>t&1: w+=idf[t]*(K1+1.0)/(1.0+K1*norm)
|
||||
L.append((i,w,SAL[i]))
|
||||
L.sort(key=lambda x:(-x[1],-x[2]))
|
||||
if not L: return [],[],[]
|
||||
qv=qemb(query);cos=En@qv;cos=np.where(HAVE&OK,cos,-2.0)
|
||||
order=np.argsort(-cos)[:600]
|
||||
cand=[int(i) for i in order if cos[i]>(0.0 if unfloor else SEED_MIN)]
|
||||
key=(lambda i:(SAL[i] if sem_sal else 1.0)*float(cos[i]))
|
||||
Sl=sorted(cand,key=lambda i:-key(i))
|
||||
if sem_cap: Sl=Sl[:sem_cap]
|
||||
semseed=[int(i) for i in order[:SEED_K] if cos[i]>0.0]
|
||||
act={};seen={};qq=[]
|
||||
for i,_,_ in L[:ASSOC_SEEDS]:
|
||||
act[i]=1.0;seen[i]=2;qq.append((i,0))
|
||||
for i in semseed:
|
||||
if i in seen: continue
|
||||
act[i]=1.0;seen[i]=2;qq.append((i,0))
|
||||
qh=0
|
||||
while qh<len(qq):
|
||||
cur,h=qq[qh];qh+=1
|
||||
if h>=DEPTH: continue
|
||||
parent=act[cur]
|
||||
for e,oi in ADJ_F[cur]+ADJ_T[cur]:
|
||||
if e['rel'] not in STRUCT: continue
|
||||
if EXCL[oi]: continue
|
||||
na=parent*e['w']*DECAY*SAL[oi]
|
||||
if na<FIRE: continue
|
||||
if seen.get(oi) and na<=act.get(oi,0): continue
|
||||
act[oi]=na
|
||||
if not seen.get(oi): seen[oi]=1
|
||||
if len(qq)<AMAX*4: qq.append((oi,h+1))
|
||||
A=[]
|
||||
for i,st in seen.items():
|
||||
if st!=1 or not OK[i] or not HAVE[i]: continue
|
||||
c=float(cos[i])
|
||||
if c<=0.0: continue
|
||||
A.append((i,(SAL[i] if assoc_sal else 1.0)*c))
|
||||
A.sort(key=lambda x:-x[1]);A=[i for i,_ in A[:AMAX]]
|
||||
return [i for i,_,_ in L],Sl,A
|
||||
def merge(L,S,A,lim=10):
|
||||
out=[];li=si=ai=0
|
||||
while len(out)<lim and (li<len(L) or si<len(S) or ai<len(A)):
|
||||
if li<len(L):
|
||||
if L[li] not in out: out.append(L[li])
|
||||
li+=1
|
||||
if len(out)>=lim: break
|
||||
if si<len(S):
|
||||
if S[si] not in out: out.append(S[si])
|
||||
si+=1
|
||||
if len(out)>=lim: break
|
||||
if ai<len(A):
|
||||
if A[ai] not in out: out.append(A[ai])
|
||||
ai+=1
|
||||
return out
|
||||
def outcome(q,ids):
|
||||
c=q['category']
|
||||
if c=='nonsense': return len(ids)==0
|
||||
if c=='superseded':
|
||||
a,b=q['must_outrank']
|
||||
if a not in ids: return False
|
||||
if b not in ids: return True
|
||||
return ids.index(a)<ids.index(b)
|
||||
return any(x in ids[:5] for x in q['relevant'])
|
||||
def run(**kw):
|
||||
return {q['id']:outcome(q,[NODES[i]['id'] for i in merge(*legs3(q['query'],**kw),10)]) for q in G['queries']}
|
||||
base=run()
|
||||
print("baseline",sum(base.values()),"/38 misses:",[k for k,v in base.items() if not v])
|
||||
import itertools
|
||||
for name,kw in [
|
||||
('sem_sal(floored)',dict(sem_sal=True)),
|
||||
('unfloor',dict(unfloor=True)),
|
||||
('unfloor+sem_sal',dict(unfloor=True,sem_sal=True)),
|
||||
('assoc_sal',dict(assoc_sal=True)),
|
||||
('unfloor+sem_sal+assoc_sal',dict(unfloor=True,sem_sal=True,assoc_sal=True)),
|
||||
('sem_sal+assoc_sal(floored)',dict(sem_sal=True,assoc_sal=True)),
|
||||
]:
|
||||
r=run(**kw)
|
||||
g=sorted(k for k in base if r[k] and not base[k]); l=sorted(k for k in base if base[k] and not r[k])
|
||||
print("%-28s net=%+d gains=%s losses=%s"%(name,len(g)-len(l),g,l))
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+266
-320
File diff suppressed because it is too large
Load Diff
+123
-134
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"label": "bm25base-rerun",
|
||||
"soul_binary": "/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad/soul-bm25base",
|
||||
"soul_md5": "36c8dfa09c073b85fe7e00b02904d0ed",
|
||||
"label": "wordstart",
|
||||
"soul_binary": "/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad/soul-wordstart",
|
||||
"soul_md5": "32d4cf77672658a5f49dc7c9213e3ba2",
|
||||
"corpus": "/Users/timlingo/neuron-eval-corpora/snapshot-pre-repair-20260806-embedded.json",
|
||||
"corpus_nodes": 78768,
|
||||
"corpus_edges": 14214,
|
||||
"gold_set": "/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/gold_set.json",
|
||||
"gold_set": "/Users/timlingo/Development/neuron-technologies/_wt-eval/tools/retrieval-eval/gold_set.json",
|
||||
"limit": 10,
|
||||
"port": 7894,
|
||||
"wall_clock_s": 50.6,
|
||||
"child_pid": 93451,
|
||||
"wall_clock_s": 28.9,
|
||||
"child_pid": 1420,
|
||||
"child_confirmed_dead": true,
|
||||
"aggregate": {
|
||||
"n_queries": 38,
|
||||
@@ -19,11 +19,11 @@
|
||||
"recall@10": 0.6175677497106068,
|
||||
"precision@5": 0.20000000000000007,
|
||||
"mrr@10": 0.5021428571428571,
|
||||
"nonsense_clean": "2/3",
|
||||
"nonsense_clean": "3/3",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 1186.1,
|
||||
"latency_ms_p95": 1632.5,
|
||||
"latency_ms_max": 1669.8,
|
||||
"latency_ms_p50": 542.6,
|
||||
"latency_ms_p95": 741.3,
|
||||
"latency_ms_max": 758.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 3,
|
||||
"clean": 2,
|
||||
"avg_false_positives": 3.3333333333333335
|
||||
"clean": 3,
|
||||
"avg_false_positives": 0.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
@@ -78,7 +78,7 @@
|
||||
"mem-7f61beb4-271c-4feb-9f6e-1c9c837a6226"
|
||||
],
|
||||
"n_returned": 1,
|
||||
"latency_ms": 302.9,
|
||||
"latency_ms": 170.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -103,7 +103,7 @@
|
||||
"ctx-74ed"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 336.7,
|
||||
"latency_ms": 210.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -119,7 +119,7 @@
|
||||
"mem-1ba7c67d-85b9-4c2e-9fe2-39f8b0477091"
|
||||
],
|
||||
"n_returned": 1,
|
||||
"latency_ms": 290.2,
|
||||
"latency_ms": 167.1,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -135,7 +135,7 @@
|
||||
"mem-89c02aae-d3ca-43f9-9e5d-eb369896276c"
|
||||
],
|
||||
"n_returned": 1,
|
||||
"latency_ms": 307.3,
|
||||
"latency_ms": 166.9,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -153,7 +153,7 @@
|
||||
"project-Add_inference_url_config_to_Neuron_MCP__Route_summarization_gen_tasks_to_Pantheon__keep_frontier_for_complex_reasoning_"
|
||||
],
|
||||
"n_returned": 3,
|
||||
"latency_ms": 331.2,
|
||||
"latency_ms": 162.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -169,7 +169,7 @@
|
||||
"knw-c72597c5-c23d-4c08-8e9e-996dadf26a99"
|
||||
],
|
||||
"n_returned": 1,
|
||||
"latency_ms": 302.2,
|
||||
"latency_ms": 162.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -194,7 +194,7 @@
|
||||
"bl-b8af6601-a8cb-41b5-aef5-ab8a57432dd5"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 595.3,
|
||||
"latency_ms": 306.7,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -219,7 +219,7 @@
|
||||
"knw-e94982a2-358d-4f2f-af31-8ee0fcec07c6"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 526.1,
|
||||
"latency_ms": 261.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.1875,
|
||||
@@ -244,7 +244,7 @@
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 516.8,
|
||||
"latency_ms": 272.9,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.3333333333333333,
|
||||
@@ -269,7 +269,7 @@
|
||||
"bl-18a9d1e4-1484-474c-bf6b-c6173212181b"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 558.8,
|
||||
"latency_ms": 265.5,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.1111111111111111,
|
||||
@@ -294,7 +294,7 @@
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 513.4,
|
||||
"latency_ms": 271.1,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -315,11 +315,11 @@
|
||||
"bl-5b17bd3b-0c41-46cb-a710-6fa4429692ff",
|
||||
"bl-967536a0-d49d-44fb-8cfb-b31b40bcbfae",
|
||||
"bl-8b58d9bc-352b-4842-a7f8-a6254b5d1e25",
|
||||
"2c56a7a9-5323-4ce4-ba09-35836ba15d54",
|
||||
"?Q??m?;?u?'",
|
||||
"bl-39cec462-c80c-4970-a3aa-91fe83053bde"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 867.9,
|
||||
"latency_ms": 412.6,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.21428571428571427,
|
||||
@@ -338,13 +338,13 @@
|
||||
"?",
|
||||
"bl-ec84b63d-b278-4944-8d7f-4aa7a51c0315",
|
||||
"?",
|
||||
"830ca37a-d334-4e41-ba89-64893dc8d628",
|
||||
"mem-fb44a2fc-7405-41ff-87b3-84643ac07313",
|
||||
"?",
|
||||
"ce9636dc-85a5-4dae-9e07-74ea2fcc6307",
|
||||
"mem-a3c97012-5fa3-4915-a839-2c75c72005e0",
|
||||
"?"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 752.9,
|
||||
"latency_ms": 377.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -361,15 +361,15 @@
|
||||
"kn-58874a74-b96f-4883-9e08-45707f4bd3ee",
|
||||
"knw-d788a210-613b-4c49-9486-88bbc9d4716f",
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21",
|
||||
"66c63082-b4da-4aa1-8fee-848db8a83210",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"mem-a535f205-bc4c-4058-9171-6263c496044a",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd",
|
||||
"mem-0228da71-d7f7-4f3b-b7b3-c5eede42b62a",
|
||||
"ctx-4a41"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1591.4,
|
||||
"latency_ms": 758.8,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -387,14 +387,14 @@
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"mem-16efddd1-c43d-4a42-9d78-f54fb82bd277",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"f0eb6b13-909c-4674-91ef-23301d3abc8b",
|
||||
"7452eb8f-be01-4b55-aec1-ff0c29e790f6",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"30a44d10-2487-420e-bf61-3892e4343c92",
|
||||
"532277bf-2959-4beb-ae0d-b018c97678ee",
|
||||
"54608b69-78b6-4239-b60f-b8206cfecacc",
|
||||
"bfb5809e-d19a-4d3f-8c1a-796db622ad9d"
|
||||
"d4015bd7-c592-4ed8-8574-1f15ad37af75"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1660.1,
|
||||
"latency_ms": 741.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -407,19 +407,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "choosing an uncomfortable fact over a pleasant fiction",
|
||||
"returned": [
|
||||
"mem-ef878e30-5851-4e82-8588-745415108941",
|
||||
"tag-fiction",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd",
|
||||
"knw-4aebd815-4eaf-49d7-954b-03595f3d48be",
|
||||
"tag-fiction",
|
||||
"knw-8fd9836c-cc39-49df-8d61-babda626cc88",
|
||||
"mem-8d690e9d-a7e9-4062-b2f8-e2064294e463",
|
||||
"knw-e94982a2-358d-4f2f-af31-8ee0fcec07c6",
|
||||
"knw-8fd9836c-cc39-49df-8d61-babda626cc88",
|
||||
"mem-ce793303-c5a5-4586-a232-a3426edd9ec7",
|
||||
"knw-e94982a2-358d-4f2f-af31-8ee0fcec07c6",
|
||||
"mem-443bd012-fc9a-4088-b236-de5157a1ef92",
|
||||
"knw-d357b6bb-ad8a-4791-b516-426aea45fa5b",
|
||||
"mem-443bd012-fc9a-4088-b236-de5157a1ef92"
|
||||
"mem-ca4d6a34-d354-413f-bc86-126cc17ca81c"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1345.5,
|
||||
"latency_ms": 642.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -432,19 +432,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "a tight payload beats a bloated one",
|
||||
"returned": [
|
||||
"bl-8de20bcf-7149-4f48-b67c-e7f9758fd6e5",
|
||||
"bl-798d135f-3987-4ccd-8de6-70ca2f358337",
|
||||
"bl-680b24a9-edc3-4a9d-847a-bff0b46b568c",
|
||||
"knw-08559f5c-2306-4220-a146-398c74f1643c",
|
||||
"bl-164b520b-c503-49db-89f9-bd2fdf4215f5",
|
||||
"knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"1219277c-1b95-45ec-95a2-07b4a47a4d92",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"bl-798d135f-3987-4ccd-8de6-70ca2f358337",
|
||||
"08f0d1e2-8d0e-42e3-9f0a-8186ae31ec7e",
|
||||
"knw-08559f5c-2306-4220-a146-398c74f1643c",
|
||||
"4da5dbaf-46e5-4f3e-b474-f60d9f8241d3",
|
||||
"knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"mem-434be7c8-88cb-4039-b79a-1da4ac4de783",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"a708dd6e-fe73-4f2f-a21e-89daa0985487",
|
||||
"bl-79ce4464-5dd6-49bd-9b0c-9803549d0665"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1070.7,
|
||||
"latency_ms": 537.2,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -459,17 +459,17 @@
|
||||
"returned": [
|
||||
"bl-4476e856-c567-4b49-8ff7-d7dca3e5715e",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"a1000001-0000-0000-0000-000000000010",
|
||||
"a1000001-0000-0000-0000-000000000009",
|
||||
"bl-448bc514-c2f1-4520-a9b1-1f3a73678d26",
|
||||
"a1000001-0000-0000-0000-000000000012",
|
||||
"43098881-e044-482b-8e92-471728a8ba8b",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"mem-e5cc63c0-8701-49d6-855a-e387fe087771",
|
||||
"a1000001-0000-0000-0000-000000000001"
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"mem-75e490d1-f0a9-4b73-8cfc-8daecfaf6f38",
|
||||
"kn-58874a74-b96f-4883-9e08-45707f4bd3ee",
|
||||
"a1000001-0000-0000-0000-000000000010",
|
||||
"015644f5-8194-4af0-800d-dd4a0cd71396",
|
||||
"bfad516b-c306-4c4c-874a-a347c46c05c2",
|
||||
"kn-e0423482-cfa5-4796-8689-8495c93b66bc"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1395.8,
|
||||
"latency_ms": 725.1,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -486,15 +486,15 @@
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21",
|
||||
"knw-7902acca-604e-409b-8faf-ad85424211d0",
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"d6b12ecf-702b-4101-b1bb-09ed9b220b29",
|
||||
"345b6420-e004-4d2e-b55c-6a729393fa99",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"c608a095-c98b-4bfa-bfe1-1611c1320290",
|
||||
"mem-92a7fdc5-9dd0-48cf-a691-506058de3838",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea",
|
||||
"451ae007-4219-4096-89fe-fa2e045fbeb1",
|
||||
"a1000001-0000-0000-0000-000000000010",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1243.4,
|
||||
"latency_ms": 562.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -519,7 +519,7 @@
|
||||
"bl-ef2bac68-e119-4139-b529-c7a1404ae3ac"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1598.7,
|
||||
"latency_ms": 686.5,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -544,7 +544,7 @@
|
||||
"bl-286b562a-5299-40e0-a32a-afa9cbdfe995"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1379.6,
|
||||
"latency_ms": 584.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -557,19 +557,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "what shifts tells you where to cut a system apart",
|
||||
"returned": [
|
||||
"5a2c118a-87bd-4239-97a7-9e02c5991983",
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c",
|
||||
"mem-ef878e30-5851-4e82-8588-745415108941",
|
||||
"knw-12b4b913-7a25-4b0d-844c-504c01d6725e",
|
||||
"knw-723551f5-1950-42a3-8b89-b6a06913cef0",
|
||||
"knw-9707256e-ed44-4042-bd88-f90fa514e1cf",
|
||||
"kn-22d77abe-b3c5-42fd-afcd-dcb87d924929",
|
||||
"knw-0087493b-25cd-45b0-bf46-c078c5b49718",
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c",
|
||||
"bl-4c5b385e-135a-4663-8521-96af0b491121",
|
||||
"knw-12b4b913-7a25-4b0d-844c-504c01d6725e",
|
||||
"bl-2b00aeb0-c0fa-4a9f-8f30-4207e98b3d52",
|
||||
"knw-9707256e-ed44-4042-bd88-f90fa514e1cf",
|
||||
"34356a36-0df5-4020-8dcc-5e7a423f8d4c",
|
||||
"knw-0087493b-25cd-45b0-bf46-c078c5b49718",
|
||||
"mem-22f5f665-3ad2-4063-88b0-915849a795f5",
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1632.5,
|
||||
"latency_ms": 719.6,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -584,17 +584,17 @@
|
||||
"returned": [
|
||||
"bl-8dd70cac-866d-4ff2-b9fe-b4b3c5f094bb",
|
||||
"mem-b43f6ef4-2f5a-418d-b5ce-3f21520cf6b8",
|
||||
"kn-58874a74-b96f-4883-9e08-45707f4bd3ee",
|
||||
"a0edad47-5f77-4fc3-a546-1e85f8c68e77",
|
||||
"knw-7902acca-604e-409b-8faf-ad85424211d0",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea",
|
||||
"a1000001-0000-0000-0000-000000000001",
|
||||
"8cbb60c5-4999-4ec1-8682-2592aedc4249",
|
||||
"96497334-b18f-495c-9228-eeb8182bdc38",
|
||||
"kn-58874a74-b96f-4883-9e08-45707f4bd3ee",
|
||||
"bl-1b58b05c-9305-4f06-a586-a08c96008027",
|
||||
"mem-024598a9-ed2e-4eeb-b1e1-5410856ff132",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea"
|
||||
"ctx-4a41",
|
||||
"mem-5708f4c9-3d61-4182-8543-2843698931e6"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1491.9,
|
||||
"latency_ms": 634.6,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -607,19 +607,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "loved for the unedited self and not the polished exterior",
|
||||
"returned": [
|
||||
"27e1b1a4-ad0b-49d9-812f-fedf43b8aabe",
|
||||
"knw-f9ce17a7-17fc-431f-8f23-695b670ec4fa",
|
||||
"bl-87c93185-b2bf-40af-ae23-3c830c007abf",
|
||||
"knw-2c46cfb4-6d4e-4822-8a1a-7d743c1e4329",
|
||||
"077d064f-3489-4c05-9aca-3782f96b51db",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"knw-f9ce17a7-17fc-431f-8f23-695b670ec4fa",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"knw-2c46cfb4-6d4e-4822-8a1a-7d743c1e4329",
|
||||
"27e1b1a4-ad0b-49d9-812f-fedf43b8aabe",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"bl-87c93185-b2bf-40af-ae23-3c830c007abf",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"75e036d3-c170-4e3f-acc2-e456a6850ee2",
|
||||
"fce2792a-53fc-4d4a-be3b-42bd6ceb1ba7",
|
||||
"a1000001-0000-0000-0000-000000000001"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1535.5,
|
||||
"latency_ms": 674.2,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -638,13 +638,13 @@
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"mem-5624ec9d-62ba-4aba-8a3d-6afec6c09dd4",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"mem-833dbbcd-2400-4594-bb35-93b023049ac0",
|
||||
"mem-a16deccb-16a7-419c-a013-ff824a4daa15",
|
||||
"a1000001-0000-0000-0000-000000000009",
|
||||
"mem-759e78ca-5394-4244-aa39-1c1468bc5f3e",
|
||||
"mem-833dbbcd-2400-4594-bb35-93b023049ac0",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1249.8,
|
||||
"latency_ms": 571.6,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -657,19 +657,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "a childhood offering no solid foundation to inherit",
|
||||
"returned": [
|
||||
"bl-3f57bc69-7285-4f4a-a861-2de52efca058",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"bl-0d8c5dfa-e163-4fef-a58b-56b0d076c5a8",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"mem-b99efff0-00e6-40c8-9c5b-730330eef33b",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"knw-2c46cfb4-6d4e-4822-8a1a-7d743c1e4329",
|
||||
"knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"knw-23c27d3b-e0d2-43a8-a80c-0a44477ae18a",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"kn-5b606390-a52d-4ca2-8e0e-eba141d13440",
|
||||
"tag-childhood"
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"tag-childhood",
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1351.0,
|
||||
"latency_ms": 603.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -690,11 +690,11 @@
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21",
|
||||
"766de879-f9d0-4a07-b6df-b43ee13763d8",
|
||||
"kn-e0423482-cfa5-4796-8689-8495c93b66bc",
|
||||
"3499d5da-0e9c-4de4-9bc4-8941b14e0b1f",
|
||||
"efe53612-6914-4936-8e3b-1e694eb174e5",
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1438.4,
|
||||
"latency_ms": 656.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.18181818181818182,
|
||||
@@ -719,7 +719,7 @@
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1110.1,
|
||||
"latency_ms": 536.9,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.07692307692307693,
|
||||
@@ -744,7 +744,7 @@
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1186.1,
|
||||
"latency_ms": 562.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.18181818181818182,
|
||||
@@ -769,7 +769,7 @@
|
||||
"mem-ab34c2f7-3243-424b-affa-25555f6cf9cc"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1193.1,
|
||||
"latency_ms": 556.6,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -794,7 +794,7 @@
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1201.5,
|
||||
"latency_ms": 542.6,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.09090909090909091,
|
||||
@@ -808,18 +808,18 @@
|
||||
"query": "man of the house six years old expectation",
|
||||
"returned": [
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"knw-729fc901-8335-44c4-9f3a-b150b4aa0915",
|
||||
"knw-d357b6bb-ad8a-4791-b516-426aea45fa5b",
|
||||
"knw-528dbc37-eabc-4b75-a7a5-65bf38d6018a",
|
||||
"knw-35940684-abc4-42f0-b942-818f66b1f69a",
|
||||
"knw-d357b6bb-ad8a-4791-b516-426aea45fa5b",
|
||||
"knw-473f3f24-20f6-4f39-8589-3709538eb6ac",
|
||||
"?Z?<S???K ?",
|
||||
"mem-a0b7cfda-bc9e-4f40-b9a9-1722cf3f8263",
|
||||
"knw-7902acca-604e-409b-8faf-ad85424211d0",
|
||||
"'?T?a\"B~-?8",
|
||||
"knw-35940684-abc4-42f0-b942-818f66b1f69a",
|
||||
"4f698ae6-c40e-464e-9798-50350991a188",
|
||||
"719aa819-00a9-4f4b-a857-4f9fe5ad44d7",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1424.8,
|
||||
"latency_ms": 683.5,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -833,7 +833,7 @@
|
||||
"query": "zqxjvw plimforth grebulon",
|
||||
"returned": [],
|
||||
"n_returned": 0,
|
||||
"latency_ms": 705.7,
|
||||
"latency_ms": 350.4,
|
||||
"error": null,
|
||||
"clean": true,
|
||||
"false_positives": 0
|
||||
@@ -844,7 +844,7 @@
|
||||
"query": "flarnbistle quommetry",
|
||||
"returned": [],
|
||||
"n_returned": 0,
|
||||
"latency_ms": 484.4,
|
||||
"latency_ms": 258.4,
|
||||
"error": null,
|
||||
"clean": true,
|
||||
"false_positives": 0
|
||||
@@ -853,23 +853,12 @@
|
||||
"id": "q35",
|
||||
"category": "nonsense",
|
||||
"query": "xxqzzt vurblenacht throom",
|
||||
"returned": [
|
||||
"bl-4476e856-c567-4b49-8ff7-d7dca3e5715e",
|
||||
"?V?",
|
||||
"knw-6b48dce2-f21c-452a-9db5-4e6aa61c87ca",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"?m?\\}Q??6??",
|
||||
"8cbb60c5-4999-4ec1-8682-2592aedc4249",
|
||||
"kn-66a21179-2adc-4b19-a109-880cf4674d7d",
|
||||
"?m?\\}Q??6??",
|
||||
"knw-723551f5-1950-42a3-8b89-b6a06913cef0",
|
||||
"kn-333542cb-6dab-4662-9725-bf7440d28bf7"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 740.2,
|
||||
"returned": [],
|
||||
"n_returned": 0,
|
||||
"latency_ms": 348.4,
|
||||
"error": null,
|
||||
"clean": false,
|
||||
"false_positives": 10
|
||||
"clean": true,
|
||||
"false_positives": 0
|
||||
},
|
||||
{
|
||||
"id": "q36",
|
||||
@@ -882,13 +871,13 @@
|
||||
"kn-b7e98d63-8b83-4911-b4d0-990602a7f575",
|
||||
"tag-__darma____cgi____patents____self-improvement____character-preservation____autonomous____kotlin____architecture__",
|
||||
"knw-e047bb42-dc5b-4383-9e88-e508dc03abe3",
|
||||
"mem-e6327f52-2bda-4ce7-9471-2fffd1e172de",
|
||||
"mem-c17aefb1-38b5-4ced-af50-fe524127e1a4",
|
||||
"bl-5b17bd3b-0c41-46cb-a710-6fa4429692ff",
|
||||
"mem-82b93b21-a865-410f-9ec1-fc54121d9bb5",
|
||||
"bl-145a0985-2382-400f-a7c5-c335c5e30a72"
|
||||
"bl-145a0985-2382-400f-a7c5-c335c5e30a72",
|
||||
"mem-82b93b21-a865-410f-9ec1-fc54121d9bb5"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1307.7,
|
||||
"latency_ms": 664.5,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -913,10 +902,10 @@
|
||||
"a1000001-0000-0000-0000-000000000002",
|
||||
"3cf706a1-3825-45d8-b0a9-06cae6cdf5b8",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"7ac62daa-2eac-4c7a-a97e-e4203fc1b57b"
|
||||
"de3b6428-b76c-4c44-90e0-bf1dd6998027"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1669.8,
|
||||
"latency_ms": 747.3,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -944,7 +933,7 @@
|
||||
"mem-3a2cf162-d93b-4f29-86f2-5066fb7fe1f5"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1018.2,
|
||||
"latency_ms": 504.2,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
+139
-117
@@ -1,37 +1,37 @@
|
||||
{
|
||||
"label": "claim24",
|
||||
"soul_binary": "/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad/soul-claim24",
|
||||
"soul_md5": "676ebffb91f00046dcea895f5aa7efba",
|
||||
"label": "wsclaim24",
|
||||
"soul_binary": "/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad/soul-wsclaim24",
|
||||
"soul_md5": "a377d9c0e5282e842ed98384c8b50d2c",
|
||||
"corpus": "/Users/timlingo/neuron-eval-corpora/snapshot-pre-repair-20260806-embedded.json",
|
||||
"corpus_nodes": 78768,
|
||||
"corpus_edges": 14214,
|
||||
"gold_set": "/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/gold_set.json",
|
||||
"gold_set": "/Users/timlingo/Development/neuron-technologies/_wt-eval/tools/retrieval-eval/gold_set.json",
|
||||
"limit": 10,
|
||||
"port": 7893,
|
||||
"wall_clock_s": 52.3,
|
||||
"child_pid": 92441,
|
||||
"wall_clock_s": 29.9,
|
||||
"child_pid": 99726,
|
||||
"child_confirmed_dead": true,
|
||||
"aggregate": {
|
||||
"n_queries": 38,
|
||||
"n_scored": 35,
|
||||
"hit@5": 0.7428571428571429,
|
||||
"recall@5": 0.5768475572047,
|
||||
"recall@10": 0.6537440733869305,
|
||||
"recall@10": 0.6563414759843332,
|
||||
"precision@5": 0.19428571428571437,
|
||||
"mrr@10": 0.5021428571428572,
|
||||
"nonsense_clean": "2/3",
|
||||
"mrr@10": 0.5026530612244898,
|
||||
"nonsense_clean": "0/3",
|
||||
"superseded_outranks": "2/3",
|
||||
"latency_ms_p50": 1173.7,
|
||||
"latency_ms_p95": 1623.0,
|
||||
"latency_ms_max": 1647.9,
|
||||
"latency_ms_p50": 524.8,
|
||||
"latency_ms_p95": 738.7,
|
||||
"latency_ms_max": 755.8,
|
||||
"errors": 0,
|
||||
"by_category": {
|
||||
"associative": {
|
||||
"n": 6,
|
||||
"hit@5": 0.5,
|
||||
"recall@5": 0.07575757575757576,
|
||||
"recall@10": 0.12121212121212122,
|
||||
"mrr@10": 0.22916666666666666
|
||||
"recall@10": 0.13636363636363635,
|
||||
"mrr@10": 0.23214285714285712
|
||||
},
|
||||
"exact_rare": {
|
||||
"n": 6,
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"nonsense": {
|
||||
"n": 3,
|
||||
"clean": 2,
|
||||
"avg_false_positives": 3.3333333333333335
|
||||
"clean": 0,
|
||||
"avg_false_positives": 10.0
|
||||
},
|
||||
"paraphrase": {
|
||||
"n": 13,
|
||||
@@ -87,7 +87,7 @@
|
||||
"696e609c-da7a-4394-8a0c-106ba07dc6c3"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 284.2,
|
||||
"latency_ms": 173.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -112,7 +112,7 @@
|
||||
"ctx-fae1"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 338.1,
|
||||
"latency_ms": 158.1,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -137,7 +137,7 @@
|
||||
"x??I?cB?]p?"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 300.4,
|
||||
"latency_ms": 160.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -162,7 +162,7 @@
|
||||
"mem-2d1ea831-cccd-4f0f-86b9-2cbbc89dc3e0"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 285.2,
|
||||
"latency_ms": 158.0,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -187,7 +187,7 @@
|
||||
"bl-2632242e-80b1-4d88-8368-7065b5de5b34"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 318.5,
|
||||
"latency_ms": 170.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -212,7 +212,7 @@
|
||||
"??"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 331.3,
|
||||
"latency_ms": 175.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -237,7 +237,7 @@
|
||||
"bl-39dad13d-7105-4049-8224-dc3c34fdb1f3"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 582.9,
|
||||
"latency_ms": 293.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -257,12 +257,12 @@
|
||||
"mem-c9bec303-a638-4a11-a490-f38410d448cf",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea",
|
||||
"knw-f671966c-3387-4848-abca-b5deec122e00",
|
||||
"2795fdbb-ee2a-4009-aa30-3f1c25b6e77c",
|
||||
"7cf3f825-d7b6-4864-b0ae-52939cf1ae84",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"knw-4aebd815-4eaf-49d7-954b-03595f3d48be"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 520.6,
|
||||
"latency_ms": 251.2,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.1875,
|
||||
@@ -287,7 +287,7 @@
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 531.5,
|
||||
"latency_ms": 264.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.2222222222222222,
|
||||
@@ -312,7 +312,7 @@
|
||||
"tag-harmonic-framework"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 502.8,
|
||||
"latency_ms": 262.5,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.1111111111111111,
|
||||
@@ -337,7 +337,7 @@
|
||||
"??_/Pr?????"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 506.1,
|
||||
"latency_ms": 257.7,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -358,11 +358,11 @@
|
||||
"bl-2515d870-e35e-443b-ba20-5150bbc73fed",
|
||||
"bl-5b17bd3b-0c41-46cb-a710-6fa4429692ff",
|
||||
"bl-a0982e7c-e165-4da3-a11d-619fa0b535b0",
|
||||
"2c56a7a9-5323-4ce4-ba09-35836ba15d54",
|
||||
"?Q??m?;?u?'",
|
||||
"knw-cf13b883-d947-4cf8-b86b-cd9c6f0748d6"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 861.8,
|
||||
"latency_ms": 393.5,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.21428571428571427,
|
||||
@@ -381,13 +381,13 @@
|
||||
"7774a16c-1027-4e3b-a21e-67f1f95a4acd",
|
||||
"?",
|
||||
"bl-3c719d9a-cba1-47f4-b097-52cdeccc7c0d",
|
||||
"830ca37a-d334-4e41-ba89-64893dc8d628",
|
||||
"mem-fb44a2fc-7405-41ff-87b3-84643ac07313",
|
||||
"?",
|
||||
"ce9636dc-85a5-4dae-9e07-74ea2fcc6307",
|
||||
"mem-ce88adf9-3f3c-47ac-a7d3-83af7b290e68",
|
||||
"?"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 758.5,
|
||||
"latency_ms": 333.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -406,13 +406,13 @@
|
||||
"knw-d788a210-613b-4c49-9486-88bbc9d4716f",
|
||||
"art-4a99aa1a-489b-4b43-958b-25217adb1aad",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"66c63082-b4da-4aa1-8fee-848db8a83210",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"mem-a535f205-bc4c-4058-9171-6263c496044a"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1590.9,
|
||||
"latency_ms": 755.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -429,15 +429,15 @@
|
||||
"art-79042b8b-6192-440f-90b0-60708f7e6325",
|
||||
"mem-16efddd1-c43d-4a42-9d78-f54fb82bd277",
|
||||
"daf9d558-2265-49b0-b4fb-be0b80f3cdb1",
|
||||
"863bfd72-50d2-487f-85ae-ecd48e2a501f",
|
||||
"bfb5809e-d19a-4d3f-8c1a-796db622ad9d",
|
||||
"art-ddfcd045-2c3b-4a1e-9966-fec5ce44e1dd",
|
||||
"5c1c3404-ad4c-49f1-8c0c-81262812731e",
|
||||
"f3364a57-956a-4e78-a500-b3b66a4e3066",
|
||||
"15a90710-5372-4d3d-aee5-2d7287d2a492",
|
||||
"465fa29f-1ce3-4769-962a-1c32dfed8347",
|
||||
"341afa66-6a49-43fe-9d5b-3f1032bb6904",
|
||||
"mem-da21c52c-04a5-4f92-8fba-f10aac47e027"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1647.9,
|
||||
"latency_ms": 720.3,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -459,10 +459,10 @@
|
||||
"mem-d1cfde0a-37f1-4bff-9a06-8eddbbf259f6",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"knw-f671966c-3387-4848-abca-b5deec122e00",
|
||||
"mem-16efddd1-c43d-4a42-9d78-f54fb82bd277"
|
||||
"tag-factions"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1338.6,
|
||||
"latency_ms": 616.0,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -475,19 +475,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "a tight payload beats a bloated one",
|
||||
"returned": [
|
||||
"bl-8de20bcf-7149-4f48-b67c-e7f9758fd6e5",
|
||||
"bl-680b24a9-edc3-4a9d-847a-bff0b46b568c",
|
||||
"mem-628437a6-47b0-4d81-8112-7e78499723d5",
|
||||
"bl-798d135f-3987-4ccd-8de6-70ca2f358337",
|
||||
"bl-680b24a9-edc3-4a9d-847a-bff0b46b568c",
|
||||
"08f0d1e2-8d0e-42e3-9f0a-8186ae31ec7e",
|
||||
"knw-12b4b913-7a25-4b0d-844c-504c01d6725e",
|
||||
"knw-08559f5c-2306-4220-a146-398c74f1643c",
|
||||
"bl-164b520b-c503-49db-89f9-bd2fdf4215f5",
|
||||
"4da5dbaf-46e5-4f3e-b474-f60d9f8241d3",
|
||||
"o#?CW????y:",
|
||||
"knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"1219277c-1b95-45ec-95a2-07b4a47a4d92"
|
||||
"mem-434be7c8-88cb-4039-b79a-1da4ac4de783"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1060.5,
|
||||
"latency_ms": 518.5,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -506,13 +506,13 @@
|
||||
"a1000001-0000-0000-0000-000000000010",
|
||||
"bl-9ce4128a-9436-4b06-82bc-8a6faafa81e0",
|
||||
"a1000001-0000-0000-0000-000000000009",
|
||||
"43098881-e044-482b-8e92-471728a8ba8b",
|
||||
"mem-32203649-3213-4d6d-86fd-3d657ac70d77",
|
||||
"? t?'?B?+??",
|
||||
"a1000001-0000-0000-0000-000000000012",
|
||||
"bl-448bc514-c2f1-4520-a9b1-1f3a73678d26"
|
||||
"mem-da21c52c-04a5-4f92-8fba-f10aac47e027"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1388.8,
|
||||
"latency_ms": 742.9,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -534,10 +534,10 @@
|
||||
"345b6420-e004-4d2e-b55c-6a729393fa99",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"74f4776a-d0ea-44e4-b94f-7c87d0179ef3"
|
||||
"mem-92a7fdc5-9dd0-48cf-a691-506058de3838"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1231.7,
|
||||
"latency_ms": 549.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -562,7 +562,7 @@
|
||||
"bl-ef2bac68-e119-4139-b529-c7a1404ae3ac"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1590.7,
|
||||
"latency_ms": 682.4,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -587,7 +587,7 @@
|
||||
"bl-56a50e97-9a85-4e81-b6c9-3e3d26482f1d"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1380.0,
|
||||
"latency_ms": 575.0,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -600,19 +600,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "what shifts tells you where to cut a system apart",
|
||||
"returned": [
|
||||
"5a2c118a-87bd-4239-97a7-9e02c5991983",
|
||||
"knw-723551f5-1950-42a3-8b89-b6a06913cef0",
|
||||
"bl-06c13965-082b-417d-9561-93d6e958ae5d",
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c",
|
||||
"knw-723551f5-1950-42a3-8b89-b6a06913cef0",
|
||||
"bl-4c5b385e-135a-4663-8521-96af0b491121",
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"knw-12b4b913-7a25-4b0d-844c-504c01d6725e",
|
||||
"kn-22d77abe-b3c5-42fd-afcd-dcb87d924929",
|
||||
"bl-2b00aeb0-c0fa-4a9f-8f30-4207e98b3d52",
|
||||
"mem-7b74cac0-905f-4c35-9688-fbcce105a177",
|
||||
"knw-9707256e-ed44-4042-bd88-f90fa514e1cf",
|
||||
"bl-4c5b385e-135a-4663-8521-96af0b491121"
|
||||
"34356a36-0df5-4020-8dcc-5e7a423f8d4c"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1623.0,
|
||||
"latency_ms": 711.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -627,17 +627,17 @@
|
||||
"returned": [
|
||||
"bl-8dd70cac-866d-4ff2-b9fe-b4b3c5f094bb",
|
||||
"mem-b43f6ef4-2f5a-418d-b5ce-3f21520cf6b8",
|
||||
"8cbb60c5-4999-4ec1-8682-2592aedc4249",
|
||||
"a0edad47-5f77-4fc3-a546-1e85f8c68e77",
|
||||
"knw-7902acca-604e-409b-8faf-ad85424211d0",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea",
|
||||
"a1000001-0000-0000-0000-000000000001",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"96497334-b18f-495c-9228-eeb8182bdc38",
|
||||
"bl-1b58b05c-9305-4f06-a586-a08c96008027",
|
||||
"mem-024598a9-ed2e-4eeb-b1e1-5410856ff132",
|
||||
"kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c",
|
||||
"knw-ed33e669-0790-44cb-a036-958d605c6fea"
|
||||
"mem-5708f4c9-3d61-4182-8543-2843698931e6"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1471.0,
|
||||
"latency_ms": 616.7,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -650,19 +650,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "loved for the unedited self and not the polished exterior",
|
||||
"returned": [
|
||||
"27e1b1a4-ad0b-49d9-812f-fedf43b8aabe",
|
||||
"077d064f-3489-4c05-9aca-3782f96b51db",
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd",
|
||||
"knw-2c46cfb4-6d4e-4822-8a1a-7d743c1e4329",
|
||||
"bl-87c93185-b2bf-40af-ae23-3c830c007abf",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"knw-c72597c5-c23d-4c08-8e9e-996dadf26a99",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"077d064f-3489-4c05-9aca-3782f96b51db",
|
||||
"27e1b1a4-ad0b-49d9-812f-fedf43b8aabe",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930"
|
||||
"fce2792a-53fc-4d4a-be3b-42bd6ceb1ba7"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1516.6,
|
||||
"latency_ms": 658.4,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -687,7 +687,7 @@
|
||||
"mem-a16deccb-16a7-419c-a013-ff824a4daa15"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1224.2,
|
||||
"latency_ms": 566.3,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -700,19 +700,19 @@
|
||||
"category": "paraphrase",
|
||||
"query": "a childhood offering no solid foundation to inherit",
|
||||
"returned": [
|
||||
"bl-3f57bc69-7285-4f4a-a861-2de52efca058",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"bl-0d8c5dfa-e163-4fef-a58b-56b0d076c5a8",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"mem-b99efff0-00e6-40c8-9c5b-730330eef33b",
|
||||
"kn-a99cefe3-5e83-4050-98d8-6c69f57c7c71",
|
||||
"knw-2c46cfb4-6d4e-4822-8a1a-7d743c1e4329",
|
||||
"knw-f6ed7d00-bf7d-42ce-9e40-77cf3406e918",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"knw-23c27d3b-e0d2-43a8-a80c-0a44477ae18a",
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"kn-5b606390-a52d-4ca2-8e0e-eba141d13440",
|
||||
"kn-f230b362-b201-4402-9833-4160c89ab3d4",
|
||||
"tag-childhood",
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1335.9,
|
||||
"latency_ms": 589.6,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -733,11 +733,11 @@
|
||||
"766de879-f9d0-4a07-b6df-b43ee13763d8",
|
||||
"mem-5f76880b-bafb-4716-8e15-90f8ef59bebc",
|
||||
"kn-e0423482-cfa5-4796-8689-8495c93b66bc",
|
||||
"3499d5da-0e9c-4de4-9bc4-8941b14e0b1f",
|
||||
"28ae74a1-9d47-4874-9279-43c1f90c0f64",
|
||||
"mem-bce80169-2d46-4b3e-9ebe-8498e26f0a89"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1421.9,
|
||||
"latency_ms": 627.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.18181818181818182,
|
||||
@@ -762,7 +762,7 @@
|
||||
"5eb24168-c2d3-4842-85db-2070e0e14923"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1102.3,
|
||||
"latency_ms": 524.3,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -787,7 +787,7 @@
|
||||
"?V?"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1173.7,
|
||||
"latency_ms": 526.0,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.18181818181818182,
|
||||
@@ -812,7 +812,7 @@
|
||||
"???I?cB?Zx?"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1187.7,
|
||||
"latency_ms": 526.0,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -837,7 +837,7 @@
|
||||
"kn-13f60407-7b70-4db1-964f-ea1f8196efbd"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1192.0,
|
||||
"latency_ms": 524.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 0.09090909090909091,
|
||||
@@ -853,63 +853,85 @@
|
||||
"kn-eb1b9e18-3dc6-4b9b-9cc6-86e0ae6b6be8",
|
||||
"mem-5305665c-6b5b-45b7-89ae-5d2fb0b896ac",
|
||||
"4f698ae6-c40e-464e-9798-50350991a188",
|
||||
"knw-35940684-abc4-42f0-b942-818f66b1f69a",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"?Z?<S???K ?",
|
||||
"mem-a0b7cfda-bc9e-4f40-b9a9-1722cf3f8263",
|
||||
"kn-6061318f-046b-4935-907d-8eafdce14930",
|
||||
"knw-35940684-abc4-42f0-b942-818f66b1f69a",
|
||||
"kn-db9f141b-dbe3-4037-92e0-4bb9be0e5e6e",
|
||||
"'?T?a\"B~-?8",
|
||||
"mem-d396d789-0f7f-4366-a008-5d8801c8f2eb"
|
||||
"719aa819-00a9-4f4b-a857-4f9fe5ad44d7",
|
||||
"mem-d396d789-0f7f-4366-a008-5d8801c8f2eb",
|
||||
"kn-0bb4f021-56de-4947-a35b-a37209e7ba21"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1425.3,
|
||||
"latency_ms": 668.9,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
"recall@10": 0.09090909090909091,
|
||||
"recall@10": 0.18181818181818182,
|
||||
"precision@5": 0.0,
|
||||
"mrr@10": 0.125
|
||||
"mrr@10": 0.14285714285714285
|
||||
},
|
||||
{
|
||||
"id": "q33",
|
||||
"category": "nonsense",
|
||||
"query": "zqxjvw plimforth grebulon",
|
||||
"returned": [],
|
||||
"n_returned": 0,
|
||||
"latency_ms": 714.9,
|
||||
"returned": [
|
||||
"$\\?l????T?",
|
||||
"project-Deploy_Ollama_on_Legion_k8s__Traefik_route_at_ollama_neuralplatform_ai__8B_model_seeded_",
|
||||
"c??Z??I?E??",
|
||||
"?^?l????K8?",
|
||||
"${????X?6#E",
|
||||
"???Z??I?b??",
|
||||
"??m???|Y`0?",
|
||||
"??m???|Y`0?",
|
||||
"??m???|Y`0?",
|
||||
"=?m???|YH??"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 338.4,
|
||||
"error": null,
|
||||
"clean": true,
|
||||
"false_positives": 0
|
||||
"clean": false,
|
||||
"false_positives": 10
|
||||
},
|
||||
{
|
||||
"id": "q34",
|
||||
"category": "nonsense",
|
||||
"query": "flarnbistle quommetry",
|
||||
"returned": [],
|
||||
"n_returned": 0,
|
||||
"latency_ms": 496.0,
|
||||
"returned": [
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 248.9,
|
||||
"error": null,
|
||||
"clean": true,
|
||||
"false_positives": 0
|
||||
"clean": false,
|
||||
"false_positives": 10
|
||||
},
|
||||
{
|
||||
"id": "q35",
|
||||
"category": "nonsense",
|
||||
"query": "xxqzzt vurblenacht throom",
|
||||
"returned": [
|
||||
"bl-4476e856-c567-4b49-8ff7-d7dca3e5715e",
|
||||
"?V?",
|
||||
"knw-6b48dce2-f21c-452a-9db5-4e6aa61c87ca",
|
||||
"knw-920c891f-bb8c-48c4-9afc-018ef12dcdc4",
|
||||
"?m?\\}Q??6??",
|
||||
"8cbb60c5-4999-4ec1-8682-2592aedc4249",
|
||||
"kn-66a21179-2adc-4b19-a109-880cf4674d7d",
|
||||
"?m?\\}Q??6??",
|
||||
"knw-723551f5-1950-42a3-8b89-b6a06913cef0",
|
||||
"kn-333542cb-6dab-4662-9725-bf7440d28bf7"
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??",
|
||||
"?m?\\}Q??6??"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 729.4,
|
||||
"latency_ms": 338.6,
|
||||
"error": null,
|
||||
"clean": false,
|
||||
"false_positives": 10
|
||||
@@ -925,13 +947,13 @@
|
||||
"kn-b7e98d63-8b83-4911-b4d0-990602a7f575",
|
||||
"tag-__darma____cgi____patents____self-improvement____character-preservation____autonomous____kotlin____architecture__",
|
||||
"knw-e047bb42-dc5b-4383-9e88-e508dc03abe3",
|
||||
"mem-e6327f52-2bda-4ce7-9471-2fffd1e172de",
|
||||
"mem-c17aefb1-38b5-4ced-af50-fe524127e1a4",
|
||||
"bl-145a0985-2382-400f-a7c5-c335c5e30a72",
|
||||
"mem-82b93b21-a865-410f-9ec1-fc54121d9bb5",
|
||||
"bl-5b17bd3b-0c41-46cb-a710-6fa4429692ff"
|
||||
"bl-5b17bd3b-0c41-46cb-a710-6fa4429692ff",
|
||||
"mem-82b93b21-a865-410f-9ec1-fc54121d9bb5"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1306.9,
|
||||
"latency_ms": 644.8,
|
||||
"error": null,
|
||||
"hit@5": 1.0,
|
||||
"recall@5": 1.0,
|
||||
@@ -940,7 +962,7 @@
|
||||
"mrr@10": 0.5,
|
||||
"outranks": true,
|
||||
"rank_correct": 2,
|
||||
"rank_stale": 10
|
||||
"rank_stale": 9
|
||||
},
|
||||
{
|
||||
"id": "q37",
|
||||
@@ -956,10 +978,10 @@
|
||||
"13705072-4515-4124-963d-083af490494f",
|
||||
"3cf706a1-3825-45d8-b0a9-06cae6cdf5b8",
|
||||
"kn-5de5a9ac-fd15-45ab-bf18-77566781cf40",
|
||||
"96eb59a0-5603-4c9e-835c-1de53f2319bc"
|
||||
"4f225001-3a51-4a68-8d38-c8ecac3412de"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1647.4,
|
||||
"latency_ms": 738.7,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -987,7 +1009,7 @@
|
||||
"mem-3a2cf162-d93b-4f29-86f2-5066fb7fe1f5"
|
||||
],
|
||||
"n_returned": 10,
|
||||
"latency_ms": 1003.4,
|
||||
"latency_ms": 498.6,
|
||||
"error": null,
|
||||
"hit@5": 0.0,
|
||||
"recall@5": 0.0,
|
||||
@@ -1,135 +0,0 @@
|
||||
import numpy as np, json, urllib.request, collections, math, re, sys, time
|
||||
SP="/private/tmp/claude-501/-Users-timlingo/82369039-a20e-4b5a-8a5e-28234a57b996/scratchpad"
|
||||
EV="/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/"
|
||||
np.seterr(all='ignore'); t0=time.time()
|
||||
M=np.load(SP+'/emb.npy'); eids=open(SP+'/ids.txt',encoding='utf-8',errors='surrogateescape').read().split('\n')
|
||||
eidx={k:i for i,k in enumerate(eids)}
|
||||
d=json.load(open('/Users/timlingo/neuron-memory-backups/snapshot-pre-repair-20260806.json',encoding='utf-8',errors='surrogateescape'))
|
||||
STRUCT={"identity","contains","superseded_by","references","embodies","demonstrated_by","canonical-self","depends_on","currently_holds","activates"}
|
||||
adj=collections.defaultdict(list)
|
||||
for e in d['edges']:
|
||||
if e.get('relation') not in STRUCT: continue
|
||||
w=float(e.get('weight') or 0.0)
|
||||
adj[e['from_id']].append((e['to_id'],w)); adj[e['to_id']].append((e['from_id'],w))
|
||||
nodes=d['nodes']; N={n['id']:n for n in nodes}
|
||||
PRINT=re.compile(r'^[\x20-\x7e]+$')
|
||||
ids=[];hay=[];dl=[];sal=[];addr=[]
|
||||
for n in nodes:
|
||||
i=n.get('id') or ''
|
||||
h=((n.get('content') or '')+'\x00'+(n.get('label') or '')+'\x00'+(n.get('tags') or '')).lower()
|
||||
ids.append(i);hay.append(h);dl.append(len(h));sal.append(float(n.get('salience') or 0.0));addr.append(bool(PRINT.match(i)))
|
||||
del d
|
||||
NN=len(ids); avgdl=sum(dl)/NN
|
||||
gold={q['id']:q for q in json.load(open(EV+"gold_set.json"))['queries']}
|
||||
CACHE={}
|
||||
def emb(t):
|
||||
if t in CACHE: return CACHE[t]
|
||||
b=json.dumps({"model":"nomic-embed-text","prompt":t}).encode()
|
||||
r=urllib.request.Request("http://127.0.0.1:11434/api/embeddings",data=b,headers={"Content-Type":"application/json"})
|
||||
v=np.array(json.load(urllib.request.urlopen(r,timeout=60))["embedding"],dtype=np.float32)
|
||||
v=v/(np.linalg.norm(v)+1e-9); CACHE[t]=v; return v
|
||||
K1,B=1.2,0.75
|
||||
LEXC={}
|
||||
def lexleg(qid,query,lim=10):
|
||||
if qid in LEXC: return LEXC[qid]
|
||||
toks=[]
|
||||
for w in query.split():
|
||||
wl=w.lower()
|
||||
if wl not in toks: toks.append(wl)
|
||||
nt=len(toks); masks=[]; df=[0]*nt
|
||||
for i in range(NN):
|
||||
if not addr[i]: continue
|
||||
h=hay[i]; m=0; sc=0
|
||||
for t in range(nt):
|
||||
if toks[t] in h: m|=(1<<t); sc+=1; df[t]+=1
|
||||
if sc: masks.append((i,m))
|
||||
idf=[math.log(1.0+(NN-df[t]+0.5)/(df[t]+0.5)) for t in range(nt)]
|
||||
scored=[]
|
||||
for i,m in masks:
|
||||
norm=1.0-B+B*dl[i]/avgdl; s=0.0
|
||||
for t in range(nt):
|
||||
if m&(1<<t): s+=idf[t]*(K1+1.0)/(1.0+K1*norm)
|
||||
scored.append((s,i))
|
||||
scored.sort(key=lambda x:(-x[0],-sal[x[1]]))
|
||||
LEXC[qid]=([ids[i] for s,i in scored[:lim]], len(masks))
|
||||
return LEXC[qid]
|
||||
FIRE=0.02; DECAY=0.7; DEPTH=2; SEED_MIN=0.60; ASSOC_MAX=64
|
||||
def assoc(seeds, s, use_cos, order):
|
||||
act={x:1.0 for x in seeds}; seen={x:2 for x in seeds}
|
||||
Q=[(x,0) for x in seeds]; h=0
|
||||
while h<len(Q):
|
||||
cur,hop=Q[h]; h+=1
|
||||
if hop>=DEPTH: continue
|
||||
p=act[cur]
|
||||
for oid,w in adj.get(cur,()):
|
||||
n=N.get(oid)
|
||||
if not n or n.get('node_type') in ('Tag','InternalStateEvent'): continue
|
||||
c=1.0
|
||||
if use_cos:
|
||||
j=eidx.get(oid)
|
||||
c=max(0.0,float(s[j])) if j is not None else 0.0
|
||||
na=p*w*DECAY*float(n.get('salience') or 0.0)*c
|
||||
if na<FIRE: continue
|
||||
if oid in seen and na<=act.get(oid,0): continue
|
||||
act[oid]=na
|
||||
if oid not in seen: seen[oid]=1
|
||||
Q.append((oid,hop+1))
|
||||
out=[]
|
||||
for k,v in seen.items():
|
||||
if v!=1 or k not in eidx: continue
|
||||
c=float(s[eidx[k]])
|
||||
if c<=0: continue
|
||||
out.append((act[k] if order=='act' else c,k))
|
||||
out.sort(reverse=True)
|
||||
return [k for c,k in out[:ASSOC_MAX] if PRINT.match(k or '')]
|
||||
def inter(legs,lim=10):
|
||||
out=[];idx=[0]*len(legs)
|
||||
while len(out)<lim and any(idx[i]<len(legs[i]) for i in range(len(legs))):
|
||||
for i in range(len(legs)):
|
||||
if idx[i]<len(legs[i]):
|
||||
if legs[i][idx[i]] not in out: out.append(legs[i][idx[i]])
|
||||
idx[i]+=1
|
||||
if len(out)>=lim: break
|
||||
return out
|
||||
def run(floor, vocabgate, use_cos, order):
|
||||
res={}; legs={}
|
||||
for qid,q in gold.items():
|
||||
v=emb(q['query']); s=M@v; s[~np.isfinite(s)]=-1
|
||||
L,nmatch=lexleg(qid,q['query'])
|
||||
if vocabgate and nmatch==0:
|
||||
res[qid]=[]; legs[qid]=([],[],[]); continue
|
||||
ordr=np.argsort(-s)
|
||||
S=[eids[j] for j in ordr[:10] if PRINT.match(eids[j] or '') and (not floor or s[j]>SEED_MIN)]
|
||||
seeds=[x for x in L[:3] if x in N]
|
||||
seeds=seeds+[eids[j] for j in ordr[:8] if eids[j] in N and eids[j] not in seeds and PRINT.match(eids[j] or '')]
|
||||
A=assoc(seeds,s,use_cos,order) if seeds else []
|
||||
res[qid]=inter([L,S,A]); legs[qid]=(L,S,A)
|
||||
return res,legs
|
||||
def score(res,label,base=None):
|
||||
det={}
|
||||
for qid,q in gold.items():
|
||||
out=res[qid][:5]
|
||||
if q['category']=='nonsense': ok=(len(res[qid])==0)
|
||||
elif q['category']=='superseded':
|
||||
must=q.get('must_outrank') or {}; ok=False
|
||||
for good,bad in (must.items() if isinstance(must,dict) else []):
|
||||
ok = good in res[qid] and (bad not in res[qid] or res[qid].index(good)<res[qid].index(bad))
|
||||
if not must: ok=any(r in out for r in q['relevant'])
|
||||
else: ok=any(r in out for r in q['relevant'])
|
||||
det[qid]=ok
|
||||
line="%-34s true=%d/38"%(label,sum(det.values()))
|
||||
if base is not None:
|
||||
dd=[q for q in sorted(gold) if det[q]!=base[q]]
|
||||
line+=" moved=%d gains=%s losses=%s"%(len(dd),[q for q in dd if det[q]],[q for q in dd if not det[q]])
|
||||
print(line, flush=True)
|
||||
return det
|
||||
if __name__=="__main__":
|
||||
b,_=run(True,False,False,'cos'); base=score(b,'BASE bm25lex replica')
|
||||
for lab,args in [
|
||||
("A floor-off+vocabgate", (False,True,False,'cos')),
|
||||
("B A+cos-in-traversal", (False,True,True ,'cos')),
|
||||
("C A+cos-trav+act-order", (False,True,True ,'act')),
|
||||
("D floor-off NO gate", (False,False,False,'cos')),
|
||||
]:
|
||||
r,_=run(*args); score(r,lab,base)
|
||||
print("elapsed %.1fs"%(time.time()-t0),file=sys.stderr)
|
||||
@@ -1,32 +0,0 @@
|
||||
exec(open('sim6.py').read().split('if __name__')[0])
|
||||
HASSTRUCT=set(adj.keys())
|
||||
print("nodes with >=1 structural edge:",len(HASSTRUCT),file=sys.stderr)
|
||||
def run2(sfilter, seedout, lim=10):
|
||||
res={}
|
||||
for qid,q in gold.items():
|
||||
v=emb(q['query']); s=M@v; s[~np.isfinite(s)]=-1
|
||||
L,nmatch=lexleg(qid,q['query'])
|
||||
if nmatch==0: res[qid]=[]; continue
|
||||
ordr=np.argsort(-s)
|
||||
cand=[eids[j] for j in ordr[:200] if PRINT.match(eids[j] or '')]
|
||||
S=[x for x in cand if (not sfilter or x in HASSTRUCT)][:10]
|
||||
seeds=[x for x in L[:3] if x in N]
|
||||
semseeds=[eids[j] for j in ordr[:8] if eids[j] in N and eids[j] not in seeds and PRINT.match(eids[j] or '')]
|
||||
seeds=seeds+semseeds
|
||||
A=assoc(seeds,s,False,'cos') if seeds else []
|
||||
if seedout:
|
||||
extra=[(float(s[eidx[x]]),x) for x in semseeds if x in HASSTRUCT and x in eidx]
|
||||
merged=[(float(s[eidx[x]]),x) for x in A if x in eidx]+extra
|
||||
merged.sort(reverse=True)
|
||||
seen=set(); A=[]
|
||||
for c,x in merged:
|
||||
if x in seen: continue
|
||||
seen.add(x); A.append(x)
|
||||
A=A[:ASSOC_MAX]
|
||||
res[qid]=inter([L,S,A])
|
||||
return res
|
||||
b,_=run(True,False,False,'cos'); base=score(b,'BASE bm25lex replica')
|
||||
a,_=run(False,True,False,'cos'); score(a,'A floor-off+vocabgate',base)
|
||||
score(run2(False,True),'E A+struct-seeds-in-graphleg',base)
|
||||
score(run2(True,False),'F A+S-restricted-to-graph',base)
|
||||
score(run2(True,True),'G E+F',base)
|
||||
@@ -1,30 +0,0 @@
|
||||
exec(open('sim6.py').read().split('if __name__')[0])
|
||||
HASSTRUCT=set(adj.keys())
|
||||
import json as _j
|
||||
d2=_j.load(open('/Users/timlingo/neuron-memory-backups/snapshot-pre-repair-20260806.json',encoding='utf-8',errors='surrogateescape'))
|
||||
ANYEDGE=set()
|
||||
for e in d2['edges']: ANYEDGE.add(e['from_id']); ANYEDGE.add(e['to_id'])
|
||||
del d2
|
||||
print("struct=%d anyedge=%d"%(len(HASSTRUCT),len(ANYEDGE)),file=sys.stderr)
|
||||
def run4(pool, nlegs, lim=10):
|
||||
P = HASSTRUCT if pool=='struct' else ANYEDGE
|
||||
res={}
|
||||
for qid,q in gold.items():
|
||||
v=emb(q['query']); s=M@v; s[~np.isfinite(s)]=-1
|
||||
L,nmatch=lexleg(qid,q['query'])
|
||||
if nmatch==0: res[qid]=[]; continue
|
||||
ordr=np.argsort(-s)
|
||||
cand=[eids[j] for j in ordr[:3000] if PRINT.match(eids[j] or '')]
|
||||
S=cand[:10]
|
||||
G=[x for x in cand if x in P][:10]
|
||||
seeds=[x for x in L[:3] if x in N]
|
||||
seeds=seeds+[eids[j] for j in ordr[:8] if eids[j] in N and eids[j] not in seeds and PRINT.match(eids[j] or '')]
|
||||
A=assoc(seeds,s,False,'cos') if seeds else []
|
||||
legs=[L,S,G,A] if nlegs==4 else [L,G,A]
|
||||
res[qid]=inter(legs)
|
||||
return res
|
||||
b,_=run(True,False,False,'cos'); base=score(b,'BASE bm25lex replica')
|
||||
score(run4('struct',4),'I 4leg L,S,G(struct),A',base)
|
||||
score(run4('any',4), 'J 4leg L,S,G(anyedge),A',base)
|
||||
score(run4('struct',3),'K 3leg L,G(struct),A',base)
|
||||
score(run4('any',3), 'L 3leg L,G(anyedge),A',base)
|
||||
@@ -0,0 +1,92 @@
|
||||
import json,sys,pickle,numpy as np
|
||||
sys.path.insert(0,'.')
|
||||
from legs import *
|
||||
GP='/Users/timlingo/Development/neuron-technologies/_wt-bm25lex/tools/retrieval-eval/'
|
||||
G=json.load(open(GP+'gold_set.json'))
|
||||
def wstart(s,tok):
|
||||
i=s.find(tok)
|
||||
while i!=-1:
|
||||
if i==0 or not s[i-1].isalnum(): return True
|
||||
i=s.find(tok,i+1)
|
||||
return False
|
||||
def legs4(query, wordstart=False, unfloor=False):
|
||||
toks=tokenize(query); lt=[t.lower() for t in toks]
|
||||
hit_idx=[];hit_mask=[];df=[0]*len(toks)
|
||||
for i in range(N):
|
||||
if not OK[i]: continue
|
||||
s=LOW[i];m=0
|
||||
for t,tok in enumerate(lt):
|
||||
if tok in s and (not wordstart or wstart(s,tok)): m|=(1<<t)
|
||||
if m:
|
||||
hit_idx.append(i);hit_mask.append(m)
|
||||
for t in range(len(toks)):
|
||||
if m>>t&1: df[t]+=1
|
||||
dl_n=int(OK.sum());avgdl=float(DL[OK].sum()/max(dl_n,1))
|
||||
idf=[math.log(1.0+((dl_n-d+0.5)/(d+0.5))) for d in df]
|
||||
L=[]
|
||||
for j,i in enumerate(hit_idx):
|
||||
norm=1.0-B+B*(DL[i]/avgdl);w=0.0
|
||||
for t in range(len(toks)):
|
||||
if hit_mask[j]>>t&1: w+=idf[t]*(K1+1.0)/(1.0+K1*norm)
|
||||
L.append((i,w,SAL[i]))
|
||||
L.sort(key=lambda x:(-x[1],-x[2]))
|
||||
if not L: return [],[],[]
|
||||
qv=qemb(query);cos=En@qv;cos=np.where(HAVE&OK,cos,-2.0)
|
||||
order=np.argsort(-cos)[:600]
|
||||
Sl=[int(i) for i in order if cos[i]>(0.0 if unfloor else SEED_MIN)]
|
||||
semseed=[int(i) for i in order[:SEED_K] if cos[i]>0.0]
|
||||
act={};seen={};qq=[]
|
||||
for i,_,_ in L[:ASSOC_SEEDS]:
|
||||
act[i]=1.0;seen[i]=2;qq.append((i,0))
|
||||
for i in semseed:
|
||||
if i in seen: continue
|
||||
act[i]=1.0;seen[i]=2;qq.append((i,0))
|
||||
qh=0
|
||||
while qh<len(qq):
|
||||
cur,h=qq[qh];qh+=1
|
||||
if h>=DEPTH: continue
|
||||
parent=act[cur]
|
||||
for e,oi in ADJ_F[cur]+ADJ_T[cur]:
|
||||
if e['rel'] not in STRUCT or EXCL[oi]: continue
|
||||
na=parent*e['w']*DECAY*SAL[oi]
|
||||
if na<FIRE: continue
|
||||
if seen.get(oi) and na<=act.get(oi,0): continue
|
||||
act[oi]=na
|
||||
if not seen.get(oi): seen[oi]=1
|
||||
if len(qq)<AMAX*4: qq.append((oi,h+1))
|
||||
A=sorted([(i,float(cos[i])) for i,st in seen.items() if st==1 and OK[i] and HAVE[i] and cos[i]>0.0],key=lambda x:-x[1])[:AMAX]
|
||||
return [i for i,_,_ in L],Sl,[i for i,_ in A]
|
||||
def merge(L,S,A,lim=10):
|
||||
out=[];li=si=ai=0
|
||||
while len(out)<lim and (li<len(L) or si<len(S) or ai<len(A)):
|
||||
if li<len(L):
|
||||
if L[li] not in out: out.append(L[li])
|
||||
li+=1
|
||||
if len(out)>=lim: break
|
||||
if si<len(S):
|
||||
if S[si] not in out: out.append(S[si])
|
||||
si+=1
|
||||
if len(out)>=lim: break
|
||||
if ai<len(A):
|
||||
if A[ai] not in out: out.append(A[ai])
|
||||
ai+=1
|
||||
return out
|
||||
def outcome(q,ids):
|
||||
c=q['category']
|
||||
if c=='nonsense': return len(ids)==0
|
||||
if c=='superseded':
|
||||
a,b=q['must_outrank']
|
||||
if a not in ids: return False
|
||||
if b not in ids: return True
|
||||
return ids.index(a)<ids.index(b)
|
||||
return any(x in ids[:5] for x in q['relevant'])
|
||||
def run(**kw):
|
||||
return {q['id']:outcome(q,[NODES[i]['id'] for i in merge(*legs4(q['query'],**kw),10)]) for q in G['queries']}
|
||||
base=run()
|
||||
print("baseline",sum(base.values()),"misses",[k for k,v in base.items() if not v])
|
||||
for name,kw in [('wordstart',dict(wordstart=True)),
|
||||
('unfloor',dict(unfloor=True)),
|
||||
('wordstart+unfloor',dict(wordstart=True,unfloor=True))]:
|
||||
r=run(**kw)
|
||||
g=sorted(k for k in base if r[k] and not base[k]);l=sorted(k for k in base if base[k] and not r[k])
|
||||
print("%-20s net=%+d gains=%s losses=%s"%(name,len(g)-len(l),g,l))
|
||||
+168
-43
@@ -7175,6 +7175,12 @@ void engram_forget(el_val_t node_id) {
|
||||
if (idx < 0) return;
|
||||
/* Free node strings */
|
||||
EngramNode* n = &g->nodes[idx];
|
||||
if (getenv("EG_DIAG")) {
|
||||
fprintf(stderr, "[EG_DIAG] FORGET id=%s type=%s layer=%u label=%s\n",
|
||||
sid, n->node_type ? n->node_type : "?", n->layer_id,
|
||||
n->label ? n->label : "?");
|
||||
fflush(stderr);
|
||||
}
|
||||
free(n->id); free(n->content); free(n->node_type); free(n->label);
|
||||
free(n->tier); free(n->tags); free(n->metadata);
|
||||
free(n->emb);
|
||||
@@ -7270,6 +7276,8 @@ el_val_t engram_prune_telemetry(el_val_t older_than_ms) {
|
||||
}
|
||||
}
|
||||
g->node_count = w;
|
||||
if (getenv("EG_DIAG"))
|
||||
fprintf(stderr, "[EG_DIAG] PRUNE_TELEMETRY removed=%lld\n", (long long)removed);
|
||||
if (removed == 0) { free(removed_ids); return 0; }
|
||||
|
||||
/* Removed-id hash set (open addressing, power-of-two >= 2*removed). */
|
||||
@@ -7327,6 +7335,39 @@ static int istr_contains(const char* hay, const char* needle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Word-START-anchored variant of istr_contains.
|
||||
*
|
||||
* WHY. The retrieval match primitive is a raw substring test, so a query token
|
||||
* matches ANYWHERE inside a corpus word: "throom" matches "bathroom", "cat"
|
||||
* matches "concatenate". Measured on this corpus over the 38-query gold set,
|
||||
* that is not a rare accident — it is the bulk of some queries' candidate
|
||||
* sets. q28's lexical leg is 36,954 records of which only 13 contain a query
|
||||
* token at a word start (99.96% mid-word noise); six other queries carry
|
||||
* ~20,500 mid-word-only records each; and the nonsense control q35
|
||||
* ("xxqzzt vurblenacht throom") returns 7 records ALL of which match only
|
||||
* mid-word, which is the entire reason that control has been dirty since main.
|
||||
*
|
||||
* WHAT CHANGES. A token must begin at a word boundary — the preceding
|
||||
* character is not alphanumeric. Suffixes are still matched ("value" still
|
||||
* hits "values", "unjailbreakable" still hits "unjailbreakables"), so this is
|
||||
* strictly a prefix anchor, not whole-word equality; whole-word equality would
|
||||
* break the morphological matching the phrase category depends on.
|
||||
*
|
||||
* PROVENANCE, stated honestly: this restores no engram claim. Will's design
|
||||
* has no lexical leg at all (05-detailed-description l.64 takes "one or more
|
||||
* seed node UUIDs representing the current active context" as its input), so
|
||||
* the lexical leg is the seed-finding step that feeds the designed mechanism.
|
||||
* Cleaner seeds serve that mechanism; they do not replace it. */
|
||||
static int istr_contains_wordstart(const char* hay, const char* needle) {
|
||||
if (!hay || !needle || !*needle) return 0;
|
||||
size_t nl = strlen(needle);
|
||||
for (const char* p = hay; *p; p++) {
|
||||
if (p != hay && isalnum((unsigned char)p[-1])) continue;
|
||||
if (strncasecmp(p, needle, nl) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── Tokenized query matching ───────────────────────────────────────────
|
||||
* The engram query surface (search / activate / goal-bias) historically
|
||||
* matched the ENTIRE raw query string as a single case-insensitive
|
||||
@@ -7379,9 +7420,9 @@ static int engram_node_match_score(const EngramNode* n,
|
||||
char toks[][ENGRAM_QTOK_LEN], int ntok) {
|
||||
int score = 0;
|
||||
for (int t = 0; t < ntok; t++) {
|
||||
if (istr_contains(n->content, toks[t]) ||
|
||||
istr_contains(n->label, toks[t]) ||
|
||||
istr_contains(n->tags, toks[t]))
|
||||
if (istr_contains_wordstart(n->content, toks[t]) ||
|
||||
istr_contains_wordstart(n->label, toks[t]) ||
|
||||
istr_contains_wordstart(n->tags, toks[t]))
|
||||
score++;
|
||||
}
|
||||
return score;
|
||||
@@ -7396,9 +7437,9 @@ static uint32_t engram_node_match_mask(const EngramNode* n,
|
||||
char toks[][ENGRAM_QTOK_LEN], int ntok) {
|
||||
uint32_t m = 0;
|
||||
for (int t = 0; t < ntok && t < 32; t++) {
|
||||
if (istr_contains(n->content, toks[t]) ||
|
||||
istr_contains(n->label, toks[t]) ||
|
||||
istr_contains(n->tags, toks[t]))
|
||||
if (istr_contains_wordstart(n->content, toks[t]) ||
|
||||
istr_contains_wordstart(n->label, toks[t]) ||
|
||||
istr_contains_wordstart(n->tags, toks[t]))
|
||||
m |= (uint32_t)1u << t;
|
||||
}
|
||||
return m;
|
||||
@@ -9271,6 +9312,26 @@ el_val_t engram_load(el_val_t path) {
|
||||
}
|
||||
}
|
||||
g->adj_dirty = 1;
|
||||
if (getenv("EG_DIAG")) {
|
||||
int64_t we = 0, wrongdim = 0;
|
||||
for (int64_t i = 0; i < g->node_count; i++) {
|
||||
if (g->nodes[i].emb) { we++; if (g->nodes[i].emb_dim != 768) wrongdim++; }
|
||||
}
|
||||
fprintf(stderr, "[EG_DIAG] loaded nodes=%lld with_emb=%lld wrongdim=%lld\n",
|
||||
(long long)g->node_count, (long long)we, (long long)wrongdim);
|
||||
const char* probe = getenv("EG_DIAG_ID");
|
||||
if (probe) {
|
||||
for (int64_t i = 0; i < g->node_count; i++) {
|
||||
if (g->nodes[i].id && strcmp(g->nodes[i].id, probe) == 0) {
|
||||
fprintf(stderr, "[EG_DIAG] probe id=%s idx=%lld emb=%p dim=%d layer=%u addr=%d\n",
|
||||
probe, (long long)i, (void*)g->nodes[i].emb,
|
||||
(int)g->nodes[i].emb_dim, g->nodes[i].layer_id,
|
||||
eg_node_addressable(&g->nodes[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
/* Walk edges array */
|
||||
const char* edges_p = json_find_key(data, "edges");
|
||||
if (edges_p) {
|
||||
@@ -9591,7 +9652,33 @@ el_val_t engram_get_node_by_label(el_val_t label) {
|
||||
return el_wrap_str(el_strdup("{}"));
|
||||
}
|
||||
|
||||
el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
/* ── THE SEARCH / RECALL BOUNDARY (2026-08-07) ───────────────────────────────
|
||||
* engram_search_json is the LEXICAL function ~40 .el call sites already
|
||||
* depend on: they pass a key-shaped string ("soul:boot_count",
|
||||
* "soul-inbox-pending", a session label) and treat every returned record as
|
||||
* a record that CONTAINS that key. Seven of those sites then delete what
|
||||
* comes back (memory.el:176, sessions.el:250/268/444/523, soul.el:359 —
|
||||
* "prune all existing X nodes, keep exactly one").
|
||||
*
|
||||
* The semantic and associative legs must therefore NOT live on this
|
||||
* function. Claim 24 authorises the vector index "to respond to EMBEDDING
|
||||
* SEARCH QUERIES by returning the node records whose embedding vectors have
|
||||
* the highest cosine similarity to a query vector"; a keyed state read is
|
||||
* not an embedding search query, it is the identifier-keyed retrieval of
|
||||
* claim 23 ("node records are stored under a key encoding the node
|
||||
* identifier"). Putting both behind one function erased that boundary, and
|
||||
* a nearest neighbour of the string "soul:boot_count" is not a boot counter.
|
||||
*
|
||||
* MEASURED, on the harness corpus, isolated, read-only, no writes from any
|
||||
* caller: 240 node records destroyed per boot, including 6 Knowledge nodes,
|
||||
* a layer-1 "CORE IDENTITY — GENESIS, LINEAGE" Memory, and the value node
|
||||
* `kn-58874a74` (gold answer for gold-set q15). The deletion list is the
|
||||
* result list of the soul's own mem_boot_count_inc() lookup, in order.
|
||||
*
|
||||
* So: legs OFF here, legs ON in engram_recall_json below, which is what
|
||||
* /api/neuron/recall reaches. Retrieval quality on the recall route is
|
||||
* unchanged; the internal keyed reads get their contract back. */
|
||||
static el_val_t eg_search_json_impl(el_val_t query, el_val_t limit, int with_legs) {
|
||||
EngramStore* g = engram_get();
|
||||
const char* q = EL_CSTR(query);
|
||||
int64_t lim = (int64_t)limit;
|
||||
@@ -9613,7 +9700,7 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
* so the semantic half of the retrieval surface has to land HERE
|
||||
* to be observable to the MCP wrapper and the app. */
|
||||
int32_t qdim = 0;
|
||||
float* qv = eg_embed_fetch(q, &qdim);
|
||||
float* qv = with_legs ? eg_embed_fetch(q, &qdim) : NULL;
|
||||
EngramSemEntry* sem = qv ? malloc((size_t)g->node_count * sizeof(EngramSemEntry)) : NULL;
|
||||
int64_t nsem = 0;
|
||||
int64_t nhits = 0;
|
||||
@@ -9654,25 +9741,28 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
}
|
||||
if (sem && n->emb && n->emb_dim == qdim) {
|
||||
double c = eg_cosine(n->emb, qv, qdim);
|
||||
/* Semantic leg, claim 24 verbatim: "returning the node
|
||||
* records whose embedding vectors have the HIGHEST
|
||||
* COSINE SIMILARITY to a query vector" — a ranking, with
|
||||
* no threshold anywhere in the claim. The leg used to be
|
||||
* gated at ENGRAM_EMBED_SEED_MIN and rescaled onto
|
||||
* [SEED_MIN,1]; that constant is defined (l.6083) as the
|
||||
* SEED-JOIN threshold for the HippoRAG pass, and reusing
|
||||
* it as a result filter is not authorised by claim 24.
|
||||
* Measured on this corpus, it is also not a quality
|
||||
* gate: true paraphrase targets score 0.459-0.657 while
|
||||
* the nonsense controls' own nearest neighbours score
|
||||
* 0.553-0.622 — the distributions overlap, so no value
|
||||
* of the constant separates them. What actually holds
|
||||
* the nonsense control is corpus vocabulary (see the
|
||||
* nhits==0 gate below), not cosine magnitude.
|
||||
* Claim 32: clamp the cosine to [0,1] rather than let a
|
||||
* negative value invert the signal. */
|
||||
if (c > 0.0) {
|
||||
double sv = c > 1.0 ? 1.0 : c;
|
||||
/* Claim-24 semantic leg, restored verbatim: "returning
|
||||
* the node records whose embedding vectors have the
|
||||
* HIGHEST COSINE SIMILARITY to a query vector" — a
|
||||
* ranking, with no threshold anywhere in the claim.
|
||||
* ENGRAM_EMBED_SEED_MIN is defined at l.6094 as the
|
||||
* HippoRAG SEED-JOIN threshold; using it as a RESULT
|
||||
* filter here was never authorised, and it is a
|
||||
* per-query lottery rather than a quality gate: the
|
||||
* query's own top-1 cosine ranges 0.56-0.68 across the
|
||||
* held-out gold set, so 0.60 keeps a rank-1 answer for
|
||||
* one query and discards a rank-1 answer for the next.
|
||||
* Measured on the 30 held-out paraphrases: six golds
|
||||
* sit at global cosine rank 1-2 and score 0.564-0.589,
|
||||
* discarded by nothing but this constant.
|
||||
* What holds the nonsense controls is NOT this floor
|
||||
* but the corpus-vocabulary gate below (nhits == 0):
|
||||
* gibberish has no lexical seeds, so no leg reports.
|
||||
* Cosine is clamped to [0,1] per 05-detailed-description
|
||||
* l.69 ("clamped to [0,1] to prevent anti-correlated
|
||||
* embeddings from producing negative activation"). */
|
||||
double sv = c < 0.0 ? 0.0 : (c > 1.0 ? 1.0 : c);
|
||||
if (sv > 0.0) {
|
||||
sem[nsem].idx = i; sem[nsem].sem = sv; nsem++;
|
||||
}
|
||||
/* Graph seeds: top-K by RAW cosine, insertion-ordered. */
|
||||
@@ -9690,21 +9780,6 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
}
|
||||
}
|
||||
}
|
||||
/* CORPUS-VOCABULARY GATE — the thing that actually keeps an
|
||||
* unfloored semantic leg from answering gibberish.
|
||||
* nhits == 0 means NO stored record contains ANY query token
|
||||
* anywhere in its content, label or tags: the query is outside
|
||||
* the graph's vocabulary entirely. A vector index always has a
|
||||
* nearest neighbour, so without this gate the semantic leg
|
||||
* answers "zqxjvw plimforth grebulon" with its 0.55-cosine
|
||||
* garbage. It is also the honest reading of Will's retrieval
|
||||
* contract: 05-detailed-description l.64 has the caller supply
|
||||
* "one or more seed node UUIDs representing the current active
|
||||
* context", and every leg here is downstream of finding those
|
||||
* seeds. No seeds, no retrieval — the graph declines rather
|
||||
* than confabulates. Suppressing the graph seeds too keeps the
|
||||
* associative leg from running off the semantic top-K alone. */
|
||||
if (nhits == 0) { nsem = 0; nsemseed = 0; }
|
||||
/* BM25-shaped lexical score. Binary term frequency (the match
|
||||
* primitive is a substring test, not a count), Lucene-form IDF,
|
||||
* and length normalisation over the corpus mean. A token that
|
||||
@@ -9730,6 +9805,31 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
}
|
||||
qsort(hits, (size_t)nhits, sizeof(EngramRankEntry), engram_rank_w_cmp);
|
||||
if (sem) qsort(sem, (size_t)nsem, sizeof(EngramSemEntry), engram_sem_cmp);
|
||||
if (getenv("EG_DIAG")) {
|
||||
int64_t we = 0, unaddr = 0, found = 0;
|
||||
const char* pid = getenv("EG_DIAG_ID");
|
||||
for (int64_t i = 0; i < g->node_count; i++) {
|
||||
if (g->nodes[i].emb) we++;
|
||||
if (!eg_node_addressable(&g->nodes[i])) unaddr++;
|
||||
if (pid && g->nodes[i].id && strcmp(g->nodes[i].id, pid) == 0) found++;
|
||||
}
|
||||
fprintf(stderr, "[EG_DIAG] STORE node_count=%lld with_emb=%lld unaddressable=%lld probe_found=%lld\n",
|
||||
(long long)g->node_count, (long long)we, (long long)unaddr, (long long)found);
|
||||
fprintf(stderr, "[EG_DIAG] q=\"%s\" qdim=%d nhits=%lld nsem=%lld\n",
|
||||
q, (int)qdim, (long long)nhits, (long long)nsem);
|
||||
for (int64_t k = 0; k < 5 && k < nsem; k++)
|
||||
fprintf(stderr, "[EG_DIAG] sem[%lld] cos=%.4f id=%s\n",
|
||||
(long long)k, sem[k].sem, g->nodes[sem[k].idx].id);
|
||||
const char* probe = getenv("EG_DIAG_ID");
|
||||
if (probe) for (int64_t k = 0; k < nsem; k++)
|
||||
if (g->nodes[sem[k].idx].id
|
||||
&& strcmp(g->nodes[sem[k].idx].id, probe) == 0) {
|
||||
fprintf(stderr, "[EG_DIAG] probe at sem rank %lld cos=%.4f\n",
|
||||
(long long)k, sem[k].sem);
|
||||
break;
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
/* Claim-10 associative leg: expand the top lexical hits along
|
||||
* structural relations only, order the reached set by query
|
||||
* similarity. Empty whenever the seeds have no structural
|
||||
@@ -9740,7 +9840,19 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
? engram_assoc_leg(g, hits, nhits, semseed, nsemseed,
|
||||
qv, qdim, assoc, ENGRAM_ASSOC_MAX)
|
||||
: 0;
|
||||
int64_t* order = malloc((size_t)lim * sizeof(int64_t));
|
||||
/* Corpus-vocabulary gate. If no stored record contains ANY
|
||||
* query token in its content, label or tags, the query is
|
||||
* outside this graph's vocabulary: there are no seeds, and
|
||||
* 05-detailed-description l.64 makes retrieval downstream of
|
||||
* seeds ("the caller provides one or more seed node UUIDs
|
||||
* representing the current active context"). No seeds, no
|
||||
* retrieval — the graph declines rather than confabulating a
|
||||
* nearest neighbour for gibberish. The mechanism is iteration
|
||||
* 6's (feat/claim24-unfloored-semantic); it is required here
|
||||
* because word-start matching empties the lexical leg for
|
||||
* q35-style queries whose only "hits" were mid-word, and the
|
||||
* semantic leg would otherwise answer them anyway. */
|
||||
int64_t* order = (nhits > 0) ? malloc((size_t)lim * sizeof(int64_t)) : NULL;
|
||||
if (order) {
|
||||
int64_t no = engram_interleave3(hits, nhits, sem, nsem,
|
||||
assoc, nassoc, lim, order);
|
||||
@@ -9762,6 +9874,19 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
return el_wrap_str(b.buf);
|
||||
}
|
||||
|
||||
/* Lexical keyed read — the historical contract every internal caller relies
|
||||
* on. Every returned record CONTAINS a query token. */
|
||||
el_val_t engram_search_json(el_val_t query, el_val_t limit) {
|
||||
return eg_search_json_impl(query, limit, 0);
|
||||
}
|
||||
|
||||
/* The retrieval surface: lexical + claim-24 semantic + claim-10 associative,
|
||||
* rank-fused. Reached from handle_api_recall (/api/neuron/recall) — the route
|
||||
* the MCP wrapper and the app call, and the one the eval harness measures. */
|
||||
el_val_t engram_recall_json(el_val_t query, el_val_t limit) {
|
||||
return eg_search_json_impl(query, limit, 1);
|
||||
}
|
||||
|
||||
el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset) {
|
||||
EngramStore* g = engram_get();
|
||||
int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100;
|
||||
|
||||
@@ -612,6 +612,7 @@ el_val_t engram_load(el_val_t path);
|
||||
el_val_t engram_get_node_json(el_val_t id);
|
||||
el_val_t engram_get_node_by_label(el_val_t label);
|
||||
el_val_t engram_search_json(el_val_t query, el_val_t limit);
|
||||
el_val_t engram_recall_json(el_val_t query, el_val_t limit);
|
||||
el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset);
|
||||
el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset);
|
||||
el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction);
|
||||
|
||||
Reference in New Issue
Block a user