@genkit-ai/vertexai
Version:
Genkit AI framework plugin for Google Cloud Vertex AI APIs including Gemini APIs, Imagen, and more.
1 lines • 18 kB
Source Map (JSON)
{"version":3,"sources":["../../src/modelgarden/anthropic.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ContentBlock as AnthropicContent,\n ImageBlockParam,\n Message,\n MessageCreateParamsBase,\n MessageParam,\n TextBlock,\n TextBlockParam,\n TextDelta,\n Tool,\n ToolResultBlockParam,\n ToolUseBlock,\n ToolUseBlockParam,\n} from '@anthropic-ai/sdk/resources/messages';\nimport { AnthropicVertex } from '@anthropic-ai/vertex-sdk';\nimport {\n GENKIT_CLIENT_HEADER,\n GenerateRequest,\n Genkit,\n Part as GenkitPart,\n MessageData,\n ModelReference,\n ModelResponseData,\n Part,\n z,\n} from 'genkit';\nimport {\n GenerationCommonConfigSchema,\n ModelAction,\n getBasicUsageStats,\n modelRef,\n} from 'genkit/model';\n\nexport const AnthropicConfigSchema = GenerationCommonConfigSchema.extend({\n location: z.string().optional(),\n});\n\nexport const claude35SonnetV2 = modelRef({\n name: 'vertexai/claude-3-5-sonnet-v2',\n info: {\n label: 'Vertex AI Model Garden - Claude 3.5 Sonnet',\n versions: ['claude-3-5-sonnet-v2@20241022'],\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n systemRole: true,\n output: ['text'],\n },\n },\n configSchema: AnthropicConfigSchema,\n});\n\nexport const claude35Sonnet = modelRef({\n name: 'vertexai/claude-3-5-sonnet',\n info: {\n label: 'Vertex AI Model Garden - Claude 3.5 Sonnet',\n versions: ['claude-3-5-sonnet@20240620'],\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n systemRole: true,\n output: ['text'],\n },\n },\n configSchema: AnthropicConfigSchema,\n});\n\nexport const claude3Sonnet = modelRef({\n name: 'vertexai/claude-3-sonnet',\n info: {\n label: 'Vertex AI Model Garden - Claude 3 Sonnet',\n versions: ['claude-3-sonnet@20240229'],\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n systemRole: true,\n output: ['text'],\n },\n },\n configSchema: AnthropicConfigSchema,\n});\n\nexport const claude3Haiku = modelRef({\n name: 'vertexai/claude-3-haiku',\n info: {\n label: 'Vertex AI Model Garden - Claude 3 Haiku',\n versions: ['claude-3-haiku@20240307'],\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n systemRole: true,\n output: ['text'],\n },\n },\n configSchema: AnthropicConfigSchema,\n});\n\nexport const claude3Opus = modelRef({\n name: 'vertexai/claude-3-opus',\n info: {\n label: 'Vertex AI Model Garden - Claude 3 Opus',\n versions: ['claude-3-opus@20240229'],\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n systemRole: true,\n output: ['text'],\n },\n },\n configSchema: AnthropicConfigSchema,\n});\n\nexport const SUPPORTED_ANTHROPIC_MODELS: Record<\n string,\n ModelReference<typeof AnthropicConfigSchema>\n> = {\n 'claude-3-5-sonnet-v2': claude35SonnetV2,\n 'claude-3-5-sonnet': claude35Sonnet,\n 'claude-3-sonnet': claude3Sonnet,\n 'claude-3-opus': claude3Opus,\n 'claude-3-haiku': claude3Haiku,\n};\n\nexport function toAnthropicRequest(\n model: string,\n input: GenerateRequest<typeof AnthropicConfigSchema>\n): MessageCreateParamsBase {\n let system: string | undefined = undefined;\n const messages: MessageParam[] = [];\n for (const msg of input.messages) {\n if (msg.role === 'system') {\n system = msg.content\n .map((c) => {\n if (!c.text) {\n throw new Error(\n 'Only text context is supported for system messages.'\n );\n }\n return c.text;\n })\n .join();\n }\n // If the last message is a tool response, we need to add a user message.\n // https://docs.anthropic.com/en/docs/build-with-claude/tool-use#handling-tool-use-and-tool-result-content-blocks\n else if (msg.content[msg.content.length - 1].toolResponse) {\n messages.push({\n role: 'user',\n content: toAnthropicContent(msg.content),\n });\n } else {\n messages.push({\n role: toAnthropicRole(msg.role),\n content: toAnthropicContent(msg.content),\n });\n }\n }\n const request = {\n model,\n messages,\n // https://docs.anthropic.com/claude/docs/models-overview#model-comparison\n max_tokens: input.config?.maxOutputTokens ?? 4096,\n } as MessageCreateParamsBase;\n if (system) {\n request['system'] = system;\n }\n if (input.tools) {\n request.tools = input.tools?.map((tool) => {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema,\n };\n }) as Array<Tool>;\n }\n if (input.config?.stopSequences) {\n request.stop_sequences = input.config?.stopSequences;\n }\n if (input.config?.temperature) {\n request.temperature = input.config?.temperature;\n }\n if (input.config?.topK) {\n request.top_k = input.config?.topK;\n }\n if (input.config?.topP) {\n request.top_p = input.config?.topP;\n }\n return request;\n}\n\nfunction toAnthropicContent(\n content: GenkitPart[]\n): Array<\n TextBlockParam | ImageBlockParam | ToolUseBlockParam | ToolResultBlockParam\n> {\n return content.map((p) => {\n if (p.text) {\n return {\n type: 'text',\n text: p.text,\n };\n }\n if (p.media) {\n let b64Data = p.media.url;\n if (b64Data.startsWith('data:')) {\n b64Data = b64Data.substring(b64Data.indexOf(',')! + 1);\n }\n\n return {\n type: 'image',\n source: {\n type: 'base64',\n data: b64Data,\n media_type: p.media.contentType as\n | 'image/jpeg'\n | 'image/png'\n | 'image/gif'\n | 'image/webp',\n },\n };\n }\n if (p.toolRequest) {\n return toAnthropicToolRequest(p.toolRequest);\n }\n if (p.toolResponse) {\n return toAnthropicToolResponse(p);\n }\n throw new Error(`Unsupported content type: ${JSON.stringify(p)}`);\n });\n}\n\nfunction toAnthropicRole(role): 'user' | 'assistant' {\n if (role === 'model') {\n return 'assistant';\n }\n if (role === 'user') {\n return 'user';\n }\n if (role === 'tool') {\n return 'assistant';\n }\n throw new Error(`Unsupported role type ${role}`);\n}\n\nfunction fromAnthropicTextPart(part: TextBlock): Part {\n return {\n text: part.text,\n };\n}\n\nfunction fromAnthropicToolCallPart(part: ToolUseBlock): Part {\n return {\n toolRequest: {\n name: part.name,\n input: part.input,\n ref: part.id,\n },\n };\n}\n\n// Converts an Anthropic part to a Genkit part.\nfunction fromAnthropicPart(part: AnthropicContent): Part {\n if (part.type === 'text') return fromAnthropicTextPart(part);\n if (part.type === 'tool_use') return fromAnthropicToolCallPart(part);\n throw new Error(\n 'Part type is unsupported/corrupted. Either data is missing or type cannot be inferred from type.'\n );\n}\n\n// Converts an Anthropic response to a Genkit response.\nexport function fromAnthropicResponse(\n input: GenerateRequest<typeof AnthropicConfigSchema>,\n response: Message\n): ModelResponseData {\n const parts = response.content as AnthropicContent[];\n const message: MessageData = {\n role: 'model',\n content: parts.map(fromAnthropicPart),\n };\n return {\n message,\n finishReason: toGenkitFinishReason(\n response.stop_reason as\n | 'end_turn'\n | 'max_tokens'\n | 'stop_sequence'\n | 'tool_use'\n | null\n ),\n custom: {\n id: response.id,\n model: response.model,\n type: response.type,\n },\n usage: {\n ...getBasicUsageStats(input.messages, message),\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n };\n}\n\nfunction toGenkitFinishReason(\n reason: 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use' | null\n): ModelResponseData['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'stop';\n case null:\n return 'unknown';\n default:\n return 'other';\n }\n}\n\nfunction toAnthropicToolRequest(tool: Record<string, any>): ToolUseBlock {\n if (!tool.name) {\n throw new Error('Tool name is required');\n }\n // Validate the tool name, Anthropic only supports letters, numbers, and underscores.\n // https://docs.anthropic.com/en/docs/build-with-claude/tool-use#specifying-tools\n if (!/^[a-zA-Z0-9_-]{1,64}$/.test(tool.name)) {\n throw new Error(\n `Tool name ${tool.name} contains invalid characters.\n Only letters, numbers, and underscores are allowed,\n and the name must be between 1 and 64 characters long.`\n );\n }\n const declaration: ToolUseBlock = {\n type: 'tool_use',\n id: tool.ref,\n name: tool.name,\n input: tool.input,\n };\n return declaration;\n}\n\nfunction toAnthropicToolResponse(part: Part): ToolResultBlockParam {\n if (!part.toolResponse?.ref) {\n throw new Error('Tool response reference is required');\n }\n\n if (!part.toolResponse.output) {\n throw new Error('Tool response output is required');\n }\n\n return {\n type: 'tool_result',\n tool_use_id: part.toolResponse.ref,\n content: JSON.stringify(part.toolResponse.output),\n };\n}\n\nexport function anthropicModel(\n ai: Genkit,\n modelName: string,\n projectId: string,\n region: string\n): ModelAction {\n const clients: Record<string, AnthropicVertex> = {};\n const clientFactory = (region: string): AnthropicVertex => {\n if (!clients[region]) {\n clients[region] = new AnthropicVertex({\n region,\n projectId,\n defaultHeaders: {\n 'X-Goog-Api-Client': GENKIT_CLIENT_HEADER,\n },\n });\n }\n return clients[region];\n };\n const model = SUPPORTED_ANTHROPIC_MODELS[modelName];\n if (!model) {\n throw new Error(`unsupported Anthropic model name ${modelName}`);\n }\n\n return ai.defineModel(\n {\n name: model.name,\n label: model.info?.label,\n configSchema: AnthropicConfigSchema,\n supports: model.info?.supports,\n versions: model.info?.versions,\n },\n async (input, sendChunk) => {\n const client = clientFactory(input.config?.location || region);\n if (!sendChunk) {\n const response = await client.messages.create({\n ...toAnthropicRequest(input.config?.version ?? modelName, input),\n stream: false,\n });\n return fromAnthropicResponse(input, response);\n } else {\n const stream = await client.messages.stream(\n toAnthropicRequest(input.config?.version ?? modelName, input)\n );\n for await (const event of stream) {\n if (event.type === 'content_block_delta') {\n sendChunk({\n index: 0,\n content: [\n {\n text: (event.delta as TextDelta).text,\n },\n ],\n });\n }\n }\n return fromAnthropicResponse(input, await stream.finalMessage());\n }\n }\n );\n}\n"],"mappings":"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","names":["region"]}