UNPKG

@langchain/community

Version:
341 lines (340 loc) 11.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseChatIflytekXinghuo = void 0; const messages_1 = require("@langchain/core/messages"); const env_1 = require("@langchain/core/utils/env"); const stream_1 = require("@langchain/core/utils/stream"); const chat_models_1 = require("@langchain/core/language_models/chat_models"); /** * Function that extracts the custom role of a generic chat message. * @param message Chat message from which to extract the custom role. * @returns The custom role of the chat message. */ function extractGenericMessageCustomRole(message) { if (message.role !== "assistant" && message.role !== "user") { console.warn(`Unknown message role: ${message.role}`); } return message.role; } /** * Function that converts a base message to a Xinghuo message role. * @param message Base message to convert. * @returns The Xinghuo message role. */ function messageToXinghuoRole(message) { const type = message._getType(); switch (type) { case "ai": return "assistant"; case "human": return "user"; case "system": throw new Error("System messages should not be here"); case "function": throw new Error("Function messages not supported"); case "generic": { if (!messages_1.ChatMessage.isInstance(message)) throw new Error("Invalid generic chat message"); return extractGenericMessageCustomRole(message); } default: throw new Error(`Unknown message type: ${type}`); } } /** * Wrapper around IflytekXingHuo large language models that use the Chat endpoint. * * To use you should have the `IFLYTEK_API_KEY` and `IFLYTEK_API_SECRET` and `IFLYTEK_APPID` * environment variable set. * * @augments BaseChatModel * @augments IflytekXinghuoChatInput */ class BaseChatIflytekXinghuo extends chat_models_1.BaseChatModel { static lc_name() { return "ChatIflytekXinghuo"; } get callKeys() { return ["stop", "signal", "options"]; } get lc_secrets() { return { iflytekApiKey: "IFLYTEK_API_KEY", iflytekApiSecret: "IFLYTEK_API_SECRET", }; } get lc_aliases() { return undefined; } constructor(fields) { super(fields ?? {}); Object.defineProperty(this, "lc_serializable", { enumerable: true, configurable: true, writable: true, value: true }); Object.defineProperty(this, "version", { enumerable: true, configurable: true, writable: true, value: "v2.1" }); Object.defineProperty(this, "iflytekAppid", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "iflytekApiKey", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "iflytekApiSecret", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "userId", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "apiUrl", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "domain", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "temperature", { enumerable: true, configurable: true, writable: true, value: 0.5 }); Object.defineProperty(this, "max_tokens", { enumerable: true, configurable: true, writable: true, value: 2048 }); Object.defineProperty(this, "top_k", { enumerable: true, configurable: true, writable: true, value: 4 }); Object.defineProperty(this, "streaming", { enumerable: true, configurable: true, writable: true, value: false }); const iflytekAppid = fields?.iflytekAppid ?? (0, env_1.getEnvironmentVariable)("IFLYTEK_APPID"); if (!iflytekAppid) { throw new Error("Iflytek APPID not found"); } else { this.iflytekAppid = iflytekAppid; } const iflytekApiKey = fields?.iflytekApiKey ?? (0, env_1.getEnvironmentVariable)("IFLYTEK_API_KEY"); if (!iflytekApiKey) { throw new Error("Iflytek API key not found"); } else { this.iflytekApiKey = iflytekApiKey; } const iflytekApiSecret = fields?.iflytekApiSecret ?? (0, env_1.getEnvironmentVariable)("IFLYTEK_API_SECRET"); if (!iflytekApiSecret) { throw new Error("Iflytek API secret not found"); } else { this.iflytekApiSecret = iflytekApiSecret; } this.userId = fields?.userId ?? this.userId; this.streaming = fields?.streaming ?? this.streaming; this.temperature = fields?.temperature ?? this.temperature; this.max_tokens = fields?.max_tokens ?? this.max_tokens; this.top_k = fields?.top_k ?? this.top_k; this.version = fields?.version ?? this.version; if (["v1.1", "v2.1", "v3.1"].includes(this.version)) { switch (this.version) { case "v1.1": this.domain = "general"; break; case "v2.1": this.domain = "generalv2"; break; case "v3.1": this.domain = "generalv3"; break; default: this.domain = "generalv2"; } this.apiUrl = `wss://spark-api.xf-yun.com/${this.version}/chat`; } else { throw new Error(`Invalid model version: ${this.version}`); } } /** * Get the identifying parameters for the model */ identifyingParams() { return { version: this.version, ...this.invocationParams(), }; } /** * Get the parameters used to invoke the model */ invocationParams() { return { streaming: this.streaming, temperature: this.temperature, top_k: this.top_k, }; } async completion(request, stream, signal) { const webSocketStream = await this.openWebSocketStream({ signal, }); const connection = await webSocketStream.connection; const header = { app_id: this.iflytekAppid, uid: this.userId, }; const parameter = { chat: { domain: this.domain, temperature: request.temperature ?? this.temperature, max_tokens: request.max_tokens ?? this.max_tokens, top_k: request.top_k ?? this.top_k, }, }; const payload = { message: { text: request.messages, }, }; const message = JSON.stringify({ header, parameter, payload, }); const { writable, readable } = connection; const writer = writable.getWriter(); await writer.write(message); const streams = stream_1.IterableReadableStream.fromReadableStream(readable); if (stream) { return streams; } else { let response = { result: "" }; for await (const chunk of streams) { const data = JSON.parse(chunk); const { header, payload } = data; if (header.code === 0) { if (header.status === 0) { response.result = payload.choices?.text[0]?.content ?? ""; } else if (header.status === 1) { response.result += payload.choices?.text[0]?.content ?? ""; } else if (header.status === 2) { response = { ...response, usage: payload.usage?.text }; break; } } else { break; } } void streams.cancel(); void webSocketStream.close(); return response; } } async _generate(messages, options, runManager) { const tokenUsage = {}; const params = this.invocationParams(); const messagesMapped = messages.map((message) => { if (typeof message.content !== "string") { throw new Error("ChatIflytekXinghuo does not support non-string message content."); } return { role: messageToXinghuoRole(message), content: message.content, }; }); const data = params.streaming ? await (async () => { const streams = await this.completion({ messages: messagesMapped, ...params }, true, options.signal); let response = { result: "" }; for await (const chunk of streams) { const data = JSON.parse(chunk); const { header, payload } = data; if (header.code === 0) { if (header.status === 0) { response.result = payload.choices?.text[0]?.content ?? ""; } else if (header.status === 1) { response.result += payload.choices?.text[0]?.content ?? ""; } else if (header.status === 2) { response = { ...response, usage: payload.usage?.text }; break; } void runManager?.handleLLMNewToken(payload.choices?.text[0]?.content); } else { break; } } void streams.cancel(); return response; })() : await this.completion({ messages: messagesMapped, ...params }, false, options.signal); const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, } = data.usage ?? {}; if (completionTokens) { tokenUsage.completionTokens = (tokenUsage.completionTokens ?? 0) + completionTokens; } if (promptTokens) { tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens; } if (totalTokens) { tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens; } const generations = []; const text = data.result ?? ""; generations.push({ text, message: new messages_1.AIMessage(text), }); return { generations, llmOutput: { tokenUsage }, }; } /** @ignore */ // eslint-disable-next-line @typescript-eslint/no-explicit-any _combineLLMOutput() { return []; } _llmType() { return "iflytek_xinghuo"; } } exports.BaseChatIflytekXinghuo = BaseChatIflytekXinghuo;