evals 1.0.7 → 2.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.
- package/README.md +9 -86
- package/cli.js +232 -0
- package/package.json +15 -31
- package/LICENSE +0 -7
- package/dist/index.js +0 -15372
- package/src/index.js +0 -190
package/src/index.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { program } from 'commander';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import OpenAI from 'openai';
|
|
5
|
-
|
|
6
|
-
program
|
|
7
|
-
.command('fetch-evals')
|
|
8
|
-
.description('Fetch the latest evals for the project')
|
|
9
|
-
.action(async () => {
|
|
10
|
-
if (!process.env.UMBRAGE_EVALS_API_KEY) {
|
|
11
|
-
throw new Error('UMBRAGE_EVALS_API_KEY is not set in the environment variables.');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const UMBRAGE_EVALS_API_KEY = process.env.UMBRAGE_EVALS_API_KEY;
|
|
15
|
-
|
|
16
|
-
const fetchEvals = async () => {
|
|
17
|
-
const url = new URL('https://api-gateway.groff.workers.dev/evals');
|
|
18
|
-
|
|
19
|
-
url.searchParams.append('page', 0);
|
|
20
|
-
url.searchParams.append('pageSize', 100);
|
|
21
|
-
url.searchParams.append('eval_type', 'OpenAI-GPT-4');
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const response = await fetch(url, {
|
|
25
|
-
method: 'GET',
|
|
26
|
-
headers: {
|
|
27
|
-
'X-API-KEY': UMBRAGE_EVALS_API_KEY,
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const data = await response.json();
|
|
36
|
-
return data.evals;
|
|
37
|
-
} catch (error) {
|
|
38
|
-
console.error('Error fetching evals:', error);
|
|
39
|
-
return []; // Return an empty array to avoid breaking downstream code
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const processPromptFile = async file => {
|
|
44
|
-
const promptFilename = file.split('.prompt.js')[0];
|
|
45
|
-
const evalsFolder = `prompts/${promptFilename}_evals`;
|
|
46
|
-
|
|
47
|
-
if (!fs.existsSync(evalsFolder)) {
|
|
48
|
-
fs.mkdirSync(evalsFolder, { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Fetch evals from the cloudflare worker
|
|
52
|
-
const evalsForPrompt = await fetchEvals();
|
|
53
|
-
|
|
54
|
-
for (const evalObject of evalsForPrompt) {
|
|
55
|
-
const { name: evalName, eval_code } = evalObject;
|
|
56
|
-
const markdownFileName = `${evalsFolder}/${evalName.replace(/[^a-z0-9]/gi, '_')}.md`;
|
|
57
|
-
fs.writeFileSync(markdownFileName, eval_code);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const currentWorkingDir = process.cwd(); // Get the current working directory
|
|
63
|
-
const promptsDir = `${currentWorkingDir}/prompts/`; // Use it as the base for your prompts directory
|
|
64
|
-
const promptFiles = fs.readdirSync(promptsDir).filter(file => file.endsWith('.prompt.js'));
|
|
65
|
-
|
|
66
|
-
const processingPromises = promptFiles.map(processPromptFile);
|
|
67
|
-
await Promise.all(processingPromises);
|
|
68
|
-
|
|
69
|
-
console.log('Done fetching evals!');
|
|
70
|
-
} catch (error) {
|
|
71
|
-
console.error('An error occurred:', error);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
program
|
|
76
|
-
.command('run-evals')
|
|
77
|
-
.description('Run evals in the current directory and log results')
|
|
78
|
-
.action(async () => {
|
|
79
|
-
if (!process.env.OPENAI_API_KEY) {
|
|
80
|
-
throw new Error('OPENAI_API_KEY is not set in the environment variables.');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const openai = new OpenAI(); // Assumes OPENAI_API_KEY is set in environment
|
|
84
|
-
const currentWorkingDir = process.cwd(); // Get the current working directory
|
|
85
|
-
const promptsDir = `${currentWorkingDir}/prompts/`; // Use it as the base for your prompts directory
|
|
86
|
-
const model = 'gpt-4-1106-preview';
|
|
87
|
-
const temperature = 0;
|
|
88
|
-
|
|
89
|
-
// Process a single markdown file
|
|
90
|
-
const processMarkdownFile = async (evalsFolder, evalFile, promptInstance) => {
|
|
91
|
-
console.log(`\nEvaluating: ${evalFile}`);
|
|
92
|
-
const evalName = evalFile.split('.md')[0];
|
|
93
|
-
const eval_code = fs.readFileSync(`${evalsFolder}/${evalFile}`, 'utf-8');
|
|
94
|
-
|
|
95
|
-
console.time('Model response time');
|
|
96
|
-
const { response: modelResponse, prompts: evalPrompts } = await promptInstance.callModel('Hi! What is your name?');
|
|
97
|
-
console.timeEnd('Model response time');
|
|
98
|
-
|
|
99
|
-
const messages = [
|
|
100
|
-
{
|
|
101
|
-
role: 'system',
|
|
102
|
-
content:
|
|
103
|
-
'You are a prompt evaluation expert. \\nYou will respond in JSON format with an "explanation" of why you have given it a grade from 0-100, and "suggestions" for improving the response in order to get a higher grade, and lastly the "grade" from 0-100 in integer number format. \\nUse the rubric to accomplish this task.',
|
|
104
|
-
},
|
|
105
|
-
{ role: 'function', name: 'grading_rubric', content: eval_code },
|
|
106
|
-
{ role: 'user', content: `Grade the following response using the rubric: \\n ${modelResponse}` },
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
console.time('Eval response time');
|
|
110
|
-
const evalResponse = await openai.chat.completions.create({
|
|
111
|
-
model,
|
|
112
|
-
messages,
|
|
113
|
-
temperature,
|
|
114
|
-
response_format: { type: 'json_object' },
|
|
115
|
-
});
|
|
116
|
-
console.timeEnd('Eval response time');
|
|
117
|
-
|
|
118
|
-
const evalResult = JSON.parse(evalResponse.choices[0].message.content);
|
|
119
|
-
console.log('evalResult', evalResult);
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
evalName,
|
|
123
|
-
evalCode: eval_code,
|
|
124
|
-
evalResult,
|
|
125
|
-
isValid: evalResult.grade && evalResult.explanation && evalResult.suggestions,
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// Process a single prompt file
|
|
130
|
-
const processPromptFile = async file => {
|
|
131
|
-
const promptFilename = file.split('.prompt.js')[0];
|
|
132
|
-
const evalsFolder = `${promptsDir}/${promptFilename}_evals`;
|
|
133
|
-
|
|
134
|
-
if (!fs.existsSync(evalsFolder)) {
|
|
135
|
-
console.error(`Evals folder not found for ${promptFilename}, please run fetch_latest_evals.js first.`);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const promptInstance = await import(`${promptsDir}${file}`).then(mod => mod.default);
|
|
140
|
-
const evaluations = [];
|
|
141
|
-
|
|
142
|
-
const evalMarkdownFiles = fs.readdirSync(evalsFolder).filter(f => f.endsWith('.md'));
|
|
143
|
-
|
|
144
|
-
for (const evalFile of evalMarkdownFiles) {
|
|
145
|
-
const result = await processMarkdownFile(evalsFolder, evalFile, promptInstance);
|
|
146
|
-
if (result.isValid) {
|
|
147
|
-
evaluations.push({
|
|
148
|
-
promptName: promptInstance.promptName,
|
|
149
|
-
modelName: promptInstance.modelName,
|
|
150
|
-
modelSettings: promptInstance.modelSettings,
|
|
151
|
-
modelResponse: result.modelResponse,
|
|
152
|
-
evalPromptsJson: JSON.stringify(result.evalPrompts),
|
|
153
|
-
evalName: result.evalName,
|
|
154
|
-
evalCode: result.evalCode,
|
|
155
|
-
grade: result.evalResult.grade,
|
|
156
|
-
explanation: result.evalResult.explanation,
|
|
157
|
-
suggestions: result.evalResult.suggestions,
|
|
158
|
-
});
|
|
159
|
-
} else {
|
|
160
|
-
// Handle invalid evaluation
|
|
161
|
-
evaluations.push({
|
|
162
|
-
promptName: promptInstance.promptName,
|
|
163
|
-
modelName: promptInstance.modelName,
|
|
164
|
-
modelSettings: promptInstance.modelSettings,
|
|
165
|
-
modelResponse: result.modelResponse,
|
|
166
|
-
evalPromptsJson: JSON.stringify(result.evalPrompts),
|
|
167
|
-
evalName: result.evalName,
|
|
168
|
-
evalCode: result.evalCode,
|
|
169
|
-
grade: 'Evaluation failed.',
|
|
170
|
-
explanation: 'Evaluation failed.',
|
|
171
|
-
suggestions: 'Evaluation failed.',
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const jsonFilePath = `${evalsFolder}/${promptFilename}_evals_results_${new Date().toISOString()}.json`;
|
|
177
|
-
fs.writeFileSync(jsonFilePath, JSON.stringify(evaluations, null, 4));
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
const promptFiles = fs.readdirSync(promptsDir).filter(file => file.endsWith('.prompt.js'));
|
|
182
|
-
const processingPromises = promptFiles.map(processPromptFile);
|
|
183
|
-
await Promise.all(processingPromises);
|
|
184
|
-
console.log('Done processing evals!');
|
|
185
|
-
} catch (error) {
|
|
186
|
-
console.error('An error occurred:', error);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
program.parse(process.argv);
|