Added new json output support
Some checks failed
Publish Library / Build NPM Project (push) Failing after 1m2s
Publish Library / Tag Version (push) Has been skipped

This commit is contained in:
2026-07-11 18:27:55 -04:00
parent 69b3297bb3
commit 436757daad
8 changed files with 307 additions and 257 deletions

View File

@@ -3,15 +3,16 @@ import {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean} from '@zti
import {AbortablePromise, Ai} from './ai.ts';
import {LLMMessage, LLMRequest} from './llm.ts';
import {LLMProvider} from './provider.ts';
import {convertSchema} from './tools.ts';
export class OpenAi extends LLMProvider {
client!: openAI;
constructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {
constructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string, public llama?: boolean) {
super();
this.client = new openAI(clean({
baseURL: host,
apiKey: token || host ? 'ignored' : undefined
apiKey: token || (host ? 'ignored' : undefined)
}));
}
@@ -64,7 +65,7 @@ export class OpenAi extends LLMProvider {
}, [] as any[]);
}
ask(message: string, options: LLMRequest = {}): AbortablePromise<string> {
ask(message: string, options: LLMRequest = {}): AbortablePromise<string | any> {
const controller = new AbortController();
return Object.assign(new Promise<any>(async (res, rej) => {
if(options.system) {
@@ -77,8 +78,8 @@ export class OpenAi extends LLMProvider {
model: options.model || this.model,
messages: history,
stream: !!options.stream,
max_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,
temperature: options.temperature || this.ai.options.llm?.temperature || 0.7,
max_completion_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || undefined,
temperature: options.temperature || this.ai.options.llm?.temperature || undefined,
tools: tools.map(t => ({
type: 'function',
function: {
@@ -93,6 +94,26 @@ export class OpenAi extends LLMProvider {
}))
};
if(options.schema) {
const schema = convertSchema(options.schema);
if(this.llama) {
delete requestParams.tools;
requestParams.response_format = {
type: 'json_schema',
json_schema: {name: 'json', schema}
}
} else {
requestParams.response_format = {
type: 'json_schema',
json_schema: {
name: 'response',
strict: true,
schema
}
};
}
}
let resp: any, isFirstMessage = true;
do {
resp = await this.client.chat.completions.create(requestParams).catch(err => {
@@ -158,12 +179,17 @@ export class OpenAi extends LLMProvider {
requestParams.messages = history;
}
} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);
history.push({role: 'assistant', content: resp.choices[0].message.content.trim() || ''});
const textContent = resp.choices[0].message.content?.trim() || '';
history.push({role: 'assistant', content: textContent});
history = this.toStandard(history);
if(options.stream) options.stream({done: true});
if(options.history) options.history.splice(0, options.history.length, ...history);
res(history.at(-1)?.content);
// Return parsed JSON if schema provided
const finalContent = history.at(-1)?.content;
res(options.schema ? JSONAttemptParse(finalContent, finalContent) : finalContent);
}), {abort: () => controller.abort()});
}
}