@beingmartinbmc/ojas 0.2.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/LICENSE +21 -0
- package/README.md +308 -0
- package/dist/aahar/index.d.ts +179 -0
- package/dist/aahar/index.d.ts.map +1 -0
- package/dist/aahar/index.js +657 -0
- package/dist/aahar/index.js.map +1 -0
- package/dist/aahar/scoring.d.ts +85 -0
- package/dist/aahar/scoring.d.ts.map +1 -0
- package/dist/aahar/scoring.js +268 -0
- package/dist/aahar/scoring.js.map +1 -0
- package/dist/agni/index.d.ts +113 -0
- package/dist/agni/index.d.ts.map +1 -0
- package/dist/agni/index.js +328 -0
- package/dist/agni/index.js.map +1 -0
- package/dist/agni/model-router.d.ts +77 -0
- package/dist/agni/model-router.d.ts.map +1 -0
- package/dist/agni/model-router.js +163 -0
- package/dist/agni/model-router.js.map +1 -0
- package/dist/agni/response-distiller.d.ts +37 -0
- package/dist/agni/response-distiller.d.ts.map +1 -0
- package/dist/agni/response-distiller.js +193 -0
- package/dist/agni/response-distiller.js.map +1 -0
- package/dist/agni/tiktoken-adapter.d.ts +55 -0
- package/dist/agni/tiktoken-adapter.d.ts.map +1 -0
- package/dist/agni/tiktoken-adapter.js +113 -0
- package/dist/agni/tiktoken-adapter.js.map +1 -0
- package/dist/chikitsa/index.d.ts +130 -0
- package/dist/chikitsa/index.d.ts.map +1 -0
- package/dist/chikitsa/index.js +565 -0
- package/dist/chikitsa/index.js.map +1 -0
- package/dist/demo.d.ts +15 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +278 -0
- package/dist/demo.js.map +1 -0
- package/dist/index.d.ts +201 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +588 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/audit.d.ts +39 -0
- package/dist/mcp/audit.d.ts.map +1 -0
- package/dist/mcp/audit.js +73 -0
- package/dist/mcp/audit.js.map +1 -0
- package/dist/mcp/contracts.d.ts +76 -0
- package/dist/mcp/contracts.d.ts.map +1 -0
- package/dist/mcp/contracts.js +44 -0
- package/dist/mcp/contracts.js.map +1 -0
- package/dist/mcp/envelope.d.ts +107 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +162 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/registry.d.ts +110 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +258 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/server.d.ts +26 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +107 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/agent.d.ts +4 -0
- package/dist/mcp/tools/agent.d.ts.map +1 -0
- package/dist/mcp/tools/agent.js +300 -0
- package/dist/mcp/tools/agent.js.map +1 -0
- package/dist/mcp/tools/context.d.ts +4 -0
- package/dist/mcp/tools/context.d.ts.map +1 -0
- package/dist/mcp/tools/context.js +261 -0
- package/dist/mcp/tools/context.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +5 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +20 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/memory.d.ts +4 -0
- package/dist/mcp/tools/memory.d.ts.map +1 -0
- package/dist/mcp/tools/memory.js +220 -0
- package/dist/mcp/tools/memory.js.map +1 -0
- package/dist/mcp/tools/output.d.ts +4 -0
- package/dist/mcp/tools/output.d.ts.map +1 -0
- package/dist/mcp/tools/output.js +206 -0
- package/dist/mcp/tools/output.js.map +1 -0
- package/dist/mcp/tools/recovery.d.ts +4 -0
- package/dist/mcp/tools/recovery.d.ts.map +1 -0
- package/dist/mcp/tools/recovery.js +165 -0
- package/dist/mcp/tools/recovery.js.map +1 -0
- package/dist/mcp/tools/registrar.d.ts +4 -0
- package/dist/mcp/tools/registrar.d.ts.map +1 -0
- package/dist/mcp/tools/registrar.js +17 -0
- package/dist/mcp/tools/registrar.js.map +1 -0
- package/dist/mcp/tools/report.d.ts +4 -0
- package/dist/mcp/tools/report.d.ts.map +1 -0
- package/dist/mcp/tools/report.js +68 -0
- package/dist/mcp/tools/report.js.map +1 -0
- package/dist/mcp/tools/shared.d.ts +37 -0
- package/dist/mcp/tools/shared.d.ts.map +1 -0
- package/dist/mcp/tools/shared.js +214 -0
- package/dist/mcp/tools/shared.js.map +1 -0
- package/dist/mcp/trace.d.ts +47 -0
- package/dist/mcp/trace.d.ts.map +1 -0
- package/dist/mcp/trace.js +216 -0
- package/dist/mcp/trace.js.map +1 -0
- package/dist/nidra/index.d.ts +275 -0
- package/dist/nidra/index.d.ts.map +1 -0
- package/dist/nidra/index.js +889 -0
- package/dist/nidra/index.js.map +1 -0
- package/dist/persistence/migrations.d.ts +10 -0
- package/dist/persistence/migrations.d.ts.map +1 -0
- package/dist/persistence/migrations.js +77 -0
- package/dist/persistence/migrations.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +30 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +209 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +104 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +5 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/pulse/index.d.ts +144 -0
- package/dist/pulse/index.d.ts.map +1 -0
- package/dist/pulse/index.js +453 -0
- package/dist/pulse/index.js.map +1 -0
- package/dist/raksha/classifiers/http-classifier.d.ts +26 -0
- package/dist/raksha/classifiers/http-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/http-classifier.js +62 -0
- package/dist/raksha/classifiers/http-classifier.js.map +1 -0
- package/dist/raksha/classifiers/index.d.ts +5 -0
- package/dist/raksha/classifiers/index.d.ts.map +1 -0
- package/dist/raksha/classifiers/index.js +8 -0
- package/dist/raksha/classifiers/index.js.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts +41 -0
- package/dist/raksha/classifiers/onnx-classifier.d.ts.map +1 -0
- package/dist/raksha/classifiers/onnx-classifier.js +99 -0
- package/dist/raksha/classifiers/onnx-classifier.js.map +1 -0
- package/dist/raksha/hallucination-detectors.d.ts +106 -0
- package/dist/raksha/hallucination-detectors.d.ts.map +1 -0
- package/dist/raksha/hallucination-detectors.js +327 -0
- package/dist/raksha/hallucination-detectors.js.map +1 -0
- package/dist/raksha/index.d.ts +168 -0
- package/dist/raksha/index.d.ts.map +1 -0
- package/dist/raksha/index.js +597 -0
- package/dist/raksha/index.js.map +1 -0
- package/dist/raksha/prompt-injection-detectors.d.ts +30 -0
- package/dist/raksha/prompt-injection-detectors.d.ts.map +1 -0
- package/dist/raksha/prompt-injection-detectors.js +153 -0
- package/dist/raksha/prompt-injection-detectors.js.map +1 -0
- package/dist/types.d.ts +1115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +71 -0
- package/dist/types.js.map +1 -0
- package/dist/util/calibration.d.ts +32 -0
- package/dist/util/calibration.d.ts.map +1 -0
- package/dist/util/calibration.js +108 -0
- package/dist/util/calibration.js.map +1 -0
- package/dist/util/id.d.ts +2 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +9 -0
- package/dist/util/id.js.map +1 -0
- package/dist/vyayam/index.d.ts +76 -0
- package/dist/vyayam/index.d.ts.map +1 -0
- package/dist/vyayam/index.js +528 -0
- package/dist/vyayam/index.js.map +1 -0
- package/dist/vyayam/tool-fault-proxy.d.ts +95 -0
- package/dist/vyayam/tool-fault-proxy.d.ts.map +1 -0
- package/dist/vyayam/tool-fault-proxy.js +170 -0
- package/dist/vyayam/tool-fault-proxy.js.map +1 -0
- package/docs/ARCHITECTURE.md +162 -0
- package/docs/BACKLOG.md +342 -0
- package/docs/CONFIGURATION.md +305 -0
- package/docs/EVIDENCE.md +232 -0
- package/docs/EVIDENCE_MATRIX.md +293 -0
- package/docs/KNOWN_FAILURES.md +367 -0
- package/docs/MCP.md +614 -0
- package/docs/MODULES.md +368 -0
- package/docs/SECURITY.md +251 -0
- package/docs/TRUST.md +88 -0
- package/docs/assets/ojas-hero.png +0 -0
- package/package.json +101 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP-backed prompt injection classifier — reference implementation.
|
|
4
|
+
*
|
|
5
|
+
* Calls an external HTTP endpoint that accepts `{ text }` and returns
|
|
6
|
+
* `{ injectionProbability, label }`. Works with any service that follows
|
|
7
|
+
* this contract (e.g. a Python FastAPI wrapping a HuggingFace classifier,
|
|
8
|
+
* the OpenAI moderation endpoint behind a thin adapter, Rebuff, etc.).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.HttpPromptInjectionClassifier = void 0;
|
|
12
|
+
class HttpPromptInjectionClassifier {
|
|
13
|
+
name;
|
|
14
|
+
opts;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.name = `prompt-injection/http(${new URL(options.url).hostname})`;
|
|
17
|
+
this.opts = {
|
|
18
|
+
url: options.url,
|
|
19
|
+
apiKey: options.apiKey,
|
|
20
|
+
timeoutMs: options.timeoutMs ?? 5000,
|
|
21
|
+
headers: options.headers,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async classify(text, signal) {
|
|
25
|
+
const ac = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => ac.abort(), this.opts.timeoutMs);
|
|
27
|
+
if (signal) {
|
|
28
|
+
signal.addEventListener('abort', () => ac.abort(), { once: true });
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const headers = {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
...this.opts.headers,
|
|
34
|
+
};
|
|
35
|
+
if (this.opts.apiKey) {
|
|
36
|
+
headers['Authorization'] = `Bearer ${this.opts.apiKey}`;
|
|
37
|
+
}
|
|
38
|
+
const res = await fetch(this.opts.url, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers,
|
|
41
|
+
body: JSON.stringify({ text }),
|
|
42
|
+
signal: ac.signal,
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
return { injectionProbability: 0, label: 'unknown', meta: { httpStatus: res.status } };
|
|
46
|
+
}
|
|
47
|
+
const body = await res.json();
|
|
48
|
+
const prob = typeof body.injectionProbability === 'number'
|
|
49
|
+
? Math.max(0, Math.min(1, body.injectionProbability))
|
|
50
|
+
: 0;
|
|
51
|
+
const label = body.label === 'injection' ? 'injection'
|
|
52
|
+
: body.label === 'safe' ? 'safe'
|
|
53
|
+
: 'unknown';
|
|
54
|
+
return { injectionProbability: prob, label, meta: body.meta };
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.HttpPromptInjectionClassifier = HttpPromptInjectionClassifier;
|
|
62
|
+
//# sourceMappingURL=http-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-classifier.js","sourceRoot":"","sources":["../../../src/raksha/classifiers/http-classifier.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAeH,MAAa,6BAA6B;IAC/B,IAAI,CAAS;IACL,IAAI,CAAkH;IAEvI,YAAY,OAA8B;QACxC,IAAI,CAAC,IAAI,GAAG,yBAAyB,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG;YACV,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACpC,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,MAAoB;QAC/C,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAA2B;gBACtC,cAAc,EAAE,kBAAkB;gBAClC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO;aACrB,CAAC;YACF,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACrB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1D,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;gBACrC,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;gBAC9B,MAAM,EAAE,EAAE,CAAC,MAAM;aAClB,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,OAAO,EAAE,oBAAoB,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;YACzF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA6B,CAAC;YACzD,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,oBAAoB,KAAK,QAAQ;gBACxD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBACrD,CAAC,CAAC,CAAC,CAAC;YACN,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW;gBACpD,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM;oBAChC,CAAC,CAAC,SAAS,CAAC;YAEd,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAA2C,EAAE,CAAC;QACvG,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF;AAvDD,sEAuDC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { OnnxPromptInjectionClassifier } from './onnx-classifier';
|
|
2
|
+
export type { OnnxClassifierOptions } from './onnx-classifier';
|
|
3
|
+
export { HttpPromptInjectionClassifier } from './http-classifier';
|
|
4
|
+
export type { HttpClassifierOptions } from './http-classifier';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/raksha/classifiers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpPromptInjectionClassifier = exports.OnnxPromptInjectionClassifier = void 0;
|
|
4
|
+
var onnx_classifier_1 = require("./onnx-classifier");
|
|
5
|
+
Object.defineProperty(exports, "OnnxPromptInjectionClassifier", { enumerable: true, get: function () { return onnx_classifier_1.OnnxPromptInjectionClassifier; } });
|
|
6
|
+
var http_classifier_1 = require("./http-classifier");
|
|
7
|
+
Object.defineProperty(exports, "HttpPromptInjectionClassifier", { enumerable: true, get: function () { return http_classifier_1.HttpPromptInjectionClassifier; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/raksha/classifiers/index.ts"],"names":[],"mappings":";;;AAAA,qDAAkE;AAAzD,gIAAA,6BAA6B,OAAA;AAEtC,qDAAkE;AAAzD,gIAAA,6BAA6B,OAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONNX Runtime–backed prompt injection classifier.
|
|
3
|
+
*
|
|
4
|
+
* Lazy-loads an ONNX model (e.g. protectai/deberta-v3-base-prompt-injection-v2)
|
|
5
|
+
* on first `classify()` call. Requires `onnxruntime-node` as an optional peer
|
|
6
|
+
* dependency — if missing at runtime, the constructor succeeds but `classify()`
|
|
7
|
+
* rejects with an actionable install message.
|
|
8
|
+
*
|
|
9
|
+
* The model must be a binary-classification ONNX file that expects tokenized
|
|
10
|
+
* input (input_ids, attention_mask) and outputs logits or probabilities.
|
|
11
|
+
* A simple whitespace+lowercase tokenizer is built in for demonstration;
|
|
12
|
+
* production callers should supply a real tokenizer via `tokenize`.
|
|
13
|
+
*/
|
|
14
|
+
import type { PromptInjectionClassifier, ClassifierResult } from '../../types';
|
|
15
|
+
export interface OnnxClassifierOptions {
|
|
16
|
+
modelPath: string;
|
|
17
|
+
/**
|
|
18
|
+
* Custom tokenizer. Receives raw text, returns `{ inputIds, attentionMask }`
|
|
19
|
+
* as BigInt64Arrays suitable for the ONNX model's expected shapes. When
|
|
20
|
+
* omitted a naive whitespace tokenizer is used (adequate for smoke testing
|
|
21
|
+
* but NOT production-grade).
|
|
22
|
+
*/
|
|
23
|
+
tokenize?: (text: string) => {
|
|
24
|
+
inputIds: BigInt64Array;
|
|
25
|
+
attentionMask: BigInt64Array;
|
|
26
|
+
};
|
|
27
|
+
/** Maximum sequence length. Tokens beyond this are truncated. */
|
|
28
|
+
maxLength?: number;
|
|
29
|
+
/** Threshold above which the injection probability triggers `label: 'injection'`. */
|
|
30
|
+
threshold?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare class OnnxPromptInjectionClassifier implements PromptInjectionClassifier {
|
|
33
|
+
readonly name = "prompt-injection/onnx";
|
|
34
|
+
private session;
|
|
35
|
+
private readonly opts;
|
|
36
|
+
private loadError;
|
|
37
|
+
constructor(options: OnnxClassifierOptions);
|
|
38
|
+
classify(text: string, signal?: AbortSignal): Promise<ClassifierResult>;
|
|
39
|
+
private getSession;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=onnx-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onnx-classifier.d.ts","sourceRoot":"","sources":["../../../src/raksha/classifiers/onnx-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,aAAa,CAAC;QAAC,aAAa,EAAE,aAAa,CAAA;KAAE,CAAC;IACvF,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,6BAA8B,YAAW,yBAAyB;IAC7E,QAAQ,CAAC,IAAI,2BAA2B;IACxC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;IACvD,OAAO,CAAC,SAAS,CAAsB;gBAE3B,OAAO,EAAE,qBAAqB;IASpC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAwB/D,UAAU;CAazB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ONNX Runtime–backed prompt injection classifier.
|
|
4
|
+
*
|
|
5
|
+
* Lazy-loads an ONNX model (e.g. protectai/deberta-v3-base-prompt-injection-v2)
|
|
6
|
+
* on first `classify()` call. Requires `onnxruntime-node` as an optional peer
|
|
7
|
+
* dependency — if missing at runtime, the constructor succeeds but `classify()`
|
|
8
|
+
* rejects with an actionable install message.
|
|
9
|
+
*
|
|
10
|
+
* The model must be a binary-classification ONNX file that expects tokenized
|
|
11
|
+
* input (input_ids, attention_mask) and outputs logits or probabilities.
|
|
12
|
+
* A simple whitespace+lowercase tokenizer is built in for demonstration;
|
|
13
|
+
* production callers should supply a real tokenizer via `tokenize`.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.OnnxPromptInjectionClassifier = void 0;
|
|
17
|
+
class OnnxPromptInjectionClassifier {
|
|
18
|
+
name = 'prompt-injection/onnx';
|
|
19
|
+
session = null;
|
|
20
|
+
opts;
|
|
21
|
+
loadError = null;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.opts = {
|
|
24
|
+
modelPath: options.modelPath,
|
|
25
|
+
tokenize: options.tokenize ?? naiveTokenize(options.maxLength ?? 128),
|
|
26
|
+
maxLength: options.maxLength ?? 128,
|
|
27
|
+
threshold: options.threshold ?? 0.5,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async classify(text, signal) {
|
|
31
|
+
if (signal?.aborted)
|
|
32
|
+
throw new DOMException('Aborted', 'AbortError');
|
|
33
|
+
const session = await this.getSession();
|
|
34
|
+
const { inputIds, attentionMask } = this.opts.tokenize(text);
|
|
35
|
+
// onnxruntime-node types are not guaranteed at compile time
|
|
36
|
+
const ort = requireOrt();
|
|
37
|
+
const feeds = {
|
|
38
|
+
input_ids: new ort.Tensor('int64', inputIds, [1, inputIds.length]),
|
|
39
|
+
attention_mask: new ort.Tensor('int64', attentionMask, [1, attentionMask.length]),
|
|
40
|
+
};
|
|
41
|
+
const results = await session.run(feeds);
|
|
42
|
+
const logits = results.logits?.data ?? results.output?.data;
|
|
43
|
+
if (!logits || logits.length < 2) {
|
|
44
|
+
return { injectionProbability: 0, label: 'unknown', meta: { error: 'unexpected model output shape' } };
|
|
45
|
+
}
|
|
46
|
+
const prob = softmax(logits[0], logits[1]);
|
|
47
|
+
const label = prob >= this.opts.threshold ? 'injection' : 'safe';
|
|
48
|
+
return { injectionProbability: prob, label, meta: { modelPath: this.opts.modelPath } };
|
|
49
|
+
}
|
|
50
|
+
async getSession() {
|
|
51
|
+
if (this.loadError)
|
|
52
|
+
throw this.loadError;
|
|
53
|
+
if (this.session)
|
|
54
|
+
return this.session;
|
|
55
|
+
try {
|
|
56
|
+
const ort = requireOrt();
|
|
57
|
+
this.session = await ort.InferenceSession.create(this.opts.modelPath);
|
|
58
|
+
return this.session;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
this.loadError = err instanceof Error ? err : new Error(String(err));
|
|
62
|
+
throw this.loadError;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.OnnxPromptInjectionClassifier = OnnxPromptInjectionClassifier;
|
|
67
|
+
function requireOrt() {
|
|
68
|
+
try {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
70
|
+
return require('onnxruntime-node');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
throw new Error('onnxruntime-node is required for OnnxPromptInjectionClassifier. ' +
|
|
74
|
+
'Install it with: npm install onnxruntime-node');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function softmax(logitSafe, logitInjection) {
|
|
78
|
+
const max = Math.max(logitSafe, logitInjection);
|
|
79
|
+
const expSafe = Math.exp(logitSafe - max);
|
|
80
|
+
const expInj = Math.exp(logitInjection - max);
|
|
81
|
+
return expInj / (expSafe + expInj);
|
|
82
|
+
}
|
|
83
|
+
function naiveTokenize(maxLength) {
|
|
84
|
+
return (text) => {
|
|
85
|
+
const words = text.toLowerCase().split(/\s+/).slice(0, maxLength);
|
|
86
|
+
const inputIds = new BigInt64Array(words.length);
|
|
87
|
+
const attentionMask = new BigInt64Array(words.length);
|
|
88
|
+
for (let i = 0; i < words.length; i++) {
|
|
89
|
+
let hash = 0;
|
|
90
|
+
for (let j = 0; j < words[i].length; j++) {
|
|
91
|
+
hash = ((hash << 5) - hash + words[i].charCodeAt(j)) | 0;
|
|
92
|
+
}
|
|
93
|
+
inputIds[i] = BigInt(Math.abs(hash) % 30000);
|
|
94
|
+
attentionMask[i] = 1n;
|
|
95
|
+
}
|
|
96
|
+
return { inputIds, attentionMask };
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=onnx-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onnx-classifier.js","sourceRoot":"","sources":["../../../src/raksha/classifiers/onnx-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in `HallucinationDetector` implementations.
|
|
3
|
+
*
|
|
4
|
+
* These detectors are deliberately **dep-free and runtime-fast**. They
|
|
5
|
+
* are not state-of-the-art; their purpose is to give Ojas users a
|
|
6
|
+
* sensible default and a working contract so they can later plug in
|
|
7
|
+
* heavier ML-backed detectors (encoder grounding models, LLM judges)
|
|
8
|
+
* via the same interface.
|
|
9
|
+
*
|
|
10
|
+
* Three detectors are shipped:
|
|
11
|
+
*
|
|
12
|
+
* 1. **`BestOfNInconsistencyDetector`** (black-box consistency)
|
|
13
|
+
* Scores how much the agent's output disagrees with alternative
|
|
14
|
+
* samples of the same prompt. We use a character-shingle Jaccard
|
|
15
|
+
* distance rather than embeddings so we don't need ML. Risk =
|
|
16
|
+
* mean pairwise distance from `output` to each sample, clamped
|
|
17
|
+
* to [0, 1].
|
|
18
|
+
*
|
|
19
|
+
* 2. **`ClaimLevelDetector`** (long-text grounding)
|
|
20
|
+
* Splits `output` into sentence-claims, then for each claim
|
|
21
|
+
* measures n-gram overlap with each `context` item. A claim is
|
|
22
|
+
* "unsupported" when its best-match overlap is below a
|
|
23
|
+
* threshold. Risk = fraction of unsupported claims, weighted by
|
|
24
|
+
* claim length.
|
|
25
|
+
*
|
|
26
|
+
* 3. **`AbstentionDetector`** (refusal recognition)
|
|
27
|
+
* Treats appropriate abstention as a **positive** signal: if
|
|
28
|
+
* the output is mostly hedging / refusal, returns low risk and
|
|
29
|
+
* `abstention: true`. The caller can then route the task to a
|
|
30
|
+
* stronger model rather than penalising the abstention.
|
|
31
|
+
*
|
|
32
|
+
* Composition: callers wanting an ensemble can wrap these via
|
|
33
|
+
* `EnsembleHallucinationDetector` (also shipped).
|
|
34
|
+
*/
|
|
35
|
+
import type { HallucinationAssessment, HallucinationDetector, HallucinationDetectorInput } from '../types';
|
|
36
|
+
export interface BestOfNDetectorPolicy {
|
|
37
|
+
/** Character-shingle length. 4 is a robust default for English. */
|
|
38
|
+
shingleK?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Minimum sample count below which we return a low-confidence
|
|
41
|
+
* "no signal" assessment instead of guessing. Default 2 (one
|
|
42
|
+
* pairwise comparison).
|
|
43
|
+
*/
|
|
44
|
+
minSamples?: number;
|
|
45
|
+
}
|
|
46
|
+
export declare class BestOfNInconsistencyDetector implements HallucinationDetector {
|
|
47
|
+
readonly name = "bestofn/n-gram-jaccard";
|
|
48
|
+
private readonly policy;
|
|
49
|
+
constructor(policy?: BestOfNDetectorPolicy);
|
|
50
|
+
detect(input: HallucinationDetectorInput): Promise<HallucinationAssessment>;
|
|
51
|
+
}
|
|
52
|
+
export interface ClaimLevelDetectorPolicy {
|
|
53
|
+
/** N-gram length for claim-to-context overlap. 4 chars works well for English. */
|
|
54
|
+
shingleK?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Per-claim grounding threshold. A claim with `bestOverlap < threshold`
|
|
57
|
+
* is marked unsupported. 0.25 is conservative — it requires a quarter
|
|
58
|
+
* of the claim's shingles to appear in some context item.
|
|
59
|
+
*/
|
|
60
|
+
groundingThreshold?: number;
|
|
61
|
+
}
|
|
62
|
+
export declare class ClaimLevelDetector implements HallucinationDetector {
|
|
63
|
+
readonly name = "claim-level/n-gram-grounding";
|
|
64
|
+
private readonly policy;
|
|
65
|
+
constructor(policy?: ClaimLevelDetectorPolicy);
|
|
66
|
+
detect(input: HallucinationDetectorInput): Promise<HallucinationAssessment>;
|
|
67
|
+
}
|
|
68
|
+
export interface AbstentionDetectorPolicy {
|
|
69
|
+
/**
|
|
70
|
+
* Minimum fraction of the output that must match an abstention
|
|
71
|
+
* pattern (by character count) for the output to be considered an
|
|
72
|
+
* abstention. Default 0.15 — a short hedge inside a long substantive
|
|
73
|
+
* answer should NOT count.
|
|
74
|
+
*/
|
|
75
|
+
minAbstentionFraction?: number;
|
|
76
|
+
}
|
|
77
|
+
export declare class AbstentionDetector implements HallucinationDetector {
|
|
78
|
+
readonly name = "abstention/canonical-hedges";
|
|
79
|
+
private readonly policy;
|
|
80
|
+
constructor(policy?: AbstentionDetectorPolicy);
|
|
81
|
+
detect(input: HallucinationDetectorInput): Promise<HallucinationAssessment>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Compose multiple detectors with weighted-average aggregation. We
|
|
85
|
+
* weight by both the configured weight AND each detector's reported
|
|
86
|
+
* confidence so a detector that signals "I don't have enough input"
|
|
87
|
+
* is automatically down-weighted in the aggregate.
|
|
88
|
+
*
|
|
89
|
+
* The `abstention` flag short-circuits: if *any* detector reports
|
|
90
|
+
* `abstention: true`, the ensemble surfaces the abstention and uses
|
|
91
|
+
* the abstention detector's risk score (low) rather than averaging
|
|
92
|
+
* across the consistency / claim-level detectors (which would
|
|
93
|
+
* incorrectly score "I don't know" as high-risk because it has no
|
|
94
|
+
* grounding signal).
|
|
95
|
+
*/
|
|
96
|
+
export interface EnsembleEntry {
|
|
97
|
+
detector: HallucinationDetector;
|
|
98
|
+
weight?: number;
|
|
99
|
+
}
|
|
100
|
+
export declare class EnsembleHallucinationDetector implements HallucinationDetector {
|
|
101
|
+
readonly name: string;
|
|
102
|
+
private readonly entries;
|
|
103
|
+
constructor(entries: ReadonlyArray<EnsembleEntry>);
|
|
104
|
+
detect(input: HallucinationDetectorInput): Promise<HallucinationAssessment>;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=hallucination-detectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hallucination-detectors.d.ts","sourceRoot":"","sources":["../../src/raksha/hallucination-detectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAEV,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,UAAU,CAAC;AAsDlB,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,4BAA6B,YAAW,qBAAqB;IACxE,QAAQ,CAAC,IAAI,4BAA4B;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAE7C,MAAM,GAAE,qBAA0B;IAOxC,MAAM,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAoClF;AAID,MAAM,WAAW,wBAAwB;IACvC,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,kBAAmB,YAAW,qBAAqB;IAC9D,QAAQ,CAAC,IAAI,kCAAkC;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAEhD,MAAM,GAAE,wBAA6B;IAO3C,MAAM,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAuElF;AAqBD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,qBAAa,kBAAmB,YAAW,qBAAqB;IAC9D,QAAQ,CAAC,IAAI,iCAAiC;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAEhD,MAAM,GAAE,wBAA6B;IAM3C,MAAM,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAqClF;AAID;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,6BAA8B,YAAW,qBAAqB;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;gBAErD,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC;IAW3C,MAAM,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAiDlF"}
|