@devilsdev/rag-core 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/all.d.ts +58 -0
- package/dist/index.cjs +275 -15
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/types/adapters/ai-sdk-middleware.d.ts +10 -0
- package/dist/types/adapters/mastra.d.ts +6 -2
- package/dist/types/agentic/agentic-pipeline.d.ts +1 -1
- package/dist/types/agentic/iterative-retriever.d.ts +1 -1
- package/dist/types/agentic/query-planner.d.ts +1 -1
- package/dist/types/agentic/self-critique.d.ts +1 -1
- package/dist/types/ai/federation/federated-learning-coordinator.d.ts +1 -1
- package/dist/types/ai/training/model-training-orchestrator.d.ts +1 -1
- package/dist/types/chunking/chunking-engine.d.ts +1 -1
- package/dist/types/citation/citation-tracker.d.ts +1 -1
- package/dist/types/connectors/anthropic-connector.d.ts +35 -1
- package/dist/types/connectors/base-connector.d.ts +1 -1
- package/dist/types/connectors/connector-utils.d.ts +20 -0
- package/dist/types/cost/cost-calculator.d.ts +1 -1
- package/dist/types/cost/cost-tracker.d.ts +1 -1
- package/dist/types/cost/token-budget.d.ts +1 -1
- package/dist/types/dashboard/dashboard-generator.d.ts +1 -1
- package/dist/types/dashboard/metrics-aggregator.d.ts +1 -1
- package/dist/types/debug/execution-tracer.d.ts +1 -1
- package/dist/types/debug/trace-inspector.d.ts +1 -1
- package/dist/types/dev/dev-server.d.ts +1 -1
- package/dist/types/dev/hot-reload.d.ts +1 -1
- package/dist/types/ecosystem/plugin-analytics-dashboard.d.ts +1 -1
- package/dist/types/ecosystem/plugin-certification.d.ts +1 -1
- package/dist/types/ecosystem/plugin-hub.d.ts +1 -1
- package/dist/types/enterprise/audit-logging.d.ts +1 -1
- package/dist/types/enterprise/data-governance.d.ts +1 -1
- package/dist/types/enterprise/multi-tenancy.d.ts +1 -1
- package/dist/types/enterprise/sso-integration.d.ts +1 -1
- package/dist/types/evaluate/pipeline-evaluator.d.ts +1 -1
- package/dist/types/graph/entity-extractor.d.ts +1 -1
- package/dist/types/graph/graph-retriever.d.ts +1 -1
- package/dist/types/graph/knowledge-graph.d.ts +1 -1
- package/dist/types/grounding/check-answer.d.ts +109 -1
- package/dist/types/grounding/llm-judge.d.ts +93 -0
- package/dist/types/grounding/provider-citations.d.ts +244 -0
- package/dist/types/guardrails/detectors.d.ts +88 -0
- package/dist/types/guardrails/evaluate-detectors.d.ts +61 -0
- package/dist/types/guardrails/guardrails-pipeline.d.ts +2 -9
- package/dist/types/guardrails/post-generation-guard.d.ts +33 -3
- package/dist/types/guardrails/pre-retrieval-guard.d.ts +29 -1
- package/dist/types/guardrails/retrieval-guard.d.ts +30 -1
- package/dist/types/mcp/mcp-server.d.ts +1 -1
- package/dist/types/observability/otel.d.ts +9 -3
- package/dist/types/observability/scores.d.ts +57 -0
- package/dist/types/reranker/cascade-reranker.d.ts +1 -1
- package/dist/types/reranker/embedding-reranker.d.ts +1 -1
- package/dist/types/reranker/scoring-reranker.d.ts +1 -1
- package/dist/types/retrieval/bm25-search.d.ts +1 -1
- package/dist/types/retrieval/hybrid-retriever.d.ts +1 -1
- package/dist/types/security/jwt-validator.d.ts +1 -1
- package/dist/types/security/plugin-sandbox.d.ts +1 -1
- package/dist/types/streaming/sse-adapter.d.ts +1 -1
- package/dist/types/streaming/stream-router.d.ts +1 -1
- package/dist/types/streaming/streaming-embedder.d.ts +1 -1
- package/dist/types/streaming/websocket-adapter.d.ts +1 -1
- package/dist/types/templates/scaffold.d.ts +1 -1
- package/dist/types/testing/contract-tests.d.ts +8 -4
- package/dist/types/utils/batch-processor.d.ts +1 -1
- package/dist/types/utils/connection-pool.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Part of [@devilsdev/rag-pipeline-utils](https://www.npmjs.com/package/@devilsdev
|
|
|
8
8
|
npm install @devilsdev/rag-core
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Exports: `createRagPipeline`, `createPipeline`, `packContext`, `createError`, `wrapError`, `ERROR_CODES`, `retry`, `withRetry`, `ChunkingEngine`, `BM25Search`, `reciprocalRankFusion`, `HybridRetriever`, `ScoringReranker`, `EmbeddingReranker`, `CascadeReranker`, `MemoryCache`, `RedisCache`, `CostCalculator`, `PRICING_METADATA`, `CostTracker`, `TokenBudget`, `createModelRouter`, `classifyQuery`, `MemoryRetriever`, `BaseConnector`.
|
|
11
|
+
Exports: `createRagPipeline`, `createPipeline`, `evaluationScores`, `toLangfuseScores`, `packContext`, `createError`, `wrapError`, `ERROR_CODES`, `retry`, `withRetry`, `ChunkingEngine`, `BM25Search`, `reciprocalRankFusion`, `HybridRetriever`, `ScoringReranker`, `EmbeddingReranker`, `CascadeReranker`, `MemoryCache`, `RedisCache`, `CostCalculator`, `PRICING_METADATA`, `CostTracker`, `TokenBudget`, `createModelRouter`, `classifyQuery`, `MemoryRetriever`, `BaseConnector`.
|
|
12
12
|
|
|
13
13
|
Documentation: https://devilsdev.github.io/rag-pipeline-utils/
|
|
14
14
|
|
package/dist/all.d.ts
CHANGED
|
@@ -50,10 +50,26 @@ export interface TelemetryOptions {
|
|
|
50
50
|
tracer?: TelemetryTracer;
|
|
51
51
|
/** The @opentelemetry/api module, for @devilsdev/rag-pipeline-utils/edge, which cannot load it itself. */
|
|
52
52
|
api?: any;
|
|
53
|
+
/**
|
|
54
|
+
* The @opentelemetry/api-logs module, for evaluation events when your SDK registers its
|
|
55
|
+
* LoggerProvider there (before sdk-logs 3). With @opentelemetry/api 1.10+ its own logs API is used.
|
|
56
|
+
*/
|
|
57
|
+
logs?: any;
|
|
58
|
+
/** A Logger (`emit(logRecord)`) for the gen_ai.evaluation.result events. */
|
|
59
|
+
logger?: { emit(logRecord: any): void };
|
|
53
60
|
/** Also record the query text and the retrieved document ids and scores. Default false. */
|
|
54
61
|
recordContent?: boolean;
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
/** A run's OpenTelemetry ids, on its result when `telemetry` is on. */
|
|
65
|
+
export interface RunTelemetry {
|
|
66
|
+
traceId: string;
|
|
67
|
+
/** The `rag.pipeline.run` span. */
|
|
68
|
+
spanId: string;
|
|
69
|
+
/** The stage spans, when the stage ran (not served from the cache). */
|
|
70
|
+
spans: { retrieval?: string; generation?: string };
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
/** A cache store: get / set / delete, optionally stats. */
|
|
58
74
|
export interface CacheBackend {
|
|
59
75
|
/** Resolves the stored value, or undefined when the key is missing or expired. */
|
|
@@ -151,6 +167,8 @@ export interface PipelineRunResult {
|
|
|
151
167
|
timing?: { totalMs: number };
|
|
152
168
|
/** The model router's decision, when the llm is a createModelRouter() and was called. */
|
|
153
169
|
route?: RouteDecision;
|
|
170
|
+
/** The run's trace and span ids, when `telemetry` is on. */
|
|
171
|
+
telemetry?: RunTelemetry;
|
|
154
172
|
}
|
|
155
173
|
|
|
156
174
|
/** Which model a createModelRouter() chose for a run. */
|
|
@@ -202,6 +220,8 @@ export interface StreamChunk {
|
|
|
202
220
|
timing?: StreamTiming;
|
|
203
221
|
/** On the last chunk, when the llm is a createModelRouter(). */
|
|
204
222
|
route?: RouteDecision;
|
|
223
|
+
/** On the last chunk, the run's trace and span ids, when `telemetry` is on. */
|
|
224
|
+
telemetry?: RunTelemetry;
|
|
205
225
|
}
|
|
206
226
|
|
|
207
227
|
/** A pipeline returned by {@link createRagPipeline}. */
|
|
@@ -307,6 +327,33 @@ export interface RerankerPlugin {
|
|
|
307
327
|
rerank(query: string, documents: SearchResult[], options?: { topK?: number; signal?: AbortSignal }): SearchResult[] | Promise<SearchResult[]>;
|
|
308
328
|
}
|
|
309
329
|
|
|
330
|
+
/** Where a guard runs a detector, with the document for retrieval guards. */
|
|
331
|
+
export interface DetectorContext {
|
|
332
|
+
stage: "query" | "document" | "output";
|
|
333
|
+
document?: any;
|
|
334
|
+
/** The request's AbortSignal, when the caller passed one to checkAsync() / filterAsync(). */
|
|
335
|
+
signal?: AbortSignal;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** What a detector found. PII detectors must give each match's exact `text`, which is redacted. */
|
|
339
|
+
export interface DetectorResult {
|
|
340
|
+
flagged: boolean;
|
|
341
|
+
score?: number;
|
|
342
|
+
labels?: string[];
|
|
343
|
+
matches?: Array<{ label?: string; text: string; start?: number; end?: number }>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* A detector for the guards' `detectors` option: prompt injection
|
|
348
|
+
* (PreRetrievalGuard, RetrievalGuard) or PII (PostGenerationGuard). Async
|
|
349
|
+
* detectors need the guards' checkAsync() / filterAsync().
|
|
350
|
+
*/
|
|
351
|
+
export interface GuardDetector {
|
|
352
|
+
name: string;
|
|
353
|
+
kind: "injection" | "pii";
|
|
354
|
+
detect(text: string, context: DetectorContext): DetectorResult | Promise<DetectorResult>;
|
|
355
|
+
}
|
|
356
|
+
|
|
310
357
|
/** The interface of {@link pluginRegistry}. */
|
|
311
358
|
export interface PluginRegistry {
|
|
312
359
|
/**
|
|
@@ -428,6 +475,11 @@ export { PipelineEvaluator } from "./types/evaluate/pipeline-evaluator";
|
|
|
428
475
|
export { ChunkingEngine } from "./types/chunking/chunking-engine";
|
|
429
476
|
export { CitationTracker } from "./types/citation/citation-tracker";
|
|
430
477
|
export { checkAnswer } from "./types/grounding/check-answer";
|
|
478
|
+
export { fromAnthropicCitations } from "./types/grounding/provider-citations";
|
|
479
|
+
export { fromOpenAIFileCitations } from "./types/grounding/provider-citations";
|
|
480
|
+
export { verifyCitations } from "./types/grounding/provider-citations";
|
|
481
|
+
export { evaluationScores } from "./types/observability/scores";
|
|
482
|
+
export { toLangfuseScores } from "./types/observability/scores";
|
|
431
483
|
export { normalizeSources } from "./types/grounding/check-answer";
|
|
432
484
|
export { createAiSdkAdapter } from "./types/adapters/ai-sdk";
|
|
433
485
|
export { createMastraScorer } from "./types/adapters/mastra";
|
|
@@ -445,6 +497,12 @@ export { HybridRetriever } from "./types/retrieval/hybrid-retriever";
|
|
|
445
497
|
export { FileVectorStore } from "./types/retrieval/file-vector-store";
|
|
446
498
|
export { PreRetrievalGuard } from "./types/guardrails/pre-retrieval-guard";
|
|
447
499
|
export { detectInjection } from "./types/guardrails/injection-detector";
|
|
500
|
+
export { patternInjectionDetector } from "./types/guardrails/detectors";
|
|
501
|
+
export { patternPIIDetector } from "./types/guardrails/detectors";
|
|
502
|
+
export { detectedText } from "./types/guardrails/detectors";
|
|
503
|
+
export { evaluateDetectors } from "./types/guardrails/evaluate-detectors";
|
|
504
|
+
export { detectorVerdict } from "./types/guardrails/evaluate-detectors";
|
|
505
|
+
export { renderDetectorReport } from "./types/guardrails/evaluate-detectors";
|
|
448
506
|
export { RetrievalGuard } from "./types/guardrails/retrieval-guard";
|
|
449
507
|
export { PostGenerationGuard } from "./types/guardrails/post-generation-guard";
|
|
450
508
|
export { GuardrailsPipeline } from "./types/guardrails/guardrails-pipeline";
|
package/dist/index.cjs
CHANGED
|
@@ -1291,12 +1291,74 @@ var require_context_packing = __commonJS({
|
|
|
1291
1291
|
}
|
|
1292
1292
|
});
|
|
1293
1293
|
|
|
1294
|
+
// src/observability/scores.js
|
|
1295
|
+
var require_scores = __commonJS({
|
|
1296
|
+
"src/observability/scores.js"(exports2, module2) {
|
|
1297
|
+
"use strict";
|
|
1298
|
+
var RETRIEVAL_METRICS = /* @__PURE__ */ new Set(["contextPrecision", "contextRecall"]);
|
|
1299
|
+
var isScore = (v) => typeof v === "number" && Number.isFinite(v);
|
|
1300
|
+
function evaluationScores(result, { explanations = false } = {}) {
|
|
1301
|
+
if (!result || typeof result !== "object") return [];
|
|
1302
|
+
const out = [];
|
|
1303
|
+
const scores = result.evaluation && result.evaluation.scores ? result.evaluation.scores : {};
|
|
1304
|
+
for (const [name, value] of Object.entries(scores)) {
|
|
1305
|
+
if (!isScore(value)) continue;
|
|
1306
|
+
out.push({
|
|
1307
|
+
name,
|
|
1308
|
+
value,
|
|
1309
|
+
target: RETRIEVAL_METRICS.has(name) ? "retrieval" : "generation"
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
if (result.citations && isScore(result.citations.groundednessScore)) {
|
|
1313
|
+
out.push({
|
|
1314
|
+
name: "citationCoverage",
|
|
1315
|
+
value: result.citations.groundednessScore,
|
|
1316
|
+
target: "generation"
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
if (typeof result.grounded === "boolean" && isScore(result.groundedness)) {
|
|
1320
|
+
const unsupported = Array.isArray(result.unsupported) ? result.unsupported : [];
|
|
1321
|
+
out.push({
|
|
1322
|
+
name: "groundedSentences",
|
|
1323
|
+
value: result.groundedness,
|
|
1324
|
+
target: "generation",
|
|
1325
|
+
label: result.grounded ? "grounded" : "ungrounded",
|
|
1326
|
+
...explanations && unsupported.length > 0 && {
|
|
1327
|
+
explanation: `Unsupported: ${unsupported.map((s) => JSON.stringify(s)).join(" ")}`
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
return out;
|
|
1332
|
+
}
|
|
1333
|
+
function toLangfuseScores(result, options = {}) {
|
|
1334
|
+
const { observationId, sessionId, comments = false } = options;
|
|
1335
|
+
const tel = result && result.telemetry || {};
|
|
1336
|
+
const traceId = options.traceId || tel.traceId;
|
|
1337
|
+
const fromSameTrace = !options.traceId || options.traceId === tel.traceId;
|
|
1338
|
+
return evaluationScores(result, { explanations: comments }).map((s) => {
|
|
1339
|
+
const observation = observationId || (fromSameTrace && tel.spans ? tel.spans[s.target] : void 0);
|
|
1340
|
+
return {
|
|
1341
|
+
name: s.name,
|
|
1342
|
+
value: s.value,
|
|
1343
|
+
dataType: "NUMERIC",
|
|
1344
|
+
...traceId && { traceId },
|
|
1345
|
+
...observation && { observationId: observation },
|
|
1346
|
+
...sessionId && { sessionId },
|
|
1347
|
+
...s.explanation && { comment: s.explanation },
|
|
1348
|
+
...s.label && { metadata: { label: s.label } }
|
|
1349
|
+
};
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
module2.exports = { evaluationScores, toLangfuseScores };
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1294
1356
|
// package.json
|
|
1295
1357
|
var require_package = __commonJS({
|
|
1296
1358
|
"package.json"(exports2, module2) {
|
|
1297
1359
|
module2.exports = {
|
|
1298
1360
|
name: "@devilsdev/rag-pipeline-utils",
|
|
1299
|
-
version: "3.
|
|
1361
|
+
version: "3.5.0",
|
|
1300
1362
|
description: "Composable retrieval-augmented generation (RAG) for Node.js: grounded citations, evaluation, guardrails, hybrid retrieval and a CLI.",
|
|
1301
1363
|
main: "dist/index.cjs",
|
|
1302
1364
|
type: "commonjs",
|
|
@@ -1392,6 +1454,11 @@ var require_package = __commonJS({
|
|
|
1392
1454
|
"benchmark:full": "node scripts/benchmark.js --iterations=500 --verbose",
|
|
1393
1455
|
"bench:speed": "node benchmarks/speed.js",
|
|
1394
1456
|
"bench:quality": "node benchmarks/quality.js",
|
|
1457
|
+
"bench:guardrails": "node benchmarks/guardrails.js",
|
|
1458
|
+
"bench:judge": "node benchmarks/judge.js",
|
|
1459
|
+
"bench:claude-citations": "node benchmarks/claude-citations.js",
|
|
1460
|
+
"bench:judge-more": "node benchmarks/judge-more.js",
|
|
1461
|
+
"bench:claude-latency": "node benchmarks/claude-latency.js",
|
|
1395
1462
|
dev: "node scripts/dev-tools.js menu",
|
|
1396
1463
|
"dev:health": "node scripts/dev-tools.js health",
|
|
1397
1464
|
"dev:setup": "node scripts/dev-tools.js setup",
|
|
@@ -1410,6 +1477,7 @@ var require_package = __commonJS({
|
|
|
1410
1477
|
"tests:ci": "jest --maxWorkers=50% --reporters=default --json --outputFile=test-results-current.json",
|
|
1411
1478
|
"test:unit": "jest __tests__/unit",
|
|
1412
1479
|
"test:integration": "jest __tests__/integration",
|
|
1480
|
+
"test:live": "jest --config jest.live.config.js --runInBand",
|
|
1413
1481
|
"test:simple": "jest --maxWorkers=1 --no-coverage",
|
|
1414
1482
|
"verify:pack": "node scripts/verify-npm-pack.js",
|
|
1415
1483
|
"smoke:pack": "node scripts/smoke-test-pack.js",
|
|
@@ -1489,6 +1557,8 @@ var require_package = __commonJS({
|
|
|
1489
1557
|
"**/*.{json,md,mdx,yml,yaml,css,scss,html}": "prettier --write --ignore-unknown"
|
|
1490
1558
|
},
|
|
1491
1559
|
devDependencies: {
|
|
1560
|
+
"@ai-sdk/anthropic": "3.0.138",
|
|
1561
|
+
"@ai-sdk/anthropic-v4": "npm:@ai-sdk/anthropic@4.0.97",
|
|
1492
1562
|
"@babel/core": "^7.26.10",
|
|
1493
1563
|
"@babel/preset-env": "^7.26.9",
|
|
1494
1564
|
"@docusaurus/core": "3.10.2",
|
|
@@ -1499,12 +1569,14 @@ var require_package = __commonJS({
|
|
|
1499
1569
|
"@fontsource/jetbrains-mono": "5.3.0",
|
|
1500
1570
|
"@octokit/rest": "^21.1.1",
|
|
1501
1571
|
"@opentelemetry/api": "^1.9.1",
|
|
1572
|
+
"@opentelemetry/api-logs": "^0.223.0",
|
|
1502
1573
|
"@opentelemetry/auto-instrumentations-node": "^0.52.1",
|
|
1503
1574
|
"@opentelemetry/context-async-hooks": "^2.12.0",
|
|
1504
1575
|
"@opentelemetry/exporter-jaeger": "^1.26.0",
|
|
1505
1576
|
"@opentelemetry/exporter-prometheus": "^0.53.0",
|
|
1506
1577
|
"@opentelemetry/exporter-trace-otlp-http": "^0.53.0",
|
|
1507
1578
|
"@opentelemetry/resources": "^1.26.0",
|
|
1579
|
+
"@opentelemetry/sdk-logs": "^0.223.0",
|
|
1508
1580
|
"@opentelemetry/sdk-metrics": "^1.26.0",
|
|
1509
1581
|
"@opentelemetry/sdk-node": "^0.53.0",
|
|
1510
1582
|
"@opentelemetry/sdk-trace-base": "^2.12.0",
|
|
@@ -1550,10 +1622,10 @@ var require_package = __commonJS({
|
|
|
1550
1622
|
"why-is-node-running": "^3.2.2"
|
|
1551
1623
|
},
|
|
1552
1624
|
dependencies: {
|
|
1553
|
-
"@devilsdev/rag-connectors": "3.
|
|
1554
|
-
"@devilsdev/rag-core": "3.
|
|
1555
|
-
"@devilsdev/rag-eval": "3.
|
|
1556
|
-
"@devilsdev/rag-guardrails": "3.
|
|
1625
|
+
"@devilsdev/rag-connectors": "3.5.0",
|
|
1626
|
+
"@devilsdev/rag-core": "3.5.0",
|
|
1627
|
+
"@devilsdev/rag-eval": "3.5.0",
|
|
1628
|
+
"@devilsdev/rag-guardrails": "3.5.0",
|
|
1557
1629
|
ajv: "^8.17.1",
|
|
1558
1630
|
axios: "^1.21.0",
|
|
1559
1631
|
chokidar: "^4.0.3",
|
|
@@ -1636,6 +1708,7 @@ var require_optional_peer = __commonJS({
|
|
|
1636
1708
|
var require_otel = __commonJS({
|
|
1637
1709
|
"src/observability/otel.js"(exports2, module2) {
|
|
1638
1710
|
"use strict";
|
|
1711
|
+
var { evaluationScores } = require_scores();
|
|
1639
1712
|
var { version: LIBRARY_VERSION } = require_package();
|
|
1640
1713
|
var { loadOptionalPeer } = require_optional_peer();
|
|
1641
1714
|
var TRACER_NAME = "@devilsdev/rag-pipeline-utils";
|
|
@@ -1653,7 +1726,7 @@ var require_otel = __commonJS({
|
|
|
1653
1726
|
const opts = option === true ? {} : option;
|
|
1654
1727
|
if (typeof opts !== "object") {
|
|
1655
1728
|
throw new TypeError(
|
|
1656
|
-
"telemetry must be true or { tracer?, api?, recordContent? }"
|
|
1729
|
+
"telemetry must be true or { tracer?, api?, logs?, logger?, recordContent? }"
|
|
1657
1730
|
);
|
|
1658
1731
|
}
|
|
1659
1732
|
const api = opts.api || loadOtelApi();
|
|
@@ -1666,7 +1739,33 @@ var require_otel = __commonJS({
|
|
|
1666
1739
|
if (!tracer || typeof tracer.startActiveSpan !== "function") {
|
|
1667
1740
|
throw new TypeError("telemetry.tracer must be an OpenTelemetry Tracer");
|
|
1668
1741
|
}
|
|
1669
|
-
|
|
1742
|
+
let logger = opts.logger || null;
|
|
1743
|
+
if (logger && typeof logger.emit !== "function") {
|
|
1744
|
+
throw new TypeError("telemetry.logger must be an OpenTelemetry Logger");
|
|
1745
|
+
}
|
|
1746
|
+
if (!logger) {
|
|
1747
|
+
if (opts.logs && !(opts.logs.logs && typeof opts.logs.logs.getLogger === "function")) {
|
|
1748
|
+
throw new TypeError(
|
|
1749
|
+
'telemetry.logs must be the @opentelemetry/api-logs module (import * as logs from "@opentelemetry/api-logs")'
|
|
1750
|
+
);
|
|
1751
|
+
}
|
|
1752
|
+
const source = [opts.logs, api].find(
|
|
1753
|
+
(m) => m && m.logs && typeof m.logs.getLogger === "function"
|
|
1754
|
+
);
|
|
1755
|
+
if (source) logger = source.logs.getLogger(TRACER_NAME, LIBRARY_VERSION);
|
|
1756
|
+
}
|
|
1757
|
+
return {
|
|
1758
|
+
api,
|
|
1759
|
+
tracer,
|
|
1760
|
+
logger,
|
|
1761
|
+
// Holds the spans of one run, so its scores find them under concurrency
|
|
1762
|
+
runKey: api.createContextKey("rag.pipeline.run"),
|
|
1763
|
+
recordContent: Boolean(opts.recordContent)
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
function recordStage(tel, stage, span) {
|
|
1767
|
+
const run = tel.api.context.active().getValue(tel.runKey);
|
|
1768
|
+
if (run) run[stage] = span.spanContext();
|
|
1670
1769
|
}
|
|
1671
1770
|
function providerOf(component) {
|
|
1672
1771
|
const name = component && component.name;
|
|
@@ -1749,8 +1848,8 @@ var require_otel = __commonJS({
|
|
|
1749
1848
|
retriever(method, [params = {}]) {
|
|
1750
1849
|
const source = component.collection || (typeof component.table === "string" ? component.table.replace(/"/g, "") : void 0);
|
|
1751
1850
|
return {
|
|
1752
|
-
name:
|
|
1753
|
-
kind: SpanKind.
|
|
1851
|
+
name: "retrieval",
|
|
1852
|
+
kind: SpanKind.INTERNAL,
|
|
1754
1853
|
attributes: clean({
|
|
1755
1854
|
"gen_ai.operation.name": "retrieval",
|
|
1756
1855
|
"gen_ai.data_source.id": source,
|
|
@@ -1808,6 +1907,7 @@ var require_otel = __commonJS({
|
|
|
1808
1907
|
};
|
|
1809
1908
|
}
|
|
1810
1909
|
};
|
|
1910
|
+
const STAGES = { retriever: "retrieval", llm: "generation" };
|
|
1811
1911
|
const METHODS = {
|
|
1812
1912
|
embedder: ["embed", "embedQuery"],
|
|
1813
1913
|
retriever: ["retrieve"],
|
|
@@ -1821,8 +1921,10 @@ var require_otel = __commonJS({
|
|
|
1821
1921
|
return (...args) => {
|
|
1822
1922
|
const spec = spanFor[kind](prop, args);
|
|
1823
1923
|
const options = { kind: spec.kind, attributes: spec.attributes };
|
|
1924
|
+
const stage = STAGES[kind];
|
|
1824
1925
|
if (prop === "generateStream") {
|
|
1825
1926
|
return tel.tracer.startActiveSpan(spec.name, options, (span) => {
|
|
1927
|
+
if (stage) recordStage(tel, stage, span);
|
|
1826
1928
|
const startedAt = performance.now();
|
|
1827
1929
|
let source;
|
|
1828
1930
|
try {
|
|
@@ -1836,6 +1938,7 @@ var require_otel = __commonJS({
|
|
|
1836
1938
|
});
|
|
1837
1939
|
}
|
|
1838
1940
|
return inSpan(tel, spec.name, options, async (span) => {
|
|
1941
|
+
if (stage) recordStage(tel, stage, span);
|
|
1839
1942
|
const out = await value.apply(target, args);
|
|
1840
1943
|
spec.after(span, out);
|
|
1841
1944
|
return out;
|
|
@@ -1890,32 +1993,49 @@ var require_otel = __commonJS({
|
|
|
1890
1993
|
"rag.pipeline.run",
|
|
1891
1994
|
{ kind: SpanKind.INTERNAL, attributes },
|
|
1892
1995
|
async (span) => {
|
|
1996
|
+
const stages = {};
|
|
1997
|
+
const runContext = tel.api.context.active().setValue(tel.runKey, stages);
|
|
1893
1998
|
let result;
|
|
1894
1999
|
try {
|
|
1895
|
-
result = await run(params);
|
|
2000
|
+
result = await tel.api.context.with(runContext, () => run(params));
|
|
1896
2001
|
} catch (error) {
|
|
1897
2002
|
markError(tel, span, error);
|
|
1898
2003
|
span.end();
|
|
1899
2004
|
throw error;
|
|
1900
2005
|
}
|
|
1901
2006
|
if (result && typeof result[Symbol.asyncIterator] === "function") {
|
|
2007
|
+
const iterator = result[Symbol.asyncIterator]();
|
|
1902
2008
|
return (async function* tracedStream() {
|
|
2009
|
+
let finished = false;
|
|
1903
2010
|
try {
|
|
1904
|
-
for
|
|
2011
|
+
for (; ; ) {
|
|
2012
|
+
const step = await tel.api.context.with(
|
|
2013
|
+
runContext,
|
|
2014
|
+
() => iterator.next()
|
|
2015
|
+
);
|
|
2016
|
+
if (step.done) break;
|
|
2017
|
+
const chunk = step.value;
|
|
1905
2018
|
if (chunk && chunk.done) {
|
|
1906
2019
|
span.setAttributes(runAttributes(tel, chunk));
|
|
2020
|
+
finishRun(tel, span, stages, chunk);
|
|
1907
2021
|
}
|
|
1908
2022
|
yield chunk;
|
|
1909
2023
|
}
|
|
2024
|
+
finished = true;
|
|
1910
2025
|
} catch (error) {
|
|
2026
|
+
finished = true;
|
|
1911
2027
|
markError(tel, span, error);
|
|
1912
2028
|
throw error;
|
|
1913
2029
|
} finally {
|
|
2030
|
+
if (!finished && typeof iterator.return === "function") {
|
|
2031
|
+
await iterator.return();
|
|
2032
|
+
}
|
|
1914
2033
|
span.end();
|
|
1915
2034
|
}
|
|
1916
2035
|
})();
|
|
1917
2036
|
}
|
|
1918
2037
|
span.setAttributes(runAttributes(tel, result));
|
|
2038
|
+
finishRun(tel, span, stages, result);
|
|
1919
2039
|
if (!result || result.success === false) {
|
|
1920
2040
|
const message = result && result.error || "run failed";
|
|
1921
2041
|
span.setAttribute("error.type", errorType(message));
|
|
@@ -1927,6 +2047,33 @@ var require_otel = __commonJS({
|
|
|
1927
2047
|
);
|
|
1928
2048
|
};
|
|
1929
2049
|
}
|
|
2050
|
+
function finishRun(tel, span, stages, result) {
|
|
2051
|
+
if (!result || typeof result !== "object") return;
|
|
2052
|
+
const own = span.spanContext();
|
|
2053
|
+
result.telemetry = {
|
|
2054
|
+
traceId: own.traceId,
|
|
2055
|
+
spanId: own.spanId,
|
|
2056
|
+
spans: Object.fromEntries(
|
|
2057
|
+
Object.entries(stages).map(([stage, ctx]) => [stage, ctx.spanId])
|
|
2058
|
+
)
|
|
2059
|
+
};
|
|
2060
|
+
if (!tel.logger) return;
|
|
2061
|
+
for (const score of evaluationScores(result, {
|
|
2062
|
+
explanations: tel.recordContent
|
|
2063
|
+
})) {
|
|
2064
|
+
const parent = stages[score.target] || own;
|
|
2065
|
+
tel.logger.emit({
|
|
2066
|
+
eventName: "gen_ai.evaluation.result",
|
|
2067
|
+
context: tel.api.trace.setSpanContext(tel.api.context.active(), parent),
|
|
2068
|
+
attributes: clean({
|
|
2069
|
+
"gen_ai.evaluation.name": score.name,
|
|
2070
|
+
"gen_ai.evaluation.score.value": score.value,
|
|
2071
|
+
"gen_ai.evaluation.score.label": score.label,
|
|
2072
|
+
"gen_ai.evaluation.explanation": score.explanation
|
|
2073
|
+
})
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
1930
2077
|
function errorType(message) {
|
|
1931
2078
|
if (message === "Execution timeout") return "timeout";
|
|
1932
2079
|
if (message === "Execution aborted") return "aborted";
|
|
@@ -5101,7 +5248,79 @@ var require_connector_utils = __commonJS({
|
|
|
5101
5248
|
reader.releaseLock();
|
|
5102
5249
|
}
|
|
5103
5250
|
}
|
|
5251
|
+
function toConnectorError(err, provider) {
|
|
5252
|
+
if (!err || typeof err !== "object" || err.isAxiosError !== true) {
|
|
5253
|
+
return err;
|
|
5254
|
+
}
|
|
5255
|
+
if (isAbortError(err)) {
|
|
5256
|
+
const aborted = new Error("The operation was aborted");
|
|
5257
|
+
aborted.name = "AbortError";
|
|
5258
|
+
aborted.code = "ABORT_ERR";
|
|
5259
|
+
return aborted;
|
|
5260
|
+
}
|
|
5261
|
+
const response = err.response;
|
|
5262
|
+
let message;
|
|
5263
|
+
if (response) {
|
|
5264
|
+
const data = response.data;
|
|
5265
|
+
const apiError = data && typeof data === "object" && typeof data.pipe !== "function" ? data.error : void 0;
|
|
5266
|
+
let detail = "";
|
|
5267
|
+
if (apiError && typeof apiError === "object") {
|
|
5268
|
+
detail = [apiError.type, apiError.message].filter(Boolean).join(": ");
|
|
5269
|
+
} else if (typeof apiError === "string") {
|
|
5270
|
+
detail = apiError;
|
|
5271
|
+
} else if (data && typeof data === "object" && typeof data.message === "string") {
|
|
5272
|
+
detail = data.message;
|
|
5273
|
+
}
|
|
5274
|
+
message = `${provider} API error ${response.status}${detail ? `: ${detail}` : ""}`;
|
|
5275
|
+
} else {
|
|
5276
|
+
message = `${provider} request failed: ${err.message}`;
|
|
5277
|
+
}
|
|
5278
|
+
const error = new Error(message);
|
|
5279
|
+
if (err.code) error.code = err.code;
|
|
5280
|
+
if (response) {
|
|
5281
|
+
error.status = response.status;
|
|
5282
|
+
error.response = {
|
|
5283
|
+
status: response.status,
|
|
5284
|
+
statusText: response.statusText,
|
|
5285
|
+
headers: response.headers,
|
|
5286
|
+
data: response.data
|
|
5287
|
+
};
|
|
5288
|
+
}
|
|
5289
|
+
return error;
|
|
5290
|
+
}
|
|
5291
|
+
async function readErrorBody(stream) {
|
|
5292
|
+
const chunks = [];
|
|
5293
|
+
let size = 0;
|
|
5294
|
+
try {
|
|
5295
|
+
for await (const chunk of stream) {
|
|
5296
|
+
size += chunk.length;
|
|
5297
|
+
if (size > 65536) break;
|
|
5298
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
5299
|
+
}
|
|
5300
|
+
} catch {
|
|
5301
|
+
} finally {
|
|
5302
|
+
if (typeof stream.destroy === "function") stream.destroy();
|
|
5303
|
+
}
|
|
5304
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
5305
|
+
try {
|
|
5306
|
+
return JSON.parse(text);
|
|
5307
|
+
} catch {
|
|
5308
|
+
return text || void 0;
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
function cleanAxiosErrors(client, provider) {
|
|
5312
|
+
client.interceptors.response.use(void 0, async (err) => {
|
|
5313
|
+
const data = err && err.response && err.response.data;
|
|
5314
|
+
if (data && typeof data.pipe === "function") {
|
|
5315
|
+
err.response.data = await readErrorBody(data);
|
|
5316
|
+
}
|
|
5317
|
+
throw toConnectorError(err, provider);
|
|
5318
|
+
});
|
|
5319
|
+
return client;
|
|
5320
|
+
}
|
|
5104
5321
|
module2.exports = {
|
|
5322
|
+
toConnectorError,
|
|
5323
|
+
cleanAxiosErrors,
|
|
5105
5324
|
textChunks,
|
|
5106
5325
|
createAbortError,
|
|
5107
5326
|
isAbortError,
|
|
@@ -5640,6 +5859,23 @@ var require_cost_calculator = __commonJS({
|
|
|
5640
5859
|
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
5641
5860
|
asOf: "2026-11-01"
|
|
5642
5861
|
},
|
|
5862
|
+
// $0.10 / $0.50 per million input / output tokens, for prompts up to
|
|
5863
|
+
// 100,000 tokens ($0.50 / $2.50 above; this table has one price per model).
|
|
5864
|
+
"claude-haiku-5.5": {
|
|
5865
|
+
input: 1e-4,
|
|
5866
|
+
output: 5e-4,
|
|
5867
|
+
unit: 1e3,
|
|
5868
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
5869
|
+
asOf: "2026-11-05"
|
|
5870
|
+
},
|
|
5871
|
+
// $10 / $50 per million input / output tokens.
|
|
5872
|
+
"claude-fable-5.1": {
|
|
5873
|
+
input: 0.01,
|
|
5874
|
+
output: 0.05,
|
|
5875
|
+
unit: 1e3,
|
|
5876
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
5877
|
+
asOf: "2026-11-05"
|
|
5878
|
+
},
|
|
5643
5879
|
"cohere-command": {
|
|
5644
5880
|
input: 1e-3,
|
|
5645
5881
|
output: 2e-3,
|
|
@@ -6032,6 +6268,8 @@ var require_cost_tracker = __commonJS({
|
|
|
6032
6268
|
budgetOptions: {}
|
|
6033
6269
|
};
|
|
6034
6270
|
var CHARS_PER_TOKEN = 4;
|
|
6271
|
+
var PROMPT_OVERHEAD_CHARS = 600;
|
|
6272
|
+
var PASSAGE_WRAPPER_CHARS = 40;
|
|
6035
6273
|
var CostTracker = class extends EventEmitter {
|
|
6036
6274
|
/**
|
|
6037
6275
|
* @param {object} [options]
|
|
@@ -6071,9 +6309,18 @@ var require_cost_tracker = __commonJS({
|
|
|
6071
6309
|
}
|
|
6072
6310
|
const inputText = result.input || result.query || result.prompt || "";
|
|
6073
6311
|
const outputText = result.output || result.answer || result.response || "";
|
|
6312
|
+
const passages = Array.isArray(result.results) ? result.results : [];
|
|
6313
|
+
const passageChars = passages.reduce((n, doc) => {
|
|
6314
|
+
const text = typeof doc === "string" ? doc : doc && (doc.content || doc.text) || "";
|
|
6315
|
+
return n + String(text).length + PASSAGE_WRAPPER_CHARS;
|
|
6316
|
+
}, 0);
|
|
6317
|
+
const promptChars = passages.length > 0 ? PROMPT_OVERHEAD_CHARS : 0;
|
|
6074
6318
|
return {
|
|
6075
|
-
inputTokens: Math.ceil(
|
|
6076
|
-
|
|
6319
|
+
inputTokens: Math.ceil(
|
|
6320
|
+
(String(inputText).length + passageChars + promptChars) / CHARS_PER_TOKEN
|
|
6321
|
+
),
|
|
6322
|
+
outputTokens: Math.ceil(String(outputText).length / CHARS_PER_TOKEN),
|
|
6323
|
+
estimated: true
|
|
6077
6324
|
};
|
|
6078
6325
|
}
|
|
6079
6326
|
/**
|
|
@@ -6096,7 +6343,7 @@ var require_cost_tracker = __commonJS({
|
|
|
6096
6343
|
tracker.startSession({ autoStarted: true });
|
|
6097
6344
|
}
|
|
6098
6345
|
const result = await pipeline.run(...args);
|
|
6099
|
-
const { inputTokens, outputTokens } = tracker._extractUsage(result);
|
|
6346
|
+
const { inputTokens, outputTokens, estimated } = tracker._extractUsage(result);
|
|
6100
6347
|
const model = result.model || result.route && result.route.model || tracker.config.model;
|
|
6101
6348
|
const costEstimate = tracker.calculator.estimate(
|
|
6102
6349
|
model,
|
|
@@ -6123,8 +6370,14 @@ var require_cost_tracker = __commonJS({
|
|
|
6123
6370
|
inputTokens,
|
|
6124
6371
|
outputTokens,
|
|
6125
6372
|
estimatedCost: costEstimate.totalCost,
|
|
6373
|
+
// The price-table entry used (as before), and the model the run
|
|
6374
|
+
// asked for, which can differ in form (claude-haiku-4-5 is priced
|
|
6375
|
+
// as claude-haiku-4.5)
|
|
6126
6376
|
model: costEstimate.model,
|
|
6127
|
-
|
|
6377
|
+
requestedModel: model,
|
|
6378
|
+
currency: "USD",
|
|
6379
|
+
// Token counts estimated from text length (no usage reported)
|
|
6380
|
+
...estimated && { tokensEstimated: true }
|
|
6128
6381
|
};
|
|
6129
6382
|
const entry = {
|
|
6130
6383
|
timestamp: Date.now(),
|
|
@@ -6811,9 +7064,15 @@ var require_core = __commonJS({
|
|
|
6811
7064
|
var { createModelRouter, classifyQuery } = require_model_router();
|
|
6812
7065
|
var { MemoryRetriever } = require_memory_retriever();
|
|
6813
7066
|
var { BaseConnector } = require_base_connector();
|
|
7067
|
+
var {
|
|
7068
|
+
evaluationScores,
|
|
7069
|
+
toLangfuseScores
|
|
7070
|
+
} = require_scores();
|
|
6814
7071
|
module2.exports = {
|
|
6815
7072
|
createRagPipeline,
|
|
6816
7073
|
createPipeline: createRagPipeline,
|
|
7074
|
+
evaluationScores,
|
|
7075
|
+
toLangfuseScores,
|
|
6817
7076
|
packContext,
|
|
6818
7077
|
createError: errorFormatter.createError,
|
|
6819
7078
|
wrapError: errorFormatter.wrapError,
|
|
@@ -6873,6 +7132,7 @@ var modules = {
|
|
|
6873
7132
|
"evaluate/relevance.js": () => require_relevance(),
|
|
6874
7133
|
"evaluate/scoring.js": () => require_scoring(),
|
|
6875
7134
|
"observability/otel.js": () => require_otel(),
|
|
7135
|
+
"observability/scores.js": () => require_scores(),
|
|
6876
7136
|
"packages/core.js": () => require_core(),
|
|
6877
7137
|
"reranker/cascade-reranker.js": () => require_cascade_reranker(),
|
|
6878
7138
|
"reranker/embedding-reranker.js": () => require_embedding_reranker(),
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createRagPipeline, createPipeline, packContext, createError, wrapError, ERROR_CODES, retry, withRetry, ChunkingEngine, BM25Search, reciprocalRankFusion, HybridRetriever, ScoringReranker, EmbeddingReranker, CascadeReranker, MemoryCache, RedisCache, CostCalculator, PRICING_METADATA, CostTracker, TokenBudget, createModelRouter, classifyQuery, MemoryRetriever, BaseConnector } from "./all";
|
|
1
|
+
export { createRagPipeline, createPipeline, evaluationScores, toLangfuseScores, packContext, createError, wrapError, ERROR_CODES, retry, withRetry, ChunkingEngine, BM25Search, reciprocalRankFusion, HybridRetriever, ScoringReranker, EmbeddingReranker, CascadeReranker, MemoryCache, RedisCache, CostCalculator, PRICING_METADATA, CostTracker, TokenBudget, createModelRouter, classifyQuery, MemoryRetriever, BaseConnector } from "./all";
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
3
|
const mod = require('./index.cjs');
|
|
4
|
-
export const { createRagPipeline, createPipeline, packContext, createError, wrapError, ERROR_CODES, retry, withRetry, ChunkingEngine, BM25Search, reciprocalRankFusion, HybridRetriever, ScoringReranker, EmbeddingReranker, CascadeReranker, MemoryCache, RedisCache, CostCalculator, PRICING_METADATA, CostTracker, TokenBudget, createModelRouter, classifyQuery, MemoryRetriever, BaseConnector } = mod;
|
|
4
|
+
export const { createRagPipeline, createPipeline, evaluationScores, toLangfuseScores, packContext, createError, wrapError, ERROR_CODES, retry, withRetry, ChunkingEngine, BM25Search, reciprocalRankFusion, HybridRetriever, ScoringReranker, EmbeddingReranker, CascadeReranker, MemoryCache, RedisCache, CostCalculator, PRICING_METADATA, CostTracker, TokenBudget, createModelRouter, classifyQuery, MemoryRetriever, BaseConnector } = mod;
|
|
5
5
|
export default mod;
|
|
@@ -35,6 +35,10 @@ export type GroundingMiddlewareOptions = {
|
|
|
35
35
|
* - Run checkAnswer on the answer
|
|
36
36
|
*/
|
|
37
37
|
check?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* - An LLM with `generate()` (this library's LLM contract, e.g. `createAiSdkAdapter({ ai, languageModel }).llm`) that rules on the sentences the lexical check failed for lack of word overlap; see checkAnswer. Give it the base model, not the wrapped one, or each judge call is grounded again
|
|
40
|
+
*/
|
|
41
|
+
judge?: any;
|
|
38
42
|
/**
|
|
39
43
|
* - Return the passages as source parts
|
|
40
44
|
*/
|
|
@@ -96,6 +100,10 @@ export type GroundingReport = {
|
|
|
96
100
|
* - Per-sentence citations
|
|
97
101
|
*/
|
|
98
102
|
citations?: Array<any>;
|
|
103
|
+
/**
|
|
104
|
+
* - With the `judge` option: the verdicts, the number of calls, the token usage when known, and `error` when the judge failed (its sentences then stay unsupported)
|
|
105
|
+
*/
|
|
106
|
+
judge?: any;
|
|
99
107
|
/**
|
|
100
108
|
* - What each enabled guard found
|
|
101
109
|
*/
|
|
@@ -135,6 +143,7 @@ export function groundingMiddleware(options?: GroundingMiddlewareOptions): any;
|
|
|
135
143
|
* @property {Function} [countTokens] - Token counter for maxContextTokens
|
|
136
144
|
* @property {string} [systemPrompt] - Replaces the default RAG system prompt
|
|
137
145
|
* @property {boolean} [check=true] - Run checkAnswer on the answer
|
|
146
|
+
* @property {Object} [judge] - An LLM with `generate()` (this library's LLM contract, e.g. `createAiSdkAdapter({ ai, languageModel }).llm`) that rules on the sentences the lexical check failed for lack of word overlap; see checkAnswer. Give it the base model, not the wrapped one, or each judge call is grounded again
|
|
138
147
|
* @property {boolean} [sources=true] - Return the passages as source parts
|
|
139
148
|
* @property {Object|boolean} [preRetrieval] - PreRetrievalGuard options (true for defaults): injection detection on the query
|
|
140
149
|
* @property {Object|boolean} [retrieval] - RetrievalGuard options (true for defaults): ACL, minimum score, injection in documents
|
|
@@ -152,6 +161,7 @@ export function groundingMiddleware(options?: GroundingMiddlewareOptions): any;
|
|
|
152
161
|
* @property {number} [groundedness] - Share of supported sentences, 0..1
|
|
153
162
|
* @property {string[]} [unsupported] - Sentences no passage supports
|
|
154
163
|
* @property {Array<Object>} [citations] - Per-sentence citations
|
|
164
|
+
* @property {Object} [judge] - With the `judge` option: the verdicts, the number of calls, the token usage when known, and `error` when the judge failed (its sentences then stay unsupported)
|
|
155
165
|
* @property {Object} guardrails - What each enabled guard found
|
|
156
166
|
*/
|
|
157
167
|
export class GroundingBlockedError extends Error {
|