UNPKG

@genkit-ai/vertexai

Version:

Genkit AI framework plugin for Google Cloud Vertex AI APIs including Gemini APIs, Imagen, and more.

459 lines 13.5 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); var anthropic_exports = {}; __export(anthropic_exports, { AnthropicConfigSchema: () => AnthropicConfigSchema, GENERIC_MODEL: () => GENERIC_MODEL, KNOWN_MODELS: () => KNOWN_MODELS, ThinkingConfigSchema: () => ThinkingConfigSchema, defineModel: () => defineModel, fromAnthropicResponse: () => fromAnthropicResponse, isAnthropicModelName: () => isAnthropicModelName, listActions: () => listActions, listKnownModels: () => listKnownModels, model: () => model, toAnthropicRequest: () => toAnthropicRequest }); module.exports = __toCommonJS(anthropic_exports); var import_vertex_sdk = require("@anthropic-ai/vertex-sdk"); var import_genkit = require("genkit"); var import_model = require("genkit/model"); var import_plugin = require("genkit/plugin"); var import_common = require("../../common/index.js"); var import_utils = require("./utils.js"); const ThinkingConfigSchema = import_genkit.z.object({ enabled: import_genkit.z.boolean().optional(), budgetTokens: import_genkit.z.number().min(1024).optional(), adaptive: import_genkit.z.boolean().optional(), display: import_genkit.z.enum(["summarized", "omitted"]).optional() }).passthrough().superRefine((value, ctx) => { if (value.enabled && value.adaptive) { ctx.addIssue({ code: import_genkit.z.ZodIssueCode.custom, path: ["adaptive"], message: "Cannot use both enabled and adaptive thinking modes simultaneously" }); } if (value.enabled) { if (value.budgetTokens === void 0) { ctx.addIssue({ code: import_genkit.z.ZodIssueCode.custom, path: ["budgetTokens"], message: "budgetTokens is required when thinking is enabled" }); } else if (!Number.isInteger(value.budgetTokens)) { ctx.addIssue({ code: import_genkit.z.ZodIssueCode.custom, path: ["budgetTokens"], message: "budgetTokens must be an integer" }); } } }); const AnthropicConfigSchema = import_model.GenerationCommonConfigSchema.extend({ location: import_genkit.z.string().optional(), thinking: ThinkingConfigSchema.optional().describe( "The thinking configuration to use for the request. Thinking is a feature that allows the model to think about the request and provide a better response." ), output_config: import_genkit.z.object({ effort: import_genkit.z.enum(["low", "medium", "high", "xhigh"]).optional() }).passthrough().describe( "Configuration for output generation, such as setting the effort parameter." ).optional() }).passthrough(); function commonRef(name, info, configSchema = AnthropicConfigSchema) { return (0, import_model.modelRef)({ name: `vertex-model-garden/${name}`, configSchema, info: info ?? { supports: { multiturn: true, media: true, tools: true, systemRole: true, output: ["text"] } } }); } const GENERIC_MODEL = commonRef("anthropic"); const KNOWN_MODELS = { "claude-opus-4-7": commonRef("claude-opus-4-7"), "claude-sonnet-4-6": commonRef("claude-sonnet-4-6"), "claude-opus-4-6": commonRef("claude-opus-4-6"), "claude-haiku-4-5@20251001": commonRef("claude-haiku-4-5@20251001"), "claude-sonnet-4-5@20250929": commonRef("claude-sonnet-4-5@20250929"), "claude-sonnet-4@20250514": commonRef("claude-sonnet-4@20250514"), "claude-opus-4-5@20251101": commonRef("claude-opus-4-5@20251101"), "claude-opus-4-1@20250805": commonRef("claude-opus-4-1@20250805"), "claude-opus-4@20250514": commonRef("claude-opus-4@20250514") }; function isAnthropicModelName(value) { return !!value?.startsWith("claude-"); } function model(version, options = {}) { const name = (0, import_utils.checkModelName)(version); return (0, import_model.modelRef)({ name: `vertex-model-garden/${name}`, config: options, configSchema: AnthropicConfigSchema, info: { ...GENERIC_MODEL.info } }); } function listActions(clientOptions) { return []; } function listKnownModels(clientOptions, pluginOptions) { return Object.keys(KNOWN_MODELS).map( (name) => defineModel(name, clientOptions, pluginOptions) ); } function defineModel(name, clientOptions, pluginOptions) { const clients = {}; const clientFactory = (region) => { if (!clients[region]) { clients[region] = new import_vertex_sdk.AnthropicVertex({ region, projectId: clientOptions.projectId, defaultHeaders: { "X-Goog-Api-Client": (0, import_common.getGenkitClientHeader)() } }); } return clients[region]; }; const ref = model(name); return (0, import_plugin.model)( { name: ref.name, ...ref.info, configSchema: ref.configSchema }, async (request, { streamingRequested, sendChunk }) => { const client = clientFactory( request.config?.location || clientOptions.location ); const modelVersion = (0, import_utils.checkModelName)(ref.name); const anthropicRequest = toAnthropicRequest(modelVersion, request); if (!streamingRequested) { const response = await client.messages.create({ ...anthropicRequest, stream: false }); return fromAnthropicResponse(request, response); } else { const stream = await client.messages.stream(anthropicRequest); for await (const event of stream) { if (event.type === "content_block_delta") { sendChunk({ index: 0, content: [ { text: event.delta.text } ] }); } } return fromAnthropicResponse(request, await stream.finalMessage()); } } ); } function toAnthropicRequest(model2, input) { let system = void 0; const messages = []; for (const msg of input.messages) { if (msg.role === "system") { system = msg.content.map((c) => { if (!c.text) { throw new Error( "Only text context is supported for system messages." ); } return c.text; }).join(); } else if (msg.content[msg.content.length - 1].toolResponse) { messages.push({ role: "user", content: toAnthropicContent(msg.content) }); } else { messages.push({ role: toAnthropicRole(msg.role), content: toAnthropicContent(msg.content) }); } } const { location, version, maxOutputTokens, stopSequences, temperature, topK, topP, thinking, output_config, ...restConfig } = input.config ?? {}; const request = { model: model2, messages, // https://docs.anthropic.com/claude/docs/models-overview#model-comparison max_tokens: maxOutputTokens ?? 4096, ...restConfig }; if (system) { request["system"] = system; } if (input.tools) { request.tools = input.tools?.map((tool) => { return { name: tool.name, description: tool.description, input_schema: tool.inputSchema }; }); } if (stopSequences) { request.stop_sequences = stopSequences; } if (temperature !== void 0) { request.temperature = temperature; } if (topK !== void 0) { request.top_k = topK; } if (topP !== void 0) { request.top_p = topP; } if (thinking) { const anthropicThinking = toAnthropicThinking(thinking); if (anthropicThinking) { request.thinking = anthropicThinking; } } if (output_config) { request.output_config = output_config; } return request; } function toAnthropicThinking(config) { if (!config) return void 0; const { enabled, budgetTokens, adaptive, display } = config; if (adaptive === true) { return { type: "adaptive", ...display !== void 0 && { display } }; } if (enabled === true) { if (budgetTokens === void 0) { throw new Error("budgetTokens is required when thinking is enabled"); } return { type: "enabled", budget_tokens: budgetTokens }; } if (enabled === false) { return { type: "disabled" }; } if (budgetTokens !== void 0) { return { type: "enabled", budget_tokens: budgetTokens }; } return void 0; } function toAnthropicContent(content) { return content.map((p) => { if (p.reasoning) { const signature = p.metadata?.thoughtSignature; return { type: "thinking", thinking: p.reasoning, ...signature ? { signature } : {} }; } if (p.text) { return { type: "text", text: p.text }; } if (p.media) { let b64Data = p.media.url; if (b64Data.startsWith("data:")) { b64Data = b64Data.substring(b64Data.indexOf(",") + 1); } return { type: "image", source: { type: "base64", data: b64Data, media_type: p.media.contentType } }; } if (p.toolRequest) { return toAnthropicToolRequest(p.toolRequest); } if (p.toolResponse) { return toAnthropicToolResponse(p); } throw new Error(`Unsupported content type: ${JSON.stringify(p)}`); }); } function toAnthropicRole(role) { if (role === "model") { return "assistant"; } if (role === "user") { return "user"; } if (role === "tool") { return "assistant"; } throw new Error(`Unsupported role type ${role}`); } function fromAnthropicTextPart(part) { return { text: part.text }; } function fromAnthropicToolCallPart(part) { return { toolRequest: { name: part.name, input: part.input, ref: part.id } }; } function fromAnthropicThinkingPart(part) { if (part.signature !== void 0) { return { reasoning: part.thinking, metadata: { thoughtSignature: part.signature } }; } return { reasoning: part.thinking }; } function fromAnthropicPart(part) { if (part.type === "text") return fromAnthropicTextPart(part); if (part.type === "tool_use") return fromAnthropicToolCallPart(part); if (part.type === "thinking") return fromAnthropicThinkingPart(part); const unknownType = part.type; console.warn( `Unexpected Anthropic content block type: ${unknownType}. Returning empty text.` ); return { text: "" }; } function fromAnthropicResponse(input, response) { const parts = response.content; const message = { role: "model", content: parts.map(fromAnthropicPart) }; return { message, finishReason: toGenkitFinishReason( response.stop_reason ), custom: { id: response.id, model: response.model, type: response.type }, raw: response, usage: { ...(0, import_model.getBasicUsageStats)(input.messages, message), inputTokens: response.usage.input_tokens, outputTokens: response.usage.output_tokens, custom: { cache_creation_input_tokens: response.usage.cache_creation_input_tokens ?? 0, cache_read_input_tokens: response.usage.cache_read_input_tokens ?? 0, ephemeral_5m_input_tokens: response.usage.cache_creation?.ephemeral_5m_input_tokens ?? 0, ephemeral_1h_input_tokens: response.usage.cache_creation?.ephemeral_1h_input_tokens ?? 0 } } }; } function toGenkitFinishReason(reason) { switch (reason) { case "end_turn": return "stop"; case "max_tokens": return "length"; case "stop_sequence": return "stop"; case "tool_use": return "stop"; case null: return "unknown"; default: return "other"; } } function toAnthropicToolRequest(tool) { if (!tool.name) { throw new Error("Tool name is required"); } if (!/^[a-zA-Z0-9_-]{1,64}$/.test(tool.name)) { throw new Error( `Tool name ${tool.name} contains invalid characters. Only letters, numbers, and underscores are allowed, and the name must be between 1 and 64 characters long.` ); } const declaration = { type: "tool_use", id: tool.ref, name: tool.name, input: tool.input }; return declaration; } function toAnthropicToolResponse(part) { if (!part.toolResponse?.ref) { throw new Error("Tool response reference is required"); } if (!part.toolResponse.output) { throw new Error("Tool response output is required"); } return { type: "tool_result", tool_use_id: part.toolResponse.ref, content: JSON.stringify(part.toolResponse.output) }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AnthropicConfigSchema, GENERIC_MODEL, KNOWN_MODELS, ThinkingConfigSchema, defineModel, fromAnthropicResponse, isAnthropicModelName, listActions, listKnownModels, model, toAnthropicRequest }); //# sourceMappingURL=anthropic.js.map