ForgeTotal.js 5
hu

Total.js 5

Beszélgetés nyelvi modellekkel AIMODEL(), NEWAIMODel() és AIPARSER()

Total.js 5 · total5@0.0.19 aillmintegrations Total.js 5-tel lefuttatva

A total5 nem tartalmaz kapcsolatot egyetlen szolgáltatóhoz sem. Három, együtt működő elemet ad:

  • A NEWAIMODEL('name', config, driver) egy vagy több modell driverét regisztrálja (az 'a,b' ugyanazt a drivert regisztrálja két névhez). A driver function(ai, done): az ai.payload tartalmazza a model, messages, tools, prompt és think értékeket, az ai.config a konfiguráció, az ai.options.stream pedig az a függvény, amelyet a hívó a stream()-nek átadott (vagy undefined). Válaszoljon a done(error, response) hívással.
  • Az AIMODEL('name') kérést indít egy regisztrált modellhez, és buildert ad vissza. A system(text), user(text) és assistant(text) üzenetet fűz hozzá, a prompt(text), tool(definition) és think() kitölti a payload többi részét, a configure({ ... }) pedig csak erre a hívásra egészíti ki az ai.config-ot. Fejezze be a callback(fn), az await promise($) vagy a stream(fn) hívással; a driver az aktuális kör után fut, így előbb mindent láncba fűzhet.
  • Az AIPARSER(provider) egy szolgáltató streamelt válaszához ad vissza parsert (a total5 forrása ismeri az openai, claude/anthropic, gemini/google, ollama és openai_responses neveket, minden más nevet általános formátumként olvas; lent csak az openai fut). A write(chunk) a stream darabjait fogadja (a befejezetlen sorokat a következő darabig megtartja), az end() lezárja, és mindkettő { content, thinking, tools, reasoning } értéket ad vissza. A parser.on('content', fn) a szöveg minden részével meghívódik, ahogy megérkezik.

A modell nem regisztrált válaszokat a hiba AI model not found.. Az alábbi példa egy helyi vezetőt regisztrál, aki visszaküldi a válaszot az adott üzenetből.

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 });
}