UNPKG

@langchain/community

Version:
1 lines 55.3 kB
{"version":3,"file":"alibaba_tongyi.cjs","names":["AIMessage","convertLangChainToolCallToOpenAI","ChatMessage","BaseChatModel","RunnableLambda","RunnablePassthrough","RunnableSequence","ChatGenerationChunk","AIMessageChunk","IterableReadableStream"],"sources":["../../src/chat_models/alibaba_tongyi.ts"],"sourcesContent":["import { type CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport {\n BaseChatModel,\n BaseChatModelCallOptions,\n BindToolsInput,\n type BaseChatModelParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n AIMessage,\n type BaseMessage,\n ChatMessage,\n AIMessageChunk,\n type OpenAIToolCall,\n type UsageMetadata,\n type ToolMessage,\n} from \"@langchain/core/messages\";\nimport { type ChatResult } from \"@langchain/core/outputs\";\nimport { ChatGenerationChunk } from \"@langchain/core/outputs\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport {\n convertLangChainToolCallToOpenAI,\n makeInvalidToolCall,\n parseToolCall,\n} from \"@langchain/core/output_parsers/openai_tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n BaseLanguageModelInput,\n StructuredOutputMethodOptions,\n ToolDefinition,\n} from \"@langchain/core/language_models/base\";\nimport { type ToolCallChunk } from \"@langchain/core/messages/tool\";\nimport {\n Runnable,\n RunnableLambda,\n RunnablePassthrough,\n RunnableSequence,\n} from \"@langchain/core/runnables\";\nimport {\n getSchemaDescription,\n InteropZodType,\n isInteropZodSchema,\n} from \"@langchain/core/utils/types\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\n\n/**\n * Type representing the role of a message in the Tongyi chat model.\n */\nexport type TongyiMessageRole = \"system\" | \"assistant\" | \"user\" | \"tool\";\n\n/**\n * Interface representing a message in the Tongyi chat model.\n */\ninterface TongyiToolCall {\n id?: string;\n type?: string;\n index?: number;\n function?: {\n name?: string;\n arguments?: string | Record<string, unknown>;\n };\n}\n\ninterface TongyiMessage {\n role: TongyiMessageRole;\n content: string;\n tool_call_id?: string;\n tool_calls?: TongyiToolCall[];\n}\n\ntype TongyiFinishReason = \"stop\" | \"tool_calls\" | \"length\" | \"null\" | null;\ntype TongyiToolChoice =\n | \"auto\"\n | \"none\"\n | {\n type: \"function\";\n function: {\n name: string;\n };\n };\n\ninterface TongyiChoiceMessage {\n role?: string;\n content?: string | null;\n tool_calls?: TongyiToolCall[] | null;\n}\n\ninterface TongyiResponseChoice {\n index?: number;\n finish_reason?: TongyiFinishReason;\n message?: TongyiChoiceMessage;\n delta?: TongyiChoiceMessage;\n tool_calls?: TongyiToolCall[];\n}\n\n/**\n * Interface representing a request for a chat completion.\n *\n * See https://help.aliyun.com/zh/dashscope/developer-reference/model-square/\n */\ninterface ChatCompletionRequest {\n model:\n | (string & NonNullable<unknown>)\n | \"qwen-turbo\"\n | \"qwen-plus\"\n | \"qwen-max\"\n | \"qwen-max-1201\"\n | \"qwen-max-longcontext\"\n // 通义千问开源系列\n | \"qwen-7b-chat\"\n | \"qwen-14b-chat\"\n | \"qwen-72b-chat\"\n // LLAMA2\n | \"llama2-7b-chat-v2\"\n | \"llama2-13b-chat-v2\"\n // 百川\n | \"baichuan-7b-v1\"\n | \"baichuan2-13b-chat-v1\"\n | \"baichuan2-7b-chat-v1\"\n // ChatGLM\n | \"chatglm3-6b\"\n | \"chatglm-6b-v2\";\n input: {\n messages: TongyiMessage[];\n };\n parameters: {\n stream?: boolean;\n result_format?: \"text\" | \"message\";\n seed?: number | null;\n max_tokens?: number | null;\n top_p?: number | null;\n top_k?: number | null;\n repetition_penalty?: number | null;\n temperature?: number | null;\n enable_search?: boolean | null;\n incremental_output?: boolean | null;\n parallel_tool_calls?: boolean | null;\n tools?: ToolDefinition[];\n tool_choice?: TongyiToolChoice;\n };\n}\n\n/**\n * Interface representing a response from a chat completion.\n */\ninterface ChatCompletionResponse {\n code?: string;\n message?: string;\n request_id?: string;\n requestId?: string;\n usage?: {\n output_tokens: number;\n input_tokens: number;\n total_tokens: number;\n };\n output?: {\n text?: string;\n finish_reason?: TongyiFinishReason;\n choices?: TongyiResponseChoice[];\n };\n}\n\nexport interface ChatAlibabaTongyiCallOptions extends BaseChatModelCallOptions {\n tools?: BindToolsInput[];\n parallel_tool_calls?: boolean;\n parallelToolCalls?: boolean;\n}\n\n/**\n * Interface defining the input to the ChatAlibabaTongyi class.\n */\ninterface AlibabaTongyiChatInput {\n /**\n * Model name to use. Available options are: qwen-turbo, qwen-plus, qwen-max, or Other compatible models.\n * Alias for `model`\n * @default \"qwen-turbo\"\n */\n modelName: string;\n\n /** Model name to use. Available options are: qwen-turbo, qwen-plus, qwen-max, or Other compatible models.\n * @default \"qwen-turbo\"\n */\n model: string;\n\n /** Whether to stream the results or not. Defaults to false. */\n streaming?: boolean;\n\n /** Messages to pass as a prefix to the prompt */\n prefixMessages?: TongyiMessage[];\n\n /**\n * API key to use when making requests. Defaults to the value of\n * `ALIBABA_API_KEY` environment variable.\n */\n alibabaApiKey?: string;\n\n /**\n * Region for the Alibaba Tongyi API endpoint.\n *\n * Available base URLs (used with `/api/v1/services/aigc/text-generation/generation`):\n * - 'china' (default): https://dashscope.aliyuncs.com/\n * - 'singapore': https://dashscope-intl.aliyuncs.com/\n * - 'us': https://dashscope-us.aliyuncs.com/\n *\n * @default \"china\"\n */\n region?: \"china\" | \"singapore\" | \"us\";\n\n /** Amount of randomness injected into the response. Ranges\n * from 0 to 1 (0 is not included). Use temp closer to 0 for analytical /\n * multiple choice, and temp closer to 1 for creative\n * and generative tasks. Defaults to 0.95.\n */\n temperature?: number;\n\n /** Total probability mass of tokens to consider at each step. Range\n * from 0 to 1.0. Defaults to 0.8.\n */\n topP?: number;\n\n topK?: number;\n\n enableSearch?: boolean;\n\n maxTokens?: number;\n\n seed?: number;\n\n /** Penalizes repeated tokens according to frequency. Range\n * from 1.0 to 2.0. Defaults to 1.0.\n */\n repetitionPenalty?: number;\n\n /** Experimental passthrough to allow parallel tool calls. */\n parallelToolCalls?: boolean;\n\n /** Custom API URL. Overrides auto-detected URL based on region and model type.\n * If not provided, text models use the text-generation endpoint and\n * VL (vision-language) models use the multimodal-generation endpoint.\n */\n apiUrl?: string;\n}\n\n/**\n * Function that extracts the custom role of a generic chat message.\n * @param message Chat message from which to extract the custom role.\n * @returns The custom role of the chat message.\n */\nfunction extractGenericMessageCustomRole(message: ChatMessage) {\n if (![\"system\", \"assistant\", \"user\", \"tool\"].includes(message.role)) {\n console.warn(`Unknown message role: ${message.role}`);\n }\n\n return message.role as TongyiMessageRole;\n}\n\nfunction normalizeToolCall(rawToolCall: TongyiToolCall): TongyiToolCall {\n const rawArguments = rawToolCall.function?.arguments;\n const normalizedArguments =\n typeof rawArguments === \"string\"\n ? rawArguments\n : JSON.stringify(rawArguments ?? {});\n return {\n ...rawToolCall,\n function: rawToolCall.function\n ? {\n ...rawToolCall.function,\n arguments: normalizedArguments,\n }\n : undefined,\n };\n}\n\nfunction normalizeToolChoice(\n toolChoice: BaseChatModelCallOptions[\"tool_choice\"] | undefined\n): TongyiToolChoice | undefined {\n if (toolChoice === undefined) {\n return undefined;\n }\n if (toolChoice === \"auto\" || toolChoice === \"none\") {\n return toolChoice;\n }\n if (toolChoice === \"any\" || toolChoice === \"required\") {\n console.warn(\n `ChatAlibabaTongyi received tool_choice=\"${toolChoice}\", which DashScope does not support directly. Falling back to \"auto\" (forced tool use is not guaranteed).`\n );\n return \"auto\";\n }\n if (typeof toolChoice === \"string\") {\n return {\n type: \"function\",\n function: { name: toolChoice },\n };\n }\n if (typeof toolChoice === \"object\" && toolChoice !== null) {\n if (\n \"type\" in toolChoice &&\n toolChoice.type === \"function\" &&\n \"function\" in toolChoice &&\n typeof toolChoice.function === \"object\" &&\n toolChoice.function !== null &&\n \"name\" in toolChoice.function &&\n typeof toolChoice.function.name === \"string\"\n ) {\n return {\n type: \"function\",\n function: {\n name: toolChoice.function.name,\n },\n };\n }\n if (\n \"type\" in toolChoice &&\n toolChoice.type === \"tool\" &&\n \"name\" in toolChoice &&\n typeof toolChoice.name === \"string\"\n ) {\n return {\n type: \"function\",\n function: { name: toolChoice.name },\n };\n }\n if (\"type\" in toolChoice && toolChoice.type === \"auto\") {\n return \"auto\";\n }\n if (\"type\" in toolChoice && toolChoice.type === \"none\") {\n return \"none\";\n }\n }\n throw new Error(\n `Unsupported tool_choice value for ChatAlibabaTongyi: ${JSON.stringify(\n toolChoice\n )}`\n );\n}\n\nfunction convertRawToolCallsToToolCallChunks(\n rawToolCalls: TongyiToolCall[]\n): ToolCallChunk[] {\n return rawToolCalls.map((rawToolCall) => {\n const normalizedToolCall = normalizeToolCall(rawToolCall);\n return {\n type: \"tool_call_chunk\",\n id: normalizedToolCall.id,\n name: normalizedToolCall.function?.name,\n args: normalizedToolCall.function?.arguments as string | undefined,\n index: normalizedToolCall.index,\n };\n });\n}\n\nfunction convertRawToolCallsToOpenAIToolCalls(\n rawToolCalls: TongyiToolCall[]\n): OpenAIToolCall[] {\n return rawToolCalls.map((rawToolCall, index) => {\n const normalizedToolCall = normalizeToolCall(rawToolCall);\n return {\n id: normalizedToolCall.id ?? `tool_call_${index}`,\n type: \"function\",\n function: {\n name: normalizedToolCall.function?.name ?? \"\",\n arguments: (normalizedToolCall.function?.arguments ?? \"{}\") as string,\n },\n index: normalizedToolCall.index,\n };\n });\n}\n\nfunction mergeToolCallStringValue(\n previousValue: string | undefined,\n deltaValue: string | undefined\n): string | undefined {\n if (deltaValue === undefined) {\n return previousValue;\n }\n if (previousValue === undefined) {\n return deltaValue;\n }\n if (deltaValue.startsWith(previousValue)) {\n return deltaValue;\n }\n if (previousValue.endsWith(deltaValue)) {\n return previousValue;\n }\n return `${previousValue}${deltaValue}`;\n}\n\nfunction mergeToolCallDelta(\n existingToolCall: TongyiToolCall | undefined,\n deltaToolCall: TongyiToolCall\n): TongyiToolCall {\n const existingArgs = normalizeToolCall(existingToolCall ?? {}).function\n ?.arguments as string | undefined;\n const deltaArgs = normalizeToolCall(deltaToolCall).function?.arguments as\n | string\n | undefined;\n const existingName = existingToolCall?.function?.name;\n const deltaName = deltaToolCall.function?.name;\n\n return {\n id: mergeToolCallStringValue(existingToolCall?.id, deltaToolCall.id),\n index: deltaToolCall.index ?? existingToolCall?.index,\n type: deltaToolCall.type ?? existingToolCall?.type,\n function: {\n name: mergeToolCallStringValue(existingName, deltaName),\n arguments: mergeToolCallStringValue(existingArgs, deltaArgs),\n },\n };\n}\n\nfunction getToolCallDeltaKey(toolCall: TongyiToolCall, fallbackIndex: number) {\n if (toolCall.index !== undefined) {\n return `index:${toolCall.index}`;\n }\n if (toolCall.id) {\n return `id:${toolCall.id}`;\n }\n return `fallback:${fallbackIndex}`;\n}\n\nfunction applyToolCallDeltas(\n toolCallState: Map<string, TongyiToolCall>,\n deltaToolCalls: TongyiToolCall[]\n): TongyiToolCall[] {\n deltaToolCalls.forEach((deltaToolCall, index) => {\n const key = getToolCallDeltaKey(deltaToolCall, index);\n const mergedToolCall = mergeToolCallDelta(\n toolCallState.get(key),\n deltaToolCall\n );\n toolCallState.set(key, mergedToolCall);\n });\n return [...toolCallState.values()];\n}\n\nfunction parseRawToolCalls(rawToolCalls: TongyiToolCall[], partial = false) {\n const toolCalls: Array<{\n name: string;\n args: Record<string, unknown>;\n type: \"tool_call\";\n id?: string;\n }> = [];\n const invalidToolCalls: ReturnType<typeof makeInvalidToolCall>[] = [];\n for (const rawToolCall of rawToolCalls) {\n const normalizedToolCall = normalizeToolCall(rawToolCall);\n try {\n const parsedToolCall = parseToolCall(normalizedToolCall, {\n returnId: true,\n partial,\n });\n if (parsedToolCall) {\n toolCalls.push(\n parsedToolCall as {\n name: string;\n args: Record<string, unknown>;\n type: \"tool_call\";\n id?: string;\n }\n );\n }\n } catch (error) {\n const errorMessage =\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ? error.message\n : \"Failed to parse tool call\";\n invalidToolCalls.push(\n makeInvalidToolCall(normalizedToolCall, errorMessage)\n );\n }\n }\n return { toolCalls, invalidToolCalls };\n}\n\nfunction convertMessagesToTongyiParams(\n messages: BaseMessage[]\n): TongyiMessage[] {\n return messages.map((message): TongyiMessage => {\n if (typeof message.content !== \"string\") {\n throw new Error(\n \"ChatAlibabaTongyi only supports string message content. Complex content types (arrays, objects) are not supported.\"\n );\n }\n const completionParam: TongyiMessage = {\n role: messageToTongyiRole(message),\n content: message.content,\n };\n if (AIMessage.isInstance(message) && !!message.tool_calls?.length) {\n completionParam.tool_calls = message.tool_calls.map(\n convertLangChainToolCallToOpenAI\n );\n return completionParam;\n }\n if (message.additional_kwargs.tool_calls != null) {\n completionParam.tool_calls = message.additional_kwargs\n .tool_calls as TongyiToolCall[];\n }\n if ((message as ToolMessage).tool_call_id != null) {\n completionParam.tool_call_id = (message as ToolMessage).tool_call_id;\n }\n return completionParam;\n });\n}\n\nfunction extractOutputMessage(output?: ChatCompletionResponse[\"output\"]): {\n text: string;\n finishReason?: TongyiFinishReason;\n rawToolCalls: TongyiToolCall[];\n} {\n if (!output) {\n return { text: \"\", finishReason: undefined, rawToolCalls: [] };\n }\n if (output.choices?.length) {\n // Keep first-choice semantics in non-stream responses for compatibility.\n const firstChoice = output.choices[0];\n const choiceMessage = firstChoice.message ?? firstChoice.delta;\n return {\n text: choiceMessage?.content ?? \"\",\n finishReason: firstChoice.finish_reason ?? output.finish_reason,\n rawToolCalls: choiceMessage?.tool_calls ?? firstChoice.tool_calls ?? [],\n };\n }\n return {\n text: output.text ?? \"\",\n finishReason: output.finish_reason,\n rawToolCalls: [],\n };\n}\n\nfunction extractOutputFromStreamChunk(\n output?: ChatCompletionResponse[\"output\"]\n): {\n text: string;\n finishReason?: TongyiFinishReason;\n rawToolCalls: TongyiToolCall[];\n} {\n if (!output) {\n return { text: \"\", finishReason: undefined, rawToolCalls: [] };\n }\n if (output.choices?.length) {\n let text = \"\";\n let finishReason = output.finish_reason;\n const rawToolCalls: TongyiToolCall[] = [];\n for (const choice of output.choices) {\n const choiceMessage = choice.delta ?? choice.message;\n text += choiceMessage?.content ?? \"\";\n if (choice.finish_reason) {\n finishReason = choice.finish_reason;\n }\n if (choiceMessage?.tool_calls?.length) {\n rawToolCalls.push(...choiceMessage.tool_calls);\n } else if (choice.tool_calls?.length) {\n rawToolCalls.push(...choice.tool_calls);\n }\n }\n return { text, finishReason, rawToolCalls };\n }\n return {\n text: output.text ?? \"\",\n finishReason: output.finish_reason,\n rawToolCalls: [],\n };\n}\n\n/**\n * Function that converts a base message to a Tongyi message role.\n * @param message Base message to convert.\n * @returns The Tongyi message role.\n */\nfunction messageToTongyiRole(message: BaseMessage): TongyiMessageRole {\n const type = message._getType();\n switch (type) {\n case \"ai\":\n return \"assistant\";\n case \"human\":\n return \"user\";\n case \"system\":\n return \"system\";\n case \"tool\":\n return \"tool\";\n case \"function\":\n throw new Error(\"Function messages not supported\");\n case \"generic\": {\n if (!ChatMessage.isInstance(message))\n throw new Error(\"Invalid generic chat message\");\n return extractGenericMessageCustomRole(message);\n }\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n\n/**\n * Wrapper around Ali Tongyi large language models that use the Chat endpoint.\n *\n * To use you should have the `ALIBABA_API_KEY`\n * environment variable set.\n *\n * @augments BaseLLM\n * @augments AlibabaTongyiChatInput\n * @example\n * ```typescript\n * // Default - uses China region\n * const qwen = new ChatAlibabaTongyi({\n * alibabaApiKey: \"YOUR-API-KEY\",\n * });\n *\n * // Specify region explicitly\n * const qwen = new ChatAlibabaTongyi({\n * model: \"qwen-turbo\",\n * temperature: 1,\n * region: \"singapore\", // or \"us\" or \"china\"\n * alibabaApiKey: \"YOUR-API-KEY\",\n * });\n *\n * const messages = [new HumanMessage(\"Hello\")];\n *\n * await qwen.call(messages);\n * ```\n */\nexport class ChatAlibabaTongyi\n extends BaseChatModel<ChatAlibabaTongyiCallOptions>\n implements AlibabaTongyiChatInput\n{\n static lc_name() {\n return \"ChatAlibabaTongyi\";\n }\n\n get callKeys() {\n return [\n \"stop\",\n \"signal\",\n \"options\",\n \"tools\",\n \"tool_choice\",\n \"parallel_tool_calls\",\n \"parallelToolCalls\",\n ];\n }\n\n get lc_secrets() {\n return {\n alibabaApiKey: \"ALIBABA_API_KEY\",\n };\n }\n\n get lc_aliases() {\n return undefined;\n }\n\n lc_serializable: boolean;\n\n alibabaApiKey?: string;\n\n streaming: boolean;\n\n prefixMessages?: TongyiMessage[];\n\n modelName: ChatCompletionRequest[\"model\"];\n\n model: ChatCompletionRequest[\"model\"];\n\n apiUrl: string;\n\n maxTokens?: number | undefined;\n\n temperature?: number | undefined;\n\n topP?: number | undefined;\n\n topK?: number | undefined;\n\n repetitionPenalty?: number | undefined;\n\n seed?: number | undefined;\n\n enableSearch?: boolean | undefined;\n\n parallelToolCalls?: boolean | undefined;\n\n region: \"china\" | \"singapore\" | \"us\";\n\n /**\n * Get the API URL based on the specified region.\n *\n * @param region - The region to get the URL for ('china', 'singapore', or 'us')\n * @returns The base URL for the specified region\n */\n private getRegionBaseUrl(region: \"china\" | \"singapore\" | \"us\"): string {\n const regionUrls = {\n china: \"https://dashscope.aliyuncs.com/\",\n singapore: \"https://dashscope-intl.aliyuncs.com/\",\n us: \"https://dashscope-us.aliyuncs.com/\",\n };\n return regionUrls[region];\n }\n\n private isMultimodalModel(modelName: string): boolean {\n return /[-_]vl([-_.]|$)/i.test(modelName);\n }\n\n constructor(\n fields: Partial<AlibabaTongyiChatInput> & BaseChatModelParams = {}\n ) {\n super(fields);\n\n this.alibabaApiKey =\n fields?.alibabaApiKey ?? getEnvironmentVariable(\"ALIBABA_API_KEY\");\n if (!this.alibabaApiKey) {\n throw new Error(\"Ali API key not found\");\n }\n\n // Set region (default to china)\n this.region =\n fields.region ??\n (getEnvironmentVariable(\"ALIBABA_REGION\") as\n | \"china\"\n | \"singapore\"\n | \"us\"\n | undefined) ??\n \"china\";\n\n // Model must be known before computing apiUrl\n this.modelName = fields?.model ?? fields.modelName ?? \"qwen-turbo\";\n this.model = this.modelName;\n\n // Set API URL: explicit override > auto-detect from model name\n if (fields.apiUrl) {\n this.apiUrl = fields.apiUrl;\n } else {\n const servicePath = this.isMultimodalModel(this.model)\n ? \"api/v1/services/aigc/multimodal-generation/generation\"\n : \"api/v1/services/aigc/text-generation/generation\";\n this.apiUrl = `${this.getRegionBaseUrl(this.region)}${servicePath}`;\n }\n\n this.lc_serializable = true;\n this.streaming = fields.streaming ?? false;\n this.prefixMessages = fields.prefixMessages ?? [];\n this.temperature = fields.temperature;\n this.topP = fields.topP;\n this.topK = fields.topK;\n this.seed = fields.seed;\n this.maxTokens = fields.maxTokens;\n this.repetitionPenalty = fields.repetitionPenalty;\n this.enableSearch = fields.enableSearch;\n this.parallelToolCalls = fields.parallelToolCalls;\n }\n\n /**\n * Get the parameters used to invoke the model\n */\n invocationParams(\n options?: this[\"ParsedCallOptions\"]\n ): ChatCompletionRequest[\"parameters\"] {\n const tools =\n options?.tools?.map((tool) => convertToOpenAITool(tool)) ?? [];\n const parallelToolCalls =\n options?.parallel_tool_calls ??\n options?.parallelToolCalls ??\n this.parallelToolCalls;\n const hasTools = tools.length > 0;\n const parameters: ChatCompletionRequest[\"parameters\"] = {\n stream: this.streaming,\n temperature: this.temperature,\n top_p: this.topP,\n top_k: this.topK,\n seed: this.seed,\n max_tokens: this.maxTokens,\n result_format: hasTools ? \"message\" : \"text\",\n enable_search: this.enableSearch,\n };\n if (hasTools) {\n parameters.tools = tools;\n }\n if (parallelToolCalls !== undefined) {\n parameters.parallel_tool_calls = parallelToolCalls;\n }\n const toolChoice = normalizeToolChoice(options?.tool_choice);\n if (toolChoice !== undefined) {\n parameters.tool_choice = toolChoice;\n }\n\n if (this.streaming) {\n parameters.incremental_output = true;\n } else {\n // DashScope generation examples include repetition_penalty in non-stream mode.\n parameters.repetition_penalty = this.repetitionPenalty;\n }\n\n return parameters;\n }\n\n /**\n * Get the identifying parameters for the model\n */\n identifyingParams(): ChatCompletionRequest[\"parameters\"] &\n Pick<ChatCompletionRequest, \"model\"> {\n return {\n model: this.model,\n ...this.invocationParams(),\n };\n }\n\n override bindTools(\n tools: BindToolsInput[],\n kwargs?: Partial<ChatAlibabaTongyiCallOptions>\n ): Runnable<\n BaseLanguageModelInput,\n AIMessageChunk,\n ChatAlibabaTongyiCallOptions\n > {\n return this.withConfig({\n tools,\n ...kwargs,\n });\n }\n\n withStructuredOutput<\n // oxlint-disable-next-line typescript/no-explicit-any\n RunOutput extends Record<string, any> = Record<string, any>,\n >(\n outputSchema:\n | InteropZodType<RunOutput>\n // oxlint-disable-next-line typescript/no-explicit-any\n | Record<string, any>,\n config?: StructuredOutputMethodOptions<false>\n ): Runnable<BaseLanguageModelInput, RunOutput>;\n\n withStructuredOutput<\n // oxlint-disable-next-line typescript/no-explicit-any\n RunOutput extends Record<string, any> = Record<string, any>,\n >(\n outputSchema:\n | InteropZodType<RunOutput>\n // oxlint-disable-next-line typescript/no-explicit-any\n | Record<string, any>,\n config?: StructuredOutputMethodOptions<true>\n ): Runnable<\n BaseLanguageModelInput,\n { raw: AIMessage | AIMessageChunk; parsed: RunOutput }\n >;\n\n withStructuredOutput<\n // oxlint-disable-next-line typescript/no-explicit-any\n RunOutput extends Record<string, any> = Record<string, any>,\n >(\n outputSchema:\n | InteropZodType<RunOutput>\n // oxlint-disable-next-line typescript/no-explicit-any\n | Record<string, any>,\n config?: StructuredOutputMethodOptions<boolean>\n ):\n | Runnable<BaseLanguageModelInput, RunOutput>\n | Runnable<\n BaseLanguageModelInput,\n { raw: AIMessage | AIMessageChunk; parsed: RunOutput }\n > {\n if (config?.strict) {\n throw new Error(`\"strict\" mode is not supported for this model.`);\n }\n\n // oxlint-disable-next-line typescript/no-explicit-any\n const schema: InteropZodType<RunOutput> | Record<string, any> =\n outputSchema;\n const name = config?.name;\n const description =\n getSchemaDescription(schema) ?? \"A function available to call.\";\n const method = config?.method;\n const includeRaw = config?.includeRaw;\n\n if (method === \"jsonMode\") {\n throw new Error(\n `ChatAlibabaTongyi only supports \"functionCalling\" for structured output.`\n );\n }\n\n let functionName = name ?? \"extract\";\n const outputFormatSchema = isInteropZodSchema(schema)\n ? toJsonSchema(schema)\n : schema;\n let tools: ToolDefinition[];\n if (isInteropZodSchema(schema)) {\n tools = [\n {\n type: \"function\",\n function: {\n name: functionName,\n description,\n parameters: outputFormatSchema,\n },\n },\n ];\n } else {\n if (\"name\" in schema && typeof schema.name === \"string\") {\n functionName = schema.name;\n }\n tools = [\n {\n type: \"function\",\n function: {\n name: functionName,\n description,\n parameters: schema,\n },\n },\n ];\n }\n\n const llm = this.bindTools(tools).withConfig({\n tool_choice: {\n type: \"function\",\n function: {\n name: functionName,\n },\n },\n ls_structured_output_format: {\n kwargs: { method: \"functionCalling\" },\n schema: outputFormatSchema,\n },\n });\n const outputParser = RunnableLambda.from<\n AIMessage | AIMessageChunk,\n RunOutput\n >((input) => {\n const toolCalls = input.tool_calls;\n if (!toolCalls || toolCalls.length === 0) {\n throw new Error(\"No tool calls found in the response.\");\n }\n const toolCall = toolCalls.find((tc) => tc.name === functionName);\n if (!toolCall) {\n throw new Error(`No tool call found with name ${functionName}.`);\n }\n return toolCall.args as RunOutput;\n });\n\n if (!includeRaw) {\n return llm.pipe(outputParser).withConfig({\n runName: \"StructuredOutput\",\n }) as Runnable<BaseLanguageModelInput, RunOutput>;\n }\n\n const parserAssign = RunnablePassthrough.assign({\n // oxlint-disable-next-line typescript/no-explicit-any\n parsed: (input: any, cfg) => outputParser.invoke(input.raw, cfg),\n });\n const parserNone = RunnablePassthrough.assign({\n parsed: () => null,\n });\n const parsedWithFallback = parserAssign.withFallbacks({\n fallbacks: [parserNone],\n });\n\n return RunnableSequence.from<\n BaseLanguageModelInput,\n { raw: AIMessage | AIMessageChunk; parsed: RunOutput }\n >([\n {\n raw: llm,\n },\n parsedWithFallback,\n ]).withConfig({\n runName: \"StructuredOutputRunnable\",\n });\n }\n\n /** @ignore */\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const parameters = this.invocationParams(options);\n const messagesMapped = convertMessagesToTongyiParams(messages);\n\n const data = parameters.stream\n ? await new Promise<ChatCompletionResponse>((resolve, reject) => {\n let response: ChatCompletionResponse | undefined;\n let concatenatedText = \"\";\n let mergedToolCalls: TongyiToolCall[] = [];\n const streamedToolCallState = new Map<string, TongyiToolCall>();\n let rejected = false;\n let resolved = false;\n this.completionWithRetry(\n {\n model: this.model,\n parameters,\n input: {\n messages: messagesMapped,\n },\n },\n true,\n options?.signal,\n (event) => {\n const data: ChatCompletionResponse = JSON.parse(event.data);\n if (data?.code) {\n if (rejected) {\n return;\n }\n rejected = true;\n reject(new Error(data?.message));\n return;\n }\n\n const { text, finishReason, rawToolCalls } =\n extractOutputFromStreamChunk(data.output);\n concatenatedText += text;\n mergedToolCalls = applyToolCallDeltas(\n streamedToolCallState,\n rawToolCalls\n );\n\n if (!response) {\n response = {\n ...data,\n output: {\n ...(data.output ?? {}),\n text: concatenatedText,\n finish_reason: finishReason,\n choices: [\n {\n finish_reason: finishReason,\n message: {\n role: \"assistant\",\n content: concatenatedText,\n tool_calls: mergedToolCalls,\n },\n },\n ],\n },\n };\n } else {\n response.output = {\n ...(response.output ?? {}),\n text: concatenatedText,\n finish_reason: finishReason ?? response.output?.finish_reason,\n choices: [\n {\n finish_reason:\n finishReason ?? response.output?.finish_reason,\n message: {\n role: \"assistant\",\n content: concatenatedText,\n tool_calls: mergedToolCalls,\n },\n },\n ],\n };\n response.usage = data.usage;\n }\n\n // eslint-disable-next-line no-void\n void runManager?.handleLLMNewToken(text ?? \"\");\n if (finishReason && finishReason !== \"null\") {\n if (resolved || rejected) {\n return;\n }\n resolved = true;\n resolve(\n response ?? {\n ...data,\n output: {\n ...(data.output ?? {}),\n text: concatenatedText,\n finish_reason: finishReason,\n },\n }\n );\n }\n }\n )\n .then(() => {\n if (resolved || rejected) {\n return;\n }\n resolved = true;\n resolve(\n response ?? {\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n total_tokens: 0,\n },\n output: {\n text: concatenatedText,\n finish_reason: \"null\",\n choices: [\n {\n finish_reason: \"null\",\n message: {\n role: \"assistant\",\n content: concatenatedText,\n tool_calls: mergedToolCalls,\n },\n },\n ],\n },\n }\n );\n })\n .catch((error) => {\n if (!rejected) {\n rejected = true;\n reject(error);\n }\n });\n })\n : await this.completionWithRetry(\n {\n model: this.model,\n parameters,\n input: {\n messages: messagesMapped,\n },\n },\n false,\n options?.signal\n ).then<ChatCompletionResponse>((data) => {\n if (data?.code) {\n throw new Error(data?.message);\n }\n\n return data;\n });\n\n const {\n input_tokens = 0,\n output_tokens = 0,\n total_tokens = 0,\n } = data.usage ?? {};\n const usageMetadata: UsageMetadata = {\n input_tokens,\n output_tokens,\n total_tokens,\n };\n const { text, finishReason, rawToolCalls } = extractOutputMessage(\n data.output\n );\n const requestId = data.request_id ?? data.requestId;\n const { toolCalls, invalidToolCalls } = parseRawToolCalls(rawToolCalls);\n const isToolResponse = rawToolCalls.length > 0;\n const message = isToolResponse\n ? new AIMessage({\n content: text,\n additional_kwargs: {\n tool_calls: convertRawToolCallsToOpenAIToolCalls(rawToolCalls),\n },\n tool_calls: toolCalls,\n invalid_tool_calls: invalidToolCalls,\n usage_metadata: usageMetadata,\n response_metadata: {\n model_provider: \"alibaba_tongyi\",\n model: this.model,\n request_id: requestId,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n },\n })\n : new AIMessage({\n content: text,\n usage_metadata: usageMetadata,\n response_metadata: {\n model_provider: \"alibaba_tongyi\",\n model: this.model,\n request_id: requestId,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n },\n });\n\n return {\n generations: [\n {\n text,\n message,\n generationInfo: finishReason\n ? { finish_reason: finishReason }\n : undefined,\n },\n ],\n llmOutput: {\n tokenUsage: {\n promptTokens: input_tokens,\n completionTokens: output_tokens,\n totalTokens: total_tokens,\n },\n },\n };\n }\n\n /** @ignore */\n async completionWithRetry(\n request: ChatCompletionRequest,\n stream: boolean,\n signal?: AbortSignal,\n onmessage?: (event: MessageEvent) => void\n ) {\n const makeCompletionRequest = async () => {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: {\n // This integration uses the native DashScope endpoint\n // (`/api/v1/services/aigc/text-generation/generation`), not the OpenAI-compatible\n // endpoint (`/compatible-mode/v1/chat/completions`). For native streaming, DashScope\n // expects `X-DashScope-SSE: enable` to emit SSE `data:` chunks our parser consumes.\n ...(stream\n ? {\n Accept: \"text/event-stream\",\n \"X-DashScope-SSE\": \"enable\",\n }\n : {}),\n Authorization: `Bearer ${this.alibabaApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n signal,\n });\n\n if (!stream) {\n return response.json();\n }\n\n if (response.body) {\n // response will not be a stream if an error occurred\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\")\n ) {\n onmessage?.(\n new MessageEvent(\"message\", {\n data: await response.text(),\n })\n );\n return;\n }\n const reader = response.body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let data = \"\";\n let continueReading = true;\n while (continueReading) {\n const { done, value } = await reader.read();\n if (done) {\n continueReading = false;\n break;\n }\n data += decoder.decode(value);\n let continueProcessing = true;\n while (continueProcessing) {\n const newlineIndex = data.indexOf(\"\\n\");\n if (newlineIndex === -1) {\n continueProcessing = false;\n break;\n }\n const line = data.slice(0, newlineIndex);\n data = data.slice(newlineIndex + 1);\n if (line.startsWith(\"data:\")) {\n const event = new MessageEvent(\"message\", {\n data: line.slice(\"data:\".length).trim(),\n });\n onmessage?.(event);\n }\n }\n }\n }\n };\n\n return this.caller.call(makeCompletionRequest);\n }\n\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const parameters = {\n ...this.invocationParams(options),\n stream: true,\n incremental_output: true,\n };\n\n const messagesMapped = convertMessagesToTongyiParams(messages);\n\n const stream = await this.caller.call(async () =>\n this.createTongyiStream(\n {\n model: this.model,\n parameters,\n input: {\n messages: messagesMapped,\n },\n },\n options?.signal\n )\n );\n\n for await (const chunk of stream) {\n /* if some error occurs:\n {\n \"code\": \"DataInspectionFailed\",\n \"message\": \"Output data may contain inappropriate content.\",\n \"request_id\": \"43d18007-5aa5-9d18-b3b3-a55aba9ce8cb\"\n }\n */\n if (!chunk.output && chunk.code) {\n throw new Error(JSON.stringify(chunk));\n }\n const { text, finishReason, rawToolCalls } = extractOutputFromStreamChunk(\n chunk.output\n );\n const toolCallChunks = convertRawToolCallsToToolCallChunks(rawToolCalls);\n const requestId = chunk.request_id ?? chunk.requestId;\n const usageMetadata: UsageMetadata | undefined = chunk.usage\n ? {\n input_tokens: chunk.usage.input_tokens ?? 0,\n output_tokens: chunk.usage.output_tokens ?? 0,\n total_tokens: chunk.usage.total_tokens ?? 0,\n }\n : undefined;\n yield new ChatGenerationChunk({\n text,\n message: new AIMessageChunk({\n content: text,\n tool_call_chunks: toolCallChunks,\n usage_metadata: usageMetadata,\n response_metadata: {\n model_provider: \"alibaba_tongyi\",\n model: this.model,\n request_id: requestId,\n ...(finishReason ? { finish_reason: finishReason } : {}),\n },\n }),\n generationInfo:\n finishReason === \"stop\" || finishReason === \"tool_calls\"\n ? {\n finish_reason: finishReason,\n request_id: requestId,\n usage: chunk.usage,\n }\n : undefined,\n });\n await runManager?.handleLLMNewToken(text);\n }\n }\n\n private async *createTongyiStream(\n request: ChatCompletionRequest,\n signal?: AbortSignal\n ) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.alibabaApiKey}`,\n // Native DashScope stream() path: keep SSE framing explicit on the\n // `/api/v1/services/aigc/text-generation/generation` endpoint.\n Accept: \"text/event-stream\",\n \"X-DashScope-SSE\": \"enable\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n signal,\n });\n\n if (!response.ok) {\n let error;\n const responseText = await response.text();\n try {\n const json = JSON.parse(responseText);\n error = new Error(\n `Tongyi call failed with status code ${response.status}: ${json.error}`\n );\n } catch {\n error = new Error(\n `Tongyi call failed with status code ${response.status}: ${responseText}`\n );\n }\n // oxlint-disable-next-line typescript/no-explicit-any\n (error as any).response = response;\n throw error;\n }\n if (!response.body) {\n throw new Error(\n \"Could not begin Tongyi stream. Please check the given URL and try again.\"\n );\n }\n const stream = IterableReadableStream.fromReadableStream(response.body);\n const decoder = new TextDecoder();\n let extra = \"\";\n for await (const chunk of stream) {\n const decoded = extra + decoder.decode(chunk);\n const lines = decoded.split(\"\\n\");\n extra = lines.pop() || \"\";\n for (const line of lines) {\n if (!line.startsWith(\"data:\")) {\n continue;\n }\n try {\n yield JSON.parse(line.slice(\"data:\".length).trim());\n } catch {\n console.warn(`Received a non-JSON parseable chunk: ${line}`);\n }\n }\n }\n }\n\n _llmType(): string {\n return \"alibaba_tongyi\";\n }\n\n /** @ignore */\n _combineLLMOutput() {\n return [];\n }\n}\n"],"mappings":"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