272 lines
21 KiB
JavaScript
272 lines
21 KiB
JavaScript
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
import { OpenAI, toFile } from "openai";
|
|
import { isString } from '@plastichub/core/primitives';
|
|
import { sync as write } from '@plastichub/fs/write';
|
|
import { sync as read } from '@plastichub/fs/read';
|
|
import { sync as exists } from '@plastichub/fs/exists';
|
|
import { resolve } from '@plastichub/osr-commons';
|
|
import { dumpAsScript, logger, toImages } from '../..';
|
|
import { Typescript, Commons, Markdown, Documents, Rust } from './system';
|
|
import { Filters } from '../filters';
|
|
import { parse } from './options';
|
|
import { web_prompt as eprompt } from '../ui/electron';
|
|
import { deepmerge as merge } from 'deepmerge-ts';
|
|
export const deepMerge = async (target, source) => {
|
|
if (!isString(target) || !source) {
|
|
logger.error(`Invalid deepmerge parameters:`, target, source);
|
|
return source;
|
|
}
|
|
target = read(target, 'json') || [];
|
|
try {
|
|
source = isString(source) ? JSON.parse(source) : source;
|
|
}
|
|
catch (e) {
|
|
logger.error('Error parsing completion:', e);
|
|
return source;
|
|
}
|
|
try {
|
|
const ret = merge(target, source);
|
|
return JSON.stringify(ret, null, 2);
|
|
}
|
|
catch (error) {
|
|
logger.error('Error merging completion:', error);
|
|
}
|
|
return target;
|
|
};
|
|
export const mergers = { deepMerge };
|
|
export const onCompletion = async (query, ret, opts) => {
|
|
if (!isString(ret)) {
|
|
logger.warn(`Invalid response :${query}`);
|
|
return;
|
|
}
|
|
const filters = opts.filters.split(',');
|
|
opts.filters = [];
|
|
filters.forEach((f) => {
|
|
if (Filters[f]) {
|
|
(opts.filters).push(Filters[f]);
|
|
}
|
|
});
|
|
if (opts.filters) {
|
|
opts.filters.forEach((f) => { ret = f(ret); });
|
|
}
|
|
if (opts.append && mergers[opts.append] && opts.dst) {
|
|
ret = await mergers[opts.append](opts.dst, ret);
|
|
}
|
|
if (opts.dst) {
|
|
let header = `${opts.showPrompt ? `// ${opts.query}` : ''}\n`;
|
|
let content = `${header}${ret}`;
|
|
write(opts.dst, content);
|
|
}
|
|
else {
|
|
process.stdout.write(ret);
|
|
}
|
|
return ret;
|
|
};
|
|
export const createOpenAIFile = async (client, filePath, purpose = 'assistants') => {
|
|
return client.files.create({
|
|
file: fs.createReadStream(filePath),
|
|
purpose: purpose
|
|
});
|
|
};
|
|
export const queryEx = async (api_key, options) => {
|
|
let ui_opts = null;
|
|
let ui_opts_variables = {};
|
|
if (options.gui === 'electron') {
|
|
const promptsFile = path.resolve(resolve(options.prompts));
|
|
const prompts = JSON.stringify(read(promptsFile, 'json') || []);
|
|
ui_opts = await eprompt(options.query, options.dst, { ...ui_opts_variables, PROMPTS: prompts, MODELS: [] });
|
|
}
|
|
options = parse(options);
|
|
if (ui_opts) {
|
|
if (ui_opts.files && ui_opts.files.length > 0) {
|
|
options.files = ui_opts.files;
|
|
}
|
|
if (ui_opts.textAreaValue !== options.query) {
|
|
options.query = ui_opts.textAreaValue;
|
|
}
|
|
if (ui_opts.target.length && ui_opts.target !== options.dst) {
|
|
options.dst = ui_opts.target;
|
|
}
|
|
}
|
|
const client = new OpenAI({ apiKey: api_key });
|
|
let messages = [];
|
|
let defaults = [...Typescript(), ...Documents()];
|
|
if (options.system && exists(options.system)) {
|
|
options.debug && logger.debug('Reading system instructions from', options.system);
|
|
try {
|
|
const system = read(options.system, 'json');
|
|
if (system) {
|
|
messages = [...system];
|
|
}
|
|
}
|
|
catch (error) {
|
|
logger.error('Error reading system instructions', error);
|
|
messages = defaults;
|
|
}
|
|
}
|
|
else {
|
|
messages = defaults;
|
|
}
|
|
const attachments = await Promise.all(options.files.map(async (file) => {
|
|
const file_id = await createOpenAIFile(client, file);
|
|
return {
|
|
file_id: file_id.id,
|
|
tools: [{ type: "file_search" }]
|
|
};
|
|
}));
|
|
const assistant = await client.beta.assistants.create({
|
|
name: "Documents Assistant",
|
|
instructions: "You are an expert data analyst.",
|
|
model: "gpt-4o",
|
|
tools: [{ type: "file_search" }],
|
|
});
|
|
const thread = await client.beta.threads.create({
|
|
messages: [
|
|
{
|
|
role: "user",
|
|
content: options.query,
|
|
attachments
|
|
}
|
|
]
|
|
});
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
const stream = client.beta.threads.runs
|
|
.stream(thread.id, {
|
|
assistant_id: assistant.id,
|
|
})
|
|
.on("textCreated", () => console.log("assistant >"))
|
|
.on("toolCallCreated", (event) => console.log("assistant " + event.type))
|
|
.on("messageDone", async (event) => {
|
|
if (event.content[0].type === "text") {
|
|
const { text } = event.content[0];
|
|
const { annotations } = text;
|
|
const citations = [];
|
|
let index = 0;
|
|
/*
|
|
for (let annotation of annotations) {
|
|
text.value = text.value.replace(annotation.text, "[" + index + "]");
|
|
const { file_citation } = annotation;
|
|
if (file_citation) {
|
|
const citedFile = await openai.files.retrieve(file_citation.file_id);
|
|
citations.push("[" + index + "]" + citedFile.filename);
|
|
}
|
|
index++;
|
|
}*/
|
|
logger.debug('OpenAI response:', text.value);
|
|
resolve(text.value);
|
|
}
|
|
});
|
|
return stream;
|
|
}
|
|
catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
};
|
|
export const query = async (query, api_key, dst, options) => {
|
|
const client = new OpenAI({ apiKey: api_key });
|
|
let messages = [];
|
|
let defaults = [...Typescript(), ...Markdown(), ...Commons(), ...Rust()];
|
|
if (options.system && exists(options.system)) {
|
|
logger.debug('Reading system instructions from', options.system);
|
|
try {
|
|
const system = read(options.system, 'json');
|
|
if (system) {
|
|
messages = [...system];
|
|
}
|
|
}
|
|
catch (error) {
|
|
logger.error('Error reading system instructions', error);
|
|
messages = defaults;
|
|
}
|
|
}
|
|
else {
|
|
messages = defaults;
|
|
}
|
|
const requestMessage = {
|
|
role: "user",
|
|
content: query
|
|
};
|
|
messages.push(requestMessage);
|
|
if (options.files && options.filesInfo.FILES) {
|
|
const images = toImages(options.filesInfo.FILES).map((image) => {
|
|
return {
|
|
role: "user",
|
|
content: [{ ...image }]
|
|
};
|
|
});
|
|
messages = [...messages, ...images];
|
|
}
|
|
const tools = [
|
|
{
|
|
type: "function",
|
|
function: {
|
|
name: "list_files",
|
|
description: "List files in a given directory.",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
order_id: {
|
|
type: "string",
|
|
description: "The directory to list files in.",
|
|
},
|
|
},
|
|
required: ["dir"],
|
|
additionalProperties: false
|
|
}
|
|
}
|
|
}
|
|
];
|
|
const completion = await client.chat.completions.create({
|
|
model: options.model || "gpt-4o",
|
|
messages: messages,
|
|
//tools: tools as any
|
|
});
|
|
if (completion.choices.length === 0) {
|
|
logger.error('OpenAI response is empty');
|
|
return;
|
|
}
|
|
let ret = completion.choices[0].message.content;
|
|
ret = await onCompletion(query, ret, options);
|
|
dumpAsScript(options);
|
|
return ret;
|
|
};
|
|
const createBuffer = (path) => {
|
|
try {
|
|
const buffer = fs.readFileSync(path);
|
|
return buffer;
|
|
}
|
|
catch (error) {
|
|
console.error('Error creating buffer:', error);
|
|
return null;
|
|
}
|
|
};
|
|
export const transcribe = async (query, api_key, dst, options) => {
|
|
const client = new OpenAI({
|
|
apiKey: api_key
|
|
});
|
|
if (!exists(options.source)) {
|
|
logger.error('Source file does not exist', options.source);
|
|
return;
|
|
}
|
|
const file = await toFile(createBuffer(options.source), 'audio.mp3', { type: 'audio/mpeg' });
|
|
if (!file) {
|
|
logger.error('Error converting source to file');
|
|
return;
|
|
}
|
|
const completion = await client.audio.transcriptions.create({
|
|
model: 'whisper-1',
|
|
file: file,
|
|
response_format: options.response_format || "verbose_json",
|
|
});
|
|
if (!completion) {
|
|
logger.error('OpenAI response is empty');
|
|
return;
|
|
}
|
|
const ret = completion;
|
|
logger.debug('OpenAI Transcribe response:', ret);
|
|
return ret;
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVmL3F1ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQzVCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFBO0FBQ3hCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQ3ZDLE9BQU8sRUFBRSxRQUFRLEVBQVksTUFBTSw2QkFBNkIsQ0FBQTtBQUNoRSxPQUFPLEVBQUUsSUFBSSxJQUFJLEtBQUssRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ3BELE9BQU8sRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDbEQsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUV0RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDakQsT0FBTyxFQUFFLFlBQVksRUFBWSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQ2hFLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ3pFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDcEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNqQyxPQUFPLEVBQUUsVUFBVSxJQUFJLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRXRELE9BQU8sRUFBRSxTQUFTLElBQUksS0FBSyxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBR2pELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxLQUFLLEVBQUUsTUFBYyxFQUFFLE1BQVcsRUFBRSxFQUFFO0lBQzNELElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxD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
|