Talk till språkmodeller med AIMODEL(), NEWAIMODELL() och AIPARSER()
total5 levererar ingen anslutning till någon leverantör. Det ger dig tre delar som fungerar tillsammans:
NEWAIMODEL('name', config, driver)registrerar drivrutinen för en eller flera modeller ('a,b'registrerar samma drivrutin för två namn). Drivrutinen ärfunction(ai, done):ai.payloadharmodel,messages,tools,promptochthink,ai.configär konfigurationen ochai.options.streamär funktionen som anroparen skickade tillstream()(ellerundefined). Svara meddone(error, response).AIMODEL('name')startar en förfrågan för en registrerad modell och returnerar en builder.system(text),user(text)ochassistant(text)lägger till ett meddelande,prompt(text),tool(definition)ochthink()fyller i resten av payloaden, ochconfigure({ ... })lägger till iai.configbara för det här anropet. Avsluta den medcallback(fn),await promise($)ellerstream(fn); drivrutinen körs efter den aktuella omgången, så du kan kedja ihop allt först.AIPARSER(provider)returnerar en parser för strömmat svar från en leverantör (källkoden itotal5känner tillopenai,claude/anthropic,gemini/google,ollamaochopenai_responses, och läser alla andra namn som ett generiskt format; nedan körs baraopenai).write(chunk)tar emot bitar av strömmen (den behåller ofullständiga rader till nästa bit),end()avslutar den, och båda returnerar{ content, thinking, tools, reasoning }.parser.on('content', fn)anropas med varje del av texten allteftersom den kommer.
En modell som inte har registrerats svar med felet AI model not found.. Exemplet registrerar en lokal förare som returnerar ett svar från de levererade meddelandena.
NEWAIMODEL('echo', { prefix: 'Echo' }, function(ai, done) {
const last = ai.payload.messages.filter(n => n.role === 'user').pop();
const text = ai.config.prefix + ': ' + (last ? last.content : '');
// A real driver would send ai.payload to the provider and send the pieces to ai.options.stream
if (ai.options.stream) {
for (const word of text.split(' '))
ai.options.stream(word + ' ');
}
done(null, { content: text, roles: ai.payload.messages.map(n => n.role), tools: ai.payload.tools.length, think: !!ai.payload.think });
});exports.install = function() {
ROUTE('POST /ask/', ask);
ROUTE('GET /ask-config/', askconfig);
ROUTE('GET /ask-stream/', askstream);
ROUTE('GET /ask-missing/', missing);
ROUTE('GET /parse/', parse);
};
async function ask($) {
const response = await AIMODEL('echo').system('You are brief.').user($.body.question).tool({ name: 'weather' }).think().promise($);
$.json(response);
}
function askconfig($) {
AIMODEL('echo').user('hello').configure({ prefix: 'Custom' }).callback($.callback());
}
function askstream($) {
const parts = [];
AIMODEL('echo').user('one two three').stream(part => parts.push(part)).callback(function(err, response) {
$.json({ parts: parts, content: response.content });
});
}
function missing($) {
AIMODEL('nobody').user('hi').callback($.callback());
}
function parse($) {
const parser = AIPARSER('openai');
const events = [];
parser.on('content', e => events.push(e.delta));
// the second piece starts in the middle of a line
parser.write('data: {"choices":[{"delta":{"content":"Hel"}}]}\n\ndata: {"choices":[{"delta":{"con');
parser.write('tent":"lo"}}]}\n\ndata: [DONE]\n');
const output = parser.end();
$.json({ output: output, events: events });
}