@devilsdev/rag-pipeline-utils 2.4.3 → 2.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BENCHMARKS.md +338 -0
- package/CHANGELOG.md +47 -0
- package/README.md +7 -0
- package/SEMVER.md +184 -0
- package/package.json +4 -2
package/BENCHMARKS.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
This document describes **how we measure** performance in
|
|
4
|
+
`@devilsdev/rag-pipeline-utils` and **how you reproduce the numbers**
|
|
5
|
+
yourself. It deliberately does not publish a headline "N ops/sec" figure.
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
Benchmark numbers that are not reproducible are marketing, not engineering.
|
|
10
|
+
RAG pipelines are particularly sensitive to factors outside the framework:
|
|
11
|
+
embedding model choice, vector store, LLM provider and region, corpus
|
|
12
|
+
size, query distribution, and hardware. A single number hides all of
|
|
13
|
+
that.
|
|
14
|
+
|
|
15
|
+
Instead, we ship:
|
|
16
|
+
|
|
17
|
+
- A **deterministic, in-process benchmark suite** that measures framework
|
|
18
|
+
overhead — DAG execution, retry policies, logging, memory patterns.
|
|
19
|
+
These numbers are comparable across runs on the same hardware and
|
|
20
|
+
make regressions easy to catch.
|
|
21
|
+
- A **methodology and reference harness** that lets you benchmark your
|
|
22
|
+
own end-to-end pipeline with your actual provider, data, and hardware.
|
|
23
|
+
These are the only numbers that matter for your workload.
|
|
24
|
+
|
|
25
|
+
When you need a headline number for a decision, generate it on the
|
|
26
|
+
system you'll deploy to, with the providers you'll actually use.
|
|
27
|
+
|
|
28
|
+
## What the suite measures
|
|
29
|
+
|
|
30
|
+
The built-in suite (`scripts/benchmark.js`) exercises **framework
|
|
31
|
+
overhead only**. Every benchmark is in-process, network-free, and
|
|
32
|
+
deterministic up to GC and OS jitter.
|
|
33
|
+
|
|
34
|
+
| Category | What it measures | Why it matters |
|
|
35
|
+
| ----------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------ |
|
|
36
|
+
| **DAG execution** (5 / 10 / 25 / 50 nodes) | Linear chain of async nodes, cold and warm | Baseline overhead of the pipeline orchestrator |
|
|
37
|
+
| **Concurrent DAG** (1 / 2 / 5 / 10 parallelism) | Tree of 20 nodes with configurable concurrency | How well the engine scales intra-query parallelism |
|
|
38
|
+
| **Retry policies** (none / conservative / aggressive) | Simulated 30% failure rate, retries with jittered backoff | Cost of reliability guarantees on the happy path |
|
|
39
|
+
| **Structured logging** (JSON / console / correlated) | Single log call with contextual payload | Per-log-line overhead when observability is on |
|
|
40
|
+
| **Memory allocation** | Array + Map + Set construction and processing | Establishes a memory-pressure floor to compare against |
|
|
41
|
+
| **CPU intensive** | Fibonacci + JSON round-trip + string ops | Sanity check against the hosting CPU |
|
|
42
|
+
|
|
43
|
+
Each benchmark reports:
|
|
44
|
+
|
|
45
|
+
- `mean`, `median`, `min`, `max` latency (ms)
|
|
46
|
+
- `p95`, `p99` latency (ms)
|
|
47
|
+
- `standardDeviation` (ms)
|
|
48
|
+
- `throughput` (ops/sec)
|
|
49
|
+
- `memory.avgDeltaHeapUsed`, `memory.peakHeapUsed`
|
|
50
|
+
- `successRate` (%) and `errors` count
|
|
51
|
+
|
|
52
|
+
All measurements include a warmup phase (default 10 iterations) and use
|
|
53
|
+
`perf_hooks.performance.now()` for timing. If the Node process is
|
|
54
|
+
started with `--expose-gc`, the suite forces a GC before each run.
|
|
55
|
+
|
|
56
|
+
## What the suite does **not** measure
|
|
57
|
+
|
|
58
|
+
The built-in suite does not exercise:
|
|
59
|
+
|
|
60
|
+
- **Embedder throughput** — provider- and model-dependent
|
|
61
|
+
- **Retrieval latency** — vector store, index size, and network bound
|
|
62
|
+
- **LLM inference latency** — model, region, and token-count bound
|
|
63
|
+
- **End-to-end query latency** — dominated by the three above
|
|
64
|
+
- **Cost per query** — provider pricing + token usage
|
|
65
|
+
|
|
66
|
+
These are intentional omissions. Claiming a number here without
|
|
67
|
+
disclosing the full stack would be misleading. Use the
|
|
68
|
+
**end-to-end harness template** below to measure them against your
|
|
69
|
+
actual stack.
|
|
70
|
+
|
|
71
|
+
## Running the suite
|
|
72
|
+
|
|
73
|
+
Three presets ship in `package.json`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 20 iterations per benchmark — fast sanity check (~30s)
|
|
77
|
+
npm run benchmark:quick
|
|
78
|
+
|
|
79
|
+
# 100 iterations, verbose — default (~2 min)
|
|
80
|
+
npm run benchmark
|
|
81
|
+
|
|
82
|
+
# 500 iterations, verbose — release-gate quality (~8 min)
|
|
83
|
+
npm run benchmark:full
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Direct invocation:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
node scripts/benchmark.js \
|
|
90
|
+
--iterations 200 \
|
|
91
|
+
--output ./my-results \
|
|
92
|
+
--verbose
|
|
93
|
+
|
|
94
|
+
# With deterministic GC
|
|
95
|
+
node --expose-gc scripts/benchmark.js --iterations 200
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Results are written to `./benchmark-results/`:
|
|
99
|
+
|
|
100
|
+
- `latest.json` — most recent run
|
|
101
|
+
- `benchmark-<timestamp>.json` — archived run
|
|
102
|
+
|
|
103
|
+
A human-readable summary is printed to stdout on completion.
|
|
104
|
+
|
|
105
|
+
## Environment disclosure template
|
|
106
|
+
|
|
107
|
+
When sharing benchmark numbers (issue reports, blog posts, PR descriptions),
|
|
108
|
+
include the following so they're interpretable:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
Package: @devilsdev/rag-pipeline-utils@<version>
|
|
112
|
+
Node: <version> (v8 <version>)
|
|
113
|
+
OS: <distro/version>, kernel <version>
|
|
114
|
+
CPU: <model>, <cores> cores, <base/boost GHz>
|
|
115
|
+
Memory: <total GB>
|
|
116
|
+
Storage: <NVMe/SSD/HDD>, <filesystem>
|
|
117
|
+
Container: <bare-metal / Docker / K8s / Lambda / etc.>
|
|
118
|
+
Providers: embedder=<…>, retriever=<…>, llm=<…>
|
|
119
|
+
Corpus: <N documents, total tokens, chunk size>
|
|
120
|
+
Query set: <N queries, source>
|
|
121
|
+
Iterations: <N>, warmup: <N>
|
|
122
|
+
GC control: --expose-gc=<yes/no>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The JSON report already captures `nodeVersion`, `platform`, `arch`,
|
|
126
|
+
`cpus`, `totalMemory`, and `loadAverage` automatically in its
|
|
127
|
+
`environment` block.
|
|
128
|
+
|
|
129
|
+
## Report schema
|
|
130
|
+
|
|
131
|
+
Each run produces a JSON document of the shape:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"timestamp": "2026-04-16T22:00:00.000Z",
|
|
136
|
+
"environment": {
|
|
137
|
+
"nodeVersion": "v20.x.x",
|
|
138
|
+
"platform": "linux",
|
|
139
|
+
"arch": "x64",
|
|
140
|
+
"cpus": 8,
|
|
141
|
+
"totalMemory": "16384MB",
|
|
142
|
+
"loadAverage": [0.12, 0.08, 0.05]
|
|
143
|
+
},
|
|
144
|
+
"benchmarks": {
|
|
145
|
+
"DAG execution (10 nodes)": {
|
|
146
|
+
"iterations": 100,
|
|
147
|
+
"errors": 0,
|
|
148
|
+
"successRate": 100,
|
|
149
|
+
"timing": {
|
|
150
|
+
"mean": 0.0,
|
|
151
|
+
"median": 0.0,
|
|
152
|
+
"min": 0.0,
|
|
153
|
+
"max": 0.0,
|
|
154
|
+
"p95": 0.0,
|
|
155
|
+
"p99": 0.0,
|
|
156
|
+
"standardDeviation": 0.0
|
|
157
|
+
},
|
|
158
|
+
"memory": {
|
|
159
|
+
"avgDeltaHeapUsed": "0KB",
|
|
160
|
+
"totalHeapDelta": "0KB",
|
|
161
|
+
"peakHeapUsed": "0KB"
|
|
162
|
+
},
|
|
163
|
+
"throughput": 0.0
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"meta": {
|
|
167
|
+
"totalDuration": "0ms",
|
|
168
|
+
"totalBenchmarks": 0,
|
|
169
|
+
"completedAt": "2026-04-16T22:00:00.000Z"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The numeric fields are intentionally left at `0.0` in this schema —
|
|
175
|
+
fill them by running the suite.
|
|
176
|
+
|
|
177
|
+
## End-to-end benchmarking your pipeline
|
|
178
|
+
|
|
179
|
+
The harness below is the minimal template for honest end-to-end numbers.
|
|
180
|
+
Adapt it to your pipeline, provider mix, and query distribution.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
// scripts/e2e-benchmark.mjs
|
|
184
|
+
import { performance } from "node:perf_hooks";
|
|
185
|
+
import { writeFileSync } from "node:fs";
|
|
186
|
+
import { createRagPipeline } from "@devilsdev/rag-pipeline-utils";
|
|
187
|
+
|
|
188
|
+
const pipeline = createRagPipeline({
|
|
189
|
+
/* your real config — same as production */
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const queries = [
|
|
193
|
+
/* your real query set — at least 50 queries drawn from production logs */
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const WARMUP = 10;
|
|
197
|
+
const ITERATIONS = 100;
|
|
198
|
+
|
|
199
|
+
async function run(query) {
|
|
200
|
+
const t0 = performance.now();
|
|
201
|
+
const result = await pipeline.run({ query });
|
|
202
|
+
const t1 = performance.now();
|
|
203
|
+
return {
|
|
204
|
+
ms: t1 - t0,
|
|
205
|
+
retrievedCount: result.results?.length ?? 0,
|
|
206
|
+
answerChars: result.answer?.length ?? 0,
|
|
207
|
+
tokens: result.usage?.totalTokens ?? null,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Warmup
|
|
212
|
+
for (let i = 0; i < WARMUP; i++) {
|
|
213
|
+
await run(queries[i % queries.length]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Measured run
|
|
217
|
+
const samples = [];
|
|
218
|
+
for (let i = 0; i < ITERATIONS; i++) {
|
|
219
|
+
samples.push(await run(queries[i % queries.length]));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const ms = samples.map((s) => s.ms).sort((a, b) => a - b);
|
|
223
|
+
const percentile = (p) => ms[Math.floor(ms.length * p)];
|
|
224
|
+
|
|
225
|
+
const report = {
|
|
226
|
+
timestamp: new Date().toISOString(),
|
|
227
|
+
iterations: ITERATIONS,
|
|
228
|
+
warmup: WARMUP,
|
|
229
|
+
latencyMs: {
|
|
230
|
+
mean: ms.reduce((a, b) => a + b, 0) / ms.length,
|
|
231
|
+
p50: percentile(0.5),
|
|
232
|
+
p95: percentile(0.95),
|
|
233
|
+
p99: percentile(0.99),
|
|
234
|
+
min: ms[0],
|
|
235
|
+
max: ms[ms.length - 1],
|
|
236
|
+
},
|
|
237
|
+
avgTokens: samples.reduce((a, b) => a + (b.tokens ?? 0), 0) / samples.length,
|
|
238
|
+
avgRetrieved:
|
|
239
|
+
samples.reduce((a, b) => a + b.retrievedCount, 0) / samples.length,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
writeFileSync("e2e-benchmark.json", JSON.stringify(report, null, 2));
|
|
243
|
+
console.table(report.latencyMs);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Run it the same way on every comparison — same corpus, same query set,
|
|
247
|
+
same providers, same hardware. Don't compare a warm run to a cold one.
|
|
248
|
+
|
|
249
|
+
## Interpreting results
|
|
250
|
+
|
|
251
|
+
### Timing percentiles
|
|
252
|
+
|
|
253
|
+
- **mean** is easy to move around by outliers; don't report it alone
|
|
254
|
+
- **p50** (median) is the "typical" experience
|
|
255
|
+
- **p95** is the tail a user will notice
|
|
256
|
+
- **p99** is where GC, cold caches, and network hiccups live — useful
|
|
257
|
+
for SLO design
|
|
258
|
+
- **standardDeviation** much larger than the mean signals high variance;
|
|
259
|
+
your benchmark is probably too short, too concurrent, or sharing a
|
|
260
|
+
noisy host
|
|
261
|
+
|
|
262
|
+
### Throughput
|
|
263
|
+
|
|
264
|
+
- Throughput is computed as `iterations / (mean_seconds)`. It's
|
|
265
|
+
single-process throughput with the harness's concurrency settings —
|
|
266
|
+
not a statement about your production service's throughput under a
|
|
267
|
+
real load mix.
|
|
268
|
+
- If you want realistic multi-tenant throughput numbers, build a
|
|
269
|
+
load-test harness (`autocannon`, `k6`, `artillery`) that hits the
|
|
270
|
+
HTTP surface you actually deploy, not the library directly.
|
|
271
|
+
|
|
272
|
+
### Memory
|
|
273
|
+
|
|
274
|
+
- `avgDeltaHeapUsed` is the _growth per iteration_. Trending up across
|
|
275
|
+
a long run means you have a leak.
|
|
276
|
+
- `peakHeapUsed` tells you the upper bound for right-sizing containers.
|
|
277
|
+
- On Windows or containerized Linux, RSS is not the same as heap used;
|
|
278
|
+
prefer platform metrics for capacity planning.
|
|
279
|
+
|
|
280
|
+
### Common pitfalls
|
|
281
|
+
|
|
282
|
+
1. **No warmup** — first-iteration numbers are dominated by JIT and
|
|
283
|
+
cold caches. Always discard a warmup window.
|
|
284
|
+
2. **Too few iterations** — 10 iterations on a ~1ms operation is mostly
|
|
285
|
+
noise. 100+ is a reasonable floor for framework benchmarks;
|
|
286
|
+
end-to-end benchmarks need enough iterations to cover your query
|
|
287
|
+
distribution.
|
|
288
|
+
3. **Correlated runs** — running the suite twice back-to-back on a
|
|
289
|
+
laptop will show the second run as faster because caches are warm.
|
|
290
|
+
For comparisons, use fresh processes and cold caches, or explicitly
|
|
291
|
+
measure warm paths.
|
|
292
|
+
4. **Shared hosts** — CI runners, personal machines with open browsers,
|
|
293
|
+
and containers on bin-packed hosts all have neighbors that will add
|
|
294
|
+
noise. Dedicated bare metal or bare VMs give the cleanest numbers.
|
|
295
|
+
5. **Stream-based workloads** — retrieval latency is not end-to-end
|
|
296
|
+
latency when the LLM streams tokens. Measure time-to-first-token
|
|
297
|
+
(TTFT) separately from total completion time.
|
|
298
|
+
|
|
299
|
+
## Regression testing in CI
|
|
300
|
+
|
|
301
|
+
The benchmark suite is deterministic enough to catch gross regressions
|
|
302
|
+
in CI. Recommended pattern:
|
|
303
|
+
|
|
304
|
+
1. Run `npm run benchmark:quick` on every PR against the default branch
|
|
305
|
+
2. Compare `latest.json` to the baseline in `main` using the keys in
|
|
306
|
+
`benchmarks.*.timing.mean`
|
|
307
|
+
3. Fail the gate if any benchmark's mean regresses by more than a
|
|
308
|
+
disclosed threshold (e.g. 25%)
|
|
309
|
+
|
|
310
|
+
This project does not yet gate on benchmark regressions in CI by default
|
|
311
|
+
— numbers on shared GitHub runners are too noisy to trust automatically.
|
|
312
|
+
If you run the suite on dedicated hardware as part of a release gate,
|
|
313
|
+
we'd welcome the workflow contribution.
|
|
314
|
+
|
|
315
|
+
## Contributing benchmark data
|
|
316
|
+
|
|
317
|
+
If you run the suite on a representative production-class host and want
|
|
318
|
+
to share the results:
|
|
319
|
+
|
|
320
|
+
1. Open a PR adding your report to `benchmark-results/community/` as
|
|
321
|
+
`<hostname-slug>-<date>.json`
|
|
322
|
+
2. Include the full environment disclosure block above in the PR
|
|
323
|
+
description
|
|
324
|
+
3. We will not average, normalize, or rank contributed numbers — they
|
|
325
|
+
remain raw data points for other users comparing against similar
|
|
326
|
+
hardware profiles
|
|
327
|
+
|
|
328
|
+
Community benchmark data is licensed under CC0 1.0 (public domain)
|
|
329
|
+
when contributed.
|
|
330
|
+
|
|
331
|
+
## See also
|
|
332
|
+
|
|
333
|
+
- [Performance guide](docs-site/docs/Performance.md) — optimization
|
|
334
|
+
strategies by component (embedding, retrieval, LLM, memory)
|
|
335
|
+
- [`scripts/benchmark.js`](scripts/benchmark.js) — the benchmark
|
|
336
|
+
harness source
|
|
337
|
+
- [SECURITY.md](SECURITY.md) — security hardening, not performance,
|
|
338
|
+
but often on the same reviewer checklist
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,52 @@ Older history (pre-2.4.0) is preserved in the
|
|
|
9
9
|
[GitHub releases](https://github.com/DevilsDev/rag-pipeline-utils/releases)
|
|
10
10
|
page.
|
|
11
11
|
|
|
12
|
+
## [2.4.4] - 2026-04-16
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`BENCHMARKS.md`** (root, ships in tarball) — methodology-first
|
|
17
|
+
benchmarks doc covering what we measure, what we don't, how to
|
|
18
|
+
run the suite, environment disclosure template, JSON report schema,
|
|
19
|
+
end-to-end harness template for benchmarking your own stack,
|
|
20
|
+
interpretation guide (percentiles, throughput, memory), common
|
|
21
|
+
pitfalls, and a CI regression pattern.
|
|
22
|
+
- **`SEMVER.md`** (root, ships in tarball) — API stability policy.
|
|
23
|
+
Defines public surface, what counts as breaking, deprecation
|
|
24
|
+
process (one-minor warning window minimum), supported runtimes,
|
|
25
|
+
TypeScript and ESM/CJS commitments.
|
|
26
|
+
- **`docs-site/docs/Security-Capabilities.md`** — capability matrix
|
|
27
|
+
distinguishing what's battle-tested (🟢) vs. recommended practice
|
|
28
|
+
(🟡) vs. example code requiring hardening (🟠) vs. out of scope
|
|
29
|
+
(🔴), across pre-retrieval, retrieval-time, and post-generation
|
|
30
|
+
guardrails plus supply-chain, auth, logging, input validation, and
|
|
31
|
+
data governance.
|
|
32
|
+
- **`docs-site/docs/Concepts-Core.md`**,
|
|
33
|
+
`Concepts-Connectors.md`, `Concepts-Evaluation.md`,
|
|
34
|
+
`Concepts-Guardrails.md` — four conceptual-module overviews mapped
|
|
35
|
+
to a future `rag-core` / `rag-connectors` / `rag-eval` /
|
|
36
|
+
`rag-guardrails` package boundary, so reviewers can reason about
|
|
37
|
+
blast radius without us splitting the codebase.
|
|
38
|
+
- **`docs-site/docs/Comparison.md`** — honest comparison vs.
|
|
39
|
+
LangChain.js and LlamaIndex.TS, including where we lose and a
|
|
40
|
+
decision framework. Currency dated to April 2026.
|
|
41
|
+
- **`examples/fastify-rag-demo/`** — runnable end-to-end RAG service:
|
|
42
|
+
Fastify 5 + OpenAI + in-memory retriever + 3-layer guardrails
|
|
43
|
+
- citations + evaluation. Ships with Dockerfile, Fly.io `fly.toml`,
|
|
44
|
+
Railway `railway.json`, ingest + smoke-test scripts, and a complete
|
|
45
|
+
README. ~150 lines of `server.js`.
|
|
46
|
+
- **`examples/README.md`** — index of runnable examples with
|
|
47
|
+
contribution guidance.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- README "Documentation" section now links to BENCHMARKS, SECURITY,
|
|
52
|
+
CHANGELOG (added in 2.4.3) plus SEMVER, the Security Capabilities
|
|
53
|
+
matrix, the Comparison page, and the runnable demo.
|
|
54
|
+
- Sidebar adds two new categories: "Concepts" (4 pages) and a
|
|
55
|
+
Comparison page under Overview. Security-Capabilities slotted under
|
|
56
|
+
Enterprise.
|
|
57
|
+
|
|
12
58
|
## [2.4.3] - 2026-04-16
|
|
13
59
|
|
|
14
60
|
### Security
|
|
@@ -78,6 +124,7 @@ First public release on the 2.4 line, introducing the v2.4 feature set.
|
|
|
78
124
|
For release notes prior to v2.4.0, see
|
|
79
125
|
[github.com/DevilsDev/rag-pipeline-utils/releases](https://github.com/DevilsDev/rag-pipeline-utils/releases).
|
|
80
126
|
|
|
127
|
+
[2.4.4]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.4
|
|
81
128
|
[2.4.3]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.3
|
|
82
129
|
[2.4.2]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.2
|
|
83
130
|
[2.4.1]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.1
|
package/README.md
CHANGED
|
@@ -157,6 +157,13 @@ import {
|
|
|
157
157
|
- **[Architecture](https://devilsdev.github.io/rag-pipeline-utils/docs/Architecture)** — plugin contracts, pipeline internals
|
|
158
158
|
- **[API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)** — complete export index
|
|
159
159
|
- **[Examples](https://devilsdev.github.io/rag-pipeline-utils/docs/Examples)** — chatbot, Q&A, code search, support
|
|
160
|
+
- **[Comparison vs LangChain.js / LlamaIndex.TS](https://devilsdev.github.io/rag-pipeline-utils/docs/Comparison)** — honest decision framework
|
|
161
|
+
- **[Runnable demo](examples/fastify-rag-demo)** — Fastify + OpenAI + guardrails, deployable in one command
|
|
162
|
+
- **[Benchmarks & methodology](BENCHMARKS.md)** — how we measure, how you reproduce
|
|
163
|
+
- **[Security policy](SECURITY.md)** — responsible disclosure, supported versions
|
|
164
|
+
- **[Security capability matrix](https://devilsdev.github.io/rag-pipeline-utils/docs/Security-Capabilities)** — what's battle-tested vs. recommended vs. example
|
|
165
|
+
- **[API stability policy (SEMVER.md)](SEMVER.md)** — what counts as breaking, deprecation windows
|
|
166
|
+
- **[Changelog](CHANGELOG.md)** — release history
|
|
160
167
|
|
|
161
168
|
## Roadmap
|
|
162
169
|
|
package/SEMVER.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# API Stability Policy
|
|
2
|
+
|
|
3
|
+
This document defines what counts as a breaking change for
|
|
4
|
+
`@devilsdev/rag-pipeline-utils`, how long each release line is
|
|
5
|
+
supported, and the deprecation process for public API surface.
|
|
6
|
+
|
|
7
|
+
It is the contract you can plan against.
|
|
8
|
+
|
|
9
|
+
## Versioning
|
|
10
|
+
|
|
11
|
+
We follow [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html):
|
|
12
|
+
|
|
13
|
+
| Release | When it lands | What changes |
|
|
14
|
+
| ----------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
15
|
+
| **Patch** (2.4.x) | Bug fixes, security patches, docs, internal refactors | Nothing public-facing breaks. Safe to adopt without reading release notes. |
|
|
16
|
+
| **Minor** (2.x.0) | New features, additive API surface, new plugins, non-breaking behavior tweaks | Review the [CHANGELOG](CHANGELOG.md) before upgrading. Backward compatible. |
|
|
17
|
+
| **Major** (x.0.0) | Breaking changes to public API or required Node versions | Requires active migration. Each major ships with a migration guide. |
|
|
18
|
+
|
|
19
|
+
Pre-release versions (`x.y.z-rc.N`, `-beta.N`, `-alpha.N`) are for
|
|
20
|
+
testing. They have no stability guarantees and may change or disappear
|
|
21
|
+
before general availability.
|
|
22
|
+
|
|
23
|
+
## Public API surface
|
|
24
|
+
|
|
25
|
+
The **public API surface** — everything covered by SemVer — is
|
|
26
|
+
everything reachable from the package entry point:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import { ... } from "@devilsdev/rag-pipeline-utils";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Plus the CLI (`npx rag-pipeline …`) and the plugin contract schemas
|
|
33
|
+
in `contracts/`.
|
|
34
|
+
|
|
35
|
+
The following are **not** part of the public API surface and may
|
|
36
|
+
change in any release, including patches:
|
|
37
|
+
|
|
38
|
+
- Any import path with `/internal/` in it
|
|
39
|
+
- Default export behavior of submodules not documented in the
|
|
40
|
+
[API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)
|
|
41
|
+
- Imports reaching into `dist/` or `src/` directly (e.g.
|
|
42
|
+
`@devilsdev/rag-pipeline-utils/src/core/dag/executor.js`)
|
|
43
|
+
- Behavior of items marked `@internal` in JSDoc
|
|
44
|
+
- Behavior marked **experimental** in release notes or JSDoc
|
|
45
|
+
- The on-disk format of internal caches, logs, or temporary files
|
|
46
|
+
- Exact wording of log messages and error `message` strings
|
|
47
|
+
- Node version support _below_ the documented minimum (see "Supported
|
|
48
|
+
runtime" below)
|
|
49
|
+
|
|
50
|
+
If you depend on any of the above, you accept that patch-level upgrades
|
|
51
|
+
may break your integration.
|
|
52
|
+
|
|
53
|
+
## Breaking changes
|
|
54
|
+
|
|
55
|
+
A **breaking change** is any change that would force a user of the
|
|
56
|
+
public API surface to modify their code, configuration, or deployment.
|
|
57
|
+
Concretely:
|
|
58
|
+
|
|
59
|
+
- Removing or renaming a public export
|
|
60
|
+
- Removing a method or property on a public class
|
|
61
|
+
- Changing the signature of a public method in a way existing callers
|
|
62
|
+
can't satisfy (added required parameter, removed optional parameter
|
|
63
|
+
type, etc.)
|
|
64
|
+
- Changing the shape of a public configuration object
|
|
65
|
+
- Tightening a type that was previously accepting
|
|
66
|
+
- Changing the default value of a public option when the new default
|
|
67
|
+
produces different behavior
|
|
68
|
+
- Throwing a new error class from a public method where callers
|
|
69
|
+
previously got a different class or a string
|
|
70
|
+
- Raising the minimum Node.js version
|
|
71
|
+
- Raising the minimum TypeScript version for typed consumers
|
|
72
|
+
- Removing support for a bundler or module format (ESM/CJS)
|
|
73
|
+
|
|
74
|
+
The following are **not** breaking changes (they ship in minors and
|
|
75
|
+
patches freely):
|
|
76
|
+
|
|
77
|
+
- Adding new exports, methods, or options
|
|
78
|
+
- Relaxing a type that was previously restrictive
|
|
79
|
+
- Widening an accepted input (e.g. accepting `Buffer` where we
|
|
80
|
+
previously only accepted `string`)
|
|
81
|
+
- Adding new optional parameters at the end of a signature
|
|
82
|
+
- Improving error messages or adding context to them
|
|
83
|
+
- Changing the shape of _logs_ (not errors)
|
|
84
|
+
- Performance improvements that don't change observable behavior
|
|
85
|
+
- Internal refactors invisible to the public API
|
|
86
|
+
|
|
87
|
+
## Deprecation process
|
|
88
|
+
|
|
89
|
+
When we need to remove public API surface, the removal is preceded by
|
|
90
|
+
at least **one minor release** with a deprecation warning.
|
|
91
|
+
|
|
92
|
+
Timeline:
|
|
93
|
+
|
|
94
|
+
1. **Minor X.Y.0** — API marked deprecated
|
|
95
|
+
- JSDoc `@deprecated` tag with migration guidance
|
|
96
|
+
- TypeScript `@deprecated` in type declarations (strikethrough in
|
|
97
|
+
IDEs)
|
|
98
|
+
- Runtime warning printed once per process when the API is called
|
|
99
|
+
(`util.deprecate` or equivalent)
|
|
100
|
+
- Documentation updated with the recommended replacement
|
|
101
|
+
- Mentioned in the [CHANGELOG](CHANGELOG.md)
|
|
102
|
+
2. **Minor X.Y.Z** and beyond — API still present, still warning
|
|
103
|
+
3. **Major (X+1).0.0** — API removed
|
|
104
|
+
|
|
105
|
+
The minimum one-minor window means a user running `npm update`
|
|
106
|
+
regularly will see deprecation warnings before the next major ships.
|
|
107
|
+
We will extend the window longer than one minor for widely-used API
|
|
108
|
+
surface.
|
|
109
|
+
|
|
110
|
+
## Supported runtime
|
|
111
|
+
|
|
112
|
+
The minimum supported Node.js version is declared in
|
|
113
|
+
[`package.json` `engines.node`](./package.json). We support Node LTS
|
|
114
|
+
versions that are in active maintenance at the time of each major
|
|
115
|
+
release.
|
|
116
|
+
|
|
117
|
+
Dropping support for a Node version is a **breaking change** and
|
|
118
|
+
lands only in major releases.
|
|
119
|
+
|
|
120
|
+
Current: **Node.js ≥ 18**. The next major release is planned to
|
|
121
|
+
require **Node.js ≥ 20** to track LTS support timelines.
|
|
122
|
+
|
|
123
|
+
## Supported release lines
|
|
124
|
+
|
|
125
|
+
See [SECURITY.md](SECURITY.md#supported-versions). In summary:
|
|
126
|
+
|
|
127
|
+
- **Latest minor** receives bug fixes and security patches
|
|
128
|
+
- **Previous minor** receives a 30-day security-only patch window
|
|
129
|
+
after a new minor ships
|
|
130
|
+
- **Older minors** are unsupported
|
|
131
|
+
|
|
132
|
+
The same matrix applies to non-security bug fixes.
|
|
133
|
+
|
|
134
|
+
## TypeScript
|
|
135
|
+
|
|
136
|
+
Type declarations ship in `dist/index.d.ts` and are considered part of
|
|
137
|
+
the public API surface. Breaking changes to _types_ that require
|
|
138
|
+
consumer code changes follow the same SemVer rules as runtime API.
|
|
139
|
+
|
|
140
|
+
Type-widening changes (making a type more permissive) are not breaking.
|
|
141
|
+
Type-narrowing changes (making a type more restrictive, causing
|
|
142
|
+
previously-compiling code to fail) are breaking.
|
|
143
|
+
|
|
144
|
+
We target the TypeScript version currently listed in
|
|
145
|
+
`package.json` `devDependencies`. Consumers using older TypeScript
|
|
146
|
+
versions may see type errors that are not regressions.
|
|
147
|
+
|
|
148
|
+
## ESM and CommonJS
|
|
149
|
+
|
|
150
|
+
The package ships **dual-module builds** — both ESM (`dist/index.mjs`)
|
|
151
|
+
and CommonJS (`dist/index.cjs`). `package.json` `exports` resolves the
|
|
152
|
+
correct entry point based on how the consumer imports it.
|
|
153
|
+
|
|
154
|
+
The ESM build is the primary development target. The CommonJS build
|
|
155
|
+
is a compatibility layer. When a feature can only be expressed in ESM
|
|
156
|
+
(e.g. top-level await, real dynamic imports), we ship it in ESM and
|
|
157
|
+
document the CJS limitation.
|
|
158
|
+
|
|
159
|
+
Dropping CommonJS support is a breaking change and will land only in
|
|
160
|
+
a major release, with a full minor of deprecation warnings first.
|
|
161
|
+
|
|
162
|
+
## What this means for you
|
|
163
|
+
|
|
164
|
+
If you are building on top of this package, you can:
|
|
165
|
+
|
|
166
|
+
- **Auto-merge patch updates** with confidence. Nothing public-facing
|
|
167
|
+
breaks.
|
|
168
|
+
- **Review minor updates** via the CHANGELOG before merging. No
|
|
169
|
+
required code changes, but new features may be worth adopting.
|
|
170
|
+
- **Plan for major updates.** Each major ships with a
|
|
171
|
+
`docs-site/docs/Migration.md` covering every breaking change and the
|
|
172
|
+
new call site.
|
|
173
|
+
|
|
174
|
+
If you find a case where a patch or minor change broke your
|
|
175
|
+
integration without a deprecation warning, open an issue — we treat
|
|
176
|
+
that as a bug against this policy.
|
|
177
|
+
|
|
178
|
+
## See also
|
|
179
|
+
|
|
180
|
+
- [SECURITY.md](SECURITY.md) — supported version windows and CVE
|
|
181
|
+
handling
|
|
182
|
+
- [CHANGELOG.md](CHANGELOG.md) — what actually changed per release
|
|
183
|
+
- [Migration guide](https://devilsdev.github.io/rag-pipeline-utils/docs/Migration)
|
|
184
|
+
— upgrade instructions between majors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devilsdev/rag-pipeline-utils",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5",
|
|
4
4
|
"description": "Composable RAG for Node.js — with built-in evaluation, citations, guardrails, and observability.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -153,7 +153,9 @@
|
|
|
153
153
|
"README.md",
|
|
154
154
|
"LICENSE",
|
|
155
155
|
"SECURITY.md",
|
|
156
|
-
"CHANGELOG.md"
|
|
156
|
+
"CHANGELOG.md",
|
|
157
|
+
"BENCHMARKS.md",
|
|
158
|
+
"SEMVER.md"
|
|
157
159
|
],
|
|
158
160
|
"publishConfig": {
|
|
159
161
|
"access": "public"
|