@appium/mcp-documentation 1.0.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/LICENSE +201 -0
  3. package/README.md +126 -0
  4. package/dist/answer-appium.d.ts +8 -0
  5. package/dist/answer-appium.d.ts.map +1 -0
  6. package/dist/answer-appium.js +38 -0
  7. package/dist/answer-appium.js.map +1 -0
  8. package/dist/appium-skills.d.ts +5 -0
  9. package/dist/appium-skills.d.ts.map +1 -0
  10. package/dist/appium-skills.js +168 -0
  11. package/dist/appium-skills.js.map +1 -0
  12. package/dist/index.d.ts +31 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +69 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/logger.d.ts +4 -0
  17. package/dist/logger.d.ts.map +1 -0
  18. package/dist/logger.js +5 -0
  19. package/dist/logger.js.map +1 -0
  20. package/dist/markdown-header-splitter.d.ts +32 -0
  21. package/dist/markdown-header-splitter.d.ts.map +1 -0
  22. package/dist/markdown-header-splitter.js +180 -0
  23. package/dist/markdown-header-splitter.js.map +1 -0
  24. package/dist/paths.d.ts +2 -0
  25. package/dist/paths.d.ts.map +1 -0
  26. package/dist/paths.js +22 -0
  27. package/dist/paths.js.map +1 -0
  28. package/dist/plugin.d.ts +19 -0
  29. package/dist/plugin.d.ts.map +1 -0
  30. package/dist/plugin.js +18 -0
  31. package/dist/plugin.js.map +1 -0
  32. package/dist/reasoning-rag.d.ts +89 -0
  33. package/dist/reasoning-rag.d.ts.map +1 -0
  34. package/dist/reasoning-rag.js +282 -0
  35. package/dist/reasoning-rag.js.map +1 -0
  36. package/dist/scripts/eval-documentation-rag.d.ts +50 -0
  37. package/dist/scripts/eval-documentation-rag.d.ts.map +1 -0
  38. package/dist/scripts/eval-documentation-rag.js +287 -0
  39. package/dist/scripts/eval-documentation-rag.js.map +1 -0
  40. package/dist/scripts/generate-embeddings-cache.d.ts +13 -0
  41. package/dist/scripts/generate-embeddings-cache.d.ts.map +1 -0
  42. package/dist/scripts/generate-embeddings-cache.js +24 -0
  43. package/dist/scripts/generate-embeddings-cache.js.map +1 -0
  44. package/dist/scripts/rag-eval-dataset.json +516 -0
  45. package/dist/scripts/simple-index-documentation.d.ts +21 -0
  46. package/dist/scripts/simple-index-documentation.d.ts.map +1 -0
  47. package/dist/scripts/simple-index-documentation.js +77 -0
  48. package/dist/scripts/simple-index-documentation.js.map +1 -0
  49. package/dist/scripts/simple-query-documentation.d.ts +13 -0
  50. package/dist/scripts/simple-query-documentation.d.ts.map +1 -0
  51. package/dist/scripts/simple-query-documentation.js +52 -0
  52. package/dist/scripts/simple-query-documentation.js.map +1 -0
  53. package/dist/sentence-transformers-embeddings.d.ts +40 -0
  54. package/dist/sentence-transformers-embeddings.d.ts.map +1 -0
  55. package/dist/sentence-transformers-embeddings.js +119 -0
  56. package/dist/sentence-transformers-embeddings.js.map +1 -0
  57. package/dist/simple-pdf-indexer.d.ts +47 -0
  58. package/dist/simple-pdf-indexer.d.ts.map +1 -0
  59. package/dist/simple-pdf-indexer.js +572 -0
  60. package/dist/simple-pdf-indexer.js.map +1 -0
  61. package/dist/tests/__mocks__/@appium/support.d.ts +92 -0
  62. package/dist/tests/__mocks__/@appium/support.d.ts.map +1 -0
  63. package/dist/tests/__mocks__/@appium/support.js +66 -0
  64. package/dist/tests/__mocks__/@appium/support.js.map +1 -0
  65. package/dist/tests/appium-skills.test.d.ts +2 -0
  66. package/dist/tests/appium-skills.test.d.ts.map +1 -0
  67. package/dist/tests/appium-skills.test.js +26 -0
  68. package/dist/tests/appium-skills.test.js.map +1 -0
  69. package/dist/tests/plugin.test.d.ts +2 -0
  70. package/dist/tests/plugin.test.d.ts.map +1 -0
  71. package/dist/tests/plugin.test.js +18 -0
  72. package/dist/tests/plugin.test.js.map +1 -0
  73. package/dist/tests/simple-pdf-indexer.test.d.ts +2 -0
  74. package/dist/tests/simple-pdf-indexer.test.d.ts.map +1 -0
  75. package/dist/tests/simple-pdf-indexer.test.js +37 -0
  76. package/dist/tests/simple-pdf-indexer.test.js.map +1 -0
  77. package/dist/tool-response.d.ts +4 -0
  78. package/dist/tool-response.d.ts.map +1 -0
  79. package/dist/tool-response.js +12 -0
  80. package/dist/tool-response.js.map +1 -0
  81. package/dist/tools.d.ts +3 -0
  82. package/dist/tools.d.ts.map +1 -0
  83. package/dist/tools.js +3 -0
  84. package/dist/tools.js.map +1 -0
  85. package/dist/uploads/documents.json +1 -0
  86. package/package.json +84 -0
  87. package/scripts/zip-assets.mjs +75 -0
  88. package/src/resources/submodules.zip +0 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Reasoning-Enhanced RAG System
3
+ *
4
+ * This module enhances the existing RAG system by adding reasoning capabilities
5
+ * using Xenova transformers during the document retrieval process.
6
+ * It can perform summarization, question-answering, and analysis on retrieved chunks.
7
+ */
8
+ import { queryVectorStore } from './simple-pdf-indexer.js';
9
+ import log from './logger.js';
10
+ /**
11
+ * Reasoning-enhanced RAG processor
12
+ */
13
+ export class ReasoningRAG {
14
+ transformers = null;
15
+ models = new Map();
16
+ isInitialized = false;
17
+ constructor() {
18
+ void this.initializeTransformers();
19
+ }
20
+ /**
21
+ * Enhanced RAG query with reasoning capabilities
22
+ */
23
+ async queryWithReasoning(query, options = {}) {
24
+ const { topK = 50, reasoningTasks = ['summarization', 'question-answering'], customConfigs, } = options;
25
+ try {
26
+ log.info(`Starting reasoning-enhanced RAG query: "${query}"`);
27
+ // Step 1: Retrieve relevant chunks using existing RAG
28
+ log.info(`Retrieving top ${topK} relevant chunks...`);
29
+ const retrievedChunks = await queryVectorStore(query, topK);
30
+ if (!retrievedChunks || retrievedChunks.length === 0) {
31
+ return {
32
+ query,
33
+ retrievedChunks: [],
34
+ reasoningResults: [],
35
+ summary: 'No relevant information found in the documentation.',
36
+ answer: 'No relevant information found to answer your query.',
37
+ sources: [],
38
+ };
39
+ }
40
+ log.info(`Retrieved ${retrievedChunks.length} chunks for reasoning`);
41
+ // Step 2: Configure reasoning models
42
+ const configs = customConfigs || [
43
+ // Summarization using T5
44
+ {
45
+ task: 'summarization',
46
+ modelName: 'Xenova/t5-small',
47
+ maxLength: 150,
48
+ minLength: 30,
49
+ },
50
+ // Question answering using DistilBERT
51
+ {
52
+ task: 'question-answering',
53
+ modelName: 'Xenova/distilbert-base-cased-distilled-squad',
54
+ },
55
+ ];
56
+ // Filter configs based on requested tasks
57
+ const filteredConfigs = configs.filter((config) => reasoningTasks.includes(config.task));
58
+ // Step 3: Perform reasoning on retrieved chunks
59
+ log.info(`Performing reasoning with ${filteredConfigs.length} different models...`);
60
+ const reasoningResults = await this.processChunksWithReasoning(retrievedChunks, filteredConfigs, query);
61
+ // Step 4: Generate comprehensive summary
62
+ log.info('Generating comprehensive summary...');
63
+ const summary = await this.generateComprehensiveSummary(reasoningResults, query);
64
+ // Step 5: Extract best answer from reasoning results
65
+ const qaResults = reasoningResults.filter((result) => result.metadata.task === 'question-answering' &&
66
+ !result.metadata.error);
67
+ const bestAnswer = qaResults.length > 0
68
+ ? qaResults.sort((a, b) => (b.confidence || 0) - (a.confidence || 0))[0].reasoningOutput
69
+ : summary;
70
+ // Step 6: Extract sources
71
+ const sources = retrievedChunks
72
+ .map((doc) => doc.metadata?.relativePath ||
73
+ doc.metadata?.filename ||
74
+ doc.metadata?.source)
75
+ .filter((source, index, arr) => source && arr.indexOf(source) === index);
76
+ log.info(`Reasoning-enhanced RAG completed. Generated ${reasoningResults.length} reasoning results from ${sources.length} sources`);
77
+ return {
78
+ query,
79
+ retrievedChunks,
80
+ reasoningResults,
81
+ summary,
82
+ answer: bestAnswer,
83
+ sources,
84
+ };
85
+ }
86
+ catch (error) {
87
+ log.error('Error in reasoning-enhanced RAG:', error);
88
+ throw new Error(`Reasoning-enhanced RAG failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
89
+ }
90
+ }
91
+ /**
92
+ * Get available reasoning models and their capabilities
93
+ */
94
+ getAvailableModels() {
95
+ return {
96
+ summarization: [
97
+ 'Xenova/t5-small',
98
+ 'Xenova/t5-base',
99
+ 'Xenova/bart-large-cnn',
100
+ ],
101
+ 'question-answering': [
102
+ 'Xenova/distilbert-base-cased-distilled-squad',
103
+ 'Xenova/roberta-base-squad2',
104
+ ],
105
+ analysis: ['Xenova/gpt2', 'Xenova/distilgpt2'],
106
+ classification: [
107
+ 'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
108
+ 'Xenova/bert-base-uncased',
109
+ ],
110
+ };
111
+ }
112
+ /**
113
+ * Clean up resources
114
+ */
115
+ async cleanup() {
116
+ this.models.clear();
117
+ log.info('Reasoning RAG resources cleaned up');
118
+ }
119
+ /**
120
+ * Initialize the transformers library dynamically
121
+ */
122
+ async initializeTransformers() {
123
+ if (this.transformers) {
124
+ return;
125
+ }
126
+ try {
127
+ // Use eval to avoid CommonJS/ESM conflict during compilation
128
+ const importTransformers = new Function('return import("@xenova/transformers")');
129
+ this.transformers = await importTransformers();
130
+ this.isInitialized = true;
131
+ log.info('Xenova transformers initialized for reasoning');
132
+ }
133
+ catch (error) {
134
+ log.error('Error importing @xenova/transformers:', error);
135
+ throw new Error(`Failed to import @xenova/transformers: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
136
+ }
137
+ }
138
+ /**
139
+ * Get or create a model pipeline for a specific task
140
+ */
141
+ async getModel(config) {
142
+ const modelKey = `${config.task}-${config.modelName}`;
143
+ if (this.models.has(modelKey)) {
144
+ return this.models.get(modelKey);
145
+ }
146
+ await this.initializeTransformers();
147
+ log.info(`Loading model for ${config.task}: ${config.modelName}`);
148
+ try {
149
+ const model = await this.transformers.pipeline(config.task, config.modelName);
150
+ this.models.set(modelKey, model);
151
+ log.info(`Successfully loaded model: ${config.modelName}`);
152
+ return model;
153
+ }
154
+ catch (error) {
155
+ log.error(`Error loading model ${config.modelName}:`, error);
156
+ throw new Error(`Failed to load model: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
157
+ }
158
+ }
159
+ /**
160
+ * Perform reasoning on a text chunk
161
+ */
162
+ async performReasoning(text, config, query) {
163
+ const model = await this.getModel(config);
164
+ try {
165
+ let reasoningOutput;
166
+ let confidence;
167
+ switch (config.task) {
168
+ case 'summarization':
169
+ const summaryResult = await model(text, {
170
+ max_length: config.maxLength || 150,
171
+ min_length: config.minLength || 30,
172
+ do_sample: false,
173
+ });
174
+ reasoningOutput = summaryResult[0].summary_text;
175
+ confidence = summaryResult[0].score;
176
+ break;
177
+ case 'question-answering':
178
+ if (!query) {
179
+ throw new Error('Query is required for question-answering task');
180
+ }
181
+ const qaResult = await model({
182
+ question: query,
183
+ context: text,
184
+ });
185
+ reasoningOutput = qaResult.answer;
186
+ confidence = qaResult.score;
187
+ break;
188
+ case 'analysis':
189
+ // For analysis, we can use a text generation model
190
+ const analysisResult = await model(`Analyze the following text and provide key insights:\n\n${text}\n\nAnalysis:`, {
191
+ max_length: config.maxLength || 200,
192
+ temperature: 0.7,
193
+ do_sample: true,
194
+ });
195
+ reasoningOutput =
196
+ analysisResult[0].generated_text.split('Analysis:')[1]?.trim() ||
197
+ 'No analysis generated';
198
+ break;
199
+ case 'classification':
200
+ // For classification, we can use a classification model
201
+ const classResult = await model(text);
202
+ reasoningOutput = `Classification: ${classResult[0].label} (confidence: ${classResult[0].score.toFixed(3)})`;
203
+ confidence = classResult[0].score;
204
+ break;
205
+ default:
206
+ throw new Error(`Unsupported reasoning task: ${config.task}`);
207
+ }
208
+ return {
209
+ originalChunk: text,
210
+ reasoningOutput,
211
+ confidence,
212
+ metadata: {
213
+ task: config.task,
214
+ model: config.modelName,
215
+ timestamp: new Date().toISOString(),
216
+ },
217
+ };
218
+ }
219
+ catch (error) {
220
+ log.error(`Error performing reasoning with ${config.task}:`, error);
221
+ return {
222
+ originalChunk: text,
223
+ reasoningOutput: `Error during reasoning: ${error instanceof Error ? error.message : String(error)}`,
224
+ metadata: {
225
+ task: config.task,
226
+ model: config.modelName,
227
+ error: true,
228
+ timestamp: new Date().toISOString(),
229
+ },
230
+ };
231
+ }
232
+ }
233
+ /**
234
+ * Process multiple chunks with reasoning in parallel
235
+ */
236
+ async processChunksWithReasoning(chunks, configs, query) {
237
+ const results = [];
238
+ // Process chunks in batches to avoid overwhelming the system
239
+ const batchSize = 5;
240
+ for (let i = 0; i < chunks.length; i += batchSize) {
241
+ const batch = chunks.slice(i, i + batchSize);
242
+ const batchPromises = batch.flatMap((chunk) => configs.map((config) => this.performReasoning(chunk.pageContent, config, query)));
243
+ const batchResults = await Promise.all(batchPromises);
244
+ results.push(...batchResults);
245
+ // Log progress for large batches
246
+ if (chunks.length > batchSize) {
247
+ log.info(`Processed reasoning for ${Math.min(i + batchSize, chunks.length)}/${chunks.length} chunks`);
248
+ }
249
+ }
250
+ return results;
251
+ }
252
+ /**
253
+ * Generate a comprehensive summary from reasoning results
254
+ */
255
+ async generateComprehensiveSummary(reasoningResults, query) {
256
+ // Extract all reasoning outputs
257
+ const summaries = reasoningResults
258
+ .filter((result) => result.metadata.task === 'summarization')
259
+ .map((result) => result.reasoningOutput);
260
+ const analyses = reasoningResults
261
+ .filter((result) => result.metadata.task === 'analysis')
262
+ .map((result) => result.reasoningOutput);
263
+ const qaResults = reasoningResults
264
+ .filter((result) => result.metadata.task === 'question-answering')
265
+ .map((result) => result.reasoningOutput);
266
+ // Combine all insights
267
+ let comprehensiveSummary = `## Query: ${query}\n\n`;
268
+ if (summaries.length > 0) {
269
+ comprehensiveSummary += `### Key Summaries:\n${summaries.map((s, i) => `${i + 1}. ${s}`).join('\n')}\n\n`;
270
+ }
271
+ if (analyses.length > 0) {
272
+ comprehensiveSummary += `### Analysis Insights:\n${analyses.map((a, i) => `${i + 1}. ${a}`).join('\n')}\n\n`;
273
+ }
274
+ if (qaResults.length > 0) {
275
+ comprehensiveSummary += `### Direct Answers:\n${qaResults.map((qa, i) => `${i + 1}. ${qa}`).join('\n')}\n\n`;
276
+ }
277
+ return comprehensiveSummary;
278
+ }
279
+ }
280
+ // Export a singleton instance
281
+ export const reasoningRAG = new ReasoningRAG();
282
+ //# sourceMappingURL=reasoning-rag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-rag.js","sourceRoot":"","sources":["../src/reasoning-rag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
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.
38
+ *
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
48
+ */
49
+ export {};
50
+ //# sourceMappingURL=eval-documentation-rag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-documentation-rag.d.ts","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG"}
@@ -0,0 +1,287 @@
1
+ /**
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.
38
+ *
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
48
+ */
49
+ import * as fs from 'node:fs';
50
+ import * as path from 'node:path';
51
+ import { fileURLToPath } from 'node:url';
52
+ import { queryVectorStore } from '../simple-pdf-indexer.js';
53
+ // -- arg parsing ----------------------------------------------------------
54
+ const __filename = fileURLToPath(import.meta.url);
55
+ const __dirname = path.dirname(__filename);
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 ----------------------------------------------------------------
67
+ function resolveDatasetPath() {
68
+ const candidates = [
69
+ path.resolve(__dirname, 'rag-eval-dataset.json'),
70
+ path.resolve(__dirname, '../../src/scripts/rag-eval-dataset.json'),
71
+ ];
72
+ for (const p of candidates) {
73
+ if (fs.existsSync(p)) {
74
+ return p;
75
+ }
76
+ }
77
+ throw new Error(`rag-eval-dataset.json not found in: ${candidates.join(', ')}`);
78
+ }
79
+ function resolveResultsDir() {
80
+ const dir = path.resolve(__dirname, '../../src/scripts/eval-results');
81
+ fs.mkdirSync(dir, { recursive: true });
82
+ return dir;
83
+ }
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) {
92
+ return retrievedRelPath === expected || retrievedRelPath.endsWith(expected);
93
+ }
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
+ }
105
+ }
106
+ if (chunkHadHit) {
107
+ hitRanks.push(chunk.rank);
108
+ }
109
+ }
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
+ };
118
+ }
119
+ // -- aggregation ----------------------------------------------------------
120
+ function aggregate(results) {
121
+ if (results.length === 0) {
122
+ return {
123
+ count: 0,
124
+ answerSpanRecall: 0,
125
+ hitAnyAt1: 0,
126
+ hitAnyAt3: 0,
127
+ hitAnyAt5: 0,
128
+ hitAnyAt10: 0,
129
+ mrr: 0,
130
+ contextEfficiency: 0,
131
+ fileRecallAt5: 0,
132
+ fileRecallAt10: 0,
133
+ };
134
+ }
135
+ const n = results.length;
136
+ const mean = (xs) => xs.reduce((a, b) => a + b, 0) / xs.length;
137
+ const hitResults = results.filter((r) => r.hitAnyAt10 === 1);
138
+ return {
139
+ count: n,
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)),
151
+ };
152
+ }
153
+ function fmt(n, dp = 3) {
154
+ return n.toFixed(dp);
155
+ }
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)}`);
159
+ }
160
+ function printPerQueryTable(results) {
161
+ const header = 'id | diff | fhr | spans | hit@5 | unique | sources';
162
+ const sep = '-'.repeat(110);
163
+ console.log(sep);
164
+ console.log(header);
165
+ console.log(sep);
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}`);
173
+ }
174
+ console.log(sep);
175
+ }
176
+ // -- main -----------------------------------------------------------------
177
+ async function runEval() {
178
+ const datasetPath = resolveDatasetPath();
179
+ const dataset = JSON.parse(fs.readFileSync(datasetPath, 'utf-8'));
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`);
183
+ const perQuery = [];
184
+ for (const q of dataset.queries) {
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
+ };
213
+ perQuery.push({
214
+ id: q.id,
215
+ query: q.query,
216
+ difficulty: q.difficulty,
217
+ category: q.category,
218
+ expectedSources: q.expectedSources,
219
+ answerSpans: q.answerSpans,
220
+ retrievedSources,
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),
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
+ }
242
+ }
243
+ if (!QUIET) {
244
+ printPerQueryTable(perQuery);
245
+ }
246
+ const overall = aggregate(perQuery);
247
+ const byDifficulty = {};
248
+ for (const d of ['easy', 'medium', 'vague']) {
249
+ byDifficulty[d] = aggregate(perQuery.filter((r) => r.difficulty === d));
250
+ }
251
+ console.log('');
252
+ printAggregate('overall', overall);
253
+ for (const d of ['easy', 'medium', 'vague']) {
254
+ printAggregate(d, byDifficulty[d]);
255
+ }
256
+ console.log('');
257
+ if (!NO_SAVE) {
258
+ const run = {
259
+ timestamp: new Date().toISOString(),
260
+ label: LABEL,
261
+ datasetVersion: dataset.version,
262
+ topK: TOP_K,
263
+ overall,
264
+ byDifficulty,
265
+ perQuery,
266
+ };
267
+ const dir = resolveResultsDir();
268
+ const stamp = run.timestamp.replace(/[:.]/g, '-');
269
+ const outPath = path.join(dir, `${LABEL}-${stamp}.json`);
270
+ const labelLatestPath = path.join(dir, `${LABEL}-latest.json`);
271
+ const latestPath = path.join(dir, 'latest.json');
272
+ fs.writeFileSync(outPath, JSON.stringify(run, null, 2));
273
+ fs.writeFileSync(labelLatestPath, JSON.stringify(run, null, 2));
274
+ fs.writeFileSync(latestPath, JSON.stringify(run, null, 2));
275
+ console.log(`Saved: ${path.relative(process.cwd(), outPath)}`);
276
+ console.log(` ${path.relative(process.cwd(), labelLatestPath)}`);
277
+ console.log(` ${path.relative(process.cwd(), latestPath)}\n`);
278
+ }
279
+ }
280
+ try {
281
+ await runEval();
282
+ }
283
+ catch (err) {
284
+ console.error('Eval failed:', err);
285
+ process.exit(1);
286
+ }
287
+ //# sourceMappingURL=eval-documentation-rag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-documentation-rag.js","sourceRoot":"","sources":["../../src/scripts/eval-documentation-rag.ts"],"names":[],"mappings":"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"}