1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
- import { matchesGEval } from '../../src/matchers';
- import { DefaultGradingProvider } from '../../src/providers/openai/defaults';
- describe('matchesGEval', () => {
- let originalCallApi: typeof DefaultGradingProvider.callApi;
- beforeEach(() => {
- originalCallApi = DefaultGradingProvider.callApi;
- jest.spyOn(DefaultGradingProvider, 'callApi').mockImplementation(async (prompt) => {
- if (prompt.includes('generate 3-4 concise evaluation steps')) {
- return {
- output: '{"steps": ["Check clarity", "Evaluate coherence", "Assess grammar"]}',
- tokenUsage: { total: 10, prompt: 5, completion: 5 },
- };
- } else {
- return {
- output: '{"score": 8, "reason": "The response is well-structured and clear"}',
- tokenUsage: { total: 15, prompt: 8, completion: 7 },
- };
- }
- });
- });
- afterEach(() => {
- DefaultGradingProvider.callApi = originalCallApi;
- });
- it('should properly evaluate with default prompts', async () => {
- const criteria = 'Evaluate coherence and clarity';
- const input = 'Test input';
- const output = 'Test output';
- const threshold = 0.7;
- const result = await matchesGEval(criteria, input, output, threshold);
- expect(result).toEqual({
- pass: true,
- score: 0.8,
- reason: 'The response is well-structured and clear',
- tokensUsed: expect.any(Object),
- });
- expect(DefaultGradingProvider.callApi).toHaveBeenCalledTimes(2);
- });
- it('should handle custom rubric prompts', async () => {
- jest.resetAllMocks();
- const mockCallApi = jest
- .fn()
- .mockImplementationOnce(() => ({
- output: '{"steps": ["Custom step 1", "Custom step 2"]}',
- tokenUsage: { total: 10, prompt: 5, completion: 5 },
- }))
- .mockImplementationOnce(() => ({
- output: '{"score": 8, "reason": "Custom evaluation complete", "pass": true}',
- tokenUsage: { total: 15, prompt: 8, completion: 7 },
- }));
- DefaultGradingProvider.callApi = mockCallApi;
- const criteria = 'Evaluate coherence and clarity';
- const input = 'Test input';
- const output = 'Test output';
- const threshold = 0.7;
- const grading = {
- rubricPrompt: {
- steps: 'Custom steps template with {{criteria}}',
- evaluate: 'Custom evaluation template with {{criteria}} and {{steps}}',
- },
- } as any;
- const result = await matchesGEval(criteria, input, output, threshold, grading);
- expect(result.score).toBe(0.8);
- expect(mockCallApi).toHaveBeenCalledTimes(2);
- expect(mockCallApi).toHaveBeenNthCalledWith(
- 1,
- expect.stringContaining('Custom steps template with'),
- );
- expect(mockCallApi).toHaveBeenNthCalledWith(
- 2,
- expect.stringContaining('Custom evaluation template with'),
- );
- DefaultGradingProvider.callApi = originalCallApi;
- });
- it('should fail when score is below threshold', async () => {
- jest
- .spyOn(DefaultGradingProvider, 'callApi')
- .mockImplementationOnce(async () => {
- return {
- output: '{"steps": ["Check clarity", "Evaluate coherence", "Assess grammar"]}',
- tokenUsage: { total: 10, prompt: 5, completion: 5 },
- };
- })
- .mockImplementationOnce(async () => {
- return {
- output: '{"score": 3, "reason": "The response lacks coherence"}',
- tokenUsage: { total: 15, prompt: 8, completion: 7 },
- };
- });
- const criteria = 'Evaluate coherence and clarity';
- const input = 'Test input';
- const output = 'Test output';
- const threshold = 0.7;
- const result = await matchesGEval(criteria, input, output, threshold);
- expect(result).toEqual({
- pass: false,
- score: 0.3,
- reason: 'The response lacks coherence',
- tokensUsed: expect.any(Object),
- });
- });
- it('tracks token usage for both API calls', async () => {
- const criteria = 'Evaluate coherence and clarity';
- const input = 'Test input';
- const output = 'Test output';
- const threshold = 0.7;
- const result = await matchesGEval(criteria, input, output, threshold);
- expect(result.tokensUsed).toEqual({
- total: 25,
- prompt: 13,
- completion: 12,
- cached: 0,
- completionDetails: expect.any(Object),
- numRequests: 0,
- });
- });
- });
|