ForgeTotal.js 5
nl

Total.js 5

Spreek naar taalmodellen met AIMODEL(), NEWAIMODELL() en AIPARSER()

Total.js 5 · total5@0.0.19 aillmintegrations Uitgevoerd met Total.js 5

total5 levert geen verbinding met een aanbieder mee. Het geeft je drie onderdelen die samenwerken:

  • NEWAIMODEL('name', config, driver) registreert de driver van een of meer modellen ('a,b' registreert dezelfde driver voor twee namen). De driver is function(ai, done): ai.payload heeft model, messages, tools, prompt en think, ai.config is de configuratie en ai.options.stream is de functie die de aanroeper aan stream() heeft doorgegeven (of undefined). Antwoord met done(error, response).
  • AIMODEL('name') start een verzoek voor een geregistreerd model en geeft een builder terug. system(text), user(text) en assistant(text) voegen een bericht toe, prompt(text), tool(definition) en think() vullen de rest van de payload en configure({ ... }) voegt alleen voor deze aanroep toe aan ai.config. Sluit het af met callback(fn), await promise($) of stream(fn); de driver draait na de huidige beurt, dus je kunt eerst alles koppelen.
  • AIPARSER(provider) geeft een parser terug voor het gestreamde antwoord van een aanbieder (de broncode van total5 kent openai, claude/anthropic, gemini/google, ollama en openai_responses en leest elke andere naam als een generiek formaat; hieronder wordt alleen openai uitgevoerd). write(chunk) neemt stukken van de stream aan (onvolledige regels houdt hij vast tot het volgende stuk), end() rondt hem af, en beide geven { content, thinking, tools, reasoning } terug. parser.on('content', fn) wordt aangeroepen met elk deel van de tekst zodra het binnenkomt.

Een model dat niet is geregistreerd antwoorden met de fout AI model not found.. Het voorbeeld registreert een lokale chauffeur die een reactie van de geleverde berichten teruggeeft.

definitions/ai.js
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 });
});
controllers/ai.js
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 });
}