UNPKG

aichat-core

Version:

AI 流式聊天业务核心TS模型封装及业务实现模块

498 lines (497 loc) 26.4 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; import OpenAI from "openai"; import McpClient from "./McpClient"; var LLMClient = (function () { function LLMClient(mcpServer, mcpClientName, apiKey, baseUrl, modelName) { if (mcpServer === void 0) { mcpServer = ""; } if (mcpClientName === void 0) { mcpClientName = ""; } this.mcpServer = ""; this.tools = []; this.initMcpState = false; this.thinkState = false; this.logDebug = false; this.llm = new OpenAI({ apiKey: apiKey, baseURL: baseUrl, dangerouslyAllowBrowser: true, }); this.modelName = modelName; this.toolChoice = "auto"; if (mcpServer !== "") { this.mcpServer = mcpServer; this.mcpClient = new McpClient(mcpClientName); } } LLMClient.prototype.initMcpServer = function () { return __awaiter(this, void 0, void 0, function () { var _a, error_1; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!this.mcpClient) { return [2]; } _b.label = 1; case 1: _b.trys.push([1, 4, , 5]); return [4, this.mcpClient.connect2Server(this.mcpServer)]; case 2: _b.sent(); console.log("=====================1.连接mcp服务成功"); _a = this; return [4, this.mcpClient.getTools()]; case 3: _a.tools = _b.sent(); console.log("=====================2.获取mcp工具列表成功,共:" + this.tools.length); this.initMcpState = true; return [3, 5]; case 4: error_1 = _b.sent(); this.tools = []; return [3, 5]; case 5: return [2]; } }); }); }; LLMClient.prototype.chatStreamLLMV2 = function (messages_1, onContentCallBack_1, onCallToolsCallBack_1, onCallToolResultCallBack_1, callBackMessage_1, controllerRef_1) { return __awaiter(this, arguments, void 0, function (messages, onContentCallBack, onCallToolsCallBack, onCallToolResultCallBack, callBackMessage, controllerRef, loop) { var stream, _toolCalls, _a, stream_1, stream_1_1, chunk, usage, _choices, _choiceMessage, newCallBackMessage, finishReason, _choiceMessage, newCallBackMessage, toolCalls, _choices, _choiceMessage, newCallBackMessage, choices, e_1_1; var _b, e_1, _c, _d; var _e; if (loop === void 0) { loop = 1; } return __generator(this, function (_f) { switch (_f.label) { case 0: console.log("=====================\u5F00\u59CB\u7B2C".concat(loop, "\u8F6E\u804A\u5929")); return [4, this.genLLMStream(messages, controllerRef)]; case 1: stream = _f.sent(); if (!(stream && typeof stream[Symbol.asyncIterator] === LLMClient.TYPE_FUNCTION)) return [3, 18]; _toolCalls = []; _f.label = 2; case 2: _f.trys.push([2, 11, 12, 17]); _a = true, stream_1 = __asyncValues(stream); _f.label = 3; case 3: return [4, stream_1.next()]; case 4: if (!(stream_1_1 = _f.sent(), _b = stream_1_1.done, !_b)) return [3, 10]; _d = stream_1_1.value; _a = false; chunk = _d; if (this.logDebug) { console.log("chunk", chunk); } callBackMessage.timed = chunk.created; callBackMessage.model = chunk.model; usage = chunk.usage; if (usage) { console.log("=====================\u7B2C".concat(loop, "\u8F6E\u6D41\u5F0F\u804A\u5929\u7ED3\u675F\uFF0Cusage : "), usage); _choices = callBackMessage.choices; if (_choices && _choices.length > 0) { _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); _choiceMessage.index = loop; _choiceMessage.thinking = 2; _choiceMessage.reasoning_content = ""; _choiceMessage.content = ""; _choiceMessage.usage = { completion_tokens: usage.completion_tokens, prompt_tokens: usage.prompt_tokens, total_tokens: usage.total_tokens, }; newCallBackMessage = JSON.parse(JSON.stringify(callBackMessage)); onContentCallBack(newCallBackMessage); } return [3, 9]; } finishReason = (_e = chunk.choices[0].finish_reason) !== null && _e !== void 0 ? _e : ""; if (!(finishReason !== "")) return [3, 6]; return [4, this.dealFinishReason(finishReason, _toolCalls, messages, onContentCallBack, onCallToolsCallBack, onCallToolResultCallBack, callBackMessage, controllerRef, loop)]; case 5: _f.sent(); _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); _choiceMessage.content = ""; _choiceMessage.reasoning_content = ""; callBackMessage.finishReason = finishReason; newCallBackMessage = JSON.parse(JSON.stringify(callBackMessage)); onContentCallBack(newCallBackMessage); return [3, 9]; case 6: toolCalls = chunk.choices[0].delta.tool_calls; if (!(toolCalls && toolCalls.length > 0)) return [3, 7]; _choices = callBackMessage.choices; if (_choices && _choices.length > 0) { _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); if (!_choiceMessage.toolsCallDes) { _choiceMessage.toolsCallDes = LLMClient.TOOLS_CALLING_DESC; _choiceMessage.content = ""; _choiceMessage.reasoning_content = ""; newCallBackMessage = JSON.parse(JSON.stringify(callBackMessage)); onContentCallBack(newCallBackMessage); } } this.dealToolCalls(toolCalls, _toolCalls); return [3, 9]; case 7: choices = chunk.choices; return [4, this.dealTextContent(choices, onContentCallBack, callBackMessage, loop)]; case 8: _f.sent(); _f.label = 9; case 9: _a = true; return [3, 3]; case 10: return [3, 17]; case 11: e_1_1 = _f.sent(); e_1 = { error: e_1_1 }; return [3, 17]; case 12: _f.trys.push([12, , 15, 16]); if (!(!_a && !_b && (_c = stream_1.return))) return [3, 14]; return [4, _c.call(stream_1)]; case 13: _f.sent(); _f.label = 14; case 14: return [3, 16]; case 15: if (e_1) throw e_1.error; return [7]; case 16: return [7]; case 17: return [3, 19]; case 18: console.error("Stream is not async iterable."); _f.label = 19; case 19: return [2]; } }); }); }; LLMClient.prototype.genLLMStream = function (messages, controllerRef) { return __awaiter(this, void 0, void 0, function () { var stream, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!(!this.tools || this.tools.length == 0)) return [3, 2]; return [4, this.llm.chat.completions.create({ model: this.modelName, messages: messages, stream: true, temperature: 0.0, }, { signal: controllerRef && controllerRef.signal, })]; case 1: _a = _b.sent(); return [3, 4]; case 2: return [4, this.llm.chat.completions.create({ model: this.modelName, messages: messages, tools: this.convert2OpenAiTools(this.tools), stream: true, temperature: 0.0, tool_choice: this.toolChoice, }, { signal: controllerRef && controllerRef.signal, })]; case 3: _a = _b.sent(); _b.label = 4; case 4: stream = _a; return [2, stream]; } }); }); }; LLMClient.prototype.filterChoiceMessage = function (callBackMessage, index) { var _a; var _choices = (_a = callBackMessage.choices) !== null && _a !== void 0 ? _a : []; if (_choices && _choices.length > 0) { var _choiceMessages = _choices.filter(function (item) { return item.index === index; }); if (_choiceMessages && _choiceMessages.length > 0) { return _choiceMessages[0]; } } var initChoiceMessage = { index: index, content: "", }; _choices.push(initChoiceMessage); return initChoiceMessage; }; LLMClient.prototype.dealFinishReason = function (finishReason_1, toolCalls_1, messages_1, onContentCallBack_1, onCallToolsCallBack_1, onCallToolResultCallBack_1, callBackMessage_1, controllerRef_1) { return __awaiter(this, arguments, void 0, function (finishReason, toolCalls, messages, onContentCallBack, onCallToolsCallBack, onCallToolResultCallBack, callBackMessage, controllerRef, loop) { var _choiceMessage, bSuccess; if (loop === void 0) { loop = 0; } return __generator(this, function (_a) { switch (_a.label) { case 0: if (!(finishReason === LLMClient.REASON_STOP)) return [3, 1]; console.log("=====================\u7B2C".concat(loop, "\u8F6E\u6D41\u5F0F\u804A\u5929\u7ED3\u675F\uFF0C\u7ED3\u675F\u539F\u56E0(\u8FD9\u4E2A\u65F6\u5019\u9700\u8981\u4E00\u4E2A\u56DE\u8C03)\uFF1A").concat(finishReason)); return [3, 5]; case 1: if (!(finishReason === LLMClient.REASON_TOO_CALLS)) return [3, 5]; console.log("=====================\u7B2C".concat(loop, "\u8F6E\u9009\u53D6\u5DE5\u5177\u7ED3\u675F\uFF0C\u7ED3\u675F\u539F\u56E0(\u8FD9\u4E2A\u65F6\u5019\u9700\u8981\u6267\u884C\u5DE5\u5177):").concat(finishReason)); console.log("=====================\u7B2C".concat(loop, "\u8F6E\u5DE5\u5177\u8BE6\u60C5\uFF1A"), toolCalls); if (!(toolCalls && toolCalls.length > 0)) return [3, 5]; _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); _choiceMessage.content = ""; _choiceMessage.reasoning_content = ""; onCallToolsCallBack && onCallToolsCallBack(toolCalls); return [4, this.reBuildMessages(toolCalls, messages, onCallToolResultCallBack, callBackMessage, loop)]; case 2: bSuccess = _a.sent(); if (!bSuccess) return [3, 4]; console.log("\u7B2C".concat(loop, "\u8F6E\u5BF9\u8BDD\u7ED3\u675F\uFF0C\u6D88\u606F\u4E0A\u4E0B\u6587\uFF1A"), messages); loop++; _choiceMessage.toolsCallDes = LLMClient.TOOLS_CALLED_DESC; return [4, this.chatStreamLLMV2(messages, onContentCallBack, onCallToolsCallBack, onCallToolResultCallBack, callBackMessage, controllerRef, loop)]; case 3: _a.sent(); return [3, 5]; case 4: throw new Error("执行工具调用构建messages异常,请排查!"); case 5: return [2]; } }); }); }; LLMClient.prototype.reBuildMessages = function (toolCalls_1, messages_1, onCallToolResultCallBack_1, callBackMessage_1) { return __awaiter(this, arguments, void 0, function (toolCalls, messages, onCallToolResultCallBack, callBackMessage, loop) { var _toolCalls, index, _i, toolCalls_2, toolCall, toolCalls_3, assistantMessage, methodName, methodArgs, callResult, toolMessage, _choiceMessage, error_2; var _a, _b, _c, _d, _e, _f, _g, _h, _j; if (loop === void 0) { loop = 0; } return __generator(this, function (_k) { switch (_k.label) { case 0: if (!this.mcpClient) { return [2, false]; } _k.label = 1; case 1: _k.trys.push([1, 6, , 7]); _toolCalls = []; index = 0; _i = 0, toolCalls_2 = toolCalls; _k.label = 2; case 2: if (!(_i < toolCalls_2.length)) return [3, 5]; toolCall = toolCalls_2[_i]; toolCalls_3 = []; toolCalls_3.push(this.buildMessageToolCall(toolCall)); assistantMessage = { role: LLMClient.ROLE_AI, tool_calls: toolCalls_3, }; messages.push(assistantMessage); methodName = (_b = (_a = toolCall.function) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : ""; methodArgs = (_d = (_c = toolCall.function) === null || _c === void 0 ? void 0 : _c.arguments) !== null && _d !== void 0 ? _d : "{}"; return [4, this.mcpClient.callTool({ id: (_e = toolCall.id) !== null && _e !== void 0 ? _e : "", function: { name: methodName, arguments: methodArgs, }, type: (_f = toolCall.type) !== null && _f !== void 0 ? _f : LLMClient.TYPE_FUNCTION, })]; case 3: callResult = _k.sent(); if (this.logDebug) { console.log("".concat(methodName, "-callResult: ") + callResult); } onCallToolResultCallBack(methodName, callResult); toolMessage = { content: callResult, role: LLMClient.ROLE_TOOL, tool_call_id: (_g = toolCall.id) !== null && _g !== void 0 ? _g : "", }; messages.push(toolMessage); _toolCalls.push({ id: (_h = toolCall.id) !== null && _h !== void 0 ? _h : "", index: (_j = toolCall.index) !== null && _j !== void 0 ? _j : index, name: methodName, arguments: methodArgs, content: callResult, }); index++; _k.label = 4; case 4: _i++; return [3, 2]; case 5: _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); _choiceMessage.tools = _toolCalls; return [2, true]; case 6: error_2 = _k.sent(); console.log("error : " + error_2); return [2, false]; case 7: return [2]; } }); }); }; LLMClient.prototype.buildMessageToolCall = function (toolCall) { var _a, _b, _c, _d, _e, _f; return { id: (_a = toolCall.id) !== null && _a !== void 0 ? _a : "", type: (_b = toolCall.type) !== null && _b !== void 0 ? _b : "function", function: { name: (_d = (_c = toolCall.function) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "", arguments: (_f = (_e = toolCall.function) === null || _e === void 0 ? void 0 : _e.arguments) !== null && _f !== void 0 ? _f : "", }, }; }; LLMClient.prototype.dealToolCalls = function (toolCalls, finalToolCalls) { for (var i = 0; i < toolCalls.length; i++) { var toolCall = toolCalls[i]; var index = toolCall.index; if (finalToolCalls.length < index + 1) { finalToolCalls.push(toolCall); } else { var tool = finalToolCalls[index]; if (tool.function && toolCall.function && typeof toolCall.function.arguments === "string") { tool.function.arguments += toolCall.function.arguments; } } } }; LLMClient.prototype.dealTextContent = function (choices_1, onContentCallBack_1, callBackMessage_1) { return __awaiter(this, arguments, void 0, function (choices, onContentCallBack, callBackMessage, loop) { var delta, _choiceMessage, content, newCallBackMessage; if (loop === void 0) { loop = 0; } return __generator(this, function (_a) { if (choices && choices.length > 0) { delta = choices[0].delta; if (!delta) { return [2]; } _choiceMessage = this.filterChoiceMessage(callBackMessage, loop); if (delta.reasoning_content) { _choiceMessage.thinking = 1; _choiceMessage.reasoning_content = delta.reasoning_content; } if (delta.content) { content = delta.content; if (content.startsWith(LLMClient.THINGKING_START_TAG)) { this.thinkState = true; return [2]; } else if (content.endsWith(LLMClient.THINGKING_END_TAG)) { this.thinkState = false; return [2]; } if (this.thinkState) { _choiceMessage.thinking = 1; _choiceMessage.reasoning_content = content; } else { _choiceMessage.thinking = 2; _choiceMessage.content = content; _choiceMessage.reasoning_content = ""; } } newCallBackMessage = JSON.parse(JSON.stringify(callBackMessage)); onContentCallBack(newCallBackMessage); } return [2]; }); }); }; LLMClient.prototype.listTools = function () { return this.tools; }; LLMClient.prototype.convert2OpenAiTools = function (tools) { if (!tools || tools.length == 0) { return []; } var openAiTools = []; for (var i = 0; i < tools.length; i++) { openAiTools.push({ type: LLMClient.TYPE_FUNCTION, function: { name: tools[i].name, description: tools[i].description, parameters: tools[i].input_schema, }, }); } return openAiTools; }; LLMClient.prototype.getLogDebug = function () { return this.logDebug; }; LLMClient.prototype.setLogDebug = function (logDebug) { if (logDebug === void 0) { logDebug = false; } this.logDebug = logDebug; }; LLMClient.prototype.getToolChoice = function () { return this.toolChoice; }; LLMClient.prototype.setToolChoice = function (toolChoice) { this.toolChoice = toolChoice; }; LLMClient.CONTENT_THINKING = "thinking"; LLMClient.TYPE_FUNCTION = "function"; LLMClient.TYPE_STRING = "string"; LLMClient.REASON_STOP = "stop"; LLMClient.REASON_TOO_CALLS = "tool_calls"; LLMClient.ROLE_AI = "assistant"; LLMClient.ROLE_SYSTEM = "system"; LLMClient.ROLE_USER = "user"; LLMClient.ROLE_TOOL = "tool"; LLMClient.THINGKING_START_TAG = "<think>"; LLMClient.THINGKING_END_TAG = "</think>"; LLMClient.TOOLS_CALLING_DESC = "工具正在调用的路上,请稍等..."; LLMClient.TOOLS_CALLED_DESC = "工具调用已完成,结果如下:"; return LLMClient; }()); export default LLMClient;