ForgeTotal.js 5
de

Total.js 5

Sprechen Sie mit Sprachmodellen mit AIMODEL(), NEWAIMODEL() und AIPARSER()

Total.js 5 · total5@0.0.19 aillmintegrations Mit Total.js 5 ausgeführt

total5 liefert keine Verbindung zu einem Anbieter mit. Es gibt dir drei Bausteine, die zusammenarbeiten:

  • NEWAIMODEL('name', config, driver) registriert den Treiber eines oder mehrerer Modelle ('a,b' registriert denselben Treiber für zwei Namen). Der Treiber ist function(ai, done): ai.payload hat model, messages, tools, prompt und think, ai.config ist die Konfiguration und ai.options.stream ist die Funktion, die der Aufrufer an stream() übergeben hat (oder undefined). Antworte mit done(error, response).
  • AIMODEL('name') startet eine Anfrage für ein registriertes Modell und gibt einen Builder zurück. system(text), user(text) und assistant(text) hängen eine Nachricht an, prompt(text), tool(definition) und think() füllen den Rest des Payloads, und configure({ ... }) ergänzt ai.config nur für diesen Aufruf. Schließe ihn mit callback(fn), await promise($) oder stream(fn) ab; der Treiber läuft nach dem aktuellen Durchlauf, du kannst also zuerst alles verketten.
  • AIPARSER(provider) gibt einen Parser für die gestreamte Antwort eines Anbieters zurück (der Quellcode von total5 kennt openai, claude/anthropic, gemini/google, ollama und openai_responses und liest jeden anderen Namen als generisches Format; unten wird nur openai ausgeführt). write(chunk) nimmt Teile des Streams entgegen (unvollständige Zeilen werden bis zum nächsten Teil behalten), end() beendet ihn, und beide geben { content, thinking, tools, reasoning } zurück. parser.on('content', fn) wird mit jedem Teil des Textes aufgerufen, sobald er eintrifft.

Ein Modell, das keine registrierten Antworten mit dem Fehler AI model not found.. Das Beispiel registriert einen lokalen Fahrer, der eine Antwort aus den versorgten Nachrichten zurückgibt.

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