UNPKG

n8n-nodes-straico-chat

Version:

Adds a Straico Chat Model to use with n8n AI Agents and Chains.

165 lines (162 loc) 7.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StraicoChatModel = void 0; const chat_models_1 = require("@langchain/core/language_models/chat_models"); const messages_1 = require("@langchain/core/messages"); class StraicoChatModel extends chat_models_1.BaseChatModel { constructor(params) { var _a, _b; super(params); this.boundTools = []; this.apiKey = params.apiKey; this.baseURL = params.baseURL || 'https://api.straico.com/v0'; this.modelName = params.modelName; this.temperature = params.temperature; this.topP = params.topP; this.maxTokens = params.maxTokens; this.presencePenalty = params.presencePenalty; this.frequencyPenalty = params.frequencyPenalty; this.timeout = (_a = params.timeout) !== null && _a !== void 0 ? _a : 60000; this.maxRetries = (_b = params.maxRetries) !== null && _b !== void 0 ? _b : 2; this.callbacks = params.callbacks; this.onFailedAttempt = params.onFailedAttempt; console.log('Model Initialized:', { apiKey: '***', baseURL: this.baseURL, modelName: this.modelName }); } async _generate(messages, options) { var _a, _b, _c, _d; console.log('Generating with messages:', messages.map(m => m.content)); let allMessages = [...messages]; const hasSystemMessage = messages.some(msg => msg._getType() === 'system'); if (!hasSystemMessage) { const defaultSystemPrompt = new messages_1.SystemMessage({ content: "You are a friendly assistant.", }); allMessages.unshift(defaultSystemPrompt); } const url = `${this.baseURL}/prompt/completion`; const headers = { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }; const messageContent = allMessages .map((msg) => { if (msg._getType() === 'human') return msg.content; if (msg._getType() === 'ai') return `Assistant: ${msg.content}`; if (msg._getType() === 'system') return `System: ${msg.content}`; return ''; }) .filter((content) => content) .join('\n'); let toolCalls = []; let prompt = messageContent; if (this.boundTools.length > 0) { const toolsSchema = JSON.stringify(this.boundTools.map((tool) => ({ name: tool.name, description: tool.description, parameters: tool.schema, })), null, 2); prompt = ` ${messageContent} You are an AI assistant capable of calling tools. If the user request requires a tool, respond with a JSON object containing: - tool: The name of the tool to call - arguments: The arguments for the tool - content: Any additional text response (optional) Available tools: ${toolsSchema} Return the response in JSON format. `; } const smartLlmSelector = this.modelName.includes('claude') ? 'quality' : 'balance'; const body = { smart_llm_selector: smartLlmSelector, message: prompt, replace_failed_models: true, ...(this.temperature && { temperature: this.temperature }), ...(this.topP && { top_p: this.topP }), ...(this.maxTokens && { max_tokens: this.maxTokens }), ...(this.presencePenalty && { presence_penalty: this.presencePenalty }), ...(this.frequencyPenalty && { frequency_penalty: this.frequencyPenalty }), response_format: this.boundTools.length > 0 ? 'json' : 'text', }; let attempts = 0; while (attempts <= this.maxRetries) { try { const requestOptions = { method: 'POST', headers, body: JSON.stringify(body), signal: AbortSignal.timeout(this.timeout), }; const response = await fetch(url, requestOptions); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); } const data = await response.json(); console.log('Straico API Response:', data); let completion = ''; if (((_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.completion) === null || _b === void 0 ? void 0 : _b.choices) === null || _c === void 0 ? void 0 : _c.length) > 0) { const choice = data.data.completion.choices[0]; completion = ((_d = choice.message) === null || _d === void 0 ? void 0 : _d.content) || choice.text || ''; } else if ((data === null || data === void 0 ? void 0 : data.completion) || (data === null || data === void 0 ? void 0 : data.message) || (data === null || data === void 0 ? void 0 : data.text) || (data === null || data === void 0 ? void 0 : data.response) || (data === null || data === void 0 ? void 0 : data.result)) { completion = data.completion || data.message || data.text || data.response || data.result || ''; } else if (typeof data === 'string') { completion = data; } if (this.boundTools.length > 0) { try { const parsed = JSON.parse(completion); if (parsed.tool && parsed.arguments) { toolCalls = [ { name: parsed.tool, args: parsed.arguments, }, ]; completion = parsed.content || ''; } } catch (e) { console.log('Failed to parse tool call response as JSON:', e); } } console.log('Generated Completion:', completion); return { generations: [ { text: completion, message: new messages_1.AIMessage({ content: completion, additional_kwargs: toolCalls.length > 0 ? { tool_calls: toolCalls } : undefined, }), }, ], }; } catch (error) { console.log('Error in _generate:', error.message); if (this.onFailedAttempt) this.onFailedAttempt(error); attempts++; if (attempts > this.maxRetries) { throw new Error(`Failed after ${this.maxRetries} retries: ${error.message}`); } await new Promise((resolve) => setTimeout(resolve, 1000 * attempts)); } } throw new Error('Unexpected error in request handling'); } bindTools(tools) { this.boundTools = tools; return this; } _llmType() { return 'straico'; } } exports.StraicoChatModel = StraicoChatModel; //# sourceMappingURL=StraicoChatModel.js.map