appium-mcp 1.79.1 → 1.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/scripts/eval-documentation-rag.d.ts +44 -17
- package/dist/scripts/eval-documentation-rag.d.ts.map +1 -1
- package/dist/scripts/eval-documentation-rag.js +181 -106
- package/dist/scripts/eval-documentation-rag.js.map +1 -1
- package/dist/scripts/rag-eval-dataset.json +337 -39
- package/package.json +1 -2
- package/server.json +2 -2
- package/src/resources/submodules.zip +0 -0
- package/src/scripts/eval-documentation-rag.ts +261 -140
- package/src/scripts/rag-eval-dataset.json +337 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.80.0](https://github.com/appium/appium-mcp/compare/v1.79.1...v1.80.0) (2026-05-28)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **rag:** update evals to use answer spans ([#371](https://github.com/appium/appium-mcp/issues/371)) ([e59ea55](https://github.com/appium/appium-mcp/commit/e59ea5597eff268021bb588312931a5d8ceef090))
|
|
6
|
+
|
|
1
7
|
## [1.79.1](https://github.com/appium/appium-mcp/compare/v1.79.0...v1.79.1) (2026-05-28)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -1,23 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RAG
|
|
2
|
+
* Answer-grounded RAG eval for the Appium documentation tool.
|
|
3
|
+
*
|
|
4
|
+
* Runs the documentation_query retrieval pipeline against a fixed set of
|
|
5
|
+
* realistic queries and asks the only question that matters downstream:
|
|
6
|
+
* "did the answer text actually land in the chunks an LLM would see?"
|
|
7
|
+
*
|
|
8
|
+
* What we measure:
|
|
9
|
+
*
|
|
10
|
+
* 1. answerSpanRecall@K
|
|
11
|
+
* For each query, the dataset declares short verbatim phrases lifted
|
|
12
|
+
* from the docs (`answerSpans`). We concatenate the top-K retrieved
|
|
13
|
+
* chunks and check what fraction of the spans appears in that text.
|
|
14
|
+
* "anyOf" semantics: a query that finds at least one span counts as a
|
|
15
|
+
* hit. Spans are 30-140 chars and chosen so any reasonable chunk
|
|
16
|
+
* containing the answer will include them, regardless of chunk
|
|
17
|
+
* boundaries -- so the metric is splitter-neutral.
|
|
18
|
+
*
|
|
19
|
+
* 2. hit@{1,3,5,10}
|
|
20
|
+
* Did any chunk at rank <= K carry any answerSpan? Direct measure of
|
|
21
|
+
* "does the LLM see the answer" at different context budgets.
|
|
22
|
+
*
|
|
23
|
+
* 3. MRR
|
|
24
|
+
* Mean reciprocal rank of the *first* chunk that carries an answerSpan.
|
|
25
|
+
* MRR-equivalent on content, not on file paths -- a chunk from the
|
|
26
|
+
* right file but wrong section is worth nothing here.
|
|
27
|
+
*
|
|
28
|
+
* 4. contextEfficiency
|
|
29
|
+
* For queries we hit, 1000 * spansCovered / totalChars(topK). Spans-per-
|
|
30
|
+
* kchar density. Low = lots of noise around the answer.
|
|
31
|
+
*
|
|
32
|
+
* 5. fileRecall@{5,10} (diagnostic only)
|
|
33
|
+
* Did the right *file* appear in top-K? Kept so we can spot the
|
|
34
|
+
* "right-file wrong-chunk" failure mode (right file present but no
|
|
35
|
+
* answerSpan landed).
|
|
36
|
+
*
|
|
37
|
+
* Match semantics: lowercase + collapse whitespace, then substring check.
|
|
3
38
|
*
|
|
4
39
|
* Usage (after `npm run build`):
|
|
5
|
-
* node dist/scripts/eval-documentation-rag.js
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the
|
|
12
|
-
*
|
|
13
|
-
* 4. Persists results to src/scripts/eval-results/<ISO>.json plus a
|
|
14
|
-
* `latest.json` so successive runs can be diffed.
|
|
15
|
-
*
|
|
16
|
-
* Notes:
|
|
17
|
-
* - The first run after a server restart pays the embedding cold start
|
|
18
|
-
* (~30-60s for the current corpus).
|
|
19
|
-
* - Match strategy: a retrieved source matches an expected source if its
|
|
20
|
-
* `relativePath` ends with the expected path (case-sensitive).
|
|
40
|
+
* node dist/scripts/eval-documentation-rag.js \
|
|
41
|
+
* [--top-k=10] [--label=NAME] [--quiet] [--no-save]
|
|
42
|
+
*
|
|
43
|
+
* --top-k=N number of chunks to retrieve & evaluate (default 10)
|
|
44
|
+
* --label=N label written into the saved run, useful for comparing
|
|
45
|
+
* index variants (e.g. --label=before, --label=after)
|
|
46
|
+
* --quiet suppress the per-query log lines and table
|
|
47
|
+
* --no-save don't persist results JSON to disk
|
|
21
48
|
*/
|
|
22
49
|
export {};
|
|
23
50
|
//# sourceMappingURL=eval-documentation-rag.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-documentation-rag.d.ts","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"eval-documentation-rag.d.ts","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG"}
|
|
@@ -1,38 +1,70 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RAG
|
|
2
|
+
* Answer-grounded RAG eval for the Appium documentation tool.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Runs the documentation_query retrieval pipeline against a fixed set of
|
|
5
|
+
* realistic queries and asks the only question that matters downstream:
|
|
6
|
+
* "did the answer text actually land in the chunks an LLM would see?"
|
|
7
|
+
*
|
|
8
|
+
* What we measure:
|
|
9
|
+
*
|
|
10
|
+
* 1. answerSpanRecall@K
|
|
11
|
+
* For each query, the dataset declares short verbatim phrases lifted
|
|
12
|
+
* from the docs (`answerSpans`). We concatenate the top-K retrieved
|
|
13
|
+
* chunks and check what fraction of the spans appears in that text.
|
|
14
|
+
* "anyOf" semantics: a query that finds at least one span counts as a
|
|
15
|
+
* hit. Spans are 30-140 chars and chosen so any reasonable chunk
|
|
16
|
+
* containing the answer will include them, regardless of chunk
|
|
17
|
+
* boundaries -- so the metric is splitter-neutral.
|
|
18
|
+
*
|
|
19
|
+
* 2. hit@{1,3,5,10}
|
|
20
|
+
* Did any chunk at rank <= K carry any answerSpan? Direct measure of
|
|
21
|
+
* "does the LLM see the answer" at different context budgets.
|
|
22
|
+
*
|
|
23
|
+
* 3. MRR
|
|
24
|
+
* Mean reciprocal rank of the *first* chunk that carries an answerSpan.
|
|
25
|
+
* MRR-equivalent on content, not on file paths -- a chunk from the
|
|
26
|
+
* right file but wrong section is worth nothing here.
|
|
27
|
+
*
|
|
28
|
+
* 4. contextEfficiency
|
|
29
|
+
* For queries we hit, 1000 * spansCovered / totalChars(topK). Spans-per-
|
|
30
|
+
* kchar density. Low = lots of noise around the answer.
|
|
31
|
+
*
|
|
32
|
+
* 5. fileRecall@{5,10} (diagnostic only)
|
|
33
|
+
* Did the right *file* appear in top-K? Kept so we can spot the
|
|
34
|
+
* "right-file wrong-chunk" failure mode (right file present but no
|
|
35
|
+
* answerSpan landed).
|
|
6
36
|
*
|
|
7
|
-
*
|
|
8
|
-
* 1. Loads the eval dataset (src/scripts/rag-eval-dataset.json).
|
|
9
|
-
* 2. For each query, calls the existing queryVectorStore() with `topChunks`
|
|
10
|
-
* chunks (default 30), dedupes by source (preserving rank), and matches
|
|
11
|
-
* the resulting source list against expectedSources.
|
|
12
|
-
* 3. Reports Recall@{1,3,5,10} and MRR, broken down by difficulty.
|
|
13
|
-
* 4. Persists results to src/scripts/eval-results/<ISO>.json plus a
|
|
14
|
-
* `latest.json` so successive runs can be diffed.
|
|
37
|
+
* Match semantics: lowercase + collapse whitespace, then substring check.
|
|
15
38
|
*
|
|
16
|
-
*
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
39
|
+
* Usage (after `npm run build`):
|
|
40
|
+
* node dist/scripts/eval-documentation-rag.js \
|
|
41
|
+
* [--top-k=10] [--label=NAME] [--quiet] [--no-save]
|
|
42
|
+
*
|
|
43
|
+
* --top-k=N number of chunks to retrieve & evaluate (default 10)
|
|
44
|
+
* --label=N label written into the saved run, useful for comparing
|
|
45
|
+
* index variants (e.g. --label=before, --label=after)
|
|
46
|
+
* --quiet suppress the per-query log lines and table
|
|
47
|
+
* --no-save don't persist results JSON to disk
|
|
21
48
|
*/
|
|
22
49
|
import * as fs from 'node:fs';
|
|
23
50
|
import * as path from 'node:path';
|
|
24
51
|
import { fileURLToPath } from 'node:url';
|
|
25
52
|
import { queryVectorStore } from '../tools/documentation/simple-pdf-indexer.js';
|
|
53
|
+
// -- arg parsing ----------------------------------------------------------
|
|
26
54
|
const __filename = fileURLToPath(import.meta.url);
|
|
27
55
|
const __dirname = path.dirname(__filename);
|
|
28
|
-
const args =
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
56
|
+
const args = process.argv.slice(2);
|
|
57
|
+
const flagSet = new Set(args);
|
|
58
|
+
const QUIET = flagSet.has('--quiet');
|
|
59
|
+
const NO_SAVE = flagSet.has('--no-save');
|
|
60
|
+
function flagValue(name, dflt) {
|
|
61
|
+
const a = args.find((x) => x.startsWith(`${name}=`));
|
|
62
|
+
return a ? a.split('=').slice(1).join('=') : dflt;
|
|
63
|
+
}
|
|
64
|
+
const TOP_K = Number(flagValue('--top-k', '10'));
|
|
65
|
+
const LABEL = flagValue('--label', 'default');
|
|
66
|
+
// -- paths ----------------------------------------------------------------
|
|
33
67
|
function resolveDatasetPath() {
|
|
34
|
-
// When compiled, this file lives in dist/scripts/. We look for the dataset
|
|
35
|
-
// beside it first (copy-docs build step), then fall back to src/scripts/.
|
|
36
68
|
const candidates = [
|
|
37
69
|
path.resolve(__dirname, 'rag-eval-dataset.json'),
|
|
38
70
|
path.resolve(__dirname, '../../src/scripts/rag-eval-dataset.json'),
|
|
@@ -42,132 +74,171 @@ function resolveDatasetPath() {
|
|
|
42
74
|
return p;
|
|
43
75
|
}
|
|
44
76
|
}
|
|
45
|
-
throw new Error(`
|
|
77
|
+
throw new Error(`rag-eval-dataset.json not found in: ${candidates.join(', ')}`);
|
|
46
78
|
}
|
|
47
79
|
function resolveResultsDir() {
|
|
48
|
-
|
|
49
|
-
const candidates = [
|
|
50
|
-
path.resolve(__dirname, '../../src/scripts/eval-results'),
|
|
51
|
-
path.resolve(__dirname, 'eval-results'),
|
|
52
|
-
];
|
|
53
|
-
const dir = candidates[0];
|
|
80
|
+
const dir = path.resolve(__dirname, '../../src/scripts/eval-results');
|
|
54
81
|
fs.mkdirSync(dir, { recursive: true });
|
|
55
82
|
return dir;
|
|
56
83
|
}
|
|
57
|
-
|
|
84
|
+
// -- matching helpers -----------------------------------------------------
|
|
85
|
+
function normalize(s) {
|
|
86
|
+
return s.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
87
|
+
}
|
|
88
|
+
function chunkContainsSpan(chunkText, span) {
|
|
89
|
+
return normalize(chunkText).includes(normalize(span));
|
|
90
|
+
}
|
|
91
|
+
function endsWithExpected(retrievedRelPath, expected) {
|
|
58
92
|
return retrievedRelPath === expected || retrievedRelPath.endsWith(expected);
|
|
59
93
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
94
|
+
// -- per-query evaluation -------------------------------------------------
|
|
95
|
+
function evaluateQuery(q, chunks) {
|
|
96
|
+
const hitRanks = [];
|
|
97
|
+
const spansCovered = new Set();
|
|
98
|
+
for (const chunk of chunks) {
|
|
99
|
+
let chunkHadHit = false;
|
|
100
|
+
for (const span of q.answerSpans) {
|
|
101
|
+
if (chunkContainsSpan(chunk.text, span)) {
|
|
102
|
+
spansCovered.add(span);
|
|
103
|
+
chunkHadHit = true;
|
|
104
|
+
}
|
|
67
105
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
return ordered;
|
|
72
|
-
}
|
|
73
|
-
function evalQuery(retrievedSources, expectedSources) {
|
|
74
|
-
for (let i = 0; i < retrievedSources.length; i++) {
|
|
75
|
-
const hit = expectedSources.find((e) => matches(retrievedSources[i], e));
|
|
76
|
-
if (hit) {
|
|
77
|
-
return { matchedAtRank: i + 1, matchedSource: retrievedSources[i] };
|
|
106
|
+
if (chunkHadHit) {
|
|
107
|
+
hitRanks.push(chunk.rank);
|
|
78
108
|
}
|
|
79
109
|
}
|
|
80
|
-
|
|
110
|
+
const firstHitRank = hitRanks.length > 0 ? hitRanks[0] : null;
|
|
111
|
+
const spansMissing = q.answerSpans.filter((s) => !spansCovered.has(s));
|
|
112
|
+
return {
|
|
113
|
+
hitRanks,
|
|
114
|
+
firstHitRank,
|
|
115
|
+
spansCovered: [...spansCovered],
|
|
116
|
+
spansMissing,
|
|
117
|
+
};
|
|
81
118
|
}
|
|
119
|
+
// -- aggregation ----------------------------------------------------------
|
|
82
120
|
function aggregate(results) {
|
|
83
121
|
if (results.length === 0) {
|
|
84
122
|
return {
|
|
85
123
|
count: 0,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
124
|
+
answerSpanRecall: 0,
|
|
125
|
+
hitAnyAt1: 0,
|
|
126
|
+
hitAnyAt3: 0,
|
|
127
|
+
hitAnyAt5: 0,
|
|
128
|
+
hitAnyAt10: 0,
|
|
90
129
|
mrr: 0,
|
|
130
|
+
contextEfficiency: 0,
|
|
131
|
+
fileRecallAt5: 0,
|
|
132
|
+
fileRecallAt10: 0,
|
|
91
133
|
};
|
|
92
134
|
}
|
|
93
135
|
const n = results.length;
|
|
94
|
-
const
|
|
136
|
+
const mean = (xs) => xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
137
|
+
const hitResults = results.filter((r) => r.hitAnyAt10 === 1);
|
|
95
138
|
return {
|
|
96
139
|
count: n,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
140
|
+
answerSpanRecall: mean(results.map((r) => r.answerSpanRecall)),
|
|
141
|
+
hitAnyAt1: mean(results.map((r) => r.hitAnyAt1)),
|
|
142
|
+
hitAnyAt3: mean(results.map((r) => r.hitAnyAt3)),
|
|
143
|
+
hitAnyAt5: mean(results.map((r) => r.hitAnyAt5)),
|
|
144
|
+
hitAnyAt10: mean(results.map((r) => r.hitAnyAt10)),
|
|
145
|
+
mrr: mean(results.map((r) => r.reciprocalRank)),
|
|
146
|
+
contextEfficiency: hitResults.length
|
|
147
|
+
? mean(hitResults.map((r) => r.contextEfficiency))
|
|
148
|
+
: 0,
|
|
149
|
+
fileRecallAt5: mean(results.map((r) => r.fileRecallAt5)),
|
|
150
|
+
fileRecallAt10: mean(results.map((r) => r.fileRecallAt10)),
|
|
102
151
|
};
|
|
103
152
|
}
|
|
104
|
-
function fmt(n) {
|
|
105
|
-
return n.toFixed(
|
|
153
|
+
function fmt(n, dp = 3) {
|
|
154
|
+
return n.toFixed(dp);
|
|
106
155
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
156
|
+
function printAggregate(label, m) {
|
|
157
|
+
const tag = `${label} (n=${m.count})`.padEnd(20);
|
|
158
|
+
console.log(`${tag} spanRecall=${fmt(m.answerSpanRecall)} hit@1=${fmt(m.hitAnyAt1)} hit@3=${fmt(m.hitAnyAt3)} hit@5=${fmt(m.hitAnyAt5)} hit@10=${fmt(m.hitAnyAt10)} MRR=${fmt(m.mrr)} ctxEff=${fmt(m.contextEfficiency, 2)} fileR@5=${fmt(m.fileRecallAt5)}`);
|
|
109
159
|
}
|
|
110
160
|
function printPerQueryTable(results) {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
diff: r.difficulty,
|
|
114
|
-
rank: rankStr(r.matchedAtRank),
|
|
115
|
-
query: r.query.length > 56 ? r.query.slice(0, 53) + '...' : r.query,
|
|
116
|
-
matched: r.matchedSource ?? '(none of expected found in top results)',
|
|
117
|
-
}));
|
|
118
|
-
const widths = {
|
|
119
|
-
id: 4,
|
|
120
|
-
diff: 7,
|
|
121
|
-
rank: 4,
|
|
122
|
-
query: Math.max(...rows.map((r) => r.query.length), 5),
|
|
123
|
-
matched: Math.max(...rows.map((r) => r.matched.length), 7),
|
|
124
|
-
};
|
|
125
|
-
const header = `${'id'.padEnd(widths.id)} | ${'diff'.padEnd(widths.diff)} | ${'rank'.padStart(widths.rank)} | ${'query'.padEnd(widths.query)} | matched`;
|
|
126
|
-
const sep = '-'.repeat(header.length + 10);
|
|
161
|
+
const header = 'id | diff | fhr | spans | hit@5 | unique | sources';
|
|
162
|
+
const sep = '-'.repeat(110);
|
|
127
163
|
console.log(sep);
|
|
128
164
|
console.log(header);
|
|
129
165
|
console.log(sep);
|
|
130
|
-
for (const r of
|
|
131
|
-
|
|
166
|
+
for (const r of results) {
|
|
167
|
+
const fhr = r.firstHitRank === null ? ' - ' : String(r.firstHitRank).padStart(3, ' ');
|
|
168
|
+
const spans = `${r.spansCovered.length}/${r.answerSpans.length}`;
|
|
169
|
+
const matched = r.retrievedSources[0]
|
|
170
|
+
? r.retrievedSources.slice(0, 2).join(', ')
|
|
171
|
+
: '(empty)';
|
|
172
|
+
console.log(`${r.id.padEnd(4)} | ${r.difficulty.padEnd(6)} | ${fhr} | ${spans.padEnd(6)} | ${String(r.hitAnyAt5).padEnd(5)} | ${String(r.uniqueFiles).padEnd(6)} | ${matched}`);
|
|
132
173
|
}
|
|
133
174
|
console.log(sep);
|
|
134
175
|
}
|
|
135
|
-
|
|
136
|
-
const tag = `${label} (n=${m.count})`.padEnd(20);
|
|
137
|
-
console.log(`${tag} R@1=${fmt(m.recallAt1)} R@3=${fmt(m.recallAt3)} R@5=${fmt(m.recallAt5)} R@10=${fmt(m.recallAt10)} MRR=${fmt(m.mrr)}`);
|
|
138
|
-
}
|
|
176
|
+
// -- main -----------------------------------------------------------------
|
|
139
177
|
async function runEval() {
|
|
140
178
|
const datasetPath = resolveDatasetPath();
|
|
141
179
|
const dataset = JSON.parse(fs.readFileSync(datasetPath, 'utf-8'));
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
console.log(`Queries: ${dataset.queries.length} | topChunks: ${TOP_CHUNKS} | match: endsWith\n`);
|
|
146
|
-
}
|
|
180
|
+
console.log(`\n=== Appium RAG eval (answer-grounded) ===`);
|
|
181
|
+
console.log(`Dataset: ${datasetPath}`);
|
|
182
|
+
console.log(`Queries: ${dataset.queries.length} topK: ${TOP_K} label: ${LABEL}\n`);
|
|
147
183
|
const perQuery = [];
|
|
148
184
|
for (const q of dataset.queries) {
|
|
149
|
-
const docs = await queryVectorStore(q.query,
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
185
|
+
const docs = await queryVectorStore(q.query, TOP_K);
|
|
186
|
+
const chunks = docs.map((d, i) => ({
|
|
187
|
+
rank: i + 1,
|
|
188
|
+
text: d.pageContent,
|
|
189
|
+
source: d.metadata?.relativePath ??
|
|
190
|
+
d.metadata?.filename,
|
|
191
|
+
charCount: d.pageContent.length,
|
|
192
|
+
}));
|
|
193
|
+
const retrievedSources = chunks
|
|
194
|
+
.map((c) => c.source)
|
|
195
|
+
.filter((s) => !!s);
|
|
196
|
+
const topKChars = chunks.reduce((a, c) => a + c.charCount, 0);
|
|
197
|
+
const uniqueFiles = new Set(retrievedSources).size;
|
|
198
|
+
const { hitRanks, firstHitRank, spansCovered, spansMissing } = evaluateQuery(q, chunks);
|
|
199
|
+
const answerSpanRecall = q.answerSpans.length === 0
|
|
200
|
+
? 0
|
|
201
|
+
: spansCovered.length / q.answerSpans.length;
|
|
202
|
+
const hitAnyAt = (k) => hitRanks.some((r) => r <= k) ? 1 : 0;
|
|
203
|
+
const reciprocalRank = firstHitRank ? 1 / firstHitRank : 0;
|
|
204
|
+
const contextEfficiency = firstHitRank !== null && topKChars > 0
|
|
205
|
+
? (1000 * spansCovered.length) / topKChars
|
|
206
|
+
: 0;
|
|
207
|
+
const fileMatched = (k) => {
|
|
208
|
+
const top = retrievedSources.slice(0, k);
|
|
209
|
+
return top.some((rs) => q.expectedSources.some((es) => endsWithExpected(rs, es)))
|
|
210
|
+
? 1
|
|
211
|
+
: 0;
|
|
212
|
+
};
|
|
156
213
|
perQuery.push({
|
|
157
214
|
id: q.id,
|
|
158
215
|
query: q.query,
|
|
159
216
|
difficulty: q.difficulty,
|
|
160
217
|
category: q.category,
|
|
161
218
|
expectedSources: q.expectedSources,
|
|
219
|
+
answerSpans: q.answerSpans,
|
|
162
220
|
retrievedSources,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
221
|
+
topKChunks: chunks.length,
|
|
222
|
+
topKChars,
|
|
223
|
+
uniqueFiles,
|
|
224
|
+
hitRanks,
|
|
225
|
+
firstHitRank,
|
|
226
|
+
spansCovered,
|
|
227
|
+
spansMissing,
|
|
228
|
+
answerSpanRecall,
|
|
229
|
+
hitAnyAt1: hitAnyAt(1),
|
|
230
|
+
hitAnyAt3: hitAnyAt(3),
|
|
231
|
+
hitAnyAt5: hitAnyAt(5),
|
|
232
|
+
hitAnyAt10: hitAnyAt(10),
|
|
233
|
+
reciprocalRank,
|
|
234
|
+
contextEfficiency,
|
|
235
|
+
fileRecallAt5: fileMatched(5),
|
|
236
|
+
fileRecallAt10: fileMatched(10),
|
|
170
237
|
});
|
|
238
|
+
if (!QUIET) {
|
|
239
|
+
const status = hitAnyAt(5) ? 'OK' : 'MISS';
|
|
240
|
+
console.log(`${status.padEnd(4)} ${q.id} spans=${spansCovered.length}/${q.answerSpans.length} fhr=${firstHitRank ?? '-'}`);
|
|
241
|
+
}
|
|
171
242
|
}
|
|
172
243
|
if (!QUIET) {
|
|
173
244
|
printPerQueryTable(perQuery);
|
|
@@ -186,19 +257,23 @@ async function runEval() {
|
|
|
186
257
|
if (!NO_SAVE) {
|
|
187
258
|
const run = {
|
|
188
259
|
timestamp: new Date().toISOString(),
|
|
260
|
+
label: LABEL,
|
|
189
261
|
datasetVersion: dataset.version,
|
|
190
|
-
|
|
262
|
+
topK: TOP_K,
|
|
191
263
|
overall,
|
|
192
264
|
byDifficulty,
|
|
193
265
|
perQuery,
|
|
194
266
|
};
|
|
195
267
|
const dir = resolveResultsDir();
|
|
196
268
|
const stamp = run.timestamp.replace(/[:.]/g, '-');
|
|
197
|
-
const outPath = path.join(dir, `${stamp}.json`);
|
|
269
|
+
const outPath = path.join(dir, `${LABEL}-${stamp}.json`);
|
|
270
|
+
const labelLatestPath = path.join(dir, `${LABEL}-latest.json`);
|
|
198
271
|
const latestPath = path.join(dir, 'latest.json');
|
|
199
272
|
fs.writeFileSync(outPath, JSON.stringify(run, null, 2));
|
|
273
|
+
fs.writeFileSync(labelLatestPath, JSON.stringify(run, null, 2));
|
|
200
274
|
fs.writeFileSync(latestPath, JSON.stringify(run, null, 2));
|
|
201
275
|
console.log(`Saved: ${path.relative(process.cwd(), outPath)}`);
|
|
276
|
+
console.log(` ${path.relative(process.cwd(), labelLatestPath)}`);
|
|
202
277
|
console.log(` ${path.relative(process.cwd(), latestPath)}\n`);
|
|
203
278
|
}
|
|
204
279
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-documentation-rag.js","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eval-documentation-rag.js","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"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"}
|