@websolutespa/payload-plugin-bowl-llm
Version:
LLM plugin for Bowl PayloadCms plugin
126 lines (125 loc) • 4.13 kB
JavaScript
import { ResponseSuccess } from '@websolutespa/payload-utils/server';
import fs from 'fs';
import OpenAI from 'openai';
import path from 'path';
import { addDataAndFileToRequest } from 'payload';
import { options } from '../options';
import { appHandler } from './app.handler';
import { errorHandler } from './error.handler';
const setLlmAppCurrentJobId = async (payload, app, jobId)=>{
await payload.update({
collection: options.slug.llmApp,
id: app.id,
data: {
settings: {
fineTuning: {
currentJobId: jobId
}
}
},
overrideAccess: true
});
};
const createFineTuningJob = async (payload, app, jsonlFilePath)=>{
const openai = new OpenAI({
apiKey: app.settings.llmConfig.secrets.openAIApiKey
});
const file = await openai.files.create({
file: fs.createReadStream(jsonlFilePath),
purpose: 'fine-tune'
});
const job = await openai.fineTuning.jobs.create({
training_file: file.id,
model: 'gpt-3.5-turbo-1106',
suffix: app.settings?.fineTuning?.modelNameSuffix ?? ''
});
return job;
};
const writeFineTuningJsonlFile = async (payload, app)=>{
const response = await payload.find({
collection: options.slug.llmFineTuning,
where: {
llmApp: {
equals: app.id
}
},
overrideAccess: true
});
const systemMessage = app.settings.llmConfig.prompt.prompt?.systemMessage || app.settings.llmConfig.prompt.systemMessage || '';
let jsonl = '';
for (const doc of response.docs){
const json = {
messages: [
{
role: 'system',
content: systemMessage
},
{
role: 'user',
content: doc.question
},
{
role: 'assistant',
content: doc.answer
}
]
};
jsonl = jsonl.concat(JSON.stringify(json) + '\n');
}
const fineTuningPath = path.join(process.cwd(), 'lib', 'fine-tuning');
fs.mkdirSync(fineTuningPath, {
recursive: true
});
const dest = path.join(fineTuningPath, 'finetuning.jsonl');
fs.writeFileSync(dest, jsonl);
return dest;
};
export async function fineTuningJobsHandler(payload) {
const result = await payload.find({
collection: options.slug.llmApp,
where: {
'settings.fineTuning.currentJobId': {
not_equals: null
}
},
overrideAccess: true
});
for (const app of result.docs){
const jobId = app.settings.fineTuning.currentJobId;
if (jobId) {
const openai = new OpenAI({
apiKey: app.settings.llmConfig.secrets.openAIApiKey
});
const fineTune = await openai.fineTuning.jobs.retrieve(jobId);
if (fineTune.status === 'succeeded') {
await payload.update({
collection: options.slug.llmApp,
id: app.id,
data: {
settings: {
fineTuning: {
currentJobId: null,
fineTunedModelName: fineTune.fine_tuned_model
}
}
},
overrideAccess: true
});
}
}
}
}
export const fineTuningHandler = async (req)=>{
try {
await addDataAndFileToRequest(req);
const app = await appHandler(req);
const { payload } = req;
const jsonlFilePath = await writeFineTuningJsonlFile(payload, app);
const job = await createFineTuningJob(payload, app, jsonlFilePath);
await setLlmAppCurrentJobId(payload, app, job.id);
return ResponseSuccess(job);
} catch (error) {
return errorHandler(error);
}
};
//# sourceMappingURL=fineTuning.handler.js.map