chore: import upstream snapshot with attribution
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { handleSimilar } from '../../src/assertions/similar';
|
||||
import { matchesSimilarity } from '../../src/matchers/similarity';
|
||||
import { createMockProvider } from '../factories/provider';
|
||||
|
||||
vi.mock('../../src/matchers/similarity', () => ({
|
||||
matchesSimilarity: vi.fn().mockImplementation(async (expected, output, _threshold, inverse) => {
|
||||
if (inverse) {
|
||||
return {
|
||||
pass: expected !== output,
|
||||
score: expected === output ? 0 : 1,
|
||||
};
|
||||
}
|
||||
return {
|
||||
pass: expected === output,
|
||||
score: expected === output ? 1 : 0,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('handleSimilar', () => {
|
||||
it('should handle string similarity assertion', async () => {
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: 'hello world',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.score).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle array of strings similarity assertion', async () => {
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: ['hello world', 'hi world'],
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: ['hello world', 'hi world'],
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.score).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle custom threshold', async () => {
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: 'hello world',
|
||||
threshold: 0.5,
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle inverse similarity assertion', async () => {
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: 'hello world',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'completely different',
|
||||
inverse: true,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'completely different' },
|
||||
},
|
||||
output: 'completely different',
|
||||
providerResponse: { output: 'completely different' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it('should fail when no array values meet threshold', async () => {
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: ['hello world', 'hi world'],
|
||||
threshold: 0.9,
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: ['hello world', 'hi world'],
|
||||
outputString: 'completely different',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'completely different' },
|
||||
},
|
||||
output: 'completely different',
|
||||
providerResponse: { output: 'completely different' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.reason).toBe('None of the provided values met the similarity threshold');
|
||||
expect(result.score).toBe(0);
|
||||
});
|
||||
|
||||
it('should report the best (highest) score when no array values meet threshold', async () => {
|
||||
// Neither value passes, but the output is closer to the second one.
|
||||
vi.mocked(matchesSimilarity)
|
||||
.mockResolvedValueOnce({ pass: false, score: 0.2 } as any)
|
||||
.mockResolvedValueOnce({ pass: false, score: 0.6 } as any);
|
||||
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: ['far value', 'closer value'],
|
||||
threshold: 0.9,
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: ['far value', 'closer value'],
|
||||
outputString: 'some output',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'some output' },
|
||||
},
|
||||
output: 'some output',
|
||||
providerResponse: { output: 'some output' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
// Report how close the output got to its closest value (0.6), not the worst (0.2).
|
||||
expect(result.score).toBe(0.6);
|
||||
});
|
||||
|
||||
it('should FAIL not-similar with an array when the output is similar to ANY value', async () => {
|
||||
// not-similar means "dissimilar to ALL". The output is too similar to the
|
||||
// first value, so the inverse check fails there and the assertion returns
|
||||
// immediately — it must fail rather than continue and pass on a later value.
|
||||
// Only the first value is evaluated, so we queue a single result (queuing a
|
||||
// second would leak into the next test, which runs in random order).
|
||||
vi.mocked(matchesSimilarity).mockResolvedValueOnce({
|
||||
pass: false,
|
||||
score: 0.05,
|
||||
reason: 'too similar',
|
||||
} as any);
|
||||
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: ['forbidden answer A', 'unrelated answer B'],
|
||||
threshold: 0.75,
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: ['forbidden answer A', 'unrelated answer B'],
|
||||
outputString: 'forbidden answer A',
|
||||
inverse: true,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: { description: 'test', vars: {}, assert: [], options: {} },
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'forbidden answer A' },
|
||||
},
|
||||
output: 'forbidden answer A',
|
||||
providerResponse: { output: 'forbidden answer A' },
|
||||
});
|
||||
|
||||
// Before the fix this returned pass: true (dissimilar to the second value
|
||||
// short-circuited the loop). The output is identical to value A, so it must fail.
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.score).toBe(0.05);
|
||||
});
|
||||
|
||||
it('should PASS not-similar with an array only when dissimilar to ALL values', async () => {
|
||||
// Dissimilar to every value → not-similar passes; report the lowest score
|
||||
// (the value it came closest to / tightest margin).
|
||||
vi.mocked(matchesSimilarity)
|
||||
.mockResolvedValueOnce({ pass: true, score: 0.8, reason: 'dissimilar' } as any)
|
||||
.mockResolvedValueOnce({ pass: true, score: 0.95, reason: 'dissimilar' } as any);
|
||||
|
||||
const result = await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: ['forbidden answer A', 'forbidden answer B'],
|
||||
threshold: 0.75,
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: ['forbidden answer A', 'forbidden answer B'],
|
||||
outputString: 'a totally different response',
|
||||
inverse: true,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: { description: 'test', vars: {}, assert: [], options: {} },
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'a totally different response' },
|
||||
},
|
||||
output: 'a totally different response',
|
||||
providerResponse: { output: 'a totally different response' },
|
||||
});
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.score).toBe(0.8);
|
||||
});
|
||||
|
||||
it('should report the closest (lowest) score across 3+ values when dissimilar to ALL (not-similar)', async () => {
|
||||
// Dissimilar to all three; the lowest score is in the MIDDLE, proving the
|
||||
// min-selection picks the tightest margin regardless of position (not just
|
||||
// first/last). The full closest result (score + reason) is propagated.
|
||||
vi.mocked(matchesSimilarity)
|
||||
.mockResolvedValueOnce({ pass: true, score: 0.9, reason: 'dissimilar to A' } as any)
|
||||
.mockResolvedValueOnce({ pass: true, score: 0.78, reason: 'closest to B' } as any)
|
||||
.mockResolvedValueOnce({ pass: true, score: 0.95, reason: 'dissimilar to C' } as any);
|
||||
|
||||
const result = await handleSimilar({
|
||||
assertion: { type: 'similar', value: ['A', 'B', 'C'], threshold: 0.75 },
|
||||
renderedValue: ['A', 'B', 'C'],
|
||||
outputString: 'a totally different response',
|
||||
inverse: true,
|
||||
test: { description: 'test', vars: {}, assert: [], options: {} },
|
||||
} as any);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.score).toBe(0.78);
|
||||
expect(result.reason).toBe('closest to B');
|
||||
});
|
||||
|
||||
it('should throw error for invalid renderedValue type', async () => {
|
||||
await expect(
|
||||
handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: 'test',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 123 as any,
|
||||
outputString: 'test',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'test' },
|
||||
},
|
||||
output: 'test',
|
||||
providerResponse: { output: 'test' },
|
||||
}),
|
||||
).rejects.toThrow('Similarity assertion type must have a string or array of strings value');
|
||||
});
|
||||
|
||||
it('should throw error for empty array value', async () => {
|
||||
await expect(
|
||||
handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: [],
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: [],
|
||||
outputString: 'test',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'test' },
|
||||
},
|
||||
output: 'test',
|
||||
providerResponse: { output: 'test' },
|
||||
}),
|
||||
).rejects.toThrow('Similarity assertion must have at least one value to compare against');
|
||||
});
|
||||
|
||||
it('should use dot_product metric when specified', async () => {
|
||||
const mockMatchesSimilarity = vi.mocked(matchesSimilarity);
|
||||
|
||||
await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar:dot',
|
||||
value: 'hello world',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
// Verify that matchesSimilarity was called with dot_product metric
|
||||
expect(mockMatchesSimilarity).toHaveBeenCalledWith(
|
||||
'hello world',
|
||||
'hello world',
|
||||
expect.any(Number),
|
||||
false,
|
||||
expect.any(Object),
|
||||
'dot_product',
|
||||
);
|
||||
});
|
||||
|
||||
it('should use euclidean metric when specified', async () => {
|
||||
const mockMatchesSimilarity = vi.mocked(matchesSimilarity);
|
||||
|
||||
await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar:euclidean',
|
||||
value: 'hello world',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
// Verify that matchesSimilarity was called with euclidean metric
|
||||
expect(mockMatchesSimilarity).toHaveBeenCalledWith(
|
||||
'hello world',
|
||||
'hello world',
|
||||
expect.any(Number),
|
||||
false,
|
||||
expect.any(Object),
|
||||
'euclidean',
|
||||
);
|
||||
});
|
||||
|
||||
it('should default to cosine metric when not specified', async () => {
|
||||
const mockMatchesSimilarity = vi.mocked(matchesSimilarity);
|
||||
|
||||
await handleSimilar({
|
||||
assertion: {
|
||||
type: 'similar',
|
||||
value: 'hello world',
|
||||
},
|
||||
baseType: 'similar' as any,
|
||||
renderedValue: 'hello world',
|
||||
outputString: 'hello world',
|
||||
inverse: false,
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
assertionValueContext: {
|
||||
prompt: 'test prompt',
|
||||
vars: {},
|
||||
test: {
|
||||
description: 'test',
|
||||
vars: {},
|
||||
assert: [],
|
||||
options: {},
|
||||
},
|
||||
logProbs: undefined,
|
||||
// @ts-ignore
|
||||
provider: createMockProvider({ response: {} }),
|
||||
providerResponse: { output: 'hello world' },
|
||||
},
|
||||
output: 'hello world',
|
||||
providerResponse: { output: 'hello world' },
|
||||
});
|
||||
|
||||
// Verify that matchesSimilarity was called with cosine metric (default)
|
||||
expect(mockMatchesSimilarity).toHaveBeenCalledWith(
|
||||
'hello world',
|
||||
'hello world',
|
||||
expect.any(Number),
|
||||
false,
|
||||
expect.any(Object),
|
||||
'cosine',
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user