Added JSON / Summary LLM safeguard
All checks were successful
Publish Library / Build NPM Project (push) Successful in 1m1s
Publish Library / Tag Version (push) Successful in 14s

This commit is contained in:
2026-03-26 12:24:20 -04:00
parent 52a3e73484
commit 5eae84f6cf
2 changed files with 48 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@ztimson/ai-utils",
"version": "0.8.11",
"version": "0.8.12",
"description": "AI Utility library",
"author": "Zak Timson",
"license": "MIT",

View File

@@ -1,3 +1,4 @@
import {sum} from '@tensorflow/tfjs';
import {JSONAttemptParse} from '@ztimson/utils';
import {AbortablePromise, Ai} from './ai.ts';
import {Anthropic} from './antrhopic.ts';
@@ -357,11 +358,30 @@ class LLM {
* @returns {Promise<{} | {} | RegExpExecArray | null>}
*/
async json(text: string, schema: string, options?: LLMRequest): Promise<any> {
const code = await this.code(text, {...options, system: [
options?.system,
`Only respond using JSON matching this schema:\n\`\`\`json\n${schema}\n\`\`\``
].filter(t => !!t).join('\n')});
return code ? JSONAttemptParse(code, {}) : null;
let system = `Your job is to convert input to JSON. Call \`submit\` exactly once with JSON matching this schema:\n\`\`\`json\n${schema}\n\`\`\``;
if(options?.system) system += '\n\n' + options.system;
return new Promise(async (resolve, reject) => {
let done = false;
const resp = await this.ask(text, {
temperature: 0.3,
...options,
system,
tools: [{
name: 'submit',
description: 'Submit JSON',
args: {json: {type: 'string', description: 'Javascript parsable JSON string', required: true}},
fn: (args) => {
try {
const json = JSON.parse(args.json);
resolve(json);
done = true;
} catch { return 'Invalid JSON'; }
return 'Done';
}
}, ...(options?.tools || [])],
});
if(!done) reject(`AI failed to create summary: ${resp}`);
});
}
/**
@@ -371,8 +391,28 @@ class LLM {
* @param options LLM request options
* @returns {Promise<string>} Summary
*/
summarize(text: string, tokens: number = 500, options?: LLMRequest): Promise<string | null> {
return this.ask(text, {system: `Generate the shortest summary possible <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options});
async summarize(text: string, tokens: number = 500, options?: LLMRequest): Promise<string | null> {
let system = `Your job is to summarize the users message. Call \`submit\` exactly once with the shortest summary possible that's <= ${tokens} tokens. Output nothing else`;
if(options?.system) system += '\n\n' + options.system;
return new Promise(async (resolve, reject) => {
let done = false;
const resp = await this.ask(text, {
temperature: 0.3,
...options,
system,
tools: [{
name: 'submit',
description: 'Submit summary',
args: {summary: {type: 'string', description: 'Summarization', required: true}},
fn: (args) => {
done = true;
resolve(args.summary || null);
return 'Done';
}
}, ...(options?.tools || [])],
});
if(!done) reject(`AI failed to create summary: ${resp}`);
});
}
}