@devilsdev/rag-pipeline-utils 1.0.0 → 1.0.1
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/.dockerignore +14 -14
- package/.eslintignore +5 -0
- package/.eslintrc.json +21 -0
- package/.github/workflows/ci.yml +46 -42
- package/.github/workflows/release.yml +20 -21
- package/CHANGELOG.md +13 -0
- package/Dockerfile +22 -22
- package/LICENSE +674 -674
- package/README.md +117 -116
- package/__tests__/fixtures/sample-eval-dataset.json +14 -14
- package/__tests__/fixtures/sample.pdf +1 -0
- package/__tests__/integration/cli/config-flow.test.js +29 -44
- package/__tests__/integration/config/load-config.test.js +52 -52
- package/__tests__/unit/core/plugin-registry.test.js +55 -55
- package/__tests__/unit/reranker/llm-reranker.test.js +42 -42
- package/__tests__/unit/reranker/reranker.snapshot.test.js +17 -17
- package/bin/cli.js +168 -168
- package/docs-site/docs/Architecture.md +76 -76
- package/docs-site/docs/CLI.md +69 -69
- package/docs-site/docs/Evaluation.md +61 -61
- package/docs-site/docs/FAQ.md +50 -50
- package/docs-site/docs/Plugins.md +61 -61
- package/docs-site/docs/Usage.md +72 -72
- package/jest.config.js +20 -13
- package/package.json +4 -2
- package/public/src/App.jsx +57 -57
- package/release.config.js +36 -23
- package/scripts/setup.js +7 -0
- package/scripts/test-global-setup.js +18 -0
- package/server.js +31 -31
- package/src/config/load-config.js +35 -35
- package/src/config/validate-schema.js +49 -49
- package/src/core/create-pipeline.js +82 -82
- package/src/core/plugin-registry.js +61 -61
- package/src/dag/dag-engine.js +69 -69
- package/src/evaluate/evaluator.js +44 -44
- package/src/evaluate/scoring.js +73 -73
- package/src/loader/csv-loader.js +30 -30
- package/src/loader/directory-loader.js +37 -37
- package/src/loader/html-loader.js +57 -57
- package/src/loader/markdown-loader.js +58 -58
- package/src/reranker/llm-reranker.js +48 -48
- package/src/utils/logger.js +29 -29
- package/src/utils/retry.js +42 -42
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
# Evaluation
|
|
2
|
-
|
|
3
|
-
This module allows you to evaluate the quality of generated LLM responses in a RAG pipeline.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🎯 Objective
|
|
8
|
-
|
|
9
|
-
Quantify how well the pipeline performs on question-answer pairs using:
|
|
10
|
-
- **BLEU**: Precision on matching tokens
|
|
11
|
-
- **ROUGE**: Recall + overlap on longest subsequences
|
|
12
|
-
- **LLM Feedback** *(planned)*: Score generation based on LLM ratings
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 📄 Dataset Format
|
|
17
|
-
|
|
18
|
-
Each entry in your JSON dataset should include:
|
|
19
|
-
|
|
20
|
-
```json
|
|
21
|
-
{
|
|
22
|
-
"prompt": "What is a vector index?",
|
|
23
|
-
"groundTruth": "A data structure for fast similarity search in vector spaces."
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Saved as: `sample-eval-dataset.json`
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## 🚀 CLI Evaluation
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
rag-pipeline evaluate ./fixtures/sample-eval-dataset.json
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Outputs:
|
|
38
|
-
- ✅ Pass/fail per item
|
|
39
|
-
- 📊 BLEU/ROUGE scores
|
|
40
|
-
- 📈 Aggregated metrics
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## 📊 Dashboard Visualization
|
|
45
|
-
|
|
46
|
-
Use the React dashboard under `/public`:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
node server.js
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Visit: [http://localhost:3000](http://localhost:3000)
|
|
53
|
-
|
|
54
|
-
Displays:
|
|
55
|
-
- Prompt vs Answer
|
|
56
|
-
- Success criteria
|
|
57
|
-
- Metric charts (BLEU, ROUGE)
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
Next → [Plugins](./Plugins.md)
|
|
1
|
+
# Evaluation
|
|
2
|
+
|
|
3
|
+
This module allows you to evaluate the quality of generated LLM responses in a RAG pipeline.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🎯 Objective
|
|
8
|
+
|
|
9
|
+
Quantify how well the pipeline performs on question-answer pairs using:
|
|
10
|
+
- **BLEU**: Precision on matching tokens
|
|
11
|
+
- **ROUGE**: Recall + overlap on longest subsequences
|
|
12
|
+
- **LLM Feedback** *(planned)*: Score generation based on LLM ratings
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 📄 Dataset Format
|
|
17
|
+
|
|
18
|
+
Each entry in your JSON dataset should include:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"prompt": "What is a vector index?",
|
|
23
|
+
"groundTruth": "A data structure for fast similarity search in vector spaces."
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Saved as: `sample-eval-dataset.json`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🚀 CLI Evaluation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
rag-pipeline evaluate ./fixtures/sample-eval-dataset.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Outputs:
|
|
38
|
+
- ✅ Pass/fail per item
|
|
39
|
+
- 📊 BLEU/ROUGE scores
|
|
40
|
+
- 📈 Aggregated metrics
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 📊 Dashboard Visualization
|
|
45
|
+
|
|
46
|
+
Use the React dashboard under `/public`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
node server.js
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Visit: [http://localhost:3000](http://localhost:3000)
|
|
53
|
+
|
|
54
|
+
Displays:
|
|
55
|
+
- Prompt vs Answer
|
|
56
|
+
- Success criteria
|
|
57
|
+
- Metric charts (BLEU, ROUGE)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
Next → [Plugins](./Plugins.md)
|
package/docs-site/docs/FAQ.md
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
# FAQ
|
|
2
|
-
|
|
3
|
-
### ❓ Can I use this with my own vector database?
|
|
4
|
-
Yes! You can implement the `Retriever` interface and register it:
|
|
5
|
-
```ts
|
|
6
|
-
registry.register('retriever', 'mydb', new MyRetriever());
|
|
7
|
-
```
|
|
8
|
-
Then use it via CLI or `.ragrc.json`.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
### ❓ Is streaming LLM response supported?
|
|
13
|
-
Yes. LLM runners can yield async output tokens. This is handled internally via `AsyncIterable` in compatible models.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
### ❓ How do I evaluate performance?
|
|
18
|
-
Use `rag-pipeline evaluate dataset.json` or open the dashboard at `http://localhost:3000` to visualize BLEU/ROUGE and pass rates.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
### ❓ What file types can I ingest?
|
|
23
|
-
Currently supported:
|
|
24
|
-
- `.pdf` (mocked)
|
|
25
|
-
- `.md`
|
|
26
|
-
- `.html`
|
|
27
|
-
- `.csv`
|
|
28
|
-
- Full directory ingestion
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
### ❓ Can I rerank results using a local model?
|
|
33
|
-
Yes, as long as your local LLM implements:
|
|
34
|
-
```ts
|
|
35
|
-
llm.generate(prompt, context): Promise<string>
|
|
36
|
-
```
|
|
37
|
-
Use it to power `LLMReranker`.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
### ❓ How do I contribute?
|
|
42
|
-
Fork the repo → add your plugin or CLI feature → test → submit PR.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
Still stuck? Open an issue at [GitHub](https://github.com/DevilsDev/rag-pipeline-utils/issues).
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
Next → [Back to Introduction](./Introduction.md)
|
|
1
|
+
# FAQ
|
|
2
|
+
|
|
3
|
+
### ❓ Can I use this with my own vector database?
|
|
4
|
+
Yes! You can implement the `Retriever` interface and register it:
|
|
5
|
+
```ts
|
|
6
|
+
registry.register('retriever', 'mydb', new MyRetriever());
|
|
7
|
+
```
|
|
8
|
+
Then use it via CLI or `.ragrc.json`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
### ❓ Is streaming LLM response supported?
|
|
13
|
+
Yes. LLM runners can yield async output tokens. This is handled internally via `AsyncIterable` in compatible models.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
### ❓ How do I evaluate performance?
|
|
18
|
+
Use `rag-pipeline evaluate dataset.json` or open the dashboard at `http://localhost:3000` to visualize BLEU/ROUGE and pass rates.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
### ❓ What file types can I ingest?
|
|
23
|
+
Currently supported:
|
|
24
|
+
- `.pdf` (mocked)
|
|
25
|
+
- `.md`
|
|
26
|
+
- `.html`
|
|
27
|
+
- `.csv`
|
|
28
|
+
- Full directory ingestion
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
### ❓ Can I rerank results using a local model?
|
|
33
|
+
Yes, as long as your local LLM implements:
|
|
34
|
+
```ts
|
|
35
|
+
llm.generate(prompt, context): Promise<string>
|
|
36
|
+
```
|
|
37
|
+
Use it to power `LLMReranker`.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
### ❓ How do I contribute?
|
|
42
|
+
Fork the repo → add your plugin or CLI feature → test → submit PR.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
Still stuck? Open an issue at [GitHub](https://github.com/DevilsDev/rag-pipeline-utils/issues).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
Next → [Back to Introduction](./Introduction.md)
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
# Plugins
|
|
2
|
-
|
|
3
|
-
The toolkit is fully modular. You can inject your own loaders, retrievers, embedders, or LLMs.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🔌 Plugin Architecture
|
|
8
|
-
|
|
9
|
-
All plugins follow a strict interface pattern. Each is registered under a namespace using the plugin registry:
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
registry.register('loader', 'my-custom', new MyLoader());
|
|
13
|
-
const loader = registry.get('loader', 'my-custom');
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
You can register plugins for:
|
|
17
|
-
- `loader`
|
|
18
|
-
- `embedder`
|
|
19
|
-
- `retriever`
|
|
20
|
-
- `llm`
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 🧱 Loader Example
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
class MyMarkdownLoader {
|
|
28
|
-
async load(filePath) {
|
|
29
|
-
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
30
|
-
return [{ chunk: () => raw.split('\n\n') }];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Register it:
|
|
36
|
-
```ts
|
|
37
|
-
registry.register('loader', 'md', new MyMarkdownLoader());
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## ⚡ Runtime Override
|
|
43
|
-
|
|
44
|
-
CLI and API will resolve plugin names from `pluginRegistry`. Use:
|
|
45
|
-
|
|
46
|
-
```json
|
|
47
|
-
{
|
|
48
|
-
"loader": "md",
|
|
49
|
-
"embedder": "cohere",
|
|
50
|
-
"retriever": "chroma",
|
|
51
|
-
"llm": "openai-gpt-4"
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
in `.ragrc.json`
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
This design keeps the core minimal and lets you evolve.
|
|
60
|
-
|
|
61
|
-
Next → [FAQ](./FAQ.md)
|
|
1
|
+
# Plugins
|
|
2
|
+
|
|
3
|
+
The toolkit is fully modular. You can inject your own loaders, retrievers, embedders, or LLMs.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🔌 Plugin Architecture
|
|
8
|
+
|
|
9
|
+
All plugins follow a strict interface pattern. Each is registered under a namespace using the plugin registry:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
registry.register('loader', 'my-custom', new MyLoader());
|
|
13
|
+
const loader = registry.get('loader', 'my-custom');
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
You can register plugins for:
|
|
17
|
+
- `loader`
|
|
18
|
+
- `embedder`
|
|
19
|
+
- `retriever`
|
|
20
|
+
- `llm`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🧱 Loader Example
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
class MyMarkdownLoader {
|
|
28
|
+
async load(filePath) {
|
|
29
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
30
|
+
return [{ chunk: () => raw.split('\n\n') }];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Register it:
|
|
36
|
+
```ts
|
|
37
|
+
registry.register('loader', 'md', new MyMarkdownLoader());
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## ⚡ Runtime Override
|
|
43
|
+
|
|
44
|
+
CLI and API will resolve plugin names from `pluginRegistry`. Use:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"loader": "md",
|
|
49
|
+
"embedder": "cohere",
|
|
50
|
+
"retriever": "chroma",
|
|
51
|
+
"llm": "openai-gpt-4"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
in `.ragrc.json`
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
This design keeps the core minimal and lets you evolve.
|
|
60
|
+
|
|
61
|
+
Next → [FAQ](./FAQ.md)
|
package/docs-site/docs/Usage.md
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
# Usage
|
|
2
|
-
|
|
3
|
-
This guide covers how to use `@yourorg/rag-pipeline-utils` programmatically via API and through the CLI.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 📦 Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @yourorg/rag-pipeline-utils
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 🔧 Programmatic API
|
|
16
|
-
|
|
17
|
-
Import and instantiate a RAG pipeline:
|
|
18
|
-
|
|
19
|
-
```js
|
|
20
|
-
import { createRagPipeline } from '@yourorg/rag-pipeline-utils';
|
|
21
|
-
|
|
22
|
-
const pipeline = createRagPipeline({
|
|
23
|
-
loader: 'markdown',
|
|
24
|
-
embedder: 'openai',
|
|
25
|
-
retriever: 'pinecone',
|
|
26
|
-
llm: 'openai-gpt-4',
|
|
27
|
-
useReranker: true
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const answer = await pipeline.query("What is retrieval-augmented generation?");
|
|
31
|
-
console.log(answer);
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 🔁 Pipeline Methods
|
|
37
|
-
|
|
38
|
-
- `pipeline.ingest(path: string)` → Load, chunk, embed, and store vectors
|
|
39
|
-
- `pipeline.query(prompt: string)` → Retrieve context, rerank (optional), and call LLM
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## 🧩 Plugin Configuration
|
|
44
|
-
|
|
45
|
-
You can customize the pipeline by registering plugins:
|
|
46
|
-
|
|
47
|
-
```js
|
|
48
|
-
registry.register('loader', 'custom', new MyCustomLoader());
|
|
49
|
-
registry.register('retriever', 'opensearch', new MyOpenSearchRetriever());
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## ⚙️ Configuration via `.ragrc.json`
|
|
55
|
-
|
|
56
|
-
Create a JSON file at your root:
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"loader": "directory",
|
|
61
|
-
"embedder": "openai",
|
|
62
|
-
"retriever": "pinecone",
|
|
63
|
-
"llm": "openai-gpt-4",
|
|
64
|
-
"useReranker": true
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Used automatically when no CLI args are passed.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
Next → [CLI](./CLI.md)
|
|
1
|
+
# Usage
|
|
2
|
+
|
|
3
|
+
This guide covers how to use `@yourorg/rag-pipeline-utils` programmatically via API and through the CLI.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📦 Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @yourorg/rag-pipeline-utils
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🔧 Programmatic API
|
|
16
|
+
|
|
17
|
+
Import and instantiate a RAG pipeline:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { createRagPipeline } from '@yourorg/rag-pipeline-utils';
|
|
21
|
+
|
|
22
|
+
const pipeline = createRagPipeline({
|
|
23
|
+
loader: 'markdown',
|
|
24
|
+
embedder: 'openai',
|
|
25
|
+
retriever: 'pinecone',
|
|
26
|
+
llm: 'openai-gpt-4',
|
|
27
|
+
useReranker: true
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const answer = await pipeline.query("What is retrieval-augmented generation?");
|
|
31
|
+
console.log(answer);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🔁 Pipeline Methods
|
|
37
|
+
|
|
38
|
+
- `pipeline.ingest(path: string)` → Load, chunk, embed, and store vectors
|
|
39
|
+
- `pipeline.query(prompt: string)` → Retrieve context, rerank (optional), and call LLM
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 🧩 Plugin Configuration
|
|
44
|
+
|
|
45
|
+
You can customize the pipeline by registering plugins:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
registry.register('loader', 'custom', new MyCustomLoader());
|
|
49
|
+
registry.register('retriever', 'opensearch', new MyOpenSearchRetriever());
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## ⚙️ Configuration via `.ragrc.json`
|
|
55
|
+
|
|
56
|
+
Create a JSON file at your root:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"loader": "directory",
|
|
61
|
+
"embedder": "openai",
|
|
62
|
+
"retriever": "pinecone",
|
|
63
|
+
"llm": "openai-gpt-4",
|
|
64
|
+
"useReranker": true
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Used automatically when no CLI args are passed.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
Next → [CLI](./CLI.md)
|
package/jest.config.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version: 0.1.0
|
|
3
|
-
* Path: /jest.config.js
|
|
4
|
-
* Description: Jest configuration for native ESM test support
|
|
5
|
-
* Author: Ali Kahwaji
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Version: 0.1.0
|
|
3
|
+
* Path: /jest.config.js
|
|
4
|
+
* Description: Jest configuration for native ESM test support
|
|
5
|
+
* Author: Ali Kahwaji
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// jest.config.js
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
verbose: true,
|
|
12
|
+
testEnvironment: 'node',
|
|
13
|
+
transform: {},
|
|
14
|
+
collectCoverage: true,
|
|
15
|
+
coverageDirectory: 'coverage',
|
|
16
|
+
moduleFileExtensions: ['js', 'json'],
|
|
17
|
+
testMatch: ['**/__tests__/**/*.test.js'],
|
|
18
|
+
roots: ['<rootDir>/__tests__'],
|
|
19
|
+
};
|
|
20
|
+
|
|
14
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devilsdev/rag-pipeline-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A modular toolkit for building RAG (Retrieval-Augmented Generation) pipelines in Node.js",
|
|
5
5
|
"main": "src/core/create-pipeline.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
11
|
+
"test": "node ./scripts/setup.js && cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
12
12
|
"test:watch": "jest --watch",
|
|
13
13
|
"lint": "eslint .",
|
|
14
14
|
"prepare": "husky install"
|
|
@@ -37,9 +37,11 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@semantic-release/changelog": "^6.0.3",
|
|
40
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
40
41
|
"@semantic-release/git": "^10.0.1",
|
|
41
42
|
"@semantic-release/github": "^9.2.6",
|
|
42
43
|
"@semantic-release/npm": "^11.0.3",
|
|
44
|
+
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
43
45
|
"@types/jest": "^29.5.14",
|
|
44
46
|
"cross-env": "^7.0.3",
|
|
45
47
|
"esbuild": "^0.25.2",
|
package/public/src/App.jsx
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version: 0.1.0
|
|
3
|
-
* Path: /public/src/App.jsx
|
|
4
|
-
* Description: Evaluation results dashboard UI
|
|
5
|
-
* Author: Ali Kahwaji
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useEffect, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
export default function App() {
|
|
11
|
-
const [results, setResults] = useState([]);
|
|
12
|
-
const [summary, setSummary] = useState({ passRate: 0, avgBLEU: 0, avgROUGE: 0 });
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
fetch('/results/sample-eval.json')
|
|
16
|
-
.then(res => res.json())
|
|
17
|
-
.then(data => {
|
|
18
|
-
setResults(data);
|
|
19
|
-
|
|
20
|
-
const total = data.length;
|
|
21
|
-
const passCount = data.filter(r => r.success).length;
|
|
22
|
-
const avgBLEU = data.reduce((s, r) => s + r.scores.bleu, 0) / total;
|
|
23
|
-
const avgROUGE = data.reduce((s, r) => s + r.scores.rouge, 0) / total;
|
|
24
|
-
|
|
25
|
-
setSummary({
|
|
26
|
-
passRate: (passCount / total * 100).toFixed(1),
|
|
27
|
-
avgBLEU: avgBLEU.toFixed(2),
|
|
28
|
-
avgROUGE: avgROUGE.toFixed(2)
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
}, []);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<main className="max-w-6xl mx-auto p-6">
|
|
35
|
-
<h1 className="text-3xl font-bold mb-4">RAG Evaluation Dashboard</h1>
|
|
36
|
-
|
|
37
|
-
<div className="mb-6 p-4 border rounded shadow bg-white">
|
|
38
|
-
<h2 className="text-xl font-semibold mb-2">Summary</h2>
|
|
39
|
-
<p> Pass Rate: <strong>{summary.passRate}%</strong></p>
|
|
40
|
-
<p> Avg BLEU: <strong>{summary.avgBLEU}</strong></p>
|
|
41
|
-
<p> Avg ROUGE: <strong>{summary.avgROUGE}</strong></p>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
{results.map((res, i) => (
|
|
45
|
-
<div key={i} className="mb-4 p-4 border-l-4 rounded bg-white shadow border-l-gray-300">
|
|
46
|
-
<h3 className="font-bold text-lg">Prompt {i + 1}</h3>
|
|
47
|
-
<p className="mt-2"><strong>Prompt:</strong> {res.prompt}</p>
|
|
48
|
-
<p><strong>Expected:</strong> {res.expected}</p>
|
|
49
|
-
<p><strong>Actual:</strong> {res.actual}</p>
|
|
50
|
-
<p> BLEU: <strong>{res.scores.bleu.toFixed(2)}</strong></p>
|
|
51
|
-
<p> ROUGE: <strong>{res.scores.rouge.toFixed(2)}</strong></p>
|
|
52
|
-
<p>Pass: <strong className={res.success ? 'text-green-600' : 'text-red-600'}>{res.success ? 'Yes' : 'No'}</strong></p>
|
|
53
|
-
</div>
|
|
54
|
-
))}
|
|
55
|
-
</main>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Version: 0.1.0
|
|
3
|
+
* Path: /public/src/App.jsx
|
|
4
|
+
* Description: Evaluation results dashboard UI
|
|
5
|
+
* Author: Ali Kahwaji
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useState } from 'react';
|
|
9
|
+
|
|
10
|
+
export default function App() {
|
|
11
|
+
const [results, setResults] = useState([]);
|
|
12
|
+
const [summary, setSummary] = useState({ passRate: 0, avgBLEU: 0, avgROUGE: 0 });
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
fetch('/results/sample-eval.json')
|
|
16
|
+
.then(res => res.json())
|
|
17
|
+
.then(data => {
|
|
18
|
+
setResults(data);
|
|
19
|
+
|
|
20
|
+
const total = data.length;
|
|
21
|
+
const passCount = data.filter(r => r.success).length;
|
|
22
|
+
const avgBLEU = data.reduce((s, r) => s + r.scores.bleu, 0) / total;
|
|
23
|
+
const avgROUGE = data.reduce((s, r) => s + r.scores.rouge, 0) / total;
|
|
24
|
+
|
|
25
|
+
setSummary({
|
|
26
|
+
passRate: (passCount / total * 100).toFixed(1),
|
|
27
|
+
avgBLEU: avgBLEU.toFixed(2),
|
|
28
|
+
avgROUGE: avgROUGE.toFixed(2)
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<main className="max-w-6xl mx-auto p-6">
|
|
35
|
+
<h1 className="text-3xl font-bold mb-4">RAG Evaluation Dashboard</h1>
|
|
36
|
+
|
|
37
|
+
<div className="mb-6 p-4 border rounded shadow bg-white">
|
|
38
|
+
<h2 className="text-xl font-semibold mb-2">Summary</h2>
|
|
39
|
+
<p> Pass Rate: <strong>{summary.passRate}%</strong></p>
|
|
40
|
+
<p> Avg BLEU: <strong>{summary.avgBLEU}</strong></p>
|
|
41
|
+
<p> Avg ROUGE: <strong>{summary.avgROUGE}</strong></p>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
{results.map((res, i) => (
|
|
45
|
+
<div key={i} className="mb-4 p-4 border-l-4 rounded bg-white shadow border-l-gray-300">
|
|
46
|
+
<h3 className="font-bold text-lg">Prompt {i + 1}</h3>
|
|
47
|
+
<p className="mt-2"><strong>Prompt:</strong> {res.prompt}</p>
|
|
48
|
+
<p><strong>Expected:</strong> {res.expected}</p>
|
|
49
|
+
<p><strong>Actual:</strong> {res.actual}</p>
|
|
50
|
+
<p> BLEU: <strong>{res.scores.bleu.toFixed(2)}</strong></p>
|
|
51
|
+
<p> ROUGE: <strong>{res.scores.rouge.toFixed(2)}</strong></p>
|
|
52
|
+
<p>Pass: <strong className={res.success ? 'text-green-600' : 'text-red-600'}>{res.success ? 'Yes' : 'No'}</strong></p>
|
|
53
|
+
</div>
|
|
54
|
+
))}
|
|
55
|
+
</main>
|
|
56
|
+
);
|
|
57
|
+
}
|