diff --git a/CHANGELOG.md b/CHANGELOG.md
index 861fcb41..686939c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,7 +35,7 @@ for the steps.
CI tests 7.x). Without it, the connector's methods reject with code
`MISSING_DEPENDENCY` and an install hint, and `rag-pipeline init` with
the openai template prints the install step. A clean install drops from
- 58 MB and 174 packages (2.7.1) to 47 MB and 162 packages. Optional peers
+ 58 MB and 188 packages (2.7.1) to 47 MB and 172 packages. Optional peers
are now always left out of the bundle.
### Removed
@@ -217,7 +217,7 @@ for the steps.
### Fixed
- **`npm install` failed on machines without husky installed globally.**
- Every release from 2.2.1 to 2.6.1 declared
+ Every release from 2.0.0 to 2.6.1 declared
`"postinstall": "husky install"`. husky is a development tool that isn't
installed in users' projects, so installing the package failed with
`husky: not found` (or `'husky' is not recognized` on Windows) on clean
@@ -792,5 +792,5 @@ For release notes prior to v2.4.0, see
[2.4.4]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.4
[2.4.3]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.3
[2.4.2]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.2
-[2.4.1]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.1
-[2.4.0]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.0
+[2.4.1]: https://www.npmjs.com/package/@devilsdev/rag-pipeline-utils/v/2.4.1
+[2.4.0]: https://www.npmjs.com/package/@devilsdev/rag-pipeline-utils/v/2.4.0
diff --git a/README.md b/README.md
index dea3a344..eae654b5 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ npm install @devilsdev/rag-pipeline-utils openai
Upgrading from 2.x? The [3.0 migration guide](https://devilsdev.github.io/rag-pipeline-utils/docs/Migration#upgrading-to-v300) lists the changes to make.
-> **`npm install` failed with `husky: not found`?** Versions 2.2.1 to 2.6.1 ran a development hook on install. Install 2.6.2 or later: `npm install @devilsdev/rag-pipeline-utils@latest`.
+> **`npm install` failed with `husky: not found`?** Versions 2.0.0 to 2.6.1 ran a development hook on install. Install 2.6.2 or later: `npm install @devilsdev/rag-pipeline-utils@latest`.
## Quick start
diff --git a/docs-site/blog/2025-11-08-enterprise-release.md b/docs-site/blog/2025-11-08-enterprise-release.md
index 803c6ee1..0447685d 100644
--- a/docs-site/blog/2025-11-08-enterprise-release.md
+++ b/docs-site/blog/2025-11-08-enterprise-release.md
@@ -8,6 +8,10 @@ date: "2025-11-08"
RAG Pipeline Utils v2.2.0 Enterprise Edition delivers production-ready infrastructure with advanced AI capabilities, comprehensive observability, and enterprise-grade security features. This release establishes the platform as a complete solution for mission-critical RAG deployments.
+
+
+> **Editor's note (2.5.0):** several features described here were simulated or incomplete: multimodal processing, federated learning, adaptive retrieval, model training, plugin certification, SSO, multi-tenancy and data governance. Since 3.0.0 they are exported only from `@devilsdev/rag-pipeline-utils/experimental`. See [Experimental modules](/docs/Experimental) for what each one really does.
+
## Enterprise Features
### Advanced AI Capabilities
diff --git a/docs-site/blog/2025-11-08-security-enhancements-v2.3.1.md b/docs-site/blog/2025-11-08-security-enhancements-v2.3.1.md
index 240359c7..2d74a467 100644
--- a/docs-site/blog/2025-11-08-security-enhancements-v2.3.1.md
+++ b/docs-site/blog/2025-11-08-security-enhancements-v2.3.1.md
@@ -3,11 +3,15 @@ slug: security-enhancements-v2.3.1
title: "RAG Pipeline Utils v2.3.1: Advanced Security Enhancements"
authors: [ali]
tags: [release, security, jwt, path-traversal, defense-in-depth]
-date: "2025-11-08"
+date: "2025-11-08T12:00"
---
RAG Pipeline Utils v2.3.1 delivers advanced security enhancements and production hardening improvements. This patch release includes critical updates to JWT validation, path traversal defense mechanisms, and race condition mitigation.
+
+
+> **Editor's note:** in 2.3.1, `sanitizePath`, `InputSanitizer` and `JWTValidator` were internal and not exported from the package. `JWTValidator` is exported since 2.4.0; the path sanitizer is not public. See [Security](/docs/Security) for the current API.
+
## Security Enhancements
### JWT Validation Hardening
diff --git a/docs-site/blog/2025-11-11-securing-production-rag.md b/docs-site/blog/2025-11-11-securing-production-rag.md
index 4bbbcaa6..d0bbae62 100644
--- a/docs-site/blog/2025-11-11-securing-production-rag.md
+++ b/docs-site/blog/2025-11-11-securing-production-rag.md
@@ -10,6 +10,8 @@ Production RAG systems handle sensitive data and require comprehensive security
+> **Editor's note:** the code in this post is illustrative and does not match the package's API. The JWT class is `JWTValidator` (exported since 2.4.0) with `verify(token)`; prompt-injection checks are `detectInjection()` and `PreRetrievalGuard`; `createRagPipeline` takes component instances such as `new OpenAIConnector()` and `new MemoryRetriever()`. See [Security](/docs/Security) and the [API Reference](/docs/API-Reference) for working examples.
+
## The Security Landscape
RAG systems introduce unique security challenges:
diff --git a/docs-site/blog/2025-11-13-comparing-rag-frameworks.md b/docs-site/blog/2025-11-13-comparing-rag-frameworks.md
index 231624dd..2c891014 100644
--- a/docs-site/blog/2025-11-13-comparing-rag-frameworks.md
+++ b/docs-site/blog/2025-11-13-comparing-rag-frameworks.md
@@ -10,6 +10,8 @@ Choosing the right RAG framework impacts development speed, performance, and mai
+> **Editor's note:** the code in this post is illustrative and does not match the package's API. The JWT class is `JWTValidator` (exported since 2.4.0) with `verify(token)`; prompt-injection checks are `detectInjection()` and `PreRetrievalGuard`; `createRagPipeline` takes component instances such as `new OpenAIConnector()` and `new MemoryRetriever()`. See [Security](/docs/Security) and the [API Reference](/docs/API-Reference) for working examples.
+
## Framework Overview
### LangChain
diff --git a/docs-site/blog/2026-04-07-v2.4.0-release.md b/docs-site/blog/2026-04-07-v2.4.0-release.md
index b13f59c6..70841737 100644
--- a/docs-site/blog/2026-04-07-v2.4.0-release.md
+++ b/docs-site/blog/2026-04-07-v2.4.0-release.md
@@ -3,7 +3,7 @@ slug: v2-4-0-release
title: "RAG Pipeline Utils v2.4.0: The Complete Node.js RAG Toolkit"
authors: [ali]
tags: [release, v2.4.0, features]
-date: "2026-04-07"
+date: "2026-04-14"
---
RAG Pipeline Utils v2.4.0 is the most significant release yet — transforming the project from a basic RAG toolkit into the most comprehensive Node.js RAG framework available. This release ships 104 public exports, up from 22 in v2.3.1.
@@ -18,7 +18,7 @@ v2.4.0 nearly quintuples the public API surface. Every major RAG concern now has
### Smart Chunking Engine
-Five strategies cover every document type: sentence, fixed-size, recursive, semantic, and structure-aware chunking. Choose the right strategy for your corpus or let the auto-selector pick one for you.
+Five strategies cover every document type: sentence, fixed-size, recursive, semantic, and structure-aware chunking. Choose the right strategy for your corpus; recursive chunking is the default.
### Citation & Grounding
@@ -26,7 +26,7 @@ Source attribution, hallucination detection, and groundedness scoring let you ve
### RAG Evaluation Framework
-Measure pipeline quality with faithfulness, relevance, context precision/recall, and groundedness metrics. Export results to JSON or CSV for offline analysis.
+Measure pipeline quality with faithfulness, relevance, context precision/recall, and groundedness metrics. Export results to JSON for offline analysis.
### Agentic RAG
@@ -62,7 +62,7 @@ Track token usage per request, enforce budget limits, and compare provider prici
### Provider Connectors
-Seven connectors ship out of the box: OpenAI, Anthropic, Cohere, Ollama, LocalEmbedder, MemoryRetriever, and HuggingFace.
+Six components ship out of the box: OpenAI, Anthropic, Cohere and Ollama connectors, LocalEmbedder and MemoryRetriever, plus a plugin registry for custom providers.
### MCP Integration
@@ -80,7 +80,7 @@ npm install @devilsdev/rag-pipeline-utils
## What's Next
-v3.0.0 will focus on intelligent caching, native Rust bindings, a Kubernetes operator, and edge deployment. Follow the [GitHub repository](https://github.com/alikahwaji/rag-pipeline-utils) for updates.
+v3.0.0 will focus on intelligent caching, native Rust bindings, a Kubernetes operator, and edge deployment. Follow the [GitHub repository](https://github.com/DevilsDev/rag-pipeline-utils) for updates.
---
diff --git a/docs-site/blog/2026-10-29-v2.6.2-release.md b/docs-site/blog/2026-10-29-v2.6.2-release.md
index 1c51b15c..2aa8dfb4 100644
--- a/docs-site/blog/2026-10-29-v2.6.2-release.md
+++ b/docs-site/blog/2026-10-29-v2.6.2-release.md
@@ -6,7 +6,7 @@ tags: [release, production]
date: "2026-10-29T12:00"
---
-v2.6.2 fixes one bug, and it's an important one: on a machine without husky installed globally, `npm install @devilsdev/rag-pipeline-utils` failed. That covers most laptops and every CI runner. Every release from 2.2.1 to 2.6.1 is affected. Please upgrade:
+v2.6.2 fixes one bug, and it's an important one: on a machine without husky installed globally, `npm install @devilsdev/rag-pipeline-utils` failed. That covers most laptops and every CI runner. Every release from 2.0.0 to 2.6.1 is affected. Please upgrade:
```bash
npm install @devilsdev/rag-pipeline-utils@latest
diff --git a/docs-site/blog/2026-10-30-v3.0-release.md b/docs-site/blog/2026-10-30-v3.0-release.md
index 3d533616..2948f8cd 100644
--- a/docs-site/blog/2026-10-30-v3.0-release.md
+++ b/docs-site/blog/2026-10-30-v3.0-release.md
@@ -39,10 +39,10 @@ The install is smaller as a result:
| Clean `npm install` | Size | Packages |
| ------------------- | ----: | -------: |
-| 2.7.1 | 58 MB | 174 |
-| 3.0.0 | 47 MB | 162 |
+| 2.7.1 | 58 MB | 188 |
+| 3.0.0 | 47 MB | 172 |
-Bundling openai 7 for everyone would have meant about 70 MB.
+Bundling openai 7 for everyone would have meant 77 MB.
### Connection failures are retried again
@@ -50,14 +50,14 @@ openai 5 and later use Node's built-in `fetch`, which reports a refused connecti
## Experimental classes leave the main entry
-Since 2.5.0, the simulated or incomplete classes (model training, federated learning, multimodal processing, adaptive retrieval, the SSO providers, multi-tenancy, data governance, `PluginSandbox` and `PluginCertification`) have lived in their own entry point and warned when imported from the main one. In 3.0.0 the main entry no longer exports them:
+Since 2.5.0, the simulated or incomplete classes (model training, federated learning, multimodal processing, adaptive retrieval, the SSO providers, multi-tenancy (`TenantManager`, `ResourceMonitor`), data governance, `PluginSandbox` and `PluginCertification`) have lived in their own entry point and warned when constructed or called through the main one. In 3.0.0 the main entry no longer exports them:
```diff
- import { TenantManager } from "@devilsdev/rag-pipeline-utils";
+ import { TenantManager } from "@devilsdev/rag-pipeline-utils/experimental";
```
-To find the imports to change, run your app or tests on 2.7.x with `node --trace-deprecation`: each `RAG_DEP_*` warning shows the line in your code that uses one of them. Both entries share the same classes in 2.x, so you can change the imports before upgrading. Importing the package also no longer loads these modules at all.
+To find the imports to change, search your code for the class names. Running your app or tests on 2.7.x with `node --trace-deprecation` helps too: each `RAG_DEP_*` warning shows the first place your code constructs that class, once per class per run, but an import that is never constructed (or only used for `instanceof`) doesn't warn. Both entries share the same classes in 2.x, so you can change the imports before upgrading. Importing the package also no longer loads these modules at all.
## Types that described the wrong thing are gone
diff --git a/docs-site/docs/API-Reference.md b/docs-site/docs/API-Reference.md
index 4e7d827e..3b83bfd9 100644
--- a/docs-site/docs/API-Reference.md
+++ b/docs-site/docs/API-Reference.md
@@ -6,13 +6,14 @@ sidebar_position: 15
Reference documentation for the public API of `@devilsdev/rag-pipeline-utils`. The version selector in the navigation bar shows which release this page describes.
-The package has three entry points:
+The package has four entry points:
-| Entry | Contents |
-| -------------------------------------------- | --------------------------------------------------------------------------- |
-| `@devilsdev/rag-pipeline-utils` | The supported API documented on this page |
-| `@devilsdev/rag-pipeline-utils/experimental` | Simulated or incomplete modules; see [Experimental modules](./Experimental) |
-| `@devilsdev/rag-pipeline-utils/cli` | The `rag-pipeline` command line; see [CLI](./CLI) |
+| Entry | Contents |
+| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
+| `@devilsdev/rag-pipeline-utils` | The supported API documented on this page |
+| `@devilsdev/rag-pipeline-utils/experimental` | Simulated or incomplete modules; see [Experimental modules](./Experimental) |
+| `@devilsdev/rag-pipeline-utils/testing` | Offline test stand-ins (`HashEmbedder`, `EchoLLM`, `fixtures`, `createTestPipeline`); see [Testing](./Testing) |
+| `@devilsdev/rag-pipeline-utils/cli` | The `rag-pipeline` command line; see [CLI](./CLI) |
Both CommonJS (`require`) and ESM (`import`) are supported. TypeScript declarations are generated from the JSDoc of every runtime export.
@@ -34,26 +35,29 @@ function createRagPipeline(config?: {
llm?: LLM | string;
reranker?: Reranker | string;
registry?: PluginRegistry;
+ cache?: boolean | CacheBackend | CacheOptions;
}): {
run(input: RunInput): Promise>;
cleanup(): void;
+ cacheStats(): object | null;
};
```
**Parameters:**
-| Parameter | Type | Required | Description |
-| ------------------ | --------------------- | -------- | ----------------------------------------------------------------- |
-| `config.loader` | `Loader \| string` | No | Loader instance or registered plugin name |
-| `config.embedder` | `Embedder \| string` | No | Embedder; used to embed the query when no `queryVector` is passed |
-| `config.retriever` | `Retriever \| string` | No | Retriever; without one, retrieval returns no documents |
-| `config.llm` | `LLM \| string` | No | Language model; without one the pipeline is retrieval-only |
-| `config.reranker` | `Reranker \| string` | No | Reranker applied to the retrieved documents |
-| `config.registry` | `PluginRegistry` | No | Registry used to resolve string names (default: `pluginRegistry`) |
+| Parameter | Type | Required | Description |
+| ------------------ | ----------------------------------- | -------- | ------------------------------------------------------------------------------- |
+| `config.loader` | `Loader \| string` | No | Loader instance or registered plugin name |
+| `config.embedder` | `Embedder \| string` | No | Embedder; used to embed the query when no `queryVector` is passed |
+| `config.retriever` | `Retriever \| string` | No | Retriever; without one, retrieval returns no documents |
+| `config.llm` | `LLM \| string` | No | Language model; without one the pipeline is retrieval-only |
+| `config.reranker` | `Reranker \| string` | No | Reranker applied to the retrieved documents |
+| `config.registry` | `PluginRegistry` | No | Registry used to resolve string names (default: `pluginRegistry`) |
+| `config.cache` | `boolean \| CacheBackend \| object` | No | Cache query embeddings, retrieval results and answers; see [Caching](./Caching) |
String names are resolved from `registry`, or from the exported `pluginRegistry` when no registry is given.
-**Returns:** an object with `run()` and `cleanup()`.
+**Returns:** an object with `run()`, `cleanup()` and `cacheStats()` (hits, misses and skips per cache layer; `null` without a cache).
**Example:**
@@ -85,6 +89,8 @@ const pipeline = createRagPipeline({
});
```
+`OpenAIConnector` needs the OpenAI SDK, an optional peer dependency: `npm install openai` (4.93 or later).
+
`MemoryRetriever` and `FileVectorStore` search by vector, so pass an `embedder` (or a `queryVector` to `run()`); otherwise they have nothing to compare against.
**Aliases:**
@@ -97,13 +103,13 @@ const pipeline = createRagPipeline({
#### pipeline.run()
-Runs one query: embed (if an embedder is configured) → retrieve → `filterResults` → rerank → generate → citations and evaluation (if requested). Documents are loaded through the loader configured in `createRagPipeline()`; there is no separate ingest method.
+Runs one query: embed (if an embedder is configured) → retrieve → `filterResults` → rerank → generate → citations and evaluation (if requested). A configured loader's `load()` is called with no arguments at the start of every run and its result is ignored; add documents to the retriever yourself with `retriever.store()` (or `rag-pipeline ingest`).
**Signature:**
```typescript
async run(params: {
- query: string;
+ query?: string;
queryVector?: number[];
options?: RunOptions;
}): Promise>
@@ -113,7 +119,7 @@ async run(params: {
| Parameter | Type | Required | Description |
| ------------------------- | --------------------------- | -------- | ------------------------------------------------------------------------------------- |
-| `query` | `string` | Yes | Natural language query |
+| `query` | `string` | No | Natural language query; give `query`, `queryVector` or both |
| `queryVector` | `number[]` | No | Pre-computed query embedding (skips the embedder) |
| `options.topK` | `number` | No | Number of documents to retrieve (default: 3) |
| `options.timeout` | `number` | No | Timeout in milliseconds; cancels in-flight work |
@@ -136,6 +142,7 @@ interface RunResult {
answer: string | null; // null when no llm is configured
citations?: object; // when options.citations is set and an llm is configured
evaluation?: object; // when options.evaluate is set
+ cache?: object; // "hit" | "miss" | "skip" per layer, when a cache is configured
}
// Failures resolve instead of throwing:
@@ -573,10 +580,10 @@ Executes async functions as a directed acyclic graph. `DAGEngine` is an alias of
**Methods:**
```typescript
-addNode(id: string, fn: (input: any) => Promise, options?: object): DAGNode
+addNode(id: string, fn: (input: any) => Promise, options?: object): object // the node
connect(fromId: string, toId: string): void
execute(seed?: any, options?: object): Promise
-validate(): void
+validate(): boolean // true, or throws
```
**Example:**
@@ -747,7 +754,7 @@ await server.start();
console.log(server.getStatus().url);
```
-`start()` binds a real port since 2.5.0, so code that constructed a `DevServer` without expecting it to listen may now see `EADDRINUSE`.
+`start()` binds the port; pass `port: 0` in tests to avoid `EADDRINUSE`.
---
@@ -773,7 +780,7 @@ createError(code: string, context?: object, originalError?: Error): EnhancedErro
wrapError(error: Error, code: string, context?: object): EnhancedError
```
-`ERROR_CODES` contains codes such as `CONFIG_NOT_FOUND`, `CONFIG_INVALID_JSON`, `CONFIG_VALIDATION_FAILED`, `PLUGIN_NOT_FOUND`, `PLUGIN_LOAD_FAILED`, `PLUGIN_CONTRACT_VIOLATION`, `PIPELINE_EXECUTION_FAILED`, `PIPELINE_STAGE_FAILED`, `VALIDATION_FAILED`, `NETWORK_TIMEOUT` and `FS_READ_ERROR`. Every code has its own message and suggestions, whose `{placeholders}` are filled from `context`; a suggestion whose placeholder has no value is left out. See the [generated reference](./api/rag-pipeline-utils/namespaces/errorFormatter/) for the full list.
+`ERROR_CODES` contains codes such as `CONFIG_NOT_FOUND`, `CONFIG_INVALID_JSON`, `CONFIG_VALIDATION_FAILED`, `PLUGIN_NOT_FOUND`, `PLUGIN_LOAD_FAILED`, `PLUGIN_CONTRACT_VIOLATION`, `PIPELINE_EXECUTION_FAILED`, `PIPELINE_STAGE_FAILED`, `VALIDATION_FAILED`, `NETWORK_TIMEOUT` and `FS_READ_ERROR`. Every code has its own message and suggestions, whose `{placeholders}` are filled from `context`. A suggestion whose placeholder has no value is left out, but a placeholder in the message stays literal, so pass every value the message uses. See the [generated reference](./api/rag-pipeline-utils/namespaces/errorFormatter/) for the full list.
**Example:**
@@ -791,8 +798,10 @@ throw createError(ERROR_CODES.PLUGIN_NOT_FOUND, { plugin: "custom-embedder" });
try {
await riskyOperation();
} catch (err) {
+ // "Pipeline execution failed at stage 'retrieval': "
throw wrapError(err, ERROR_CODES.PIPELINE_EXECUTION_FAILED, {
stage: "retrieval",
+ reason: err.message,
});
}
```
@@ -807,15 +816,6 @@ The shared plugin registry. Plugins registered here are resolvable by name in `c
**Methods:**
-#### validatePlugin()
-
-```typescript
-validatePlugin(stage: PluginType, plugin: object, options?: { registry?: boolean }):
- { valid: boolean; errors: string[]; warnings: string[] }
-```
-
-Checks a plugin without throwing; `{ registry: true }` adds the rules `register()` enforces. See [Testing a plugin in code](./Plugins.md#testing-a-plugin-in-code).
-
#### register()
```typescript
@@ -849,6 +849,7 @@ list(category: PluginType): string[]
- `'retriever'` - Document retrievers
- `'llm'` - Language models
- `'reranker'` - Result rerankers
+- `'evaluator'` - Evaluators (accepted by the registry; not called by `createRagPipeline`)
**Example:**
@@ -873,6 +874,17 @@ console.log(pluginRegistry.list("embedder"));
To install third-party plugins into a project, use `rag-pipeline hub install ` (see [CLI](./CLI)).
+### validatePlugin
+
+Exported from the package root (`import { validatePlugin } from "@devilsdev/rag-pipeline-utils"`); it is not a registry method.
+
+```typescript
+validatePlugin(stage: PluginType, plugin: object, options?: { registry?: boolean }):
+ { valid: boolean; errors: string[]; warnings: string[] }
+```
+
+Checks a plugin without throwing; `{ registry: true }` adds the rules `register()` enforces. See [Testing a plugin in code](./Plugins.md#testing-a-plugin-in-code).
+
---
## Performance
@@ -926,7 +938,7 @@ Every method receives an optional `signal` (an `AbortSignal`) that it should pas
```typescript
interface Loader {
- load(source?: string): Promise;
+ load(): unknown; // called with no arguments at the start of each run; the result is ignored
}
```
@@ -998,7 +1010,18 @@ interface Document {
id: string;
content: string;
metadata?: Record;
- score?: number;
+ vector?: number[]; // the embedding the built-in retrievers read
+}
+```
+
+**SearchResult** (what retrievers return and rerankers and `llm.generate()` receive):
+
+```typescript
+interface SearchResult {
+ id: string;
+ score: number; // similarity; higher is closer
+ content?: string;
+ metadata?: Record;
}
```
@@ -1008,6 +1031,7 @@ interface Document {
interface StreamChunk {
token: string;
done: boolean;
+ results?: SearchResult[]; // final chunk of a retrieval-only (no llm) stream
citations?: object; // final chunk only, when options.citations is set
evaluation?: object; // final chunk only, when options.evaluate is set
}
@@ -1015,9 +1039,9 @@ interface StreamChunk {
---
-## Deprecations
+## Removed in 3.0
-Experimental modules are deprecated on the main entry: `ModelTrainingOrchestrator`, `FederatedLearningCoordinator`, `MultiModalProcessor`, `AdaptiveRetrievalEngine`, `SSOManager`, `SAMLProvider`, `OAuth2Provider`, `ActiveDirectoryProvider`, `OIDCProvider`, `TenantManager`, `ResourceMonitor`, `DataGovernanceManager` / `DataGovernance`, `PluginSandbox` and `PluginCertification`. Using one from `@devilsdev/rag-pipeline-utils` emits a one-time `DeprecationWarning` (`RAG_DEP_*` codes); import it from `@devilsdev/rag-pipeline-utils/experimental` instead. The classes are shared by both entries, so `instanceof` checks keep working. See [Experimental modules](./Experimental).
+`ModelTrainingOrchestrator`, `FederatedLearningCoordinator`, `MultiModalProcessor`, `AdaptiveRetrievalEngine`, `SSOManager`, `SAMLProvider`, `OAuth2Provider`, `ActiveDirectoryProvider`, `OIDCProvider`, `TenantManager`, `ResourceMonitor`, `DataGovernanceManager` / `DataGovernance`, `PluginSandbox` and `PluginCertification` are no longer exported from `@devilsdev/rag-pipeline-utils`; import them from `@devilsdev/rag-pipeline-utils/experimental` (see [Experimental modules](./Experimental)). 3.0 also removed the TypeScript types `LoadConfigOptions`, `LLMResponse`, `DAGNode`, `DAGOptions`, `ErrorFormatter`, `EvalResult` and `Document.embedding`; the [migration guide](./Migration#upgrading-to-v300) lists replacements.
## Version Information
diff --git a/docs-site/docs/Architecture.md b/docs-site/docs/Architecture.md
index 0e4342fa..cc3ed808 100644
--- a/docs-site/docs/Architecture.md
+++ b/docs-site/docs/Architecture.md
@@ -24,7 +24,7 @@ This guide outlines the internal architecture of @devilsdev/rag-pipeline-utils:
- **Liskov Substitution Principle (LSP)**: Any plugin can be replaced with another of the same type
- An OpenAI embedder can be swapped for the Cohere or local TF-IDF embedder
- - Retrievers (`MemoryRetriever`, `FileVectorStore`, `HybridRetriever`, `GraphRetriever`, custom stores) are interchangeable as long as they implement `retrieve()`
+ - Retrievers (`MemoryRetriever`, `FileVectorStore`, `HybridRetriever`, `GraphRetriever`, `PgVectorRetriever`, `QdrantRetriever`, custom stores) are interchangeable as long as they implement `retrieve()`
- **Interface Segregation Principle (ISP)**: Plugins only implement the methods of their stage
@@ -183,13 +183,13 @@ Components that ignore `signal` still work: on abort the run settles anyway and
### **Configuration-driven components (CLI)**
-The CLI reads `.ragrc.json` pipeline entries `{ stage, name, config }`. A name resolves to a built-in component (for example `local`, `openai`, `ollama`, `cohere` embedders; `file-store` and `memory` retrievers; `openai`, `anthropic`, `ollama` LLMs; `scoring` reranker), to a custom module listed under `plugins`, or to a plugin registered on `pluginRegistry`. See the [CLI reference](./CLI.md).
+The CLI reads `.ragrc.json` pipeline entries `{ stage, name, config }`. A name resolves to a built-in component (for example `local`, `openai`, `ollama`, `cohere` embedders; `file-store`, `memory`, `pgvector` and `qdrant` retrievers; `openai`, `anthropic`, `ollama` LLMs; `scoring` reranker), to a custom module listed under `plugins`, or to a plugin registered on `pluginRegistry`. See the [CLI reference](./CLI.md).
---
## Pipeline Factory Pattern
-`createRagPipeline({ loader, embedder, retriever, llm, reranker, registry })` returns `{ run, cleanup }`. Each component may be an instance or a name resolved from `registry` (default: the exported `pluginRegistry`).
+`createRagPipeline({ loader, embedder, retriever, llm, reranker, registry, cache })` returns `{ run, cleanup, cacheStats }`; `cache` enables the pipeline cache (see [Caching](./Caching.md)). Each component may be an instance or a name resolved from `registry` (default: the exported `pluginRegistry`).
`run({ query, queryVector, options })` performs, in order:
@@ -213,7 +213,7 @@ There is no middleware stack. Cross-cutting behaviour is added by wrapping the p
- **Retries**: built-in connectors retry transient failures (network errors, 408/409/425/429/5xx) with exponential backoff, jitter and `Retry-After`. `retry` / `withRetry` are exported for your own components.
- **Cost**: `CostTracker` wraps a pipeline and records token usage and cost; `CostCalculator` exposes pricing provenance (`PRICING_METADATA`).
- **Tracing**: `ExecutionTracer` wraps a pipeline and records per-run traces; `TraceInspector` analyses them.
-- **Caching**: `EmbeddingReranker` keeps an LRU cache of document embeddings (`cacheSize`).
+- **Caching**: `createRagPipeline({ cache })` caches query embeddings, retrieval results and answers (see [Caching](./Caching.md)); `EmbeddingReranker` keeps an LRU cache of document embeddings (`cacheSize`).
---
@@ -265,7 +265,7 @@ Some classes are simulations or incomplete: `ModelTrainingOrchestrator`, `Federa
## Pipeline Flow
-The flow below describes 2.5.0. Hybrid retrieval, reranking, citations, evaluation, guardrails and agentic RAG were added in 2.4.0; cancellation, the pre-generation retrieval guard and retrieval-only runs in 2.5.0.
+The flow below describes 3.0.0. Hybrid retrieval, reranking, citations, evaluation, guardrails and agentic RAG were added in 2.4.0; cancellation, the pre-generation retrieval guard and retrieval-only runs in 2.5.0; the pipeline cache in 2.6.0.
```
Ingestion: Documents → Loader (chunks) → Embedder → Retriever.store() (e.g. FileVectorStore)
diff --git a/docs-site/docs/Benchmarks.md b/docs-site/docs/Benchmarks.md
index 507b399c..1c9ffc43 100644
--- a/docs-site/docs/Benchmarks.md
+++ b/docs-site/docs/Benchmarks.md
@@ -107,7 +107,7 @@ Dataset: BEIR SciFact (test split), 5,183 documents, 300 queries, 339 relevance
- **`HashEmbedder` is the testing stand-in**, shown as a floor.
- **TF-IDF vectors are long.** `LocalEmbedder` vectors have one dimension
per vocabulary token (10,000 here), so an exact search over them in
- `MemoryRetriever` takes about 60 ms per query on this corpus.
+ `MemoryRetriever` takes about 70 ms per query on this corpus.
- The metrics are those of BEIR and trec_eval. Recall@100 shows how many
relevant documents a reranker could still recover from the top 100.
diff --git a/docs-site/docs/CLI.md b/docs-site/docs/CLI.md
index c28df6cb..4f121ea2 100644
--- a/docs-site/docs/CLI.md
+++ b/docs-site/docs/CLI.md
@@ -28,7 +28,7 @@ rag-pipeline ingest ./docs # index .md, .html, .csv and .txt files
rag-pipeline query "How many vacation days do employees get?"
```
-With the default `local` template there is no language model, so `query` prints the best-matching passages. Use `--template openai`, `ollama` or `anthropic` (or edit the config) to generate answers.
+With the default `local` template there is no language model, so `query` prints the best-matching passages. Use `--template openai`, `ollama` or `anthropic` (or edit the config) to generate answers. The `openai` embedder and LLM need the OpenAI SDK: `npm install openai` (an optional peer dependency since 3.0.0).
---
@@ -36,11 +36,15 @@ With the default `local` template there is no language model, so `query` prints
> **Tip:** the [configuration builder](./Config-Builder.mdx) writes this file for you in the browser.
-`init` writes a file like this:
+`init` (the default `local` template) writes:
```json
{
"namespace": "default",
+ "metadata": {
+ "name": "rag-pipeline",
+ "createdAt": "2026-10-30T12:00:00.000Z"
+ },
"pipeline": [
{ "stage": "loader", "name": "auto" },
{ "stage": "embedder", "name": "local" },
@@ -48,12 +52,13 @@ With the default `local` template there is no language model, so `query` prints
"stage": "retriever",
"name": "file-store",
"config": { "path": ".rag/index.json" }
- },
- { "stage": "llm", "name": "openai", "config": { "model": "gpt-4o-mini" } }
+ }
]
}
```
+`--template openai` uses `openai` for the embedder and adds `{ "stage": "llm", "name": "openai" }`; `ollama` does the same with `ollama`; `anthropic` keeps the `local` embedder and adds an `anthropic` LLM. Add `"config": { "model": "gpt-4o-mini" }` to an entry to override its defaults.
+
Each pipeline entry is `{ "stage", "name", "config"? }`. `config` is passed to the component's constructor. Names resolve in this order:
1. **Built-in components** (`rag-pipeline info --plugins` lists them):
@@ -160,7 +165,7 @@ rag-pipeline query "remote work" --top-k 5 --json
| Option | Description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `--top-k ` | Passages to retrieve (default 3) |
-| `--json` | Print `{ answer, results, citations }` as JSON |
+| `--json` | Print `{ answer, results, citations }` as JSON (`answer` is `null` and `citations` absent without an `llm`) |
| `--streaming` | Print the answer as the model generates it (needs an `llm` stage) |
| `--timeout ` | Abort the query after this many milliseconds; exits `1` with `Execution timeout` |
| `--trace` | Time spent in each stage: embed, retrieve, rerank, generate |
@@ -179,7 +184,7 @@ With `--json`, `--trace`, `--stats` and `--explain` add `trace`, `stats` and `ex
## `eval`
-Runs a test set through the configured pipeline and index, prints the scores, and exits `1` when the run fails, so it can gate a CI job. A run fails when a case errors, a metric is below its `--min`, or the run regressed from a `--baseline` report.
+Runs a test set through the configured pipeline and index, prints the scores, and exits `1` when the run fails, so it can gate a CI job. A run fails when a case errors, a metric is below its `--min` or was not measured, or the run regressed from a `--baseline` report.
```bash
# On your main branch: save a baseline
diff --git a/docs-site/docs/Comparison.md b/docs-site/docs/Comparison.md
index 73bbf92c..22bbfea5 100644
--- a/docs-site/docs/Comparison.md
+++ b/docs-site/docs/Comparison.md
@@ -14,30 +14,30 @@ right choice for **your** workload — not whether it's "the best" in
the abstract.
> **Currency**: this comparison reflects the state of each project
-> as of **April 2026**. The JS RAG ecosystem moves fast. If you read
+> as of **October 2026** (3.0.0). The JS RAG ecosystem moves fast. If you read
> this six months later, double-check the points where each project
> has likely improved.
## At a glance
-| Dimension | `@devilsdev/rag-pipeline-utils` | LangChain.js | LlamaIndex.TS |
-| -------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------- |
-| **Primary focus** | Production RAG pipelines for Node.js services | General-purpose LLM orchestration | Indexing-first RAG with rich data structures |
-| **License** | MIT | MIT | MIT |
-| **Bundle** | Single package (plus an `/experimental` entry for simulated modules) | Many packages (`@langchain/core`, `@langchain/community`, etc.) | Single package, larger surface |
-| **Built-in evaluation** | ✅ Faithfulness, relevance, context P/R, groundedness | 🟡 Via separate `langsmith` (paid SaaS option) | 🟡 Some metrics, evolving |
-| **Built-in citations** | ✅ Per-sentence attribution + groundedness score | 🟡 Doable manually | 🟡 Doable manually |
-| **Built-in guardrails** | ✅ 3-layer (pre / retrieval / post) | 🟡 Via integrations (Guardrails AI, etc.) | 🟡 Via integrations |
-| **Vector store ecosystem** | In-memory and JSON-file stores + plugin contract for any | ✅ 50+ integrations | ✅ Many integrations + native indexes |
-| **LLM provider ecosystem** | OpenAI, Anthropic, Cohere, Ollama + plugin contract | ✅ Largest ecosystem | ✅ Large ecosystem |
-| **Agentic / tools** | 🟡 Query planning (heuristic or LLM-proposed) + iterative retrieval via DAG | ✅ Mature agent framework, tool use | ✅ Agent framework |
-| **GraphRAG** | ✅ Knowledge-graph construction + traversal | 🟡 Via integrations | 🟡 Via property graphs |
-| **MCP support** | ✅ First-class | 🟡 Community add-ons | 🟡 Community add-ons |
-| **TypeScript types** | ✅ `.d.ts` generated from JSDoc; build fails on undeclared exports | ✅ Native TS | ✅ Native TS |
-| **Module format** | Dual ESM + CJS | Mostly ESM, some CJS | Mostly ESM |
-| **Stability policy** | ✅ Documented [SEMVER policy](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/SEMVER.md) | Versioned per package | Versioned |
-| **Security policy** | ✅ Documented disclosure + capability matrix | Via GitHub Security | Via GitHub Security |
-| **Production complexity** | Low — pipeline + components | Medium — many abstractions | Medium — index types vocabulary |
+| Dimension | `@devilsdev/rag-pipeline-utils` | LangChain.js | LlamaIndex.TS |
+| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------- |
+| **Primary focus** | Production RAG pipelines for Node.js services | General-purpose LLM orchestration | Indexing-first RAG with rich data structures |
+| **License** | MIT | MIT | MIT |
+| **Bundle** | Single package (plus `/testing` helpers and an `/experimental` entry for simulated modules) | Many packages (`@langchain/core`, `@langchain/community`, etc.) | Single package, larger surface |
+| **Built-in evaluation** | ✅ Faithfulness, relevance, context P/R, groundedness | 🟡 Via separate `langsmith` (paid SaaS option) | 🟡 Some metrics, evolving |
+| **Built-in citations** | ✅ Per-sentence attribution + groundedness score | 🟡 Doable manually | 🟡 Doable manually |
+| **Built-in guardrails** | ✅ 3-layer (pre / retrieval / post) | 🟡 Via integrations (Guardrails AI, etc.) | 🟡 Via integrations |
+| **Vector store ecosystem** | In-memory and JSON-file stores, PostgreSQL/pgvector and Qdrant, BM25 and hybrid search, plus a plugin contract for any other | ✅ 50+ integrations | ✅ Many integrations + native indexes |
+| **LLM provider ecosystem** | OpenAI (and OpenAI-compatible APIs via `baseURL`), Anthropic, Ollama, any Vercel AI SDK model via `createAiSdkAdapter`; Cohere for embeddings and reranking; plus a plugin contract | ✅ Largest ecosystem | ✅ Large ecosystem |
+| **Agentic / tools** | 🟡 Query planning (heuristic or LLM-proposed) + iterative retrieval via DAG | ✅ Mature agent framework, tool use | ✅ Agent framework |
+| **GraphRAG** | ✅ Knowledge-graph construction + traversal | 🟡 Via integrations | 🟡 Via property graphs |
+| **MCP support** | ✅ First-class | 🟡 Community add-ons | 🟡 Community add-ons |
+| **TypeScript types** | ✅ `.d.ts` generated from JSDoc; build fails on undeclared exports | ✅ Native TS | ✅ Native TS |
+| **Module format** | Dual ESM + CJS | Mostly ESM, some CJS | Mostly ESM |
+| **Stability policy** | ✅ Documented [SEMVER policy](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/SEMVER.md) | Versioned per package | Versioned |
+| **Security policy** | ✅ Documented disclosure + capability matrix | Via GitHub Security | Via GitHub Security |
+| **Production complexity** | Low — pipeline + components | Medium — many abstractions | Medium — index types vocabulary |
## Where each one wins
@@ -78,7 +78,7 @@ the abstract.
add no API spend; they are also less nuanced than LLM-judged metrics.
- You need a **predictable, narrow surface area for security review**.
One package, MIT-licensed, no required SaaS.
-- You want **ESM-first dual-build** and a documented [SEMVER policy](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/SEMVER.md)
+- You want a **dual ESM + CommonJS build** and a documented [SEMVER policy](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/SEMVER.md)
with explicit deprecation windows.
- You want **MCP** (Model Context Protocol) support as a first-class
feature, so your pipeline can plug into Claude Desktop and other
@@ -119,13 +119,13 @@ This framework explicitly does not try to be:
Node.js library. There's no UI to drag-and-drop pipelines together.
- **A managed vector store.** Bring your own (or use the in-memory
retriever for development).
-- **A Python framework.** Node.js only.
+- **A Python framework.** Node.js 22 or later only.
## How to decide
Pick `@devilsdev/rag-pipeline-utils` if you can answer **yes** to:
-- Are you building in **Node.js**?
+- Are you building on **Node.js 22+**?
- Is your primary workload **RAG** (not general agents)?
- Do you need **citations or evaluation** to be a first-class concern?
- Do you value **a small, narrow API** over breadth of integrations?
diff --git a/docs-site/docs/Concepts-Connectors.md b/docs-site/docs/Concepts-Connectors.md
index 7e56dd45..72a47bff 100644
--- a/docs-site/docs/Concepts-Connectors.md
+++ b/docs-site/docs/Concepts-Connectors.md
@@ -34,11 +34,11 @@ defined as a JSON schema in `contracts/`.
| `GraphRetriever` | Knowledge-graph retrieval over extracted entities. |
| `PgVectorRetriever` | PostgreSQL with pgvector: cosine similarity, upserts in one transaction, an HNSW index. See [PostgreSQL with pgvector](#postgresql-with-pgvector). |
| `QdrantRetriever` | Qdrant over its REST API, with no client package. See [Qdrant](#qdrant). |
-| Pinecone, Weaviate, Qdrant | Build your own retriever using the documented contract — examples in [Examples](./Examples). |
+| Pinecone, Weaviate, others | Build your own retriever with the [retriever contract](./Plugins); [examples/openai-pinecone](https://github.com/DevilsDev/rag-pipeline-utils/tree/main/examples/openai-pinecone) adapts a Pinecone index. |
### PostgreSQL with pgvector
-`PgVectorRetriever` keeps documents in a PostgreSQL table with the [pgvector](https://github.com/pgvector/pgvector) extension. Pass a [`pg`](https://www.npmjs.com/package/pg) Pool you manage, or a connection string and install `pg` (an optional dependency, loaded only when used):
+`PgVectorRetriever` keeps documents in a PostgreSQL table with the [pgvector](https://github.com/pgvector/pgvector) extension. Pass a [`pg`](https://www.npmjs.com/package/pg) Pool you manage, or a connection string and install `pg` yourself (`npm install pg`; an optional peer dependency, loaded only when used):
```javascript no-run
import pg from "pg";
@@ -150,12 +150,12 @@ As with pgvector, the CLI's `local` embedder can't be used with it; use `openai`
| Connector | Notes |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
-| `OpenAIConnector` | OpenAI Chat Completions (default model `gpt-4o-mini`) + streaming via `generateStream()`. |
+| `OpenAIConnector` | OpenAI Chat Completions (default model `gpt-4o-mini`) + streaming via `generateStream()`. Needs `npm install openai`. |
| `AnthropicConnector` | Anthropic Messages API + streaming. Reads `ANTHROPIC_API_KEY`. |
| `OllamaConnector` | Local Ollama server for offline development and self-hosted production. |
| Custom | Implement the `llm` contract: `generate(query, docs, { signal, ...options })` returning a string, and optionally `generateStream(...)`. |
-All built-in connectors retry only transient failures (network errors, 408/409/425/429/5xx) with exponential backoff, jitter and `Retry-After`, fail fast with `MISSING_API_KEY` when no key is configured, honour the run's `AbortSignal`, and pass retrieved context to the model as delimited, untrusted reference data in the user message.
+All built-in connectors retry only transient failures (network errors, 408/409/425/429/5xx) with exponential backoff, jitter and `Retry-After`, fail fast with `MISSING_API_KEY` when a hosted API has no key configured (`OpenAIConnector` also rejects with `MISSING_DEPENDENCY` when the optional `openai` package isn't installed), honour the run's `AbortSignal`, and pass retrieved context to the model as delimited, untrusted reference data in the user message.
### OpenAI-compatible providers (`baseURL`)
@@ -253,4 +253,4 @@ is breaking and ships only in major versions.
- [Plugins](./Plugins) — full plugin development guide
- [Architecture](./Architecture.md#plugin-system) — internal plugin registry design
-- [Examples](./Examples) — recipe for a custom Pinecone retriever, custom embedder, etc.
+- [Plugins](./Plugins) — writing a custom retriever or embedder; [examples/openai-pinecone](https://github.com/DevilsDev/rag-pipeline-utils/tree/main/examples/openai-pinecone) adapts a Pinecone index
diff --git a/docs-site/docs/Concepts-Core.md b/docs-site/docs/Concepts-Core.md
index 5d2f0c8d..c618c6db 100644
--- a/docs-site/docs/Concepts-Core.md
+++ b/docs-site/docs/Concepts-Core.md
@@ -16,20 +16,20 @@ guardrails you bolt on top.
> Today everything ships as one npm package. The conceptual modules
> describe **what code is responsible for what** so you can reason
> about blast radius, security review scope, and dependency footprint
-> without us splitting the codebase. A real monorepo split is on the
-> [roadmap](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/README.md#roadmap).
+> without us splitting the codebase. Splitting into scoped packages is on the
+> [roadmap](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/.github/PROJECT_ROADMAP.md) for 3.x.
## What's in rag-core
-| Surface | Purpose |
-| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `createRagPipeline({ loader, embedder, retriever, llm, reranker, registry })` | The factory. Wires the components into a runnable pipeline and returns `{ run, cleanup }`. |
-| `run({ query, queryVector, options })` | The main execution entry point. Resolves `{ success, query, results, answer, citations?, evaluation? }`; failures, timeouts and aborts resolve `{ success: false, error }`. |
-| `pluginRegistry` | Holds registered loader, embedder, retriever, reranker and LLM plugins by name. Validates them against the contract schemas in `contracts/`. |
-| Plugin contracts | JSON files in `contracts/` that define the required methods for each plugin type. |
-| Cancellation | Each run creates an `AbortController`; its signal reaches every component call. `options.signal` lets callers cancel and `options.timeout` aborts the run. |
-| `retry` / `withRetry` | Retry helpers with backoff for your own components (the built-in connectors already retry transient failures). |
-| `logger` | `pino`-based structured logger. |
+| Surface | Purpose |
+| ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `createRagPipeline({ loader, embedder, retriever, llm, reranker, registry, cache })` | The factory. Wires the components into a runnable pipeline and returns `{ run, cleanup, cacheStats }`; `cache` is described in [Caching](./Caching). |
+| `run({ query, queryVector, options })` | The main execution entry point. Resolves `{ success, query, results, answer, citations?, evaluation? }`; failures, timeouts and aborts resolve `{ success: false, error }`. |
+| `pluginRegistry` | Holds registered loader, embedder, retriever, reranker, LLM and evaluator plugins by name. Validates them against the contract schemas in `contracts/`. |
+| Plugin contracts | JSON files in `contracts/` that define the required methods for each plugin type. |
+| Cancellation | Each run creates an `AbortController`; its signal reaches every component call. `options.signal` lets callers cancel and `options.timeout` aborts the run. |
+| `retry` / `withRetry` | Retry helpers with backoff for your own components (the built-in connectors already retry transient failures). |
+| `logger` | `pino`-based structured logger. |
## Minimum viable pipeline
@@ -47,6 +47,7 @@ const pipeline = createRagPipeline({
retriever: new MemoryRetriever(), // populate with retriever.store([...])
llm: openai,
});
+// OpenAIConnector needs the OpenAI SDK: npm install openai
const result = await pipeline.run({ query: "What does X do?" });
```
diff --git a/docs-site/docs/Concepts-Evaluation.md b/docs-site/docs/Concepts-Evaluation.md
index b5a14096..718c9e2e 100644
--- a/docs-site/docs/Concepts-Evaluation.md
+++ b/docs-site/docs/Concepts-Evaluation.md
@@ -15,13 +15,17 @@ that gap.
## What's in rag-eval
-| Surface | Purpose |
-| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `PipelineEvaluator` | Score a pipeline result (`{ query, answer, results }`) on faithfulness, relevance, context precision, context recall and groundedness. |
-| `CitationTracker` | Per-sentence attribution of the generated answer to source documents, plus a hallucination report. |
-| `compute*()` functions | Standalone metrics: `computeFaithfulness`, `computeAnswerRelevance`, `computeContextPrecision`, `computeContextRecall`, `computeGroundedness`. |
-| `checkNumericConsistency()` / `extractNumbers()` | The numeric check used by claim support: numbers in a claim must appear in the source ("20" equals "twenty"). |
-| `evaluateRagDataset()` | Batch helper: runs `[{ prompt, expected }]` from a JSON file through a pipeline and scores each answer against `expected` with BLEU/ROUGE. Needs an `llm`. |
+| Surface | Purpose |
+| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `PipelineEvaluator` | Score a pipeline result (`{ query, answer, results }`) on faithfulness, relevance, context precision, context recall and groundedness. |
+| `CitationTracker` | Per-sentence attribution of the generated answer to source documents, plus a hallucination report. |
+| `compute*()` functions | Standalone metrics: `computeFaithfulness`, `computeAnswerRelevance`, `computeContextPrecision`, `computeContextRecall`, `computeGroundedness`. |
+| `checkNumericConsistency()` / `extractNumbers()` | The numeric check used by claim support: numbers in a claim must appear in the source ("20" equals "twenty"). |
+| `evaluateRagDataset()` | Batch helper: runs `[{ prompt, expected }]` from a JSON file through a pipeline built from a config and scores each answer against `expected` with BLEU/ROUGE. Needs an `llm`. |
+| `runEvaluation()` / `compareConfigurations()` | Run a test set through a pipeline and report regressions against a baseline (also `rag-pipeline eval`). |
+| `validateDataset()` / `generateSyntheticDataset()` | Check a test set; draft one from your documents with an LLM (also `rag-pipeline generate-dataset`). |
+| `checkAnswer()` | Check an answer from any framework against its sources. |
+| `computeSemanticSimilarity()` | Embedding cosine similarity to a reference answer. |
All metrics are computed locally and deterministically; no judge LLM is called. Grounding is lexical (the share of a sentence's content words found in a document, optionally IDF-weighted) plus a numeric-consistency check. Negation ("not twenty days"), units ("20 hours" vs "20 days") and claims that combine several documents are not checked.
@@ -81,6 +85,8 @@ if (total / cases.length < baseline.faithfulness - 0.05) {
}
```
+`compareConfigurations(dataset, { baseline, candidate })` and `rag-pipeline eval tests.json --baseline eval-main.json` do this for you; see [Evaluation](./Evaluation#run-a-test-set-and-compare-configurations).
+
## Citations
Citations are produced by the `CitationTracker` and returned alongside
@@ -145,5 +151,5 @@ Pin the package version if you require score stability across upgrades.
## Related
- [Evaluation](./Evaluation) — full reference, metric formulas, dataset format
-- [Benchmarks](./Benchmarks) — performance methodology (separate from quality)
+- [Benchmarks](./Benchmarks) — speed and retrieval-quality (BEIR SciFact) results and methodology
- [Architecture](./Architecture) — how citation tracking is woven into the pipeline
diff --git a/docs-site/docs/Concepts-Guardrails.md b/docs-site/docs/Concepts-Guardrails.md
index d064f708..1a676750 100644
--- a/docs-site/docs/Concepts-Guardrails.md
+++ b/docs-site/docs/Concepts-Guardrails.md
@@ -69,6 +69,8 @@ layer to disable it; the others still run.
## Wiring it up
+The example uses `OpenAIConnector`, which needs the OpenAI SDK: `npm install openai`.
+
```js no-run
import {
createRagPipeline,
diff --git a/docs-site/docs/Deployment-AWS.md b/docs-site/docs/Deployment-AWS.md
index 9605c444..43f42b9f 100644
--- a/docs-site/docs/Deployment-AWS.md
+++ b/docs-site/docs/Deployment-AWS.md
@@ -8,7 +8,7 @@ Deploy RAG Pipeline Utils on AWS using ECS, EKS, or Lambda with production-grade
:::note What you deploy
-`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:2.5.0` refer to your application image built against version 2.5.0 of the package. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
+`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:3.0.0` refer to your application image built against version 3.0.0 of the package, which needs Node.js 22 or later. If your service uses `OpenAIConnector`, add `openai` to its dependencies (`npm install openai`): since 3.0.0 it is an optional peer dependency, and without it the connector rejects with `MISSING_DEPENDENCY`. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
:::
@@ -47,10 +47,10 @@ aws ecr get-login-password --region us-east-1 | \
123456789012.dkr.ecr.us-east-1.amazonaws.com
# Tag and push image
-docker tag rag-pipeline-utils:2.5.0 \
- 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:2.5.0
+docker tag rag-pipeline-utils:3.0.0 \
+ 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:3.0.0
-docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:2.5.0
+docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:3.0.0
```
### ECS Task Definition
@@ -67,7 +67,7 @@ docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:2.5.
"containerDefinitions": [
{
"name": "rag-app",
- "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:2.5.0",
+ "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:3.0.0",
"essential": true,
"portMappings": [
{
@@ -106,19 +106,13 @@ docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/rag-pipeline-utils:2.5.
"healthCheck": {
"command": [
"CMD-SHELL",
- "node -e \"require('http').get('http://localhost:3000/health')\""
+ "node -e \"require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))\""
],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
- },
- "resourceRequirements": [
- {
- "type": "InferenceAccelerator",
- "value": "device_1"
- }
- ]
+ }
}
]
}
@@ -423,6 +417,8 @@ spec:
### Lambda Function Code
+Install the dependencies the function ships with, into the layer: `npm install --prefix layer/nodejs @devilsdev/rag-pipeline-utils openai`. `openai` is an optional peer dependency that `OpenAIConnector` needs.
+
```javascript no-run
// lambda/index.js
const {
@@ -615,7 +611,9 @@ aws logs filter-log-events \
```javascript
// Enable X-Ray
const AWSXRay = require("aws-xray-sdk-core");
-const AWS = AWSXRay.captureAWS(require("aws-sdk"));
+// AWS SDK v3 clients (the nodejs22.x runtime does not include SDK v2)
+const { S3Client } = require("@aws-sdk/client-s3");
+const s3 = AWSXRay.captureAWSv3Client(new S3Client({}));
// Instrument HTTP requests
AWSXRay.captureHTTPsGlobal(require("http"));
@@ -650,7 +648,7 @@ AWSXRay.captureHTTPsGlobal(require("https"));
aws lambda put-provisioned-concurrency-config \
--function-name rag-pipeline-query \
--provisioned-concurrent-executions 10 \
- --qualifier LATEST
+ --qualifier live # a published version or alias; $LATEST is not allowed
```
## Troubleshooting
diff --git a/docs-site/docs/Deployment-Azure.md b/docs-site/docs/Deployment-Azure.md
index 25824ebf..f716f981 100644
--- a/docs-site/docs/Deployment-Azure.md
+++ b/docs-site/docs/Deployment-Azure.md
@@ -8,7 +8,7 @@ Deploy RAG Pipeline Utils on Microsoft Azure using Container Instances, AKS, or
:::note What you deploy
-`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:2.5.0` refer to your application image built against version 2.5.0 of the package. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
+`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:3.0.0` refer to your application image built against version 3.0.0 of the package, which needs Node.js 22 or later. If your service uses `OpenAIConnector`, add `openai` to its dependencies (`npm install openai`): since 3.0.0 it is an optional peer dependency, and without it the connector rejects with `MISSING_DEPENDENCY`. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
:::
@@ -44,8 +44,8 @@ az acr create \
az acr login --name ragpipelineacr
# Tag and push image
-docker tag rag-pipeline-utils:2.5.0 ragpipelineacr.azurecr.io/rag-pipeline:2.5.0
-docker push ragpipelineacr.azurecr.io/rag-pipeline:2.5.0
+docker tag rag-pipeline-utils:3.0.0 ragpipelineacr.azurecr.io/rag-pipeline:3.0.0
+docker push ragpipelineacr.azurecr.io/rag-pipeline:3.0.0
```
## Azure Container Instances
@@ -57,7 +57,7 @@ docker push ragpipelineacr.azurecr.io/rag-pipeline:2.5.0
az container create \
--resource-group rag-pipeline-rg \
--name rag-pipeline-aci \
- --image ragpipelineacr.azurecr.io/rag-pipeline:2.5.0 \
+ --image ragpipelineacr.azurecr.io/rag-pipeline:3.0.0 \
--cpu 2 \
--memory 4 \
--registry-login-server ragpipelineacr.azurecr.io \
@@ -88,7 +88,7 @@ az container create \
},
"imageName": {
"type": "string",
- "defaultValue": "ragpipelineacr.azurecr.io/rag-pipeline:2.5.0"
+ "defaultValue": "ragpipelineacr.azurecr.io/rag-pipeline:3.0.0"
}
},
"resources": [
@@ -210,6 +210,8 @@ spec:
### Function Code
+Add the dependencies the function ships with: `npm install @devilsdev/rag-pipeline-utils openai`. `openai` is an optional peer dependency that `OpenAIConnector` needs.
+
```javascript no-run
// function-app/index.js
const {
@@ -280,7 +282,7 @@ az functionapp create \
--resource-group rag-pipeline-rg \
--consumption-plan-location eastus \
--runtime node \
- --runtime-version 20 \
+ --runtime-version 22 \
--functions-version 4 \
--name rag-pipeline-func \
--storage-account ragpipelinestorage
@@ -311,7 +313,7 @@ az containerapp create \
--name rag-pipeline-app \
--resource-group rag-pipeline-rg \
--environment rag-pipeline-env \
- --image ragpipelineacr.azurecr.io/rag-pipeline:2.5.0 \
+ --image ragpipelineacr.azurecr.io/rag-pipeline:3.0.0 \
--target-port 3000 \
--ingress external \
--registry-server ragpipelineacr.azurecr.io \
diff --git a/docs-site/docs/Deployment-Docker.md b/docs-site/docs/Deployment-Docker.md
index d7de9eb4..4b9b84a0 100644
--- a/docs-site/docs/Deployment-Docker.md
+++ b/docs-site/docs/Deployment-Docker.md
@@ -8,7 +8,7 @@ Deploy RAG Pipeline Utils in production using Docker containers with optimized c
:::note What you deploy
-`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:2.5.0` refer to your application image built against version 2.5.0 of the package. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
+`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:3.0.0` refer to your application image built against version 3.0.0 of the package, which needs Node.js 22 or later. If your service uses `OpenAIConnector`, add `openai` to its dependencies (`npm install openai`): since 3.0.0 it is an optional peer dependency, and without it the connector rejects with `MISSING_DEPENDENCY`. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
:::
@@ -54,7 +54,7 @@ WORKDIR /app
COPY package*.json ./
# Install production dependencies only
-RUN npm ci --only=production && \
+RUN npm ci --omit=dev && \
npm cache clean --force
# Copy application code
@@ -106,7 +106,7 @@ RUN npm ci
# Copy source and build
COPY . .
RUN npm run build && \
- npm prune --production
+ npm prune --omit=dev
# Production stage
FROM node:22-alpine AS production
@@ -147,7 +147,7 @@ CMD ["node", "dist/index.js"]
**Build optimized image:**
```bash
-docker build -t rag-pipeline-utils:2.5.0 -f Dockerfile.production .
+docker build -t rag-pipeline-utils:3.0.0 -f Dockerfile.production .
```
## Docker Compose Setup
@@ -163,7 +163,7 @@ services:
build:
context: .
dockerfile: Dockerfile.production
- image: rag-pipeline-utils:2.5.0
+ image: rag-pipeline-utils:3.0.0
container_name: rag-pipeline-app
restart: unless-stopped
ports:
@@ -184,7 +184,7 @@ services:
"CMD",
"node",
"-e",
- "require('http').get('http://localhost:3000/health')",
+ "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))",
]
interval: 30s
timeout: 10s
@@ -222,7 +222,7 @@ services:
build:
context: .
dockerfile: Dockerfile.production
- image: rag-pipeline-utils:2.5.0
+ image: rag-pipeline-utils:3.0.0
container_name: rag-app
restart: unless-stopped
ports:
@@ -376,7 +376,7 @@ version: "3.8"
services:
rag-app:
- image: rag-pipeline-utils:2.5.0
+ image: rag-pipeline-utils:3.0.0
secrets:
- openai_api_key
- jwt_secret
@@ -421,7 +421,7 @@ ENV NODE_ENV=production \
```dockerfile
# Optimize build time with layer caching
COPY package*.json ./
-RUN npm ci --only=production
+RUN npm ci --omit=dev
# Copy source last (changes frequently)
COPY . .
@@ -463,10 +463,10 @@ services:
```bash
# Scan image for vulnerabilities
-docker scan rag-pipeline-utils:2.5.0
+docker scout cves rag-pipeline-utils:3.0.0
# Use Trivy for comprehensive scanning
-trivy image rag-pipeline-utils:2.5.0
+trivy image rag-pipeline-utils:3.0.0
```
## Monitoring and Logging
@@ -512,24 +512,24 @@ scrape_configs:
```bash
# Build production image
docker build \
- -t rag-pipeline-utils:2.5.0 \
+ -t rag-pipeline-utils:3.0.0 \
-f Dockerfile.production \
--build-arg NODE_ENV=production \
.
# Tag for registry
-docker tag rag-pipeline-utils:2.5.0 your-registry.com/rag-pipeline-utils:2.5.0
+docker tag rag-pipeline-utils:3.0.0 your-registry.com/rag-pipeline-utils:3.0.0
```
### 2. Push to Registry
```bash
# Push to Docker Hub
-docker push your-registry.com/rag-pipeline-utils:2.5.0
+docker push your-registry.com/rag-pipeline-utils:3.0.0
# Or use private registry
docker login your-registry.com
-docker push your-registry.com/rag-pipeline-utils:2.5.0
+docker push your-registry.com/rag-pipeline-utils:3.0.0
```
### 3. Deploy to Production
@@ -630,6 +630,6 @@ docker network inspect rag-network
## Additional Resources
- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/)
-- [Node.js Docker Guide](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/)
+- [Node.js Docker best practices](https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md)
- [Docker Security](https://docs.docker.com/engine/security/)
- [Docker Compose Reference](https://docs.docker.com/compose/compose-file/)
diff --git a/docs-site/docs/Deployment-GCP.md b/docs-site/docs/Deployment-GCP.md
index f160ee68..f82cfba8 100644
--- a/docs-site/docs/Deployment-GCP.md
+++ b/docs-site/docs/Deployment-GCP.md
@@ -8,7 +8,7 @@ Deploy RAG Pipeline Utils on Google Cloud Platform using Cloud Run, GKE, or Clou
:::note What you deploy
-`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:2.5.0` refer to your application image built against version 2.5.0 of the package. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
+`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:3.0.0` refer to your application image built against version 3.0.0 of the package, which needs Node.js 22 or later. If your service uses `OpenAIConnector`, add `openai` to its dependencies (`npm install openai`): since 3.0.0 it is an optional peer dependency, and without it the connector rejects with `MISSING_DEPENDENCY`. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
:::
@@ -46,10 +46,10 @@ gcloud artifacts repositories create rag-pipeline \
gcloud auth configure-docker us-central1-docker.pkg.dev
# Tag and push image
-docker tag rag-pipeline-utils:2.5.0 \
- us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0
+docker tag rag-pipeline-utils:3.0.0 \
+ us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:3.0.0
-docker push us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0
+docker push us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:3.0.0
```
## Google Cloud Run
@@ -59,7 +59,7 @@ docker push us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0
```bash
# Deploy to Cloud Run
gcloud run deploy rag-pipeline \
- --image us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0 \
+ --image us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:3.0.0 \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
@@ -99,7 +99,7 @@ spec:
containerConcurrency: 80
timeoutSeconds: 300
containers:
- - image: us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0
+ - image: us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:3.0.0
resources:
limits:
cpu: "2000m"
@@ -170,7 +170,7 @@ spec:
serviceAccountName: rag-pipeline-sa
containers:
- name: rag-app
- image: us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:2.5.0
+ image: us-central1-docker.pkg.dev/PROJECT_ID/rag-pipeline/app:3.0.0
ports:
- containerPort: 3000
env:
@@ -233,6 +233,8 @@ kubectl annotate serviceaccount rag-pipeline-sa \
### Function Code
+Add the dependencies the function ships with: `npm install @devilsdev/rag-pipeline-utils openai @google-cloud/functions-framework`. `openai` is an optional peer dependency that `OpenAIConnector` needs.
+
```javascript no-run
// index.js
const functions = require("@google-cloud/functions-framework");
diff --git a/docs-site/docs/Deployment-Kubernetes.md b/docs-site/docs/Deployment-Kubernetes.md
index 02c4682b..0ad84f0e 100644
--- a/docs-site/docs/Deployment-Kubernetes.md
+++ b/docs-site/docs/Deployment-Kubernetes.md
@@ -8,7 +8,7 @@ Deploy RAG Pipeline Utils on Kubernetes with production-grade configurations, He
:::note What you deploy
-`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:2.5.0` refer to your application image built against version 2.5.0 of the package. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
+`@devilsdev/rag-pipeline-utils` is a library plus a CLI; it does not ship a production HTTP server. These guides deploy **your own** Node.js service or function that calls `createRagPipeline`. Dockerfiles, `/health` endpoints and image names such as `rag-pipeline-utils:3.0.0` refer to your application image built against version 3.0.0 of the package, which needs Node.js 22 or later. If your service uses `OpenAIConnector`, add `openai` to its dependencies (`npm install openai`): since 3.0.0 it is an optional peer dependency, and without it the connector rejects with `MISSING_DEPENDENCY`. `rag-pipeline serve` / `DevServer` is meant for local use: it binds to `127.0.0.1` by default and has no authentication, so do not expose it directly.
:::
@@ -47,7 +47,7 @@ metadata:
namespace: production
labels:
app: rag-pipeline
- version: v2.5.0
+ version: v3.0.0
spec:
replicas: 3
selector:
@@ -57,7 +57,7 @@ spec:
metadata:
labels:
app: rag-pipeline
- version: v2.5.0
+ version: v3.0.0
spec:
serviceAccountName: rag-pipeline
securityContext:
@@ -66,7 +66,7 @@ spec:
fsGroup: 1001
containers:
- name: rag-app
- image: your-registry.com/rag-pipeline-utils:2.5.0
+ image: your-registry.com/rag-pipeline-utils:3.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
@@ -201,7 +201,7 @@ data:
{
"stage": "retriever",
"name": "file-store",
- "config": { "path": "/data/index.json" }
+ "config": { "path": "/app/data/index.json" }
},
{ "stage": "llm", "name": "openai", "config": { "model": "gpt-4o-mini" } }
]
@@ -266,8 +266,8 @@ helm/rag-pipeline/
apiVersion: v2
name: rag-pipeline
description: RAG Pipeline Utils Helm Chart
-version: 2.5.0
-appVersion: "2.5.0"
+version: 3.0.0
+appVersion: "3.0.0"
keywords:
- rag
- ai
@@ -286,7 +286,7 @@ replicaCount: 3
image:
repository: your-registry.com/rag-pipeline-utils
- tag: "2.5.0"
+ tag: "3.0.0"
pullPolicy: IfNotPresent
service:
@@ -628,7 +628,7 @@ spec:
spec:
containers:
- name: rag-app
- image: rag-pipeline:2.4.5
+ image: rag-pipeline:2.7.1
---
# Green deployment
apiVersion: apps/v1
@@ -649,7 +649,7 @@ spec:
spec:
containers:
- name: rag-app
- image: rag-pipeline:2.5.0
+ image: rag-pipeline:3.0.0
---
# Service switches between blue and green
apiVersion: v1
@@ -672,7 +672,7 @@ helm install rag-pipeline ./helm/rag-pipeline \
--namespace production \
--create-namespace \
--values values-production.yaml \
- --set image.tag=2.5.0 \
+ --set image.tag=3.0.0 \
--set secrets.openaiApiKey=$OPENAI_API_KEY
# Dry run first
@@ -688,7 +688,7 @@ helm install rag-pipeline ./helm/rag-pipeline \
helm upgrade rag-pipeline ./helm/rag-pipeline \
--namespace production \
--values values-production.yaml \
- --set image.tag=2.5.0 \
+ --set image.tag=3.0.0 \
--wait --timeout 5m
# Check rollout status
diff --git a/docs-site/docs/Enterprise.md b/docs-site/docs/Enterprise.md
index 16124d7c..9f5856b6 100644
--- a/docs-site/docs/Enterprise.md
+++ b/docs-site/docs/Enterprise.md
@@ -2,7 +2,7 @@
> **Experimental:** SSO (SAML/OAuth2/OIDC/Active Directory), multi-tenancy, data governance, model training, federated learning, multimodal processing, adaptive retrieval, the plugin sandbox and `PluginCertification` are simulated or incomplete. They are exported from `@devilsdev/rag-pipeline-utils/experimental` and must not be used for authentication, tenant isolation, compliance or plugin isolation. See [Experimental modules](./Experimental.md) for what each one really does.
-This page covers the supported building blocks in **@devilsdev/rag-pipeline-utils** for running RAG in regulated or multi-user environments: audit logging, token validation, access-controlled retrieval, plugin signatures, cost limits and observability. They are all exported from the main entry. There are no `/enterprise`, `/observability` or `/testing` subpaths. The package exposes only `.`, `./experimental` and `./cli`.
+This page covers the supported building blocks in **@devilsdev/rag-pipeline-utils** for running RAG in regulated or multi-user environments: audit logging, token validation, access-controlled retrieval, plugin signatures, cost limits and observability. They are all exported from the main entry. There are no `/enterprise` or `/observability` subpaths. The package exposes `.`, `./experimental`, `./testing` (test helpers such as `createTestPipeline`) and `./cli`.
---
diff --git a/docs-site/docs/Evaluation.md b/docs-site/docs/Evaluation.md
index b8ec4eda..d58435de 100644
--- a/docs-site/docs/Evaluation.md
+++ b/docs-site/docs/Evaluation.md
@@ -2,7 +2,7 @@
**@devilsdev/rag-pipeline-utils** ships a set of lexical evaluation metrics for RAG output: answer-level scores (BLEU, ROUGE), grounding metrics (faithfulness, answer relevance, context precision and recall, groundedness), citation tracking and hallucination detection. All of them run locally, synchronously and without calling a model.
-Evaluation is a library API; the `rag-pipeline` CLI has no `evaluate` command.
+Evaluation is a library API, and the CLI runs it too: `rag-pipeline eval ` scores a test set and fails on low scores or regressions, and `rag-pipeline generate-dataset` writes a test set from your index (see [CLI Reference](./CLI.md#eval)).
---
@@ -111,7 +111,7 @@ Signatures:
| --------------------------------------------------------------- | ----------------------------------------------------------------- |
| `computeFaithfulness(answer, retrievedDocs, options)` | `options.threshold` (default 0.5) |
| `computeAnswerRelevance(query, answer, options)` | |
-| `computeContextPrecision(query, retrievedDocs, options)` | |
+| `computeContextPrecision(query, retrievedDocs, options)` | `options.threshold` (default 0.2) |
| `computeContextRecall(referenceAnswer, retrievedDocs, options)` | `options.threshold` (default 0.5) |
| `computeGroundedness(query, answer, retrievedDocs, options)` | `options.weights`, `options.threshold`, `options.referenceAnswer` |
@@ -412,7 +412,7 @@ Each case records the scores it has:
| ------------------ | ----------------------------------------------------------------------------------- |
| `faithfulness` | Share of the answer's sentences supported by the retrieved documents |
| `relevance` | How well the answer addresses the question |
-| `contextPrecision` | Share of retrieved documents that support the answer |
+| `contextPrecision` | Share of retrieved documents relevant to the question |
| `contextRecall` | How much of the `expected` answer the retrieved documents support; needs `expected` |
| `groundedness` | The weighted combination of the above |
| `citationCoverage` | Share of the answer's sentences with a supporting citation |
diff --git a/docs-site/docs/Examples.md b/docs-site/docs/Examples.md
index fd505b9e..21cfb44a 100644
--- a/docs-site/docs/Examples.md
+++ b/docs-site/docs/Examples.md
@@ -4,7 +4,7 @@ sidebar_position: 16
# Code Examples
-Examples of common RAG Pipeline Utils use cases. They use the package's real exports; replace the provider connectors with the ones you use.
+Examples of common RAG Pipeline Utils use cases. They use the package's real exports; replace the provider connectors with the ones you use. Examples that use `OpenAIConnector` also need `npm install openai` (an optional peer dependency since 3.0.0).
:::tip[Run the examples in your browser]
diff --git a/docs-site/docs/Experimental.md b/docs-site/docs/Experimental.md
index 8e8fcc58..e58919bb 100644
--- a/docs-site/docs/Experimental.md
+++ b/docs-site/docs/Experimental.md
@@ -25,8 +25,8 @@ Experimental modules are **not** covered by the guarantees in [SEMVER.md](https:
| `SAMLProvider` | Refuses to authenticate: SAML assertions cannot be verified without a vetted XML-signature library. Only the explicit `devBypass` returns a development user. |
| `TenantManager`, `ResourceMonitor` | Tenant and workspace usage figures are random, so quota enforcement passes or fails at random. |
| `DataGovernanceManager` (`DataGovernance`) | Data classification is random; the compliance report always says "compliant"; GDPR erasure reports deleted records without deleting anything. |
-| `PluginSandbox` | `execute()` calls methods that do not exist and fails. Plugins are not isolated; they run in-process with your permissions. Requires the optional `isolated-vm` peer dependency. |
-| `PluginCertification` | `submitForCertification()` uses fixed placeholder scores. For scores computed from a plugin's files use `rag-pipeline hub certify check `. |
+| `PluginSandbox` | Not usable: in 3.0.0 the constructor throws (`PluginSignatureVerifier is not a constructor`), even with `isolated-vm` installed, and `execute()` calls methods that do not exist. Plugins are not isolated; they run in-process with your permissions. Requires the optional `isolated-vm` >= 6 peer dependency. |
+| `PluginCertification` | `submitForCertification()` uses fixed placeholder scores, then POSTs the result to a hard-coded registry (`https://registry.rag-pipeline.dev`; override with `registryUrl`), so without a reachable registry it rejects with `fetch failed`. For scores computed from a plugin's files use `rag-pipeline hub certify check `. |
## Migrating from the main entry
@@ -41,7 +41,7 @@ To migrate, change the import path. In 2.x the classes are the same objects in b
+ import { TenantManager } from "@devilsdev/rag-pipeline-utils/experimental";
```
-Warnings can be silenced with Node's `--no-deprecation` flag, but changing the import is the better fix.
+In 2.x the warnings could be silenced with Node's `--no-deprecation` flag; 3.0 prints none, because the main-entry exports are gone.
## Supported alternatives
diff --git a/docs-site/docs/FAQ.md b/docs-site/docs/FAQ.md
index c47cf182..117eb13d 100644
--- a/docs-site/docs/FAQ.md
+++ b/docs-site/docs/FAQ.md
@@ -36,7 +36,7 @@ Yes. Pass an `AbortSignal` as `options.signal`, or set `options.timeout` in mill
### How do I evaluate performance?
-Evaluation is a library API, not a CLI command. Use `PipelineEvaluator` (or `run({ query, options: { evaluate: true } })`) to score individual pipeline results, and `evaluateRagDataset(datasetPath, pipelineConfig)` for a `{ prompt, expected }[]` dataset with BLEU/ROUGE. Context recall is only computed when you pass a `referenceAnswer`. `DashboardGenerator` renders metrics as a standalone HTML page. For latency, `rag-pipeline ai benchmark` reports p50/p95/mean per stage. See [Evaluation](./Evaluation.md).
+From the command line, `rag-pipeline eval ` scores a `.json` or `.jsonl` test set (with `--min faithfulness=0.8`, `--baseline` and `--report`), and `rag-pipeline generate-dataset` creates one. In code, use `PipelineEvaluator` (or `run({ query, options: { evaluate: true } })`) to score individual pipeline results, and `evaluateRagDataset(datasetPath, pipelineConfig)` for a `{ prompt, expected }[]` dataset with BLEU/ROUGE. Context recall is only computed when you pass a `referenceAnswer`. `DashboardGenerator` renders metrics as a standalone HTML page. For latency, `rag-pipeline ai benchmark` reports p50/p95/mean per stage. See [Evaluation](./Evaluation.md).
---
diff --git a/docs-site/docs/Introduction.md b/docs-site/docs/Introduction.md
index 66ae6c5e..e698fefc 100644
--- a/docs-site/docs/Introduction.md
+++ b/docs-site/docs/Introduction.md
@@ -46,11 +46,11 @@ Retrieval-Augmented Generation (RAG) is a powerful AI architecture that combines
- **Evaluation**: faithfulness, answer relevance, context precision, context recall (with a reference answer) and groundedness via `PipelineEvaluator`
- **Citations**: per-sentence source attribution and hallucination detection, including a numeric-consistency check
- **Guardrails**: pre-retrieval injection detection, retrieval filtering (ACL, relevance, freshness, optional injection scan) and post-generation checks
-- **Reranking**: scoring, embedding, LLM and cascade rerankers
+- **Reranking**: scoring, embedding and cascade rerankers, plus Cohere's rerank API via `CohereConnector`
### **Developer Experience**
-- **CLI**: `init`, `ingest`, `query`, `run`, `serve`, `validate`, `doctor`, `hub` and `ai` against a local file-backed index
+- **CLI**: `init`, `ingest`, `query`, `run`, `eval`, `generate-dataset`, `serve`, `validate`, `doctor`, `info`, `config`, `hub` and `ai`
- **Configuration Schema**: validated `.ragrc.json`
- **Hot Reload**: `HotReloadManager` and `DevServer` for local development
- **TypeScript**: declarations for every runtime export
@@ -95,15 +95,15 @@ graph TD
Each stage is a plugin that implements one contract method: loader `load()`, embedder `embed()` (optionally `embedQuery()`), retriever `store()` and `retrieve()`, llm `generate()` (optionally `generateStream()`), reranker `rerank()`. Built-in implementations:
-| Stage | Library classes | `.ragrc.json` names (CLI) |
-| --------- | ---------------------------------------------------------------------------- | ------------------------------------- |
-| Loader | (bring your own) | `auto` (.md, .html, .csv, .txt) |
-| Embedder | `LocalEmbedder`, `OpenAIConnector`, `OllamaConnector`, `CohereConnector` | `local`, `openai`, `ollama`, `cohere` |
-| Retriever | `MemoryRetriever`, `FileVectorStore`, `HybridRetriever`, `GraphRetriever` | `memory`, `file-store` |
-| LLM | `OpenAIConnector`, `AnthropicConnector`, `OllamaConnector` | `openai`, `anthropic`, `ollama` |
-| Reranker | `ScoringReranker`, `EmbeddingReranker`, `CascadeReranker`, `CohereConnector` | `scoring` |
+| Stage | Library classes | `.ragrc.json` names (CLI) |
+| --------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
+| Loader | (bring your own) | `auto` (.md, .html, .csv, .txt) |
+| Embedder | `LocalEmbedder`, `OpenAIConnector`, `OllamaConnector`, `CohereConnector` | `local`, `openai`, `ollama`, `cohere` |
+| Retriever | `MemoryRetriever`, `FileVectorStore`, `HybridRetriever`, `GraphRetriever`, `PgVectorRetriever`, `QdrantRetriever` | `memory`, `file-store`, `pgvector`, `qdrant` |
+| LLM | `OpenAIConnector`, `AnthropicConnector`, `OllamaConnector` | `openai`, `anthropic`, `ollama` |
+| Reranker | `ScoringReranker`, `EmbeddingReranker`, `CascadeReranker`, `CohereConnector` | `scoring` |
-Hosted vector databases (Pinecone, Chroma, Weaviate, Qdrant and others) are not built in; connect them with a custom retriever plugin (see [Plugins](./Plugins.md)).
+Qdrant (`QdrantRetriever`) and PostgreSQL with pgvector (`PgVectorRetriever`, needs `npm install pg`) are built in. Connect other vector databases (Pinecone, Chroma, Weaviate and others) with a custom retriever plugin (see [Plugins](./Plugins.md)).
---
@@ -149,8 +149,8 @@ console.log("Answer:", response.answer); // null without an llm
### CLI Usage
```bash
-# Install globally
-npm install -g @devilsdev/rag-pipeline-utils
+# Install globally, with the OpenAI SDK the openai template uses
+npm install -g @devilsdev/rag-pipeline-utils openai
# Write .ragrc.json in the current directory (OpenAI embeddings and LLM)
rag-pipeline init --no-interactive --template openai
@@ -165,8 +165,9 @@ rag-pipeline query "What is the plugin architecture?"
rag-pipeline serve --port 3000
```
-Evaluation and dashboards are library APIs (`PipelineEvaluator`,
-`DashboardGenerator`) rather than CLI commands; see
+Evaluate a test set from the command line with `rag-pipeline eval `
+(it exits 1 on failures, low scores or regressions) and create one with
+`rag-pipeline generate-dataset`; in code, use `PipelineEvaluator`. See
[Evaluation](./Evaluation.md). The full command list is in the
[CLI Reference](./CLI.md).
@@ -207,7 +208,7 @@ SSO, multi-tenancy, data governance, model training, federated learning, multi-m
### Contributing
-We welcome contributions! See our [Contributing Guide](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/CONTRIBUTING.md) for details on:
+We welcome contributions! See our [Contributing Guide](https://github.com/DevilsDev/rag-pipeline-utils/blob/main/docs/CONTRIBUTING.md) for details on:
- Setting up the development environment
- Running tests and linting
diff --git a/docs-site/docs/Migration.md b/docs-site/docs/Migration.md
index 2af6ef0d..bc490396 100644
--- a/docs-site/docs/Migration.md
+++ b/docs-site/docs/Migration.md
@@ -33,7 +33,7 @@ Any version from 4.93 works, so a project that already uses `openai` keeps its o
+ import { TenantManager } from "@devilsdev/rag-pipeline-utils/experimental";
```
-From the main entry they are now `undefined` in JavaScript and a compile error in TypeScript. To find the imports to change, run your app or tests on 2.7.x with `--trace-deprecation`: each `RAG_DEP_*` warning then shows the line in your code that uses one. 2.5.0 to 2.7.x export the same classes from both entries, so you can change the imports before upgrading.
+From the main entry they are now `undefined` in JavaScript and a compile error in TypeScript. To find the imports to change, search your code for the class names. Running your app or tests on 2.7.x with `--trace-deprecation` helps too: each `RAG_DEP_*` warning shows the first place your code constructs that class, once per class per run, but an import that is never constructed (or only used for `instanceof`) doesn't warn. 2.5.0 to 2.7.x export the same classes from both entries, so you can change the imports before upgrading.
**4. TypeScript: replace the removed types.** 2.7.0 corrected the declarations and deprecated the types below, because they didn't describe what the code reads or returns. 3.0.0 removes them:
@@ -84,7 +84,7 @@ See [Experimental modules](./Experimental.md) for what each one actually does.
- **`RetrievalGuard` with `enforceACL`** now fails closed: when `context.userPermissions` is missing, documents are removed.
- **`DevServer` now listens**: `start()` binds port 3000 by default (pass `port: 0` for a free port), so existing callers may see `EADDRINUSE`. The default host is `127.0.0.1` (was `localhost`), and the default `watchPaths` is `[]`.
- **No default plugin registry**: `rag-pipeline hub` / `plugin` registry operations need `--registry ` or the `RAG_PLUGIN_REGISTRY` environment variable.
-- **Removed CLI flags**: `--trace`, `--stats`, `--parallel`, `--streaming`, `--max-memory`, `--preview`, `--validate`, `--explain`, `--abort-timeout`, `--quiet` and `config show --format` had no effect and were removed. Remove them from scripts. See the [CLI reference](./CLI.md).
+- **Removed CLI flags**: `--trace`, `--stats`, `--parallel`, `--streaming`, `--max-memory`, `--preview`, `--validate`, `--explain`, `--abort-timeout`, `--quiet` and `config show --format` had no effect and were removed. Remove them from scripts. (`query --trace`, `--stats`, `--streaming`, `--explain` and the global `--quiet` came back in 2.6.0 with working implementations.) See the [CLI reference](./CLI.md).
- **Prompts**: built-in connectors now put retrieved context in the user message as delimited, untrusted data. Answers may differ slightly.
**New in 2.5.0**: `options.signal` (an `AbortSignal`) on `run()` for cancellation; `FileVectorStore`; a working CLI workflow (`init`, `ingest`, `query`, `run`, `serve`); and `checkNumericConsistency`, `extractNumbers`, `detectInjection` and `PRICING_METADATA` exports. See the [API Reference](./API-Reference.md).
@@ -138,8 +138,8 @@ await pluginRegistry.register("llm", "my-llm", {
4. **Update Evaluation Scripts**:
-The CLI has no `eval` or `evaluate` command. Run dataset evaluation through
-the library instead (see [Evaluation](./Evaluation.md)):
+Since 2.7.0, `rag-pipeline eval tests.json` runs a test set from the CLI (see
+[CLI](./CLI.md#eval)). In code, evaluate through the library (see [Evaluation](./Evaluation.md)):
```javascript no-run
const {
@@ -245,13 +245,15 @@ class MyLoader {
### **Migrating from LangChain**
+The `OpenAIConnector` examples in this section need the OpenAI SDK: `npm install openai`.
+
**Key Differences**:
- Plugin-based vs. chain-based architecture
- Built-in evaluation framework
- Streaming support built in
-The pipeline itself only exposes `run()`. To load, embed, index or generate outside a run, call the component directly.
+The pipeline exposes `run()` (plus `cleanup()` and `cacheStats()`). To load, embed, index or generate outside a run, call the component directly.
**Migration Steps**:
@@ -295,7 +297,7 @@ const results = await retriever.retrieve({
});
```
-For a vector index that persists to disk, use `FileVectorStore`. Hosted vector databases need a custom retriever plugin (see [Plugins](./Plugins.md)).
+For a vector index that persists to disk, use `FileVectorStore`. For PostgreSQL or Qdrant, use the built-in `PgVectorRetriever` or `QdrantRetriever` (`pgvector` or `qdrant` in `.ragrc.json`; see [PostgreSQL with pgvector](./Concepts-Connectors.md#postgresql-with-pgvector) and [Qdrant](./Concepts-Connectors.md#qdrant)). Other hosted databases need a custom retriever plugin (see [Plugins](./Plugins.md)).
3. **LLM Integration**:
@@ -338,7 +340,7 @@ pipeline.add_node(component=reader, name="Reader", inputs=["Retriever"])
// @devilsdev/rag-pipeline-utils
const pipeline = createRagPipeline({
embedder, // e.g. new OllamaConnector()
- retriever, // e.g. new MemoryRetriever() or a custom retriever plugin
+ retriever, // e.g. new MemoryRetriever(), FileVectorStore, PgVectorRetriever or QdrantRetriever
llm, // e.g. new OllamaConnector()
});
```
@@ -481,8 +483,8 @@ rag-pipeline --dry-run query "test query"
rag-pipeline query "test query" --json
```
-To score sample data, use `PipelineEvaluator` (see
-[Evaluation](./Evaluation.md)).
+To score sample data, run `rag-pipeline eval tests.json` or use
+`PipelineEvaluator` (see [Evaluation](./Evaluation.md)).
3. **Performance Comparison**:
@@ -518,7 +520,7 @@ rm -rf .rag && cp -r .rag.pre-migration .rag
cp .ragrc.json.pre-migration .ragrc.json
# Downgrade package if needed (pin the version you came from)
-npm install @devilsdev/rag-pipeline-utils@2.4.4
+npm install @devilsdev/rag-pipeline-utils@^2.7.1
```
---
diff --git a/docs-site/docs/Performance.md b/docs-site/docs/Performance.md
index d76cdb9f..9ca58e1e 100644
--- a/docs-site/docs/Performance.md
+++ b/docs-site/docs/Performance.md
@@ -19,7 +19,7 @@ time rag-pipeline query "test" --json
rag-pipeline doctor --category performance
```
-`ai benchmark` takes `--queries ` (JSON array of strings or one per line; by default queries are sampled from the index), `--runs ` (default 3), `--top-k ` and `--json`. The repository's internal benchmark suite (DAG engine, retry policy, monitoring overhead) runs with `npm run benchmark` from a clone; see [Benchmarks](./Benchmarks.md).
+`ai benchmark` takes `--queries ` (JSON array of strings or one per line; by default queries are sampled from the index), `--runs ` (default 3), `--top-k ` and `--json`. The repository's internal benchmark suite (DAG engine, retry policy, monitoring overhead) runs with `npm run benchmark` from a clone; retrieval speed and quality benchmarks run with `npm run bench:speed` and `npm run bench:quality` (see [Benchmarks](./Benchmarks.md)).
### **In your application**
@@ -165,7 +165,7 @@ for await (const { id, vector, progress } of streamer.embedStream(documents)) {
### **Parallel batches**
-`ParallelProcessor.ParallelEmbedder` splits text chunks into batches and embeds them with a concurrency limit and per-batch retries. It calls `embedder.embed(batch)` with an **array** of strings and expects an array of vectors back, so use it with embedders that accept batches:
+`ParallelProcessor.ParallelEmbedder` splits text chunks into batches and embeds them with a concurrency limit and per-batch retries. By default (`mode: "auto"`) it calls `embedBatch(texts)` when the embedder has one, embeds one text at a time for the built-in connectors, and otherwise calls `embed(batch)` with an array of strings. Force a strategy with `mode: "batch"` or `mode: "single"`:
```javascript no-run
const { ParallelProcessor } = require("@devilsdev/rag-pipeline-utils");
@@ -174,6 +174,7 @@ const parallel = new ParallelProcessor.ParallelEmbedder(batchEmbedder, {
batchSize: 10, // default
maxConcurrency: 3, // default
retryAttempts: 2, // default
+ mode: "auto", // default
});
const vectors = await parallel.embedBatch(chunks); // chunks: string[]
@@ -183,7 +184,7 @@ const vectors = await parallel.embedBatch(chunks); // chunks: string[]
## **Retrieval and Reranking**
-- **Index choice.** `MemoryRetriever` holds all vectors in memory and compares every one per query; it enforces `maxDocuments` (default 100000) and, with `eviction: "fifo"`, drops the oldest documents instead of throwing when full. `FileVectorStore` (the CLI's `file-store` retriever) persists the index to JSON, stores mostly-zero vectors sparsely and rounds values to 7 significant digits (about 10x smaller files for the `local` embedder). Both do an exhaustive cosine scan; for large corpora, plug in a dedicated vector database as a custom retriever.
+- **Index choice.** `MemoryRetriever` holds all vectors in memory and compares every one per query; it enforces `maxDocuments` (default 100000) and, with `eviction: "fifo"`, drops the oldest documents instead of throwing when full. `FileVectorStore` (the CLI's `file-store` retriever) persists the index to JSON, stores mostly-zero vectors sparsely and rounds values to 7 significant digits (about 10x smaller files for the `local` embedder). Both do an exhaustive cosine scan; for large corpora use `PgVectorRetriever` (PostgreSQL with pgvector, HNSW) or `QdrantRetriever`, or plug in another store as a custom retriever.
- **`topK`.** Retrieve only what the next stage needs. With a reranker, retrieve more candidates and let the reranker cut them down.
- **`EmbeddingReranker`** caches document embeddings in an LRU (`cacheSize`, default 1000; `0` disables) and limits concurrent embedding calls (`concurrency`, default 4). Call `clearCache()` after retraining the embedder.
- **`CascadeReranker`** lets a cheap reranker (for example `ScoringReranker`) prune candidates before an expensive one runs.
@@ -257,7 +258,7 @@ The pipeline object holds no per-request state, so you can scale horizontally be
- [ ] Bound memory: `maxDocuments` / `eviction` on `MemoryRetriever`, `cacheSize` on `EmbeddingReranker`
- [ ] Track token cost with `CostTracker` and set a budget
-There are no published reference throughput or latency figures for this package; numbers depend on your providers, models, corpus and hardware. Measure your own.
+Reference figures for the built-in stores and retrievers, measured in CI, are on the [Benchmarks](./Benchmarks.md) page. Your numbers depend on your providers, models, corpus and hardware, so measure your own.
---
diff --git a/docs-site/docs/Plugins.md b/docs-site/docs/Plugins.md
index d93ec43d..a55d89e4 100644
--- a/docs-site/docs/Plugins.md
+++ b/docs-site/docs/Plugins.md
@@ -282,7 +282,7 @@ await pluginRegistry.register("llm", "echo", echoLlm, manifest, {
- The manifest must carry `signature` (Ed25519, base64) and `signerId`. Signers come from a trusted-keys file; the trust store is empty by default.
- A signed `contentDigest` in the manifest binds the plugin code. When it is present, it is always checked against `options.content` (`{ files, baseDir, contents }`).
-- The exported `pluginRegistry` verifies signatures only when `NODE_ENV` is `production`. Registries constructed with `requireSignedPlugins: true` refuse plugins that have no signed manifest. With `requireContentDigest: true` they also refuse manifests that have no `contentDigest`.
+- The exported `pluginRegistry` verifies signatures only when `NODE_ENV` is `production`. Registries constructed with `requireSignedPlugins: true` (`new pluginRegistry.PluginRegistry({ verifySignatures: true, requireSignedPlugins: true })`) refuse plugins that have no signed manifest. With `requireContentDigest: true` they also refuse manifests that have no `contentDigest`.
- `PluginSignatureVerifier` is exported for verifying manifests yourself (`verifyPluginSignature(manifest, signature, signerId, content?)`).
---
@@ -322,15 +322,15 @@ const anthropic = new AnthropicConnector({
const cohere = new CohereConnector({ apiKey: process.env.COHERE_API_KEY });
```
-| Connector | Stages | Notes |
-| -------------------- | ------------------ | -------------------------------------------------------------------- |
-| `OpenAIConnector` | llm, embedder | Default models `gpt-4o-mini` and `text-embedding-3-small`; streaming |
-| `AnthropicConnector` | llm | Default model `claude-3-5-sonnet-20241022`; streaming |
-| `CohereConnector` | embedder, reranker | `embed-english-v3.0`, `rerank-english-v3.0` |
-| `OllamaConnector` | llm, embedder | Local server; defaults `llama3` and `nomic-embed-text`; streaming |
-| `LocalEmbedder` | embedder | Offline TF-IDF; call `train(documents)` first |
-| `MemoryRetriever` | retriever | In-memory cosine similarity; `maxDocuments`, `eviction: 'fifo'` |
-| `FileVectorStore` | retriever | JSON-file index used by the CLI (`file-store`) |
+| Connector | Stages | Notes |
+| -------------------- | ------------------ | ------------------------------------------------------------------------------------------------ |
+| `OpenAIConnector` | llm, embedder | Needs `npm install openai`; default models `gpt-4o-mini` and `text-embedding-3-small`; streaming |
+| `AnthropicConnector` | llm | Default model `claude-3-5-sonnet-20241022`; streaming |
+| `CohereConnector` | embedder, reranker | `embed-english-v3.0`, `rerank-english-v3.0` |
+| `OllamaConnector` | llm, embedder | Local server; defaults `llama3` and `nomic-embed-text`; streaming |
+| `LocalEmbedder` | embedder | Offline TF-IDF; call `train(documents)` first |
+| `MemoryRetriever` | retriever | In-memory cosine similarity; `maxDocuments`, `eviction: 'fifo'` |
+| `FileVectorStore` | retriever | JSON-file index used by the CLI (`file-store`) |
API keys are read when the connector is constructed (from `apiKey` or `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `COHERE_API_KEY`). Transient failures (network errors, 408/409/425/429/5xx) are retried with exponential backoff and jitter, and `Retry-After` is honoured.
diff --git a/docs-site/docs/Security-Capabilities.md b/docs-site/docs/Security-Capabilities.md
index 5afcb59e..f10bc5d4 100644
--- a/docs-site/docs/Security-Capabilities.md
+++ b/docs-site/docs/Security-Capabilities.md
@@ -59,7 +59,7 @@ For **how to report a vulnerability**, see [SECURITY.md in the repo](https://git
| --------------------------------------------------- | -------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Pinned GitHub Actions by SHA | 🟢 Implemented | `.github/workflows/*.yml` | Actions are pinned to a commit SHA, not a tag. |
| Dependabot enabled | 🟢 Implemented | `.github/dependabot.yml` | Weekly npm scan. |
-| Runtime `npm audit` gate | 🟢 Implemented | `.github/workflows/supply-chain.yml` | `npm audit --audit-level=high --omit=dev`. For 2.5.0 it reports no high or critical findings. |
+| Runtime `npm audit` gate | 🟢 Implemented | `.github/workflows/supply-chain.yml` | `npm audit --audit-level=high --omit=dev`. For 3.0.0 it reports no high or critical findings. |
| License allowlist enforcement | 🟢 Implemented | `supply-chain.yml` license-checker step | Production dependencies are checked against an allowlist of licenses. |
| SBOM generation | 🟢 Implemented | `npm run sbom` | CycloneDX format. |
| Provenance attestation (`npm publish --provenance`) | 🟢 Implemented | `.github/workflows/release.yml` | Releases are published from the release workflow with OIDC and `--provenance`. |
diff --git a/docs-site/docs/Security.md b/docs-site/docs/Security.md
index a6ef63c7..f5412e5e 100644
--- a/docs-site/docs/Security.md
+++ b/docs-site/docs/Security.md
@@ -275,10 +275,10 @@ try {
**Key Features:**
-- **Race Condition Mitigation**: Optimized check-then-set pattern prevents concurrent replay attacks
+- **Race Condition Mitigation**: a check-then-set pattern limits concurrent replays within one process
- **Separate Tracking**: Self-signed and external tokens tracked independently
- **Consistent Validation**: `strictValidation` flag now properly controls iss/aud checks
-- **Audit Logging**: All replay attempts logged for security monitoring
+- **Replay events**: each replay attempt increments `stats.replayAttempts` and emits a `replay_detected` event; nothing is logged unless you listen for it. The JTI store is in memory per `JWTValidator` instance, so replays across processes or after a restart are not detected
---
@@ -338,7 +338,7 @@ const encryptedConfig = encryption.encrypt(sensitiveConfig);
**Data in Transit**:
-`createRagPipeline` has no transport or TLS settings; it accepts only `{ loader, embedder, retriever, llm, reranker, registry }`. The built-in OpenAI, Anthropic and Cohere connectors call HTTPS endpoints through their SDKs. Enforce TLS at your own HTTP layer (load balancer, reverse proxy or Node `https` server), and keep `rag-pipeline serve` / `DevServer` on loopback: they bind to `127.0.0.1` by default, accept JSON only with a 64 KB body limit, send no CORS headers and are meant for local use.
+`createRagPipeline` has no transport or TLS settings; it accepts only `{ loader, embedder, retriever, llm, reranker, cache, registry }`. The built-in connectors default to HTTPS endpoints (OpenAI through the optional `openai` SDK, Anthropic and Cohere through axios); a custom `baseURL` is your responsibility. Enforce TLS at your own HTTP layer (load balancer, reverse proxy or Node `https` server), and keep `rag-pipeline serve` / `DevServer` on loopback: they bind to `127.0.0.1` by default, accept JSON only with a 64 KB body limit, send no CORS headers and are meant for local use.
### **Data Sanitization**
@@ -505,7 +505,7 @@ Decode URL-encoded input once before this check, and reject input that still con
### **Plugins run in-process**
-Plugins (loaders, embedders, retrievers, LLMs, rerankers) run in the same Node.js process as your application, with its permissions. There is no working sandbox: `PluginSandbox` is an experimental module whose `execute()` fails, and it does not isolate plugins (see [Experimental](./Experimental.md)). Only install plugins you have reviewed or whose publisher you trust, and run the pipeline under an operating-system account or container with the least privileges it needs.
+Plugins (loaders, embedders, retrievers, LLMs, rerankers) run in the same Node.js process as your application, with its permissions. There is no working sandbox: `PluginSandbox` is an experimental module that cannot currently be constructed (its constructor throws), and it does not isolate plugins (see [Experimental](./Experimental.md)). Only install plugins you have reviewed or whose publisher you trust, and run the pipeline under an operating-system account or container with the least privileges it needs.
### **Installing plugins with the CLI**
@@ -844,7 +844,8 @@ class IncidentResponse {
- [ ] Input validation and sanitization implemented
- [ ] Output filtering for sensitive data
- [ ] Plugins reviewed before install; signature verification enabled (`NODE_ENV=production`) with trusted signers configured
-- [ ] `GuardrailsPipeline` with `enforceACL` and `context.userPermissions` where documents are access-controlled- [ ] Authentication and authorization configured
+- [ ] `GuardrailsPipeline` with `enforceACL` and `context.userPermissions` where documents are access-controlled
+- [ ] Authentication and authorization configured
- [ ] Audit logging enabled
- [ ] Anomaly detection active
- [ ] Incident response plan in place
diff --git a/docs-site/docs/Troubleshooting.md b/docs-site/docs/Troubleshooting.md
index d8dfc681..2e730c57 100644
--- a/docs-site/docs/Troubleshooting.md
+++ b/docs-site/docs/Troubleshooting.md
@@ -16,14 +16,14 @@ This comprehensive troubleshooting guide helps you diagnose and resolve common i
# Clear npm cache
npm cache clean --force
-# Use a supported Node.js version (18+ required)
-nvm use 18
+# Use a supported Node.js version (22+ required; 2.x runs on 18+)
+nvm use 22
npm install @devilsdev/rag-pipeline-utils
```
**Common Dependency Problems**:
-- **`husky: not found`** (on Windows, `'husky' is not recognized as an internal or external command`): versions 2.2.1 to 2.6.1 ran `husky install`, a development hook, when the package was installed, so `npm install` failed wherever husky wasn't installed globally, including CI runners. Upgrade to 2.6.2 or later: `npm install @devilsdev/rag-pipeline-utils@latest`. If you can't upgrade yet, `npm install --ignore-scripts @devilsdev/rag-pipeline-utils@2.6.1` skips the hook; the package needs no install scripts.
+- **`husky: not found`** (on Windows, `'husky' is not recognized as an internal or external command`): versions 2.0.0 to 2.6.1 ran `husky install`, a development hook, when the package was installed, so `npm install` failed wherever husky wasn't installed globally, including CI runners. Upgrade to 2.6.2 or later: `npm install @devilsdev/rag-pipeline-utils@latest`. If you can't upgrade yet, `npm install --ignore-scripts @devilsdev/rag-pipeline-utils@2.6.1` skips the hook; the package needs no install scripts.
- **Node.js version**: Node.js 22 or newer is required (`engines.node >= 22`); 2.x needs Node.js 18 or newer.
- **`Cannot find module 'isolated-vm'`**: importing 2.4.5 failed in clean installs with this error. Upgrade to 2.5.0, where `isolated-vm` is an optional peer dependency loaded only when the experimental `PluginSandbox` runs. Install it yourself only if you use `PluginSandbox`.
- **`pino-pretty`** is an optional peer dependency as well; install it only for pretty-printed logs.
@@ -348,8 +348,9 @@ missing from `scores` and listed in `metadata.metricsSkipped`. See
**Metric Debugging**:
-Evaluation runs through the library, not the CLI. Score a single pair to
-isolate a metric:
+Run a whole test set with `rag-pipeline eval ` (see
+[CLI](./CLI.md#eval)), or score a single pair in the library to isolate a
+metric:
```javascript
const { scoreAnswer } = require("@devilsdev/rag-pipeline-utils");
@@ -362,10 +363,12 @@ console.log(
**Data Format Validation**:
-The package has no dataset validator. Check the fields your evaluation loop
-reads before running it:
+`rag-pipeline eval` validates the dataset before running it. From code,
+`validateDataset(cases)` returns `{ valid, errors, warnings, cases }`:
```javascript
+const { validateDataset } = require("@devilsdev/rag-pipeline-utils");
+
const testData = [
{
id: "test-001",
@@ -374,14 +377,9 @@ const testData = [
},
];
-const invalid = testData.filter(
- (c) => typeof c.prompt !== "string" || typeof c.expected !== "string",
-);
-if (invalid.length) {
- console.error(
- "Invalid test cases:",
- invalid.map((c) => c.id),
- );
+const { valid, errors } = validateDataset(testData);
+if (!valid) {
+ console.error("Invalid test cases:", errors);
}
```
diff --git a/docs-site/docs/Usage.md b/docs-site/docs/Usage.md
index d54d9c53..3c5a62e0 100644
--- a/docs-site/docs/Usage.md
+++ b/docs-site/docs/Usage.md
@@ -22,9 +22,11 @@ yarn add @devilsdev/rag-pipeline-utils
pnpm add @devilsdev/rag-pipeline-utils
```
+To use `OpenAIConnector`, also install the OpenAI SDK: `npm install openai`. It is an optional peer dependency (since 3.0.0), like `pg` for `PgVectorRetriever`.
+
### **System Requirements**
-- **Node.js**: >= 18.0.0
+- **Node.js**: >= 22 (2.x runs on Node.js 18 and later)
- **Memory**: depends on corpus size; the in-memory and file-based retrievers keep the index in memory while running
- **Storage**: varies with the vector store and document size
diff --git a/docs-site/docs/Use-Cases.md b/docs-site/docs/Use-Cases.md
index 86938f5a..52503cfe 100644
--- a/docs-site/docs/Use-Cases.md
+++ b/docs-site/docs/Use-Cases.md
@@ -26,7 +26,7 @@ rag-pipeline --config configs/anthropic.json run --ingest ./docs --query "How do
### 2. Plugin-Based Evaluation Benchmarks
-**Use Case:** You want to run BLEU/ROUGE scoring across prompt templates or documents. Evaluation is a library API (there is no CLI command for it):
+**Use Case:** You want to run BLEU/ROUGE scoring across prompt templates or documents. In code (to run a whole test set from the command line, use `rag-pipeline eval `):
```js no-run
const { scoreAnswer } = require("@devilsdev/rag-pipeline-utils");
@@ -52,7 +52,7 @@ const {
} = require("@devilsdev/rag-pipeline-utils");
// Index built earlier with `rag-pipeline ingest` from a config created by
-// `rag-pipeline init --template openai`; query vectors must come from the
+// `rag-pipeline init --template openai` (install `openai` too); query vectors must come from the
// same embedder that built the index
const store = new FileVectorStore({ path: ".rag/index.json" });
diff --git a/docs-site/docs/intro.mdx b/docs-site/docs/intro.mdx
deleted file mode 100644
index 3547735c..00000000
--- a/docs-site/docs/intro.mdx
+++ /dev/null
@@ -1,6 +0,0 @@
----
-id: intro
-title: Introduction
----
-
-Welcome to RAG Pipeline Utils! This is the starting point for your documentation.
diff --git a/docs-site/docusaurus.config.js b/docs-site/docusaurus.config.js
index 88c385fb..08a0a10f 100644
--- a/docs-site/docusaurus.config.js
+++ b/docs-site/docusaurus.config.js
@@ -97,9 +97,9 @@ const config = {
],
includeUnmatchedLast: true,
rootContent:
- "Composable RAG for Node.js. Install with `npm install @devilsdev/rag-pipeline-utils`. The package is CommonJS and ESM with TypeScript types; classes under `@devilsdev/rag-pipeline-utils/experimental` are simulated or incomplete and not for production.",
+ "Composable RAG for Node.js 22 and later. Install with `npm install @devilsdev/rag-pipeline-utils`; add `openai` to use `OpenAIConnector` and `pg` for `PgVectorRetriever` (optional peer dependencies). The package is CommonJS and ESM with TypeScript types; classes under `@devilsdev/rag-pipeline-utils/experimental` are simulated or incomplete and not for production.",
fullRootContent:
- "Composable RAG for Node.js. Install with `npm install @devilsdev/rag-pipeline-utils`. The package is CommonJS and ESM with TypeScript types; classes under `@devilsdev/rag-pipeline-utils/experimental` are simulated or incomplete and not for production.",
+ "Composable RAG for Node.js 22 and later. Install with `npm install @devilsdev/rag-pipeline-utils`; add `openai` to use `OpenAIConnector` and `pg` for `PgVectorRetriever` (optional peer dependencies). The package is CommonJS and ESM with TypeScript types; classes under `@devilsdev/rag-pipeline-utils/experimental` are simulated or incomplete and not for production.",
},
],
],
@@ -276,9 +276,6 @@ const config = {
docs: {
sidebarPath: "./sidebars.js",
lastVersion: "current",
- // versioned_docs/version-2.3.1 is kept on disk until 3.0 but no
- // longer built or listed.
- onlyIncludeVersions: ["current"],
versions: {
current: {
label: PKG_VERSION,
diff --git a/docs-site/sidebars.js b/docs-site/sidebars.js
index 4dfdda55..f7648787 100644
--- a/docs-site/sidebars.js
+++ b/docs-site/sidebars.js
@@ -2,7 +2,6 @@
/**
* Sidebar configuration for RAG Pipeline Utils documentation site
- * Version: 2.0.0
* Author: Ali Kahwaji
* Updated: Structured for modular clarity and DX
* @type {import('@docusaurus/plugin-content-docs').SidebarsConfig}
diff --git a/docs-site/src/components/ConfigBuilder/index.js b/docs-site/src/components/ConfigBuilder/index.js
index cd16f533..87a8d1ea 100644
--- a/docs-site/src/components/ConfigBuilder/index.js
+++ b/docs-site/src/components/ConfigBuilder/index.js
@@ -241,6 +241,12 @@ export default function ConfigBuilder() {
with rag-pipeline init.