Parla con i modelli linguistici con AIMODEL(), NEWAIMODEL() e AIPARSER()
total5 non spedisce una connessione a nessun provider. Ti dà tre pezzi che lavorano insieme:
NEWAIMODEL('name', config, driver)registra il driver di uno o più modelli ('a,b'registra lo stesso driver per due nomi). Il driver èfunction(ai, done):ai.payloadhamodel,messages,tools,promptethink,ai.configè la configurazione eai.options.streamè la funzione chiamante passato astream()(oundefined). Rispondi condone(error, response).AIMODEL('name')avvia una richiesta per un modello registrato e restituisce un costruttore.system(text),user(text)eassistant(text)aggiungono un messaggio,prompt(text),tool(definition)ethink()riempiono il resto del payload econfigure({ ... })aggiunge aai.configsolo per questa chiamata. Finiscilo concallback(fn),await promise($)ostream(fn); l'autista corre dietro alla svolta attuale, quindi puoi prima concatenare tutto.AIPARSER(provider)restituisce un parser per la risposta streamed di un provider (la fonte ditotal5conosceopenai,claude/anthropic,gemini/google,ollamaeopenai_responses, e legge qualsiasi altro nome come formato generico; di seguito viene eseguito soloopenai).write(chunk)prende pezzi del flusso (mantiene le righe incomplete fino al pezzo successivo),end()lo termina ed entrambi restituiscono{ content, thinking, tools, reasoning }.parser.on('content', fn)viene chiamato con ogni parte del testo man mano che arriva.
Un modello non registrato risponde con l'errore AI model not found.. L'esempio registra un driver locale che restituisce una risposta dai messaggi forniti.
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 });
}