UNPKG

anthropic-vertex-ai

Version:

[nalaso/anthropic-vertex-ai](https://github.com/nalaso/anthropic-vertex-ai) is a community provider that uses Anthropic models through Vertex AI to provide language model support for the Vercel AI SDK.

689 lines (681 loc) 23.3 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 src_exports = {}; __export(src_exports, { anthropicVertex: () => anthropicVertex, createAnthropicVertex: () => createAnthropicVertex }); module.exports = __toCommonJS(src_exports); // src/anthropic-vertex-provider.ts var import_provider_utils4 = require("@ai-sdk/provider-utils"); var import_google_auth_library = require("google-auth-library"); // src/anthropic-messages-language-model.ts var import_provider2 = require("@ai-sdk/provider"); var import_provider_utils3 = require("@ai-sdk/provider-utils"); var import_zod2 = require("zod"); // src/anthropic-error.ts var import_provider_utils = require("@ai-sdk/provider-utils"); var import_zod = require("zod"); var anthropicErrorDataSchema = import_zod.z.object({ type: import_zod.z.literal("error"), error: import_zod.z.object({ type: import_zod.z.string(), message: import_zod.z.string() }) }); var anthropicFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({ errorSchema: anthropicErrorDataSchema, errorToMessage: (data) => data.error.message }); // src/convert-to-anthropic-messages-prompt.ts var import_provider = require("@ai-sdk/provider"); var import_provider_utils2 = require("@ai-sdk/provider-utils"); function convertToAnthropicMessagesPrompt(prompt) { var _a; const blocks = groupIntoBlocks(prompt); let system = void 0; const messages = []; for (let i = 0; i < blocks.length; i++) { const block = blocks[i]; const type = block.type; switch (type) { case "system": { if (system != null) { throw new import_provider.UnsupportedFunctionalityError({ functionality: "Multiple system messages that are separated by user/assistant messages" }); } system = block.messages.map(({ content }) => content).join("\n"); break; } case "user": { const anthropicContent = []; for (const { role, content } of block.messages) { switch (role) { case "user": { for (const part of content) { switch (part.type) { case "text": { anthropicContent.push({ type: "text", text: part.text }); break; } case "image": { if (part.image instanceof URL) { throw new import_provider.UnsupportedFunctionalityError({ functionality: "Image URLs in user messages" }); } anthropicContent.push({ type: "image", source: { type: "base64", media_type: (_a = part.mimeType) != null ? _a : "image/jpeg", data: (0, import_provider_utils2.convertUint8ArrayToBase64)(part.image) } }); break; } } } break; } case "tool": { for (const part of content) { anthropicContent.push({ type: "tool_result", tool_use_id: part.toolCallId, content: JSON.stringify(part.result), is_error: part.isError }); } break; } default: { const _exhaustiveCheck = role; throw new Error(`Unsupported role: ${_exhaustiveCheck}`); } } } messages.push({ role: "user", content: anthropicContent }); break; } case "assistant": { if (block.messages.length > 1) { throw new import_provider.UnsupportedFunctionalityError({ functionality: "Multiple assistant messages in block" }); } const { content } = block.messages[0]; messages.push({ role: "assistant", content: content.map((part, j) => { switch (part.type) { case "text": { if (i === blocks.length - 1 && j === block.messages.length - 1) { return { type: "text", text: part.text.trim() }; } return { type: "text", text: part.text }; } case "tool-call": { return { type: "tool_use", id: part.toolCallId, name: part.toolName, input: part.args }; } } }) }); break; } default: { const _exhaustiveCheck = type; throw new Error(`Unsupported type: ${_exhaustiveCheck}`); } } } return { system, messages }; } function groupIntoBlocks(prompt) { const blocks = []; let currentBlock = void 0; for (const { role, content } of prompt) { switch (role) { case "system": { if ((currentBlock == null ? void 0 : currentBlock.type) !== "system") { currentBlock = { type: "system", messages: [] }; blocks.push(currentBlock); } currentBlock.messages.push({ role, content }); break; } case "assistant": { if ((currentBlock == null ? void 0 : currentBlock.type) !== "assistant") { currentBlock = { type: "assistant", messages: [] }; blocks.push(currentBlock); } currentBlock.messages.push({ role, content }); break; } case "user": { if ((currentBlock == null ? void 0 : currentBlock.type) !== "user") { currentBlock = { type: "user", messages: [] }; blocks.push(currentBlock); } currentBlock.messages.push({ role, content }); break; } case "tool": { if ((currentBlock == null ? void 0 : currentBlock.type) !== "user") { currentBlock = { type: "user", messages: [] }; blocks.push(currentBlock); } currentBlock.messages.push({ role, content }); break; } default: { const _exhaustiveCheck = role; throw new Error(`Unsupported role: ${_exhaustiveCheck}`); } } } return blocks; } // src/map-anthropic-stop-reason.ts function mapAnthropicStopReason(finishReason) { switch (finishReason) { case "end_turn": case "stop_sequence": return "stop"; case "tool_use": return "tool-calls"; case "max_tokens": return "length"; default: return "other"; } } // src/anthropic-messages-language-model.ts var AnthropicMessagesLanguageModel = class { constructor(modelId, settings, config) { this.specificationVersion = "v1"; this.defaultObjectGenerationMode = "tool"; this.supportsImageUrls = false; this.defaultVersion = "vertex-2023-10-16"; this.modelId = modelId; this.settings = settings; this.config = config; this.path = `/projects/${config.projectId}/locations/${config.region}/publishers/anthropic/models/${modelId}`; } get provider() { return this.config.provider; } async getArgs({ mode, prompt, maxTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences, responseFormat, seed }) { const type = mode.type; const warnings = []; if (frequencyPenalty != null) { warnings.push({ type: "unsupported-setting", setting: "frequencyPenalty" }); } if (presencePenalty != null) { warnings.push({ type: "unsupported-setting", setting: "presencePenalty" }); } if (seed != null) { warnings.push({ type: "unsupported-setting", setting: "seed" }); } if (responseFormat != null && responseFormat.type !== "text") { warnings.push({ type: "unsupported-setting", setting: "responseFormat", details: "JSON response format is not supported." }); } const messagesPrompt = convertToAnthropicMessagesPrompt(prompt); const baseArgs = { anthropic_version: this.defaultVersion, // model specific settings: top_k: topK != null ? topK : this.settings.topK, // standardized settings: max_tokens: maxTokens != null ? maxTokens : 4096, // 4096: max model output tokens temperature, top_p: topP, stop_sequences: stopSequences, // prompt: system: messagesPrompt.system, messages: messagesPrompt.messages }; switch (type) { case "regular": { return { args: { ...baseArgs, ...prepareToolsAndToolChoice(mode) }, warnings }; } case "object-json": { throw new import_provider2.UnsupportedFunctionalityError({ functionality: "json-mode object generation" }); } case "object-tool": { const { name, description, parameters } = mode.tool; return { args: { ...baseArgs, tools: [{ name, description, input_schema: parameters }], tool_choice: { type: "tool", name } }, warnings }; } default: { const _exhaustiveCheck = type; throw new Error(`Unsupported type: ${_exhaustiveCheck}`); } } } async doGenerate(options) { var _a; const { args, warnings } = await this.getArgs(options); const authClient = await ((_a = this.config.googleAuth) == null ? void 0 : _a.getClient()); const authHeaders = await (authClient == null ? void 0 : authClient.getRequestHeaders()); options.headers = { ...authHeaders, ...options.headers }; const specifier = "rawPredict"; const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}${this.path}:${specifier}`, headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers), body: args, failedResponseHandler: anthropicFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)( anthropicMessagesResponseSchema ), abortSignal: options.abortSignal, fetch: this.config.fetch }); const { messages: rawPrompt, ...rawSettings } = args; let text = ""; for (const content of response.content) { if (content.type === "text") { text += content.text; } } let toolCalls = void 0; if (response.content.some((content) => content.type === "tool_use")) { toolCalls = []; for (const content of response.content) { if (content.type === "tool_use") { toolCalls.push({ toolCallType: "function", toolCallId: content.id, toolName: content.name, args: JSON.stringify(content.input) }); } } } return { text, toolCalls, finishReason: mapAnthropicStopReason(response.stop_reason), usage: { promptTokens: response.usage.input_tokens, completionTokens: response.usage.output_tokens }, rawCall: { rawPrompt, rawSettings }, rawResponse: { headers: responseHeaders }, warnings }; } async doStream(options) { var _a; const { args, warnings } = await this.getArgs(options); const authClient = await ((_a = this.config.googleAuth) == null ? void 0 : _a.getClient()); const authHeaders = await (authClient == null ? void 0 : authClient.getRequestHeaders()); options.headers = { ...authHeaders, ...options.headers }; const specifier = "streamRawPredict"; const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}${this.path}:${specifier}`, headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers), body: { ...args, stream: true }, failedResponseHandler: anthropicFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)( anthropicMessagesChunkSchema ), abortSignal: options.abortSignal, fetch: this.config.fetch }); const { messages: rawPrompt, ...rawSettings } = args; let finishReason = "other"; const usage = { promptTokens: Number.NaN, completionTokens: Number.NaN }; const toolCallContentBlocks = {}; return { stream: response.pipeThrough( new TransformStream({ transform(chunk, controller) { if (!chunk.success) { controller.enqueue({ type: "error", error: chunk.error }); return; } const value = chunk.value; switch (value.type) { case "ping": { return; } case "content_block_start": { const contentBlockType = value.content_block.type; switch (contentBlockType) { case "text": { return; } case "tool_use": { toolCallContentBlocks[value.index] = { toolCallId: value.content_block.id, toolName: value.content_block.name, jsonText: "" }; return; } default: { const _exhaustiveCheck = contentBlockType; throw new Error( `Unsupported content block type: ${_exhaustiveCheck}` ); } } } case "content_block_stop": { if (toolCallContentBlocks[value.index] != null) { const contentBlock = toolCallContentBlocks[value.index]; controller.enqueue({ type: "tool-call", toolCallType: "function", toolCallId: contentBlock.toolCallId, toolName: contentBlock.toolName, args: contentBlock.jsonText }); delete toolCallContentBlocks[value.index]; } return; } case "content_block_delta": { const deltaType = value.delta.type; switch (deltaType) { case "text_delta": { controller.enqueue({ type: "text-delta", textDelta: value.delta.text }); return; } case "input_json_delta": { const contentBlock = toolCallContentBlocks[value.index]; controller.enqueue({ type: "tool-call-delta", toolCallType: "function", toolCallId: contentBlock.toolCallId, toolName: contentBlock.toolName, argsTextDelta: value.delta.partial_json }); contentBlock.jsonText += value.delta.partial_json; return; } default: { const _exhaustiveCheck = deltaType; throw new Error( `Unsupported delta type: ${_exhaustiveCheck}` ); } } } case "message_start": { usage.promptTokens = value.message.usage.input_tokens; usage.completionTokens = value.message.usage.output_tokens; return; } case "message_delta": { usage.completionTokens = value.usage.output_tokens; finishReason = mapAnthropicStopReason(value.delta.stop_reason); return; } case "message_stop": { controller.enqueue({ type: "finish", finishReason, usage }); return; } default: { const _exhaustiveCheck = value; throw new Error(`Unsupported chunk type: ${_exhaustiveCheck}`); } } } }) ), rawCall: { rawPrompt, rawSettings }, rawResponse: { headers: responseHeaders }, warnings }; } }; var anthropicMessagesResponseSchema = import_zod2.z.object({ type: import_zod2.z.literal("message"), content: import_zod2.z.array( import_zod2.z.discriminatedUnion("type", [ import_zod2.z.object({ type: import_zod2.z.literal("text"), text: import_zod2.z.string() }), import_zod2.z.object({ type: import_zod2.z.literal("tool_use"), id: import_zod2.z.string(), name: import_zod2.z.string(), input: import_zod2.z.unknown() }) ]) ), stop_reason: import_zod2.z.string().optional().nullable(), usage: import_zod2.z.object({ input_tokens: import_zod2.z.number(), output_tokens: import_zod2.z.number() }) }); var anthropicMessagesChunkSchema = import_zod2.z.discriminatedUnion("type", [ import_zod2.z.object({ type: import_zod2.z.literal("message_start"), message: import_zod2.z.object({ usage: import_zod2.z.object({ input_tokens: import_zod2.z.number(), output_tokens: import_zod2.z.number() }) }) }), import_zod2.z.object({ type: import_zod2.z.literal("content_block_start"), index: import_zod2.z.number(), content_block: import_zod2.z.discriminatedUnion("type", [ import_zod2.z.object({ type: import_zod2.z.literal("text"), text: import_zod2.z.string() }), import_zod2.z.object({ type: import_zod2.z.literal("tool_use"), id: import_zod2.z.string(), name: import_zod2.z.string() }) ]) }), import_zod2.z.object({ type: import_zod2.z.literal("content_block_delta"), index: import_zod2.z.number(), delta: import_zod2.z.discriminatedUnion("type", [ import_zod2.z.object({ type: import_zod2.z.literal("input_json_delta"), partial_json: import_zod2.z.string() }), import_zod2.z.object({ type: import_zod2.z.literal("text_delta"), text: import_zod2.z.string() }) ]) }), import_zod2.z.object({ type: import_zod2.z.literal("content_block_stop"), index: import_zod2.z.number() }), import_zod2.z.object({ type: import_zod2.z.literal("message_delta"), delta: import_zod2.z.object({ stop_reason: import_zod2.z.string().optional().nullable() }), usage: import_zod2.z.object({ output_tokens: import_zod2.z.number() }) }), import_zod2.z.object({ type: import_zod2.z.literal("message_stop") }), import_zod2.z.object({ type: import_zod2.z.literal("ping") }) ]); function prepareToolsAndToolChoice(mode) { var _a; const tools = ((_a = mode.tools) == null ? void 0 : _a.length) ? mode.tools : void 0; if (tools == null) { return { tools: void 0, tool_choice: void 0 }; } const mappedTools = tools.map((tool) => ({ name: tool.name, description: tool.description, input_schema: tool.parameters })); const toolChoice = mode.toolChoice; if (toolChoice == null) { return { tools: mappedTools, tool_choice: void 0 }; } const type = toolChoice.type; switch (type) { case "auto": return { tools: mappedTools, tool_choice: { type: "auto" } }; case "required": return { tools: mappedTools, tool_choice: { type: "any" } }; case "none": return { tools: void 0, tool_choice: void 0 }; case "tool": return { tools: mappedTools, tool_choice: { type: "tool", name: toolChoice.toolName } }; default: { const _exhaustiveCheck = type; throw new Error(`Unsupported tool choice type: ${_exhaustiveCheck}`); } } } // src/anthropic-vertex-provider.ts function createAnthropicVertex(options = {}) { const getConfig = () => { const config = { projectId: (0, import_provider_utils4.loadSetting)({ settingValue: options.projectId, settingName: "projectId", environmentVariableName: "GOOGLE_VERTEX_PROJECT_ID", description: "Google Vertex project id" }), region: (0, import_provider_utils4.loadSetting)({ settingValue: options.region, settingName: "region", environmentVariableName: "GOOGLE_VERTEX_REGION", description: "Google Vertex region" }), googleAuth: options.googleAuth }; if (!config.region) { throw new Error( "No region was given. The client should be instantiated with the `region` option or the `GOOGLE_VERTEX_REGION` environment variable should be set." ); } if (!config.projectId) { throw new Error( "No project was given. The client should be instantiated with the `projectID` option or the `GOOGLE_VERTEX_PROJECT_ID` environment variable should be set." ); } return config; }; const createChatModel = (modelId, settings = {}) => { var _a, _b; const config = getConfig(); const baseURL = (_a = (0, import_provider_utils4.withoutTrailingSlash)(options.baseURL)) != null ? _a : `https://${config.region}-aiplatform.googleapis.com/v1`; const auth = (_b = options.googleAuth) != null ? _b : new import_google_auth_library.GoogleAuth({ scopes: "https://www.googleapis.com/auth/cloud-platform" }); return new AnthropicMessagesLanguageModel(modelId, settings, { provider: "anthropic.messages", baseURL, headers: () => ({ ...options.headers }), fetch: options.fetch, projectId: config.projectId, region: config.region, googleAuth: auth }); }; const provider = function(modelId, settings) { if (new.target) { throw new Error( "The Anthropic model function cannot be called with the new keyword." ); } return createChatModel(modelId, settings); }; provider.languageModel = createChatModel; provider.chat = createChatModel; return provider; } var anthropicVertex = createAnthropicVertex(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { anthropicVertex, createAnthropicVertex }); //# sourceMappingURL=index.js.map