Compare commits

..

2 Commits

Author SHA1 Message Date
596e99daa7 Use word count for summary (more predictable)
All checks were successful
Publish Library / Build NPM Project (push) Successful in 55s
Publish Library / Tag Version (push) Successful in 33s
2026-03-26 13:10:46 -04:00
eda4eed87d Added JSON / Summary LLM safeguard
All checks were successful
Publish Library / Build NPM Project (push) Successful in 41s
Publish Library / Tag Version (push) Successful in 21s
2026-03-26 12:50:52 -04:00
2 changed files with 12 additions and 9 deletions

View File

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

View File

@@ -358,7 +358,7 @@ class LLM {
* @returns {Promise<{} | {} | RegExpExecArray | null>}
*/
async json(text: string, schema: string, options?: LLMRequest): Promise<any> {
let system = `Your job is to convert input to JSON. Call the \`submit\` tool exactly once with JSON matching this schema:\n\`\`\`json\n${schema}\n\`\`\``;
let system = `Your job is to convert input to JSON using tool calls. Call the \`submit\` tool at least once with JSON matching this schema:\n\`\`\`json\n${schema}\n\`\`\`\n\nResponses are ignored`;
if(options?.system) system += '\n\n' + options.system;
return new Promise(async (resolve, reject) => {
let done = false;
@@ -376,23 +376,23 @@ class LLM {
resolve(json);
done = true;
} catch { return 'Invalid JSON'; }
return 'Done';
return 'Saved';
}
}, ...(options?.tools || [])],
});
if(!done) reject(`AI failed to create summary: ${resp}`);
if(!done) reject(`AI failed to create JSON:\n${resp}`);
});
}
/**
* Create a summary of some text
* @param {string} text Text to summarize
* @param {number} tokens Max number of tokens
* @param {number} length Max number of words
* @param options LLM request options
* @returns {Promise<string>} Summary
*/
async summarize(text: string, tokens: number = 500, options?: LLMRequest): Promise<string | null> {
let system = `Your job is to summarize the users message. Call the \`submit\` tool exactly once with the shortest summary possible that's <= ${tokens} tokens. Output nothing else`;
async summarize(text: string, length: number = 500, options?: LLMRequest): Promise<string | null> {
let system = `Your job is to summarize the users message using tool calls. Call the \`submit\` tool at least once with the shortest summary possible that's <= ${length} words. The tool call will respond with the token count. Responses are ignored`;
if(options?.system) system += '\n\n' + options.system;
return new Promise(async (resolve, reject) => {
let done = false;
@@ -405,13 +405,16 @@ class LLM {
description: 'Submit summary',
args: {summary: {type: 'string', description: 'Text summarization', required: true}},
fn: (args) => {
if(!args.summary) return 'No summary provided';
const count = args.summary.split(' ').length;
if(count > length) return `Too long: ${length} words`;
done = true;
resolve(args.summary || null);
return 'Done';
return `Saved: ${length} words`;
}
}, ...(options?.tools || [])],
});
if(!done) reject(`AI failed to create summary: ${resp}`);
if(!done) reject(`AI failed to create summary:\n${resp}`);
});
}
}