UNPKG

zhipu-ai-provider

Version:

Vercel AI Custom Provider for Services from Zhipu

781 lines (770 loc) 26.9 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { createZhipu: () => createZhipu, zhipu: () => zhipu }); module.exports = __toCommonJS(index_exports); // src/zhipu-provider.ts var import_provider_utils5 = require("@ai-sdk/provider-utils"); // src/zhipu-chat-language-model.ts var import_provider3 = require("@ai-sdk/provider"); var import_provider_utils3 = require("@ai-sdk/provider-utils"); var import_zod2 = require("zod"); // src/convert-to-zhipu-chat-messages.ts var import_provider = require("@ai-sdk/provider"); var import_provider_utils = require("@ai-sdk/provider-utils"); function convertToZhipuChatMessages(prompt) { const messages = []; for (let i = 0; i < prompt.length; i++) { const { role, content } = prompt[i]; const isLastMessage = i === prompt.length - 1; switch (role) { case "system": { messages.push({ role: "system", content }); break; } case "user": { if (content.length === 1 && content[0].type === "text") { messages.push({ role: "user", content: content[0].text }); break; } if (content.every((part) => part.type === "text")) { messages.push({ role: "user", content: content.map((part) => part.text).join("") }); break; } messages.push({ role: "user", content: content.map((part) => { var _a; switch (part.type) { case "text": { return { type: "text", text: part.text }; } case "image": { return { type: "image_url", image_url: { url: part.image instanceof URL ? part.image.toString() : `data:${(_a = part.mimeType) != null ? _a : "image/jpeg"};base64,${(0, import_provider_utils.convertUint8ArrayToBase64)(part.image)}` } }; } case "file": { throw new import_provider.UnsupportedFunctionalityError({ functionality: "File content parts in user messages" }); } } }) }); break; } case "assistant": { let text = ""; const toolCalls = []; for (const part of content) { switch (part.type) { case "text": { text += part.text; break; } case "redacted-reasoning": case "reasoning": { break; } case "tool-call": { toolCalls.push({ id: part.toolCallId, type: "function", function: { name: part.toolName, arguments: JSON.stringify(part.args) } }); break; } default: { const _exhaustiveCheck = part; throw new Error(`Unsupported part: ${_exhaustiveCheck}`); } } } messages.push({ role: "assistant", content: text, prefix: isLastMessage ? true : void 0, tool_calls: toolCalls.length > 0 ? toolCalls : void 0 }); break; } case "tool": { for (const toolResponse of content) { messages.push({ role: "tool", content: JSON.stringify(toolResponse.result), tool_call_id: toolResponse.toolCallId }); } break; } default: { const _exhaustiveCheck = role; throw new Error(`Unsupported role: ${_exhaustiveCheck}`); } } } return messages; } // src/map-zhipu-finish-reason.ts function mapZhipuFinishReason(finishReason) { switch (finishReason) { case "stop": return "stop"; case "length": return "length"; case "tool_calls": return "tool-calls"; case "sensitive": return "content-filter"; case "network_error": return "error"; default: return "unknown"; } } // src/zhipu-error.ts var import_provider_utils2 = require("@ai-sdk/provider-utils"); var import_zod = require("zod"); var zhipuErrorDataSchema = import_zod.z.object({ error: import_zod.z.object({ message: import_zod.z.string(), code: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).nullish() }) }); var zhipuFailedResponseHandler = (0, import_provider_utils2.createJsonErrorResponseHandler)({ errorSchema: zhipuErrorDataSchema, errorToMessage: (data) => data.error.message }); // src/get-response-metadata.ts function getResponseMetadata({ id, model, created }) { return { id: id != null ? id : void 0, modelId: model != null ? model : void 0, timestamp: created != null ? new Date(created * 1e3) : void 0 }; } // src/zhipu-prepare-tools.ts var import_provider2 = require("@ai-sdk/provider"); function prepareTools(mode) { var _a; const tools = ((_a = mode.tools) == null ? void 0 : _a.length) ? mode.tools : void 0; const toolWarnings = []; if (tools == null) { return { tools: void 0, tool_choice: void 0, toolWarnings }; } const zhipuTools = []; for (const tool of tools) { if (tool.type === "provider-defined") { toolWarnings.push({ type: "unsupported-tool", tool }); } else { zhipuTools.push({ type: "function", function: { name: tool.name, description: tool.description, parameters: tool.parameters } }); } } const toolChoice = mode.toolChoice; if (toolChoice == null) { return { tools: zhipuTools, tool_choice: void 0, toolWarnings }; } const type = toolChoice.type; switch (type) { case "none": return { tools: zhipuTools, tool_choice: void 0, toolWarnings }; case "auto": case "required": return { tools: zhipuTools, tool_choice: "auto", toolWarnings }; // zhipu does not support tool mode directly, // so we filter the tools and force the tool choice through 'any' case "tool": return { tools: zhipuTools.filter( (tool) => tool.function.name === toolChoice.toolName ), tool_choice: "auto", toolWarnings }; default: { const _exhaustiveCheck = type; throw new import_provider2.UnsupportedFunctionalityError({ functionality: `Unsupported tool choice type: ${_exhaustiveCheck}` }); } } } // src/zhipu-chat-language-model.ts var ZhipuChatLanguageModel = class { /** * Constructs a new ZhipuChatLanguageModel. * @param modelId - The model identifier. * @param settings - Settings for the chat. * @param config - Model configuration. */ constructor(modelId, settings, config) { this.specificationVersion = "v1"; this.defaultObjectGenerationMode = "json"; this.supportsImageUrls = false; this.modelId = modelId; this.settings = settings; this.config = config; this.config.isMultiModel = this.modelId.includes("4v"); this.config.isReasoningModel = this.modelId.includes("zero"); } /** * Getter for the provider name. */ get provider() { return this.config.provider; } getArgs({ mode, prompt, maxTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences, responseFormat, seed }) { const type = mode.type; const warnings = []; if (!this.config.isMultiModel && prompt.every((msg) => msg.role === "user" && !msg.content.every((part) => part.type === "text"))) { warnings.push({ type: "other", message: "Non-vision models does not support message parts" }); } if (topK != null) { warnings.push({ type: "unsupported-setting", setting: "topK" }); } if (frequencyPenalty != null) { warnings.push({ type: "unsupported-setting", setting: "frequencyPenalty" }); } if (presencePenalty != null) { warnings.push({ type: "unsupported-setting", setting: "presencePenalty" }); } if (stopSequences != null && this.config.isMultiModel) { warnings.push({ type: "unsupported-setting", setting: "stopSequences", details: "Stop sequences are not supported for vision model" }); } if (stopSequences != null && stopSequences.length > 1) { warnings.push({ type: "unsupported-setting", setting: "stopSequences", details: "Only supports one stop sequence" }); } if (seed != null) { warnings.push({ type: "unsupported-setting", setting: "seed" }); } if (responseFormat != null && responseFormat.type === "json" && (this.config.isMultiModel || this.config.isReasoningModel)) { warnings.push({ type: "unsupported-setting", setting: "responseFormat", details: "JSON response format is not supported with vision and reasoning models." }); } if (responseFormat != null && responseFormat.type === "json" && responseFormat.schema != null) { warnings.push({ type: "unsupported-setting", setting: "responseFormat", details: "JSON response format schema is only supported with structuredOutputs, provide the schema." }); } const baseArgs = { // model id: model: this.modelId, // model specific settings: user_id: this.settings.userId, do_sample: this.settings.doSample, request_id: this.settings.requestId, // standardized settings: max_tokens: maxTokens, temperature, top_p: topP, // response format: response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? { type: "json_object" } : void 0, // messages: messages: convertToZhipuChatMessages(prompt) }; switch (type) { case "regular": { const { tools, tool_choice, toolWarnings } = prepareTools(mode); return { args: { ...baseArgs, tools, tool_choice }, warnings: [...warnings, ...toolWarnings] }; } case "object-json": { return { args: { ...baseArgs, response_format: { type: "json_object" } }, warnings }; } case "object-tool": { return { args: { ...baseArgs, tool_choice: "auto", tools: [mode.tool] }, warnings }; } default: { const _exhaustiveCheck = type; throw new Error(`Unsupported type: ${_exhaustiveCheck}`); } } } async doGenerate(options) { var _a, _b, _c; const { args, warnings } = this.getArgs(options); const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}/chat/completions`, headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers), body: args, failedResponseHandler: zhipuFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)( zhipuChatResponseSchema ), abortSignal: options.abortSignal, fetch: this.config.fetch }); const { messages: rawPrompt, ...rawSettings } = args; const choice = response.choices[0]; return { text: (_a = choice.message.content) != null ? _a : void 0, toolCalls: (_b = choice.message.tool_calls) == null ? void 0 : _b.map((toolCall) => ({ toolCallType: "function", toolCallId: toolCall.id, toolName: toolCall.function.name, args: toolCall.function.arguments })), finishReason: mapZhipuFinishReason(choice.finish_reason), usage: { promptTokens: response.usage.prompt_tokens, completionTokens: (_c = response.usage.completion_tokens) != null ? _c : NaN }, rawCall: { rawPrompt, rawSettings }, rawResponse: { headers: responseHeaders }, request: { body: JSON.stringify(args) }, response: getResponseMetadata(response), warnings }; } async doStream(options) { const { args, warnings } = this.getArgs(options); const body = { ...args, stream: true }; const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}/chat/completions`, headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers), body, failedResponseHandler: zhipuFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)(zhipuChatChunkSchema), abortSignal: options.abortSignal, fetch: this.config.fetch }); const { messages: rawPrompt, ...rawSettings } = args; const toolCalls = []; let finishReason = "unknown"; let usage = { promptTokens: void 0, completionTokens: void 0 }; let isFirstChunk = true; return { stream: response.pipeThrough( new TransformStream({ transform(chunk, controller) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l; if (chunk.success == false) { finishReason = "error"; controller.enqueue({ type: "error", error: chunk.error }); return; } const value = chunk.value; if (isFirstChunk) { isFirstChunk = false; controller.enqueue({ type: "response-metadata", ...getResponseMetadata(value) }); } if (value.usage != null) { const { prompt_tokens, completion_tokens } = value.usage; usage = { promptTokens: prompt_tokens != null ? prompt_tokens : void 0, completionTokens: completion_tokens != null ? completion_tokens : void 0 }; } const choice = value.choices[0]; if ((choice == null ? void 0 : choice.finish_reason) != null) { if (choice.finish_reason === "network_error") { controller.enqueue({ type: "error", error: new Error(`Error: Network Error`) }); return; } finishReason = mapZhipuFinishReason(choice.finish_reason); } if ((choice == null ? void 0 : choice.delta) == null) { return; } const delta = choice.delta; if (delta.content != null) { controller.enqueue({ type: "text-delta", textDelta: delta.content }); } const mappedToolCalls = delta.tool_calls; if (mappedToolCalls != null) { for (const toolCallDelta of mappedToolCalls) { const index = toolCallDelta.index; if (toolCalls[index] == null) { if (toolCallDelta.type !== "function") { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'function' type.` }); } if (toolCallDelta.id == null) { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'id' to be a string.` }); } if (((_a = toolCallDelta.function) == null ? void 0 : _a.name) == null) { throw new import_provider3.InvalidResponseDataError({ data: toolCallDelta, message: `Expected 'function.name' to be a string.` }); } toolCalls[index] = { id: toolCallDelta.id, type: "function", function: { name: toolCallDelta.function.name, arguments: (_b = toolCallDelta.function.arguments) != null ? _b : "" }, hasFinished: false }; const toolCall2 = toolCalls[index]; if (((_c = toolCall2.function) == null ? void 0 : _c.name) != null && ((_d = toolCall2.function) == null ? void 0 : _d.arguments) != null) { if (toolCall2.function.arguments.length > 0) { controller.enqueue({ type: "tool-call-delta", toolCallType: "function", toolCallId: toolCall2.id, toolName: toolCall2.function.name, argsTextDelta: toolCall2.function.arguments }); } if ((0, import_provider_utils3.isParsableJson)(toolCall2.function.arguments)) { controller.enqueue({ type: "tool-call", toolCallType: "function", toolCallId: (_e = toolCall2.id) != null ? _e : (0, import_provider_utils3.generateId)(), toolName: toolCall2.function.name, args: toolCall2.function.arguments }); toolCall2.hasFinished = true; } } continue; } const toolCall = toolCalls[index]; if (toolCall.hasFinished) { continue; } if (((_f = toolCallDelta.function) == null ? void 0 : _f.arguments) != null) { toolCall.function.arguments += (_h = (_g = toolCallDelta.function) == null ? void 0 : _g.arguments) != null ? _h : ""; } controller.enqueue({ type: "tool-call-delta", toolCallType: "function", toolCallId: toolCall.id, toolName: toolCall.function.name, argsTextDelta: (_i = toolCallDelta.function.arguments) != null ? _i : "" }); if (((_j = toolCall.function) == null ? void 0 : _j.name) != null && ((_k = toolCall.function) == null ? void 0 : _k.arguments) != null && (0, import_provider_utils3.isParsableJson)(toolCall.function.arguments)) { controller.enqueue({ type: "tool-call", toolCallType: "function", toolCallId: (_l = toolCall.id) != null ? _l : (0, import_provider_utils3.generateId)(), toolName: toolCall.function.name, args: toolCall.function.arguments }); toolCall.hasFinished = true; } } } }, flush(controller) { var _a, _b; controller.enqueue({ type: "finish", finishReason, usage: { promptTokens: (_a = usage.promptTokens) != null ? _a : NaN, completionTokens: (_b = usage.completionTokens) != null ? _b : NaN } }); } }) ), rawCall: { rawPrompt, rawSettings }, rawResponse: { headers: responseHeaders }, request: { body: JSON.stringify(body) }, warnings }; } }; var zhipuChatResponseSchema = import_zod2.z.object({ id: import_zod2.z.string().nullish(), created: import_zod2.z.number().nullish(), model: import_zod2.z.string().nullish(), choices: import_zod2.z.array( import_zod2.z.object({ message: import_zod2.z.object({ role: import_zod2.z.literal("assistant"), content: import_zod2.z.string().nullish(), tool_calls: import_zod2.z.array( import_zod2.z.object({ id: import_zod2.z.string(), index: import_zod2.z.number().nullish(), type: import_zod2.z.literal("function"), function: import_zod2.z.object({ name: import_zod2.z.string(), arguments: import_zod2.z.string() }) }) ).nullish() }), index: import_zod2.z.number(), finish_reason: import_zod2.z.string().nullish() }) ), usage: import_zod2.z.object({ prompt_tokens: import_zod2.z.number(), completion_tokens: import_zod2.z.number().nullish(), total_tokens: import_zod2.z.number().nullish() }), web_search: import_zod2.z.object({ icon: import_zod2.z.string(), title: import_zod2.z.string(), link: import_zod2.z.string(), media: import_zod2.z.string(), content: import_zod2.z.string() }).nullish() }); var zhipuChatChunkSchema = import_zod2.z.object({ id: import_zod2.z.string().nullish(), created: import_zod2.z.number().nullish(), model: import_zod2.z.string().nullish(), choices: import_zod2.z.array( import_zod2.z.object({ delta: import_zod2.z.object({ role: import_zod2.z.enum(["assistant"]).optional(), content: import_zod2.z.string().nullish(), tool_calls: import_zod2.z.array( import_zod2.z.object({ id: import_zod2.z.string(), index: import_zod2.z.number(), type: import_zod2.z.literal("function"), function: import_zod2.z.object({ name: import_zod2.z.string(), arguments: import_zod2.z.string() }) }) ).nullish() }), finish_reason: import_zod2.z.string().nullish(), index: import_zod2.z.number() }) ), usage: import_zod2.z.object({ prompt_tokens: import_zod2.z.number(), completion_tokens: import_zod2.z.number().nullish(), total_tokens: import_zod2.z.number().nullish() }).nullish(), web_search: import_zod2.z.object({ icon: import_zod2.z.string(), title: import_zod2.z.string(), link: import_zod2.z.string(), media: import_zod2.z.string(), content: import_zod2.z.string() }).nullish() }); // src/zhipu-embedding-model.ts var import_provider4 = require("@ai-sdk/provider"); var import_provider_utils4 = require("@ai-sdk/provider-utils"); var import_zod3 = require("zod"); var ZhipuEmbeddingModel = class { constructor(modelId, settings, config) { this.specificationVersion = "v1"; this.modelId = modelId; this.settings = settings; this.config = config; } get provider() { return this.config.provider; } get maxEmbeddingsPerCall() { var _a; return (_a = this.config.maxEmbeddingsPerCall) != null ? _a : 64; } get supportsParallelCalls() { var _a; return (_a = this.config.supportsParallelCalls) != null ? _a : true; } async doEmbed({ values, abortSignal, headers }) { if (values.length > this.maxEmbeddingsPerCall) { throw new import_provider4.TooManyEmbeddingValuesForCallError({ provider: this.provider, modelId: this.modelId, maxEmbeddingsPerCall: this.maxEmbeddingsPerCall, values }); } const { responseHeaders, value: response } = await (0, import_provider_utils4.postJsonToApi)({ url: `${this.config.baseURL}/embeddings`, headers: (0, import_provider_utils4.combineHeaders)(this.config.headers(), headers), body: { model: this.modelId, input: values, dimension: this.settings.dimensions }, failedResponseHandler: zhipuFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils4.createJsonResponseHandler)( ZhipuTextEmbeddingResponseSchema ), abortSignal, fetch: this.config.fetch }); return { embeddings: response.data.map((item) => item.embedding), usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0, rawResponse: { headers: responseHeaders } }; } }; var ZhipuTextEmbeddingResponseSchema = import_zod3.z.object({ data: import_zod3.z.array( import_zod3.z.object({ embedding: import_zod3.z.array(import_zod3.z.number()), index: import_zod3.z.number().nullish(), object: import_zod3.z.string().nullish() }) ), usage: import_zod3.z.object({ prompt_tokens: import_zod3.z.number(), total_tokens: import_zod3.z.number().nullish() }).nullish() }); // src/zhipu-provider.ts function createZhipu(options = {}) { var _a; const baseURL = (_a = (0, import_provider_utils5.withoutTrailingSlash)(options.baseURL)) != null ? _a : "https://open.bigmodel.cn/api/paas/v4"; const getHeaders = () => ({ Authorization: `Bearer ${(0, import_provider_utils5.loadApiKey)({ apiKey: options.apiKey, environmentVariableName: "ZHIPU_API_KEY", description: "ZHIPU API key" })}`, ...options.headers }); const createChatModel = (modelId, settings = {}) => new ZhipuChatLanguageModel(modelId, settings, { provider: "zhipu.chat", baseURL, headers: getHeaders, fetch: options.fetch }); const createEmbeddingModel = (modelId, settings = {}) => new ZhipuEmbeddingModel(modelId, settings, { provider: "zhipu.embedding", baseURL, headers: getHeaders, fetch: options.fetch }); const provider = function(modelId, settings) { if (new.target) { throw new Error( "The Zhipu model function cannot be called with the new keyword." ); } return createChatModel(modelId, settings); }; provider.languageModel = createChatModel; provider.chat = createChatModel; provider.embedding = createEmbeddingModel; provider.textEmbedding = createEmbeddingModel; provider.textEmbeddingModel = createEmbeddingModel; return provider; } var zhipu = createZhipu(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createZhipu, zhipu }); //# sourceMappingURL=index.js.map