promptfoo 0.103.13 → 0.103.14
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/dist/package.json +13 -13
- package/dist/src/app/assets/{index-CNZfEf8i.js → index-gCO1so_L.js} +233 -232
- package/dist/src/app/assets/{index.es-vrsSPryr.js → index.es-BebRurvf.js} +1 -1
- package/dist/src/app/assets/{sync-B_Y0n4tJ.js → sync-cefC8sLm.js} +1 -1
- package/dist/src/app/index.html +1 -1
- package/dist/src/fetch.d.ts +2 -0
- package/dist/src/fetch.d.ts.map +1 -1
- package/dist/src/fetch.js +2 -1
- package/dist/src/fetch.js.map +1 -1
- package/dist/src/providers/azure.d.ts.map +1 -1
- package/dist/src/providers/azure.js +10 -0
- package/dist/src/providers/azure.js.map +1 -1
- package/dist/src/providers/http.d.ts +5 -3
- package/dist/src/providers/http.d.ts.map +1 -1
- package/dist/src/providers/http.js +7 -6
- package/dist/src/providers/http.js.map +1 -1
- package/dist/src/redteam/commands/generate.d.ts.map +1 -1
- package/dist/src/redteam/commands/generate.js +30 -9
- package/dist/src/redteam/commands/generate.js.map +1 -1
- package/dist/src/redteam/graders.d.ts.map +1 -1
- package/dist/src/redteam/graders.js +13 -13
- package/dist/src/redteam/graders.js.map +1 -1
- package/dist/src/redteam/index.d.ts +1 -0
- package/dist/src/redteam/index.d.ts.map +1 -1
- package/dist/src/redteam/index.js +1 -1
- package/dist/src/redteam/index.js.map +1 -1
- package/dist/src/redteam/plugins/harmful/graders.d.ts +52 -0
- package/dist/src/redteam/plugins/harmful/graders.d.ts.map +1 -1
- package/dist/src/redteam/plugins/harmful/graders.js +577 -22
- package/dist/src/redteam/plugins/harmful/graders.js.map +1 -1
- package/dist/src/redteam/types.d.ts +1 -0
- package/dist/src/redteam/types.d.ts.map +1 -1
- package/dist/src/redteam/util.d.ts.map +1 -1
- package/dist/src/redteam/util.js +2 -0
- package/dist/src/redteam/util.js.map +1 -1
- package/dist/src/server/server.d.ts.map +1 -1
- package/dist/src/server/server.js +1 -7
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/validators/redteam.d.ts +3 -0
- package/dist/src/validators/redteam.d.ts.map +1 -1
- package/dist/src/validators/redteam.js +2 -0
- package/dist/src/validators/redteam.js.map +1 -1
- package/dist/test/assertions/answerRelevance.test.d.ts +2 -0
- package/dist/test/assertions/answerRelevance.test.d.ts.map +1 -0
- package/dist/test/assertions/answerRelevance.test.js +177 -0
- package/dist/test/assertions/answerRelevance.test.js.map +1 -0
- package/dist/test/assertions/contextFaithfulness.test.d.ts +2 -0
- package/dist/test/assertions/contextFaithfulness.test.d.ts.map +1 -0
- package/dist/test/assertions/contextFaithfulness.test.js +226 -0
- package/dist/test/assertions/contextFaithfulness.test.js.map +1 -0
- package/dist/test/assertions/contextRecall.test.d.ts +2 -0
- package/dist/test/assertions/contextRecall.test.d.ts.map +1 -0
- package/dist/test/assertions/contextRecall.test.js +243 -0
- package/dist/test/assertions/contextRecall.test.js.map +1 -0
- package/dist/test/assertions/contextRelevance.test.d.ts +2 -0
- package/dist/test/assertions/contextRelevance.test.d.ts.map +1 -0
- package/dist/test/assertions/contextRelevance.test.js +238 -0
- package/dist/test/assertions/contextRelevance.test.js.map +1 -0
- package/dist/test/assertions/geval.test.d.ts +2 -0
- package/dist/test/assertions/geval.test.d.ts.map +1 -0
- package/dist/test/assertions/geval.test.js +222 -0
- package/dist/test/assertions/geval.test.js.map +1 -0
- package/dist/test/assertions/modelGradedClosedQa.test.d.ts +2 -0
- package/dist/test/assertions/modelGradedClosedQa.test.d.ts.map +1 -0
- package/dist/test/assertions/modelGradedClosedQa.test.js +200 -0
- package/dist/test/assertions/modelGradedClosedQa.test.js.map +1 -0
- package/dist/test/fetch.test.js +66 -18
- package/dist/test/fetch.test.js.map +1 -1
- package/dist/test/providers/azure.test.js +41 -11
- package/dist/test/providers/azure.test.js.map +1 -1
- package/dist/test/providers/http.test.js +70 -2
- package/dist/test/providers/http.test.js.map +1 -1
- package/dist/test/providers/index.test.js +0 -454
- package/dist/test/providers/index.test.js.map +1 -1
- package/dist/test/providers/openai.test.js +509 -0
- package/dist/test/providers/openai.test.js.map +1 -1
- package/dist/test/redteam/commands/generate.test.js +7 -0
- package/dist/test/redteam/commands/generate.test.js.map +1 -1
- package/dist/test/redteam/extraction/purpose.test.js +1 -0
- package/dist/test/redteam/extraction/purpose.test.js.map +1 -1
- package/dist/test/redteam/strategies/index.test.js +1 -0
- package/dist/test/redteam/strategies/index.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const geval_1 = require("../../src/assertions/geval");
|
|
4
|
+
const matchers_1 = require("../../src/matchers");
|
|
5
|
+
jest.mock('../../src/matchers');
|
|
6
|
+
describe('handleGEval', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.resetAllMocks();
|
|
9
|
+
});
|
|
10
|
+
it('should handle string renderedValue', async () => {
|
|
11
|
+
const mockMatchesGEval = jest.mocked(matchers_1.matchesGEval);
|
|
12
|
+
mockMatchesGEval.mockResolvedValue({
|
|
13
|
+
pass: true,
|
|
14
|
+
score: 0.8,
|
|
15
|
+
reason: 'test reason',
|
|
16
|
+
});
|
|
17
|
+
const result = await (0, geval_1.handleGEval)({
|
|
18
|
+
assertion: {
|
|
19
|
+
type: 'g-eval',
|
|
20
|
+
value: 'test criteria',
|
|
21
|
+
threshold: 0.7,
|
|
22
|
+
},
|
|
23
|
+
renderedValue: 'test criteria',
|
|
24
|
+
prompt: 'test prompt',
|
|
25
|
+
outputString: 'test output',
|
|
26
|
+
test: {
|
|
27
|
+
vars: {},
|
|
28
|
+
assert: [],
|
|
29
|
+
options: {},
|
|
30
|
+
},
|
|
31
|
+
baseType: 'g-eval',
|
|
32
|
+
context: {
|
|
33
|
+
prompt: 'test prompt',
|
|
34
|
+
vars: {},
|
|
35
|
+
test: {
|
|
36
|
+
vars: {},
|
|
37
|
+
assert: [],
|
|
38
|
+
options: {},
|
|
39
|
+
},
|
|
40
|
+
logProbs: undefined,
|
|
41
|
+
provider: {
|
|
42
|
+
id: () => 'test-provider',
|
|
43
|
+
callApi: async () => ({ output: 'test' }),
|
|
44
|
+
},
|
|
45
|
+
providerResponse: {
|
|
46
|
+
output: 'test output',
|
|
47
|
+
error: undefined,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
inverse: false,
|
|
51
|
+
output: 'test output',
|
|
52
|
+
providerResponse: {
|
|
53
|
+
output: 'test output',
|
|
54
|
+
error: undefined,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
expect(result).toEqual({
|
|
58
|
+
assertion: {
|
|
59
|
+
type: 'g-eval',
|
|
60
|
+
value: 'test criteria',
|
|
61
|
+
threshold: 0.7,
|
|
62
|
+
},
|
|
63
|
+
pass: true,
|
|
64
|
+
score: 0.8,
|
|
65
|
+
reason: 'test reason',
|
|
66
|
+
});
|
|
67
|
+
expect(mockMatchesGEval).toHaveBeenCalledWith('test criteria', 'test prompt', 'test output', 0.7, {});
|
|
68
|
+
});
|
|
69
|
+
it('should handle array renderedValue', async () => {
|
|
70
|
+
const mockMatchesGEval = jest.mocked(matchers_1.matchesGEval);
|
|
71
|
+
mockMatchesGEval.mockResolvedValueOnce({
|
|
72
|
+
pass: true,
|
|
73
|
+
score: 0.8,
|
|
74
|
+
reason: 'test reason 1',
|
|
75
|
+
});
|
|
76
|
+
mockMatchesGEval.mockResolvedValueOnce({
|
|
77
|
+
pass: false,
|
|
78
|
+
score: 0.6,
|
|
79
|
+
reason: 'test reason 2',
|
|
80
|
+
});
|
|
81
|
+
const result = await (0, geval_1.handleGEval)({
|
|
82
|
+
assertion: {
|
|
83
|
+
type: 'g-eval',
|
|
84
|
+
value: ['criteria1', 'criteria2'],
|
|
85
|
+
threshold: 0.7,
|
|
86
|
+
},
|
|
87
|
+
renderedValue: ['criteria1', 'criteria2'],
|
|
88
|
+
prompt: 'test prompt',
|
|
89
|
+
outputString: 'test output',
|
|
90
|
+
test: {
|
|
91
|
+
vars: {},
|
|
92
|
+
assert: [],
|
|
93
|
+
options: {},
|
|
94
|
+
},
|
|
95
|
+
baseType: 'g-eval',
|
|
96
|
+
context: {
|
|
97
|
+
prompt: 'test prompt',
|
|
98
|
+
vars: {},
|
|
99
|
+
test: {
|
|
100
|
+
vars: {},
|
|
101
|
+
assert: [],
|
|
102
|
+
options: {},
|
|
103
|
+
},
|
|
104
|
+
logProbs: undefined,
|
|
105
|
+
provider: {
|
|
106
|
+
id: () => 'test-provider',
|
|
107
|
+
callApi: async () => ({ output: 'test' }),
|
|
108
|
+
},
|
|
109
|
+
providerResponse: {
|
|
110
|
+
output: 'test output',
|
|
111
|
+
error: undefined,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
inverse: false,
|
|
115
|
+
output: 'test output',
|
|
116
|
+
providerResponse: {
|
|
117
|
+
output: 'test output',
|
|
118
|
+
error: undefined,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
expect(result).toEqual({
|
|
122
|
+
assertion: {
|
|
123
|
+
type: 'g-eval',
|
|
124
|
+
value: ['criteria1', 'criteria2'],
|
|
125
|
+
threshold: 0.7,
|
|
126
|
+
},
|
|
127
|
+
pass: true,
|
|
128
|
+
score: 0.7,
|
|
129
|
+
reason: 'test reason 2',
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
it('should use default threshold if not provided', async () => {
|
|
133
|
+
const mockMatchesGEval = jest.mocked(matchers_1.matchesGEval);
|
|
134
|
+
mockMatchesGEval.mockResolvedValue({
|
|
135
|
+
pass: true,
|
|
136
|
+
score: 0.8,
|
|
137
|
+
reason: 'test reason',
|
|
138
|
+
});
|
|
139
|
+
await (0, geval_1.handleGEval)({
|
|
140
|
+
assertion: {
|
|
141
|
+
type: 'g-eval',
|
|
142
|
+
value: 'test criteria',
|
|
143
|
+
},
|
|
144
|
+
renderedValue: 'test criteria',
|
|
145
|
+
prompt: 'test prompt',
|
|
146
|
+
outputString: 'test output',
|
|
147
|
+
test: {
|
|
148
|
+
vars: {},
|
|
149
|
+
assert: [],
|
|
150
|
+
options: {},
|
|
151
|
+
},
|
|
152
|
+
baseType: 'g-eval',
|
|
153
|
+
context: {
|
|
154
|
+
prompt: 'test prompt',
|
|
155
|
+
vars: {},
|
|
156
|
+
test: {
|
|
157
|
+
vars: {},
|
|
158
|
+
assert: [],
|
|
159
|
+
options: {},
|
|
160
|
+
},
|
|
161
|
+
logProbs: undefined,
|
|
162
|
+
provider: {
|
|
163
|
+
id: () => 'test-provider',
|
|
164
|
+
callApi: async () => ({ output: 'test' }),
|
|
165
|
+
},
|
|
166
|
+
providerResponse: {
|
|
167
|
+
output: 'test output',
|
|
168
|
+
error: undefined,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
inverse: false,
|
|
172
|
+
output: 'test output',
|
|
173
|
+
providerResponse: {
|
|
174
|
+
output: 'test output',
|
|
175
|
+
error: undefined,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
expect(mockMatchesGEval).toHaveBeenCalledWith('test criteria', 'test prompt', 'test output', 0.7, {});
|
|
179
|
+
});
|
|
180
|
+
it('should throw error for invalid renderedValue type', async () => {
|
|
181
|
+
await expect((0, geval_1.handleGEval)({
|
|
182
|
+
assertion: {
|
|
183
|
+
type: 'g-eval',
|
|
184
|
+
value: 'test',
|
|
185
|
+
},
|
|
186
|
+
renderedValue: undefined,
|
|
187
|
+
prompt: 'test',
|
|
188
|
+
outputString: 'test',
|
|
189
|
+
test: {
|
|
190
|
+
vars: {},
|
|
191
|
+
assert: [],
|
|
192
|
+
options: {},
|
|
193
|
+
},
|
|
194
|
+
baseType: 'g-eval',
|
|
195
|
+
context: {
|
|
196
|
+
prompt: 'test prompt',
|
|
197
|
+
vars: {},
|
|
198
|
+
test: {
|
|
199
|
+
vars: {},
|
|
200
|
+
assert: [],
|
|
201
|
+
options: {},
|
|
202
|
+
},
|
|
203
|
+
logProbs: undefined,
|
|
204
|
+
provider: {
|
|
205
|
+
id: () => 'test-provider',
|
|
206
|
+
callApi: async () => ({ output: 'test' }),
|
|
207
|
+
},
|
|
208
|
+
providerResponse: {
|
|
209
|
+
output: 'test output',
|
|
210
|
+
error: undefined,
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
inverse: false,
|
|
214
|
+
output: 'test',
|
|
215
|
+
providerResponse: {
|
|
216
|
+
output: 'test',
|
|
217
|
+
error: undefined,
|
|
218
|
+
},
|
|
219
|
+
})).rejects.toThrow('G-Eval assertion type must have a string or array of strings value');
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=geval.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geval.test.js","sourceRoot":"","sources":["../../../test/assertions/geval.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelGradedClosedQa.test.d.ts","sourceRoot":"","sources":["../../../test/assertions/modelGradedClosedQa.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const modelGradedClosedQa_1 = require("../../src/assertions/modelGradedClosedQa");
|
|
4
|
+
const matchers_1 = require("../../src/matchers");
|
|
5
|
+
const templates_1 = require("../../src/util/templates");
|
|
6
|
+
jest.mock('../../src/matchers');
|
|
7
|
+
jest.mock('../../src/util/templates');
|
|
8
|
+
describe('handleModelGradedClosedQa', () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
jest.resetAllMocks();
|
|
11
|
+
const mockNunjucksEnv = {
|
|
12
|
+
options: { autoescape: true },
|
|
13
|
+
render: jest.fn(),
|
|
14
|
+
renderString: jest.fn().mockImplementation((str) => str),
|
|
15
|
+
addFilter: jest.fn(),
|
|
16
|
+
getFilter: jest.fn(),
|
|
17
|
+
hasExtension: jest.fn(),
|
|
18
|
+
addExtension: jest.fn(),
|
|
19
|
+
removeExtension: jest.fn(),
|
|
20
|
+
getExtension: jest.fn(),
|
|
21
|
+
addGlobal: jest.fn(),
|
|
22
|
+
getGlobal: jest.fn(),
|
|
23
|
+
getTemplate: jest.fn(),
|
|
24
|
+
express: jest.fn(),
|
|
25
|
+
on: jest.fn(),
|
|
26
|
+
};
|
|
27
|
+
jest.mocked(templates_1.getNunjucksEngine).mockReturnValue(mockNunjucksEnv);
|
|
28
|
+
jest.mocked(matchers_1.matchesClosedQa).mockResolvedValue({
|
|
29
|
+
pass: true,
|
|
30
|
+
score: 1,
|
|
31
|
+
reason: 'test reason',
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
it('should validate string value', async () => {
|
|
35
|
+
const params = {
|
|
36
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
37
|
+
baseType: 'model-graded-closedqa',
|
|
38
|
+
context: {
|
|
39
|
+
prompt: 'test prompt',
|
|
40
|
+
vars: {},
|
|
41
|
+
test: { vars: {} },
|
|
42
|
+
logProbs: undefined,
|
|
43
|
+
provider: undefined,
|
|
44
|
+
providerResponse: undefined,
|
|
45
|
+
},
|
|
46
|
+
inverse: false,
|
|
47
|
+
output: 'test output',
|
|
48
|
+
outputString: 'test output',
|
|
49
|
+
prompt: 'test prompt',
|
|
50
|
+
providerResponse: {},
|
|
51
|
+
renderedValue: {},
|
|
52
|
+
test: {
|
|
53
|
+
options: {},
|
|
54
|
+
vars: {},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
await expect((0, modelGradedClosedQa_1.handleModelGradedClosedQa)(params)).rejects.toThrow('model-graded-closedqa assertion type must have a string value');
|
|
58
|
+
});
|
|
59
|
+
it('should validate prompt exists', async () => {
|
|
60
|
+
const params = {
|
|
61
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
62
|
+
baseType: 'model-graded-closedqa',
|
|
63
|
+
context: {
|
|
64
|
+
prompt: undefined,
|
|
65
|
+
vars: {},
|
|
66
|
+
test: { vars: {} },
|
|
67
|
+
logProbs: undefined,
|
|
68
|
+
provider: undefined,
|
|
69
|
+
providerResponse: undefined,
|
|
70
|
+
},
|
|
71
|
+
inverse: false,
|
|
72
|
+
output: 'test output',
|
|
73
|
+
outputString: 'test output',
|
|
74
|
+
prompt: undefined,
|
|
75
|
+
providerResponse: {},
|
|
76
|
+
renderedValue: 'test value',
|
|
77
|
+
test: {
|
|
78
|
+
options: {},
|
|
79
|
+
vars: {},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
await expect((0, modelGradedClosedQa_1.handleModelGradedClosedQa)(params)).rejects.toThrow('model-graded-closedqa assertion type must have a prompt');
|
|
83
|
+
});
|
|
84
|
+
it('should validate rubricPrompt is string if provided', async () => {
|
|
85
|
+
const params = {
|
|
86
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
87
|
+
baseType: 'model-graded-closedqa',
|
|
88
|
+
context: {
|
|
89
|
+
prompt: 'test prompt',
|
|
90
|
+
vars: {},
|
|
91
|
+
test: { vars: {} },
|
|
92
|
+
logProbs: undefined,
|
|
93
|
+
provider: undefined,
|
|
94
|
+
providerResponse: undefined,
|
|
95
|
+
},
|
|
96
|
+
inverse: false,
|
|
97
|
+
output: 'test output',
|
|
98
|
+
outputString: 'test output',
|
|
99
|
+
prompt: 'test prompt',
|
|
100
|
+
providerResponse: {},
|
|
101
|
+
renderedValue: 'test value',
|
|
102
|
+
test: {
|
|
103
|
+
options: {
|
|
104
|
+
rubricPrompt: {},
|
|
105
|
+
},
|
|
106
|
+
vars: {},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
await expect((0, modelGradedClosedQa_1.handleModelGradedClosedQa)(params)).rejects.toThrow('rubricPrompt must be a string');
|
|
110
|
+
});
|
|
111
|
+
it('should process rubricPrompt with nunjucks if provided', async () => {
|
|
112
|
+
const mockRenderString = jest.fn().mockReturnValue('rendered rubric');
|
|
113
|
+
const mockNunjucksEnv = {
|
|
114
|
+
options: { autoescape: true },
|
|
115
|
+
render: jest.fn(),
|
|
116
|
+
renderString: mockRenderString,
|
|
117
|
+
addFilter: jest.fn(),
|
|
118
|
+
getFilter: jest.fn(),
|
|
119
|
+
hasExtension: jest.fn(),
|
|
120
|
+
addExtension: jest.fn(),
|
|
121
|
+
removeExtension: jest.fn(),
|
|
122
|
+
getExtension: jest.fn(),
|
|
123
|
+
addGlobal: jest.fn(),
|
|
124
|
+
getGlobal: jest.fn(),
|
|
125
|
+
getTemplate: jest.fn(),
|
|
126
|
+
express: jest.fn(),
|
|
127
|
+
on: jest.fn(),
|
|
128
|
+
};
|
|
129
|
+
jest.mocked(templates_1.getNunjucksEngine).mockReturnValue(mockNunjucksEnv);
|
|
130
|
+
const params = {
|
|
131
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
132
|
+
baseType: 'model-graded-closedqa',
|
|
133
|
+
context: {
|
|
134
|
+
prompt: 'test prompt',
|
|
135
|
+
vars: { var: 'value' },
|
|
136
|
+
test: { vars: { var: 'value' } },
|
|
137
|
+
logProbs: undefined,
|
|
138
|
+
provider: undefined,
|
|
139
|
+
providerResponse: undefined,
|
|
140
|
+
},
|
|
141
|
+
inverse: false,
|
|
142
|
+
output: 'test output',
|
|
143
|
+
outputString: 'test output',
|
|
144
|
+
prompt: 'test prompt',
|
|
145
|
+
providerResponse: {},
|
|
146
|
+
renderedValue: 'test value',
|
|
147
|
+
test: {
|
|
148
|
+
options: {
|
|
149
|
+
rubricPrompt: 'test rubric {{ var }}',
|
|
150
|
+
},
|
|
151
|
+
vars: {
|
|
152
|
+
var: 'value',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
await (0, modelGradedClosedQa_1.handleModelGradedClosedQa)(params);
|
|
157
|
+
expect(mockRenderString).toHaveBeenCalledWith('test rubric {{ var }}', { var: 'value' });
|
|
158
|
+
});
|
|
159
|
+
it('should call matchesClosedQa with correct parameters', async () => {
|
|
160
|
+
const params = {
|
|
161
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
162
|
+
baseType: 'model-graded-closedqa',
|
|
163
|
+
context: {
|
|
164
|
+
prompt: 'test prompt',
|
|
165
|
+
vars: { var: 'value' },
|
|
166
|
+
test: { vars: { var: 'value' } },
|
|
167
|
+
logProbs: undefined,
|
|
168
|
+
provider: undefined,
|
|
169
|
+
providerResponse: undefined,
|
|
170
|
+
},
|
|
171
|
+
inverse: false,
|
|
172
|
+
output: 'test output',
|
|
173
|
+
outputString: 'test output',
|
|
174
|
+
prompt: 'test prompt',
|
|
175
|
+
providerResponse: {},
|
|
176
|
+
renderedValue: 'test value',
|
|
177
|
+
test: {
|
|
178
|
+
options: {
|
|
179
|
+
rubricPrompt: 'test rubric',
|
|
180
|
+
},
|
|
181
|
+
vars: {
|
|
182
|
+
var: 'value',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
const result = await (0, modelGradedClosedQa_1.handleModelGradedClosedQa)(params);
|
|
187
|
+
expect(matchers_1.matchesClosedQa).toHaveBeenCalledWith('test prompt', 'test value', 'test output', {
|
|
188
|
+
rubricPrompt: 'test rubric',
|
|
189
|
+
}, {
|
|
190
|
+
var: 'value',
|
|
191
|
+
});
|
|
192
|
+
expect(result).toEqual({
|
|
193
|
+
assertion: { type: 'model-graded-closedqa' },
|
|
194
|
+
pass: true,
|
|
195
|
+
score: 1,
|
|
196
|
+
reason: 'test reason',
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=modelGradedClosedQa.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelGradedClosedQa.test.js","sourceRoot":"","sources":["../../../test/assertions/modelGradedClosedQa.test.ts"],"names":[],"mappings":"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"}
|
package/dist/test/fetch.test.js
CHANGED
|
@@ -30,7 +30,7 @@ jest.mock('../src/logger');
|
|
|
30
30
|
jest.mock('../src/envars', () => ({
|
|
31
31
|
getEnvString: jest.fn().mockImplementation((key, defaultValue = '') => ''),
|
|
32
32
|
getEnvBool: jest.fn().mockImplementation((key, defaultValue = false) => false),
|
|
33
|
-
getEnvInt: jest.fn().
|
|
33
|
+
getEnvInt: jest.fn().mockImplementation((key, defaultValue = 0) => defaultValue),
|
|
34
34
|
}));
|
|
35
35
|
jest.mock('fs', () => ({
|
|
36
36
|
readFileSync: jest.fn(),
|
|
@@ -266,7 +266,6 @@ describe('fetchWithProxy', () => {
|
|
|
266
266
|
const mockCertContent = 'mock-cert-content';
|
|
267
267
|
const mockProxyUrl = 'http://proxy.example.com';
|
|
268
268
|
process.env.HTTPS_PROXY = mockProxyUrl;
|
|
269
|
-
// Update basePath in cliState
|
|
270
269
|
cliState_1.default.basePath = mockBasePath;
|
|
271
270
|
jest.mocked(envars_1.getEnvString).mockImplementation((key, defaultValue = '') => {
|
|
272
271
|
if (key === 'PROMPTFOO_CA_CERT_PATH') {
|
|
@@ -307,7 +306,6 @@ describe('fetchWithProxy', () => {
|
|
|
307
306
|
},
|
|
308
307
|
});
|
|
309
308
|
expect(undici_1.setGlobalDispatcher).toHaveBeenCalledWith(expect.any(undici_1.ProxyAgent));
|
|
310
|
-
// Reset basePath
|
|
311
309
|
cliState_1.default.basePath = undefined;
|
|
312
310
|
});
|
|
313
311
|
it('should not create ProxyAgent when no proxy URL is found', async () => {
|
|
@@ -324,6 +322,10 @@ describe('fetchWithProxy', () => {
|
|
|
324
322
|
};
|
|
325
323
|
const allProxyVars = ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy'];
|
|
326
324
|
const testCases = [
|
|
325
|
+
{
|
|
326
|
+
env: { HTTPS_PROXY: mockProxyUrls.HTTPS_PROXY },
|
|
327
|
+
expected: { url: mockProxyUrls.HTTPS_PROXY },
|
|
328
|
+
},
|
|
327
329
|
{
|
|
328
330
|
env: { https_proxy: mockProxyUrls.https_proxy },
|
|
329
331
|
expected: { url: mockProxyUrls.https_proxy },
|
|
@@ -342,10 +344,6 @@ describe('fetchWithProxy', () => {
|
|
|
342
344
|
allProxyVars.forEach((key) => {
|
|
343
345
|
delete process.env[key];
|
|
344
346
|
});
|
|
345
|
-
const existingProxyVars = allProxyVars.filter((key) => process.env[key]);
|
|
346
|
-
if (existingProxyVars.length > 0) {
|
|
347
|
-
console.warn('Found unexpected proxy variables:', existingProxyVars);
|
|
348
|
-
}
|
|
349
347
|
Object.entries(testCase.env).forEach(([key, value]) => {
|
|
350
348
|
process.env[key] = value;
|
|
351
349
|
});
|
|
@@ -361,12 +359,15 @@ describe('fetchWithProxy', () => {
|
|
|
361
359
|
});
|
|
362
360
|
expect(undici_1.setGlobalDispatcher).toHaveBeenCalledWith(expect.any(undici_1.ProxyAgent));
|
|
363
361
|
const debugCalls = jest.mocked(logger_1.default.debug).mock.calls;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
362
|
+
const normalizedCalls = debugCalls.map((call) => call[0].replace(/\/$/, ''));
|
|
363
|
+
// On Windows, environment variables are case-insensitive
|
|
364
|
+
const isWindows = process.platform === 'win32';
|
|
365
|
+
const expectedEnvVar = Object.keys(testCase.env)[0];
|
|
366
|
+
const expectedUrl = testCase.expected.url;
|
|
367
|
+
expect(normalizedCalls).toEqual([
|
|
368
|
+
expect.stringMatching(new RegExp(`Found proxy configuration in ${isWindows ? '.*' : expectedEnvVar}: ${expectedUrl}`, isWindows ? 'i' : '')),
|
|
369
|
+
`Using proxy: ${expectedUrl}`,
|
|
370
|
+
]);
|
|
370
371
|
allProxyVars.forEach((key) => {
|
|
371
372
|
delete process.env[key];
|
|
372
373
|
});
|
|
@@ -508,14 +509,14 @@ describe('fetchWithRetries', () => {
|
|
|
508
509
|
it('should make retries+1 total attempts', async () => {
|
|
509
510
|
jest.mocked(global.fetch).mockRejectedValue(new Error('Network error'));
|
|
510
511
|
await expect((0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 2)).rejects.toThrow('Request failed after 2 retries: Network error');
|
|
511
|
-
expect(global.fetch).toHaveBeenCalledTimes(3);
|
|
512
|
-
expect(time_1.sleep).toHaveBeenCalledTimes(2);
|
|
512
|
+
expect(global.fetch).toHaveBeenCalledTimes(3);
|
|
513
|
+
expect(time_1.sleep).toHaveBeenCalledTimes(2);
|
|
513
514
|
});
|
|
514
515
|
it('should not sleep after the final attempt', async () => {
|
|
515
516
|
jest.mocked(global.fetch).mockRejectedValue(new Error('Network error'));
|
|
516
517
|
await expect((0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 1)).rejects.toThrow('Request failed after 1 retries: Network error');
|
|
517
|
-
expect(global.fetch).toHaveBeenCalledTimes(2);
|
|
518
|
-
expect(time_1.sleep).toHaveBeenCalledTimes(1);
|
|
518
|
+
expect(global.fetch).toHaveBeenCalledTimes(2);
|
|
519
|
+
expect(time_1.sleep).toHaveBeenCalledTimes(1);
|
|
519
520
|
});
|
|
520
521
|
it('should handle 5XX errors when PROMPTFOO_RETRY_5XX is true', async () => {
|
|
521
522
|
jest.mocked(envars_1.getEnvBool).mockImplementation((key) => {
|
|
@@ -560,8 +561,55 @@ describe('fetchWithRetries', () => {
|
|
|
560
561
|
const mockFetch = jest.fn().mockRejectedValue(new Error('Network error'));
|
|
561
562
|
global.fetch = mockFetch;
|
|
562
563
|
await expect((0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 2)).rejects.toThrow('Request failed after 2 retries: Network error');
|
|
563
|
-
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
564
|
+
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
564
565
|
expect(time_1.sleep).toHaveBeenCalledTimes(2);
|
|
565
566
|
});
|
|
567
|
+
it('should handle detailed error information', async () => {
|
|
568
|
+
const error = new Error('Network error');
|
|
569
|
+
error.code = 'ECONNREFUSED';
|
|
570
|
+
error.cause = 'Connection refused';
|
|
571
|
+
jest.mocked(global.fetch).mockRejectedValue(error);
|
|
572
|
+
await expect((0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 1)).rejects.toThrow('Request failed after 1 retries: Network error');
|
|
573
|
+
expect(global.fetch).toHaveBeenCalledTimes(2);
|
|
574
|
+
expect(time_1.sleep).toHaveBeenCalledTimes(1);
|
|
575
|
+
});
|
|
576
|
+
it('should handle non-Error objects in rejection', async () => {
|
|
577
|
+
jest.mocked(global.fetch).mockRejectedValue('String error');
|
|
578
|
+
await expect((0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 1)).rejects.toThrow('Request failed after 1 retries: undefined');
|
|
579
|
+
expect(global.fetch).toHaveBeenCalledTimes(2);
|
|
580
|
+
expect(time_1.sleep).toHaveBeenCalledTimes(1);
|
|
581
|
+
});
|
|
582
|
+
it('should handle rate limits with OpenAI specific headers', async () => {
|
|
583
|
+
const rateLimitedResponse = (0, utils_1.createMockResponse)({
|
|
584
|
+
status: 429,
|
|
585
|
+
headers: new Headers({
|
|
586
|
+
'x-ratelimit-reset-tokens': '5',
|
|
587
|
+
}),
|
|
588
|
+
});
|
|
589
|
+
const successResponse = (0, utils_1.createMockResponse)();
|
|
590
|
+
const mockFetch = jest
|
|
591
|
+
.fn()
|
|
592
|
+
.mockResolvedValueOnce(rateLimitedResponse)
|
|
593
|
+
.mockResolvedValueOnce(successResponse);
|
|
594
|
+
global.fetch = mockFetch;
|
|
595
|
+
await (0, fetch_1.fetchWithRetries)('https://example.com', {}, 1000, 2);
|
|
596
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
597
|
+
expect(logger_1.default.debug).toHaveBeenCalledWith(expect.stringContaining('Rate limited on URL'));
|
|
598
|
+
expect(time_1.sleep).toHaveBeenCalledTimes(1);
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
describe('sanitizeUrl', () => {
|
|
602
|
+
it('should mask credentials in URLs', () => {
|
|
603
|
+
const url = 'https://username:password@example.com/api';
|
|
604
|
+
expect((0, fetch_1.sanitizeUrl)(url)).toBe('https://***:***@example.com/api');
|
|
605
|
+
});
|
|
606
|
+
it('should handle URLs without credentials', () => {
|
|
607
|
+
const url = 'https://example.com/api';
|
|
608
|
+
expect((0, fetch_1.sanitizeUrl)(url)).toBe(url);
|
|
609
|
+
});
|
|
610
|
+
it('should return original string for invalid URLs', () => {
|
|
611
|
+
const invalidUrl = 'not-a-url';
|
|
612
|
+
expect((0, fetch_1.sanitizeUrl)(invalidUrl)).toBe(invalidUrl);
|
|
613
|
+
});
|
|
566
614
|
});
|
|
567
615
|
//# sourceMappingURL=fetch.test.js.map
|