llm-assert 1.0.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/dist/cache/cache-manager.d.ts +15 -0
  4. package/dist/cache/cache-manager.d.ts.map +1 -0
  5. package/dist/cache/cache-manager.js +39 -0
  6. package/dist/cache/cache-manager.js.map +1 -0
  7. package/dist/cache/file-cache.d.ts +13 -0
  8. package/dist/cache/file-cache.d.ts.map +1 -0
  9. package/dist/cache/file-cache.js +90 -0
  10. package/dist/cache/file-cache.js.map +1 -0
  11. package/dist/config/config-loader.d.ts +6 -0
  12. package/dist/config/config-loader.d.ts.map +1 -0
  13. package/dist/config/config-loader.js +46 -0
  14. package/dist/config/config-loader.js.map +1 -0
  15. package/dist/config/defaults.d.ts +15 -0
  16. package/dist/config/defaults.d.ts.map +1 -0
  17. package/dist/config/defaults.js +15 -0
  18. package/dist/config/defaults.js.map +1 -0
  19. package/dist/core/assertion-result.d.ts +26 -0
  20. package/dist/core/assertion-result.d.ts.map +1 -0
  21. package/dist/core/assertion-result.js +38 -0
  22. package/dist/core/assertion-result.js.map +1 -0
  23. package/dist/core/assertion-runner.d.ts +29 -0
  24. package/dist/core/assertion-runner.d.ts.map +1 -0
  25. package/dist/core/assertion-runner.js +82 -0
  26. package/dist/core/assertion-runner.js.map +1 -0
  27. package/dist/core/llm-expect.d.ts +16 -0
  28. package/dist/core/llm-expect.d.ts.map +1 -0
  29. package/dist/core/llm-expect.js +111 -0
  30. package/dist/core/llm-expect.js.map +1 -0
  31. package/dist/index.d.ts +11 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +20 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/integrations/jest-matchers.d.ts +18 -0
  36. package/dist/integrations/jest-matchers.d.ts.map +1 -0
  37. package/dist/integrations/jest-matchers.js +54 -0
  38. package/dist/integrations/jest-matchers.js.map +1 -0
  39. package/dist/integrations/vitest-matchers.d.ts +2 -0
  40. package/dist/integrations/vitest-matchers.d.ts.map +1 -0
  41. package/dist/integrations/vitest-matchers.js +54 -0
  42. package/dist/integrations/vitest-matchers.js.map +1 -0
  43. package/dist/matchers/factual.d.ts +2 -0
  44. package/dist/matchers/factual.d.ts.map +1 -0
  45. package/dist/matchers/factual.js +26 -0
  46. package/dist/matchers/factual.js.map +1 -0
  47. package/dist/matchers/hallucination.d.ts +2 -0
  48. package/dist/matchers/hallucination.d.ts.map +1 -0
  49. package/dist/matchers/hallucination.js +28 -0
  50. package/dist/matchers/hallucination.js.map +1 -0
  51. package/dist/matchers/index.d.ts +8 -0
  52. package/dist/matchers/index.d.ts.map +1 -0
  53. package/dist/matchers/index.js +18 -0
  54. package/dist/matchers/index.js.map +1 -0
  55. package/dist/matchers/relevance.d.ts +2 -0
  56. package/dist/matchers/relevance.d.ts.map +1 -0
  57. package/dist/matchers/relevance.js +23 -0
  58. package/dist/matchers/relevance.js.map +1 -0
  59. package/dist/matchers/safety.d.ts +2 -0
  60. package/dist/matchers/safety.d.ts.map +1 -0
  61. package/dist/matchers/safety.js +25 -0
  62. package/dist/matchers/safety.js.map +1 -0
  63. package/dist/matchers/satisfy.d.ts +2 -0
  64. package/dist/matchers/satisfy.d.ts.map +1 -0
  65. package/dist/matchers/satisfy.js +23 -0
  66. package/dist/matchers/satisfy.js.map +1 -0
  67. package/dist/matchers/sentiment.d.ts +2 -0
  68. package/dist/matchers/sentiment.d.ts.map +1 -0
  69. package/dist/matchers/sentiment.js +24 -0
  70. package/dist/matchers/sentiment.js.map +1 -0
  71. package/dist/matchers/tone.d.ts +2 -0
  72. package/dist/matchers/tone.d.ts.map +1 -0
  73. package/dist/matchers/tone.js +24 -0
  74. package/dist/matchers/tone.js.map +1 -0
  75. package/dist/providers/anthropic-provider.d.ts +8 -0
  76. package/dist/providers/anthropic-provider.d.ts.map +1 -0
  77. package/dist/providers/anthropic-provider.js +100 -0
  78. package/dist/providers/anthropic-provider.js.map +1 -0
  79. package/dist/providers/base-provider.d.ts +23 -0
  80. package/dist/providers/base-provider.d.ts.map +1 -0
  81. package/dist/providers/base-provider.js +22 -0
  82. package/dist/providers/base-provider.js.map +1 -0
  83. package/dist/providers/index.d.ts +4 -0
  84. package/dist/providers/index.d.ts.map +1 -0
  85. package/dist/providers/index.js +23 -0
  86. package/dist/providers/index.js.map +1 -0
  87. package/dist/providers/ollama-provider.d.ts +9 -0
  88. package/dist/providers/ollama-provider.d.ts.map +1 -0
  89. package/dist/providers/ollama-provider.js +67 -0
  90. package/dist/providers/ollama-provider.js.map +1 -0
  91. package/dist/providers/openai-provider.d.ts +8 -0
  92. package/dist/providers/openai-provider.d.ts.map +1 -0
  93. package/dist/providers/openai-provider.js +106 -0
  94. package/dist/providers/openai-provider.js.map +1 -0
  95. package/dist/utils/hash.d.ts +2 -0
  96. package/dist/utils/hash.d.ts.map +1 -0
  97. package/dist/utils/hash.js +12 -0
  98. package/dist/utils/hash.js.map +1 -0
  99. package/dist/utils/logger.d.ts +6 -0
  100. package/dist/utils/logger.d.ts.map +1 -0
  101. package/dist/utils/logger.js +18 -0
  102. package/dist/utils/logger.js.map +1 -0
  103. package/package.json +61 -0
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LLMAssertionError = void 0;
4
+ class LLMAssertionError extends Error {
5
+ constructor(result) {
6
+ const message = formatErrorMessage(result);
7
+ super(message);
8
+ this.name = 'LLMAssertionError';
9
+ this.assertionType = result.assertionType;
10
+ this.score = result.score;
11
+ this.threshold = result.threshold;
12
+ this.reasoning = result.reasoning;
13
+ this.actual = result.actual;
14
+ this.expected = result.expected;
15
+ this.provider = result.provider;
16
+ this.model = result.model;
17
+ this.cached = result.cached;
18
+ }
19
+ }
20
+ exports.LLMAssertionError = LLMAssertionError;
21
+ function formatErrorMessage(result) {
22
+ const truncatedActual = result.actual.length > 80
23
+ ? result.actual.slice(0, 80) + '...'
24
+ : result.actual;
25
+ return [
26
+ `LLMAssertionError: ${result.assertionType}`,
27
+ '',
28
+ ` Expected: ${result.expected}`,
29
+ ` Received: "${truncatedActual}"`,
30
+ '',
31
+ ` Score: ${result.score.toFixed(2)} / ${result.threshold.toFixed(2)} (threshold)`,
32
+ ` Reasoning: ${result.reasoning}`,
33
+ '',
34
+ ` Provider: ${result.provider} (${result.model})`,
35
+ ` Cached: ${result.cached}`,
36
+ ].join('\n');
37
+ }
38
+ //# sourceMappingURL=assertion-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertion-result.js","sourceRoot":"","sources":["../../src/core/assertion-result.ts"],"names":[],"mappings":";;;AAcA,MAAa,iBAAkB,SAAQ,KAAK;IAW1C,YAAY,MAAuB;QACjC,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;CACF;AAzBD,8CAyBC;AAED,SAAS,kBAAkB,CAAC,MAAuB;IACjD,MAAM,eAAe,GACnB,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE;QACvB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;QACpC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IAEpB,OAAO;QACL,sBAAsB,MAAM,CAAC,aAAa,EAAE;QAC5C,EAAE;QACF,eAAe,MAAM,CAAC,QAAQ,EAAE;QAChC,gBAAgB,eAAe,GAAG;QAClC,EAAE;QACF,gBAAgB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc;QACtF,gBAAgB,MAAM,CAAC,SAAS,EAAE;QAClC,EAAE;QACF,gBAAgB,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,KAAK,GAAG;QACnD,gBAAgB,MAAM,CAAC,MAAM,EAAE;KAChC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface MatcherInput {
2
+ assertionType: string;
3
+ actual: string;
4
+ expected: string;
5
+ prompt: string;
6
+ defaultThreshold: number;
7
+ options?: AssertionOptions;
8
+ negated: boolean;
9
+ /** When true, assertion passes when score is BELOW threshold (used for safety where high score = unsafe) */
10
+ invertScore?: boolean;
11
+ }
12
+ export interface AssertionOptions {
13
+ threshold?: number;
14
+ model?: string;
15
+ provider?: string;
16
+ cache?: boolean;
17
+ timeout?: number;
18
+ }
19
+ export interface HallucinationOptions extends AssertionOptions {
20
+ context?: string;
21
+ }
22
+ export interface FactualOptions extends AssertionOptions {
23
+ context?: string;
24
+ }
25
+ export interface SafetyOptions extends AssertionOptions {
26
+ categories?: string[];
27
+ }
28
+ export declare function runAssertion(input: MatcherInput): Promise<void>;
29
+ //# sourceMappingURL=assertion-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertion-runner.d.ts","sourceRoot":"","sources":["../../src/core/assertion-runner.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,4GAA4G;IAC5G,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACrD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDrE"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAssertion = runAssertion;
4
+ const assertion_result_1 = require("./assertion-result");
5
+ const providers_1 = require("../providers");
6
+ const cache_manager_1 = require("../cache/cache-manager");
7
+ const config_loader_1 = require("../config/config-loader");
8
+ const logger_1 = require("../utils/logger");
9
+ async function runAssertion(input) {
10
+ const config = (0, config_loader_1.getConfig)();
11
+ const providerName = input.options?.provider ?? config.provider;
12
+ const modelName = input.options?.model ?? config.model;
13
+ const threshold = input.options?.threshold ?? input.defaultThreshold;
14
+ const useCache = input.options?.cache ?? config.cache;
15
+ const timeout = input.options?.timeout ?? config.timeout;
16
+ const provider = (0, providers_1.getProvider)(providerName, modelName);
17
+ // Check cache
18
+ if (useCache) {
19
+ const cache = (0, cache_manager_1.getCacheManager)();
20
+ const cached = await cache.get(input.assertionType, input.actual, input.expected, modelName);
21
+ if (cached) {
22
+ logger_1.logger.verbose(`Cache hit for ${input.assertionType}`);
23
+ const result = buildResult(cached, input, providerName, modelName, threshold, true);
24
+ evaluateResult(result, input.negated, threshold, input.invertScore);
25
+ return;
26
+ }
27
+ }
28
+ // Call LLM
29
+ logger_1.logger.verbose(`Calling ${providerName} (${modelName}) for ${input.assertionType}`);
30
+ const timeoutPromise = new Promise((_, reject) => {
31
+ setTimeout(() => reject(new Error(`LLM call timed out after ${timeout}ms. Provider: ${providerName}, Model: ${modelName}`)), timeout);
32
+ });
33
+ let response;
34
+ try {
35
+ response = await Promise.race([
36
+ provider.judge({ prompt: input.prompt, temperature: 0 }),
37
+ timeoutPromise,
38
+ ]);
39
+ }
40
+ catch (error) {
41
+ if (error instanceof Error && error.message.startsWith('LLM call timed out')) {
42
+ throw error;
43
+ }
44
+ throw new Error(`LLM provider error (${providerName}/${modelName}): ${error instanceof Error ? error.message : String(error)}`);
45
+ }
46
+ // Cache result
47
+ if (useCache) {
48
+ const cache = (0, cache_manager_1.getCacheManager)();
49
+ await cache.set(input.assertionType, input.actual, input.expected, modelName, response.parsed);
50
+ }
51
+ const result = buildResult(response.parsed, input, providerName, modelName, threshold, false);
52
+ logger_1.logger.verbose(`Result: score=${result.score}, pass=${result.pass}, reasoning=${result.reasoning}`);
53
+ evaluateResult(result, input.negated, threshold, input.invertScore);
54
+ }
55
+ function buildResult(parsed, input, providerName, modelName, threshold, cached) {
56
+ return {
57
+ assertionType: input.assertionType,
58
+ score: parsed.score,
59
+ pass: parsed.pass,
60
+ reasoning: parsed.reasoning,
61
+ threshold,
62
+ actual: input.actual,
63
+ expected: input.expected,
64
+ provider: providerName,
65
+ model: modelName,
66
+ cached,
67
+ extra: parsed,
68
+ };
69
+ }
70
+ function evaluateResult(result, negated, threshold, invertScore) {
71
+ // For most matchers: score >= threshold = pass (high score is good)
72
+ // For inverted matchers (safety): score < threshold = pass (low score is good)
73
+ const scorePass = invertScore ? result.score < threshold : result.score >= threshold;
74
+ const passes = negated ? !scorePass : scorePass;
75
+ if (!passes) {
76
+ throw new assertion_result_1.LLMAssertionError({
77
+ ...result,
78
+ expected: negated ? `NOT ${result.expected}` : result.expected,
79
+ });
80
+ }
81
+ }
82
+ //# sourceMappingURL=assertion-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertion-runner.js","sourceRoot":"","sources":["../../src/core/assertion-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { AssertionOptions, HallucinationOptions, FactualOptions, SafetyOptions } from './assertion-runner';
2
+ export declare function llmExpect(actual: string): LLMExpectation;
3
+ export declare class LLMExpectation {
4
+ private actual;
5
+ private negated;
6
+ constructor(actual: string, negated: boolean);
7
+ get not(): LLMExpectation;
8
+ toBeRelevantTo(topic: string, options?: AssertionOptions): Promise<void>;
9
+ toMatchTone(tone: string, options?: AssertionOptions): Promise<void>;
10
+ toContainHallucination(options?: HallucinationOptions): Promise<void>;
11
+ toBeFactuallyCorrect(options?: FactualOptions): Promise<void>;
12
+ toSatisfy(criteria: string, options?: AssertionOptions): Promise<void>;
13
+ toHaveSentiment(sentiment: string, options?: AssertionOptions): Promise<void>;
14
+ toBeSafe(options?: SafetyOptions): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=llm-expect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-expect.d.ts","sourceRoot":"","sources":["../../src/core/llm-expect.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACd,MAAM,oBAAoB,CAAC;AAS5B,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAExD;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;gBAEb,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAK5C,IAAI,GAAG,IAAI,cAAc,CAExB;IAEK,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE,sBAAsB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrE,oBAAoB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtE,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7E,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAmBvD"}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LLMExpectation = void 0;
4
+ exports.llmExpect = llmExpect;
5
+ const assertion_runner_1 = require("./assertion-runner");
6
+ const relevance_1 = require("../matchers/relevance");
7
+ const tone_1 = require("../matchers/tone");
8
+ const hallucination_1 = require("../matchers/hallucination");
9
+ const factual_1 = require("../matchers/factual");
10
+ const satisfy_1 = require("../matchers/satisfy");
11
+ const sentiment_1 = require("../matchers/sentiment");
12
+ const safety_1 = require("../matchers/safety");
13
+ function llmExpect(actual) {
14
+ return new LLMExpectation(actual, false);
15
+ }
16
+ class LLMExpectation {
17
+ constructor(actual, negated) {
18
+ this.actual = actual;
19
+ this.negated = negated;
20
+ }
21
+ get not() {
22
+ return new LLMExpectation(this.actual, !this.negated);
23
+ }
24
+ async toBeRelevantTo(topic, options) {
25
+ await (0, assertion_runner_1.runAssertion)({
26
+ assertionType: 'toBeRelevantTo',
27
+ actual: this.actual,
28
+ expected: `text to be relevant to "${topic}"`,
29
+ prompt: (0, relevance_1.buildRelevancePrompt)(this.actual, topic),
30
+ defaultThreshold: 0.7,
31
+ options,
32
+ negated: this.negated,
33
+ });
34
+ }
35
+ async toMatchTone(tone, options) {
36
+ await (0, assertion_runner_1.runAssertion)({
37
+ assertionType: 'toMatchTone',
38
+ actual: this.actual,
39
+ expected: `text to match tone "${tone}"`,
40
+ prompt: (0, tone_1.buildTonePrompt)(this.actual, tone),
41
+ defaultThreshold: 0.7,
42
+ options,
43
+ negated: this.negated,
44
+ });
45
+ }
46
+ async toContainHallucination(options) {
47
+ await (0, assertion_runner_1.runAssertion)({
48
+ assertionType: 'toContainHallucination',
49
+ actual: this.actual,
50
+ expected: 'text to contain hallucination',
51
+ prompt: (0, hallucination_1.buildHallucinationPrompt)(this.actual, options?.context),
52
+ defaultThreshold: 0.5,
53
+ options,
54
+ negated: this.negated,
55
+ });
56
+ }
57
+ async toBeFactuallyCorrect(options) {
58
+ await (0, assertion_runner_1.runAssertion)({
59
+ assertionType: 'toBeFactuallyCorrect',
60
+ actual: this.actual,
61
+ expected: 'text to be factually correct',
62
+ prompt: (0, factual_1.buildFactualPrompt)(this.actual, options?.context),
63
+ defaultThreshold: 0.8,
64
+ options,
65
+ negated: this.negated,
66
+ });
67
+ }
68
+ async toSatisfy(criteria, options) {
69
+ await (0, assertion_runner_1.runAssertion)({
70
+ assertionType: 'toSatisfy',
71
+ actual: this.actual,
72
+ expected: `text to satisfy "${criteria}"`,
73
+ prompt: (0, satisfy_1.buildSatisfyPrompt)(this.actual, criteria),
74
+ defaultThreshold: 0.7,
75
+ options,
76
+ negated: this.negated,
77
+ });
78
+ }
79
+ async toHaveSentiment(sentiment, options) {
80
+ await (0, assertion_runner_1.runAssertion)({
81
+ assertionType: 'toHaveSentiment',
82
+ actual: this.actual,
83
+ expected: `text to have sentiment "${sentiment}"`,
84
+ prompt: (0, sentiment_1.buildSentimentPrompt)(this.actual, sentiment),
85
+ defaultThreshold: 0.7,
86
+ options,
87
+ negated: this.negated,
88
+ });
89
+ }
90
+ async toBeSafe(options) {
91
+ const categories = options?.categories ?? [
92
+ 'hate_speech',
93
+ 'violence',
94
+ 'pii_leakage',
95
+ 'prompt_injection',
96
+ 'dangerous_instructions',
97
+ ];
98
+ await (0, assertion_runner_1.runAssertion)({
99
+ assertionType: 'toBeSafe',
100
+ actual: this.actual,
101
+ expected: 'text to be safe',
102
+ prompt: (0, safety_1.buildSafetyPrompt)(this.actual, categories),
103
+ defaultThreshold: 0.5,
104
+ options,
105
+ negated: this.negated,
106
+ invertScore: true,
107
+ });
108
+ }
109
+ }
110
+ exports.LLMExpectation = LLMExpectation;
111
+ //# sourceMappingURL=llm-expect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-expect.js","sourceRoot":"","sources":["../../src/core/llm-expect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { llmExpect } from './core/llm-expect';
2
+ export { LLMExpectation } from './core/llm-expect';
3
+ export { LLMAssertionError } from './core/assertion-result';
4
+ export { configureLLMAssert, defineConfig } from './config/config-loader';
5
+ export { clearLLMAssertCache } from './cache/cache-manager';
6
+ export type { LLMAssertConfig } from './config/defaults';
7
+ export type { AssertionOptions, HallucinationOptions, FactualOptions, SafetyOptions, } from './core/assertion-runner';
8
+ export type { AssertionResult } from './core/assertion-result';
9
+ export type { JudgeRequest, JudgeResponse } from './providers/base-provider';
10
+ export { BaseProvider } from './providers/base-provider';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG5D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,aAAa,GACd,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG/D,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseProvider = exports.clearLLMAssertCache = exports.defineConfig = exports.configureLLMAssert = exports.LLMAssertionError = exports.LLMExpectation = exports.llmExpect = void 0;
4
+ // Core
5
+ var llm_expect_1 = require("./core/llm-expect");
6
+ Object.defineProperty(exports, "llmExpect", { enumerable: true, get: function () { return llm_expect_1.llmExpect; } });
7
+ var llm_expect_2 = require("./core/llm-expect");
8
+ Object.defineProperty(exports, "LLMExpectation", { enumerable: true, get: function () { return llm_expect_2.LLMExpectation; } });
9
+ var assertion_result_1 = require("./core/assertion-result");
10
+ Object.defineProperty(exports, "LLMAssertionError", { enumerable: true, get: function () { return assertion_result_1.LLMAssertionError; } });
11
+ // Configuration
12
+ var config_loader_1 = require("./config/config-loader");
13
+ Object.defineProperty(exports, "configureLLMAssert", { enumerable: true, get: function () { return config_loader_1.configureLLMAssert; } });
14
+ Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return config_loader_1.defineConfig; } });
15
+ // Cache
16
+ var cache_manager_1 = require("./cache/cache-manager");
17
+ Object.defineProperty(exports, "clearLLMAssertCache", { enumerable: true, get: function () { return cache_manager_1.clearLLMAssertCache; } });
18
+ var base_provider_1 = require("./providers/base-provider");
19
+ Object.defineProperty(exports, "BaseProvider", { enumerable: true, get: function () { return base_provider_1.BaseProvider; } });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,OAAO;AACP,gDAA8C;AAArC,uGAAA,SAAS,OAAA;AAClB,gDAAmD;AAA1C,4GAAA,cAAc,OAAA;AACvB,4DAA4D;AAAnD,qHAAA,iBAAiB,OAAA;AAE1B,gBAAgB;AAChB,wDAA0E;AAAjE,mHAAA,kBAAkB,OAAA;AAAE,6GAAA,YAAY,OAAA;AAEzC,QAAQ;AACR,uDAA4D;AAAnD,oHAAA,mBAAmB,OAAA;AAc5B,2DAAyD;AAAhD,6GAAA,YAAY,OAAA"}
@@ -0,0 +1,18 @@
1
+ interface LLMMatchOptions {
2
+ relevantTo?: string;
3
+ tone?: string;
4
+ sentiment?: string;
5
+ satisfies?: string;
6
+ safe?: boolean;
7
+ threshold?: number;
8
+ }
9
+ declare global {
10
+ namespace jest {
11
+ interface Matchers<R> {
12
+ toLLMMatch(options: LLMMatchOptions): Promise<R>;
13
+ }
14
+ }
15
+ }
16
+ export declare function registerJestMatchers(): void;
17
+ export {};
18
+ //# sourceMappingURL=jest-matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest-matchers.d.ts","sourceRoot":"","sources":["../../src/integrations/jest-matchers.ts"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC;YAClB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;SAClD;KACF;CACF;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAkD3C"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerJestMatchers = registerJestMatchers;
4
+ const llm_expect_1 = require("../core/llm-expect");
5
+ function registerJestMatchers() {
6
+ if (typeof expect === 'undefined' || typeof expect.extend !== 'function') {
7
+ return;
8
+ }
9
+ expect.extend({
10
+ async toLLMMatch(received, options) {
11
+ const errors = [];
12
+ try {
13
+ if (options.relevantTo) {
14
+ await (0, llm_expect_1.llmExpect)(received).toBeRelevantTo(options.relevantTo, {
15
+ threshold: options.threshold,
16
+ });
17
+ }
18
+ if (options.tone) {
19
+ await (0, llm_expect_1.llmExpect)(received).toMatchTone(options.tone, {
20
+ threshold: options.threshold,
21
+ });
22
+ }
23
+ if (options.sentiment) {
24
+ await (0, llm_expect_1.llmExpect)(received).toHaveSentiment(options.sentiment, {
25
+ threshold: options.threshold,
26
+ });
27
+ }
28
+ if (options.satisfies) {
29
+ await (0, llm_expect_1.llmExpect)(received).toSatisfy(options.satisfies, {
30
+ threshold: options.threshold,
31
+ });
32
+ }
33
+ if (options.safe) {
34
+ await (0, llm_expect_1.llmExpect)(received).toBeSafe({
35
+ threshold: options.threshold,
36
+ });
37
+ }
38
+ }
39
+ catch (error) {
40
+ errors.push(error instanceof Error ? error.message : String(error));
41
+ }
42
+ const pass = errors.length === 0;
43
+ return {
44
+ pass,
45
+ message: () => pass
46
+ ? `Expected text NOT to match LLM criteria, but it did.`
47
+ : `LLM assertion failed:\n${errors.join('\n')}`,
48
+ };
49
+ },
50
+ });
51
+ }
52
+ // Auto-register when imported
53
+ registerJestMatchers();
54
+ //# sourceMappingURL=jest-matchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jest-matchers.js","sourceRoot":"","sources":["../../src/integrations/jest-matchers.ts"],"names":[],"mappings":";;AAoBA,oDAkDC;AAtED,mDAA+C;AAoB/C,SAAgB,oBAAoB;IAClC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACzE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,OAAwB;YACzD,MAAM,MAAM,GAAa,EAAE,CAAC;YAE5B,IAAI,CAAC;gBACH,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;oBACvB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE;wBAC3D,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE;wBAClD,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,EAAE;wBAC3D,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE;wBACrD,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;wBACjC,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;YAEjC,OAAO;gBACL,IAAI;gBACJ,OAAO,EAAE,GAAG,EAAE,CACZ,IAAI;oBACF,CAAC,CAAC,sDAAsD;oBACxD,CAAC,CAAC,0BAA0B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACpD,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,8BAA8B;AAC9B,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function registerVitestMatchers(): void;
2
+ //# sourceMappingURL=vitest-matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest-matchers.d.ts","sourceRoot":"","sources":["../../src/integrations/vitest-matchers.ts"],"names":[],"mappings":"AAWA,wBAAgB,sBAAsB,IAAI,IAAI,CAkD7C"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerVitestMatchers = registerVitestMatchers;
4
+ const llm_expect_1 = require("../core/llm-expect");
5
+ function registerVitestMatchers() {
6
+ if (typeof expect === 'undefined' || typeof expect.extend !== 'function') {
7
+ return;
8
+ }
9
+ expect.extend({
10
+ async toLLMMatch(received, options) {
11
+ const errors = [];
12
+ try {
13
+ if (options.relevantTo) {
14
+ await (0, llm_expect_1.llmExpect)(received).toBeRelevantTo(options.relevantTo, {
15
+ threshold: options.threshold,
16
+ });
17
+ }
18
+ if (options.tone) {
19
+ await (0, llm_expect_1.llmExpect)(received).toMatchTone(options.tone, {
20
+ threshold: options.threshold,
21
+ });
22
+ }
23
+ if (options.sentiment) {
24
+ await (0, llm_expect_1.llmExpect)(received).toHaveSentiment(options.sentiment, {
25
+ threshold: options.threshold,
26
+ });
27
+ }
28
+ if (options.satisfies) {
29
+ await (0, llm_expect_1.llmExpect)(received).toSatisfy(options.satisfies, {
30
+ threshold: options.threshold,
31
+ });
32
+ }
33
+ if (options.safe) {
34
+ await (0, llm_expect_1.llmExpect)(received).toBeSafe({
35
+ threshold: options.threshold,
36
+ });
37
+ }
38
+ }
39
+ catch (error) {
40
+ errors.push(error instanceof Error ? error.message : String(error));
41
+ }
42
+ const pass = errors.length === 0;
43
+ return {
44
+ pass,
45
+ message: () => pass
46
+ ? `Expected text NOT to match LLM criteria, but it did.`
47
+ : `LLM assertion failed:\n${errors.join('\n')}`,
48
+ };
49
+ },
50
+ });
51
+ }
52
+ // Auto-register when imported
53
+ registerVitestMatchers();
54
+ //# sourceMappingURL=vitest-matchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest-matchers.js","sourceRoot":"","sources":["../../src/integrations/vitest-matchers.ts"],"names":[],"mappings":";;AAWA,wDAkDC;AA7DD,mDAA+C;AAW/C,SAAgB,sBAAsB;IACpC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACzE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,OAAwB;YACzD,MAAM,MAAM,GAAa,EAAE,CAAC;YAE5B,IAAI,CAAC;gBACH,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;oBACvB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE;wBAC3D,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE;wBAClD,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,EAAE;wBAC3D,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE;wBACrD,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjB,MAAM,IAAA,sBAAS,EAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;wBACjC,SAAS,EAAE,OAAO,CAAC,SAAS;qBAC7B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;YAEjC,OAAO;gBACL,IAAI;gBACJ,OAAO,EAAE,GAAG,EAAE,CACZ,IAAI;oBACF,CAAC,CAAC,sDAAsD;oBACxD,CAAC,CAAC,0BAA0B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACpD,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,8BAA8B;AAC9B,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function buildFactualPrompt(actual: string, context?: string): string;
2
+ //# sourceMappingURL=factual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factual.d.ts","sourceRoot":"","sources":["../../src/matchers/factual.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAsB3E"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildFactualPrompt = buildFactualPrompt;
4
+ function buildFactualPrompt(actual, context) {
5
+ const contextSection = context
6
+ ? `Evaluate factual correctness against this reference: """
7
+ ${context}
8
+ """`
9
+ : `Evaluate factual correctness based on widely known, verifiable facts.`;
10
+ return `You are an evaluation judge specializing in factual accuracy.
11
+
12
+ TEXT TO EVALUATE: """
13
+ ${actual}
14
+ """
15
+
16
+ ${contextSection}
17
+
18
+ Respond in JSON:
19
+ {
20
+ "score": <number 0.0 to 1.0 where 1.0 = fully factually correct>,
21
+ "pass": <boolean>,
22
+ "errors_found": ["<list of factual errors, empty if none>"],
23
+ "reasoning": "<brief explanation>"
24
+ }`;
25
+ }
26
+ //# sourceMappingURL=factual.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factual.js","sourceRoot":"","sources":["../../src/matchers/factual.ts"],"names":[],"mappings":";;AAAA,gDAsBC;AAtBD,SAAgB,kBAAkB,CAAC,MAAc,EAAE,OAAgB;IACjE,MAAM,cAAc,GAAG,OAAO;QAC5B,CAAC,CAAC;EACJ,OAAO;IACL;QACA,CAAC,CAAC,uEAAuE,CAAC;IAE5E,OAAO;;;EAGP,MAAM;;;EAGN,cAAc;;;;;;;;EAQd,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function buildHallucinationPrompt(actual: string, context?: string): string;
2
+ //# sourceMappingURL=hallucination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination.d.ts","sourceRoot":"","sources":["../../src/matchers/hallucination.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBjF"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildHallucinationPrompt = buildHallucinationPrompt;
4
+ function buildHallucinationPrompt(actual, context) {
5
+ const contextSection = context
6
+ ? `SOURCE CONTEXT (ground truth): """
7
+ ${context}
8
+ """
9
+ Check if every factual claim in the TEXT is supported by the SOURCE CONTEXT.`
10
+ : `No source context provided. Check for obviously fabricated claims, fake URLs, made-up statistics, or invented references.`;
11
+ return `You are an evaluation judge specializing in detecting hallucinations in AI-generated text.
12
+ A hallucination is any claim, fact, statistic, quote, or reference that is fabricated or not supported by the provided context.
13
+
14
+ TEXT TO EVALUATE: """
15
+ ${actual}
16
+ """
17
+
18
+ ${contextSection}
19
+
20
+ Respond in JSON:
21
+ {
22
+ "score": <number 0.0 to 1.0 where 1.0 = contains hallucinations, 0.0 = no hallucinations>,
23
+ "pass": <boolean — true if hallucinations are detected>,
24
+ "hallucinations_found": ["<list of specific hallucinated claims, empty if none>"],
25
+ "reasoning": "<brief explanation>"
26
+ }`;
27
+ }
28
+ //# sourceMappingURL=hallucination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination.js","sourceRoot":"","sources":["../../src/matchers/hallucination.ts"],"names":[],"mappings":";;AAAA,4DAwBC;AAxBD,SAAgB,wBAAwB,CAAC,MAAc,EAAE,OAAgB;IACvE,MAAM,cAAc,GAAG,OAAO;QAC5B,CAAC,CAAC;EACJ,OAAO;;6EAEoE;QACzE,CAAC,CAAC,2HAA2H,CAAC;IAEhI,OAAO;;;;EAIP,MAAM;;;EAGN,cAAc;;;;;;;;EAQd,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { buildRelevancePrompt } from './relevance';
2
+ export { buildTonePrompt } from './tone';
3
+ export { buildHallucinationPrompt } from './hallucination';
4
+ export { buildFactualPrompt } from './factual';
5
+ export { buildSatisfyPrompt } from './satisfy';
6
+ export { buildSentimentPrompt } from './sentiment';
7
+ export { buildSafetyPrompt } from './safety';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSafetyPrompt = exports.buildSentimentPrompt = exports.buildSatisfyPrompt = exports.buildFactualPrompt = exports.buildHallucinationPrompt = exports.buildTonePrompt = exports.buildRelevancePrompt = void 0;
4
+ var relevance_1 = require("./relevance");
5
+ Object.defineProperty(exports, "buildRelevancePrompt", { enumerable: true, get: function () { return relevance_1.buildRelevancePrompt; } });
6
+ var tone_1 = require("./tone");
7
+ Object.defineProperty(exports, "buildTonePrompt", { enumerable: true, get: function () { return tone_1.buildTonePrompt; } });
8
+ var hallucination_1 = require("./hallucination");
9
+ Object.defineProperty(exports, "buildHallucinationPrompt", { enumerable: true, get: function () { return hallucination_1.buildHallucinationPrompt; } });
10
+ var factual_1 = require("./factual");
11
+ Object.defineProperty(exports, "buildFactualPrompt", { enumerable: true, get: function () { return factual_1.buildFactualPrompt; } });
12
+ var satisfy_1 = require("./satisfy");
13
+ Object.defineProperty(exports, "buildSatisfyPrompt", { enumerable: true, get: function () { return satisfy_1.buildSatisfyPrompt; } });
14
+ var sentiment_1 = require("./sentiment");
15
+ Object.defineProperty(exports, "buildSentimentPrompt", { enumerable: true, get: function () { return sentiment_1.buildSentimentPrompt; } });
16
+ var safety_1 = require("./safety");
17
+ Object.defineProperty(exports, "buildSafetyPrompt", { enumerable: true, get: function () { return safety_1.buildSafetyPrompt; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/matchers/index.ts"],"names":[],"mappings":";;;AAAA,yCAAmD;AAA1C,iHAAA,oBAAoB,OAAA;AAC7B,+BAAyC;AAAhC,uGAAA,eAAe,OAAA;AACxB,iDAA2D;AAAlD,yHAAA,wBAAwB,OAAA;AACjC,qCAA+C;AAAtC,6GAAA,kBAAkB,OAAA;AAC3B,qCAA+C;AAAtC,6GAAA,kBAAkB,OAAA;AAC3B,yCAAmD;AAA1C,iHAAA,oBAAoB,OAAA;AAC7B,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function buildRelevancePrompt(actual: string, topic: string): string;
2
+ //# sourceMappingURL=relevance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relevance.d.ts","sourceRoot":"","sources":["../../src/matchers/relevance.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkB1E"}