UNPKG

genkitx-anthropic

Version:

Firebase Genkit AI framework plugin for Anthropic APIs.

505 lines 16.3 kB
"use strict"; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name); var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); 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 __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it); var claude_exports = {}; __export(claude_exports, { AnthropicConfigSchema: () => AnthropicConfigSchema, SUPPORTED_CLAUDE_MODELS: () => SUPPORTED_CLAUDE_MODELS, claude35Haiku: () => claude35Haiku, claude35Sonnet: () => claude35Sonnet, claude37Sonnet: () => claude37Sonnet, claude3Haiku: () => claude3Haiku, claude3Opus: () => claude3Opus, claude3Sonnet: () => claude3Sonnet, claudeModel: () => claudeModel, claudeRunner: () => claudeRunner, fromAnthropicContentBlockChunk: () => fromAnthropicContentBlockChunk, fromAnthropicResponse: () => fromAnthropicResponse, fromAnthropicStopReason: () => fromAnthropicStopReason, toAnthropicMessageContent: () => toAnthropicMessageContent, toAnthropicMessages: () => toAnthropicMessages, toAnthropicRequestBody: () => toAnthropicRequestBody, toAnthropicRole: () => toAnthropicRole, toAnthropicTool: () => toAnthropicTool, toAnthropicToolResponseContent: () => toAnthropicToolResponseContent }); module.exports = __toCommonJS(claude_exports); var import_genkit = require("genkit"); var import_genkit2 = require("genkit"); var import_model = require("genkit/model"); const AnthropicConfigSchema = import_genkit2.GenerationCommonConfigSchema.extend({ tool_choice: import_genkit.z.union([ import_genkit.z.object({ type: import_genkit.z.literal("auto") }), import_genkit.z.object({ type: import_genkit.z.literal("any") }), import_genkit.z.object({ type: import_genkit.z.literal("tool"), name: import_genkit.z.string() }) ]).optional(), metadata: import_genkit.z.object({ user_id: import_genkit.z.string().optional() }).optional() }); const claude37Sonnet = (0, import_model.modelRef)({ name: "anthropic/claude-3-7-sonnet", info: { versions: ["claude-3-7-sonnet-20250219", "claude-3-7-sonnet-latest"], label: "Anthropic - Claude 3.7 Sonnet", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-7-sonnet-latest" }); const claude35Sonnet = (0, import_model.modelRef)({ name: "anthropic/claude-3-5-sonnet", info: { versions: [ "claude-3-5-sonnet-20240620", "claude-3-5-sonnet-20241022", "claude-3-5-sonnet-latest" ], label: "Anthropic - Claude 3.5 Sonnet", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-5-sonnet-latest" }); const claude3Opus = (0, import_model.modelRef)({ name: "anthropic/claude-3-opus", info: { versions: ["claude-3-opus-20240229"], label: "Anthropic - Claude 3 Opus", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-opus-20240229" }); const claude3Sonnet = (0, import_model.modelRef)({ name: "anthropic/claude-3-sonnet", info: { versions: ["claude-3-sonnet-20240229"], label: "Anthropic - Claude 3 Sonnet", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-sonnet-20240229" }); const claude3Haiku = (0, import_model.modelRef)({ name: "anthropic/claude-3-haiku", info: { versions: ["claude-3-haiku-20240307"], label: "Anthropic - Claude 3 Haiku", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-haiku-20240307" }); const claude35Haiku = (0, import_model.modelRef)({ name: "anthropic/claude-3-5-haiku", info: { versions: ["claude-3-5-haiku-20241022", "claude-3-5-haiku-latest"], label: "Anthropic - Claude 3.5 Haiku", supports: { multiturn: true, tools: true, media: true, systemRole: true, output: ["text"] } }, configSchema: AnthropicConfigSchema, version: "claude-3-5-haiku-latest" }); const SUPPORTED_CLAUDE_MODELS = { "claude-3-7-sonnet": claude37Sonnet, "claude-3-5-sonnet": claude35Sonnet, "claude-3-opus": claude3Opus, "claude-3-sonnet": claude3Sonnet, "claude-3-haiku": claude3Haiku, "claude-3-5-haiku": claude35Haiku }; function toAnthropicRole(role, toolMessageType) { switch (role) { case "user": return "user"; case "model": return "assistant"; case "tool": return toolMessageType === "tool_use" ? "assistant" : "user"; default: throw new Error(`role ${role} doesn't map to an Anthropic role.`); } } const isMediaObject = (obj) => typeof obj === "object" && obj !== null && "url" in obj && typeof obj.url === "string"; const extractDataFromBase64Url = (url) => { const match = url.match(/^data:([^;]+);base64,(.+)$/); return match && { contentType: match[1], data: match[2] }; }; function toAnthropicToolResponseContent(part) { var _a, _b, _c, _d, _e, _f, _g, _h, _i; if (!part.toolResponse) { throw Error( `Invalid genkit part provided to toAnthropicToolResponseContent: ${JSON.stringify( part )}.` ); } const isMedia = isMediaObject((_a = part.toolResponse) == null ? void 0 : _a.output); const isString = typeof ((_b = part.toolResponse) == null ? void 0 : _b.output) === "string"; let base64Data; if (isMedia) { base64Data = extractDataFromBase64Url( ((_c = part.toolResponse) == null ? void 0 : _c.output).url ); } else if (isString) { base64Data = extractDataFromBase64Url((_d = part.toolResponse) == null ? void 0 : _d.output); } return base64Data ? { type: "image", source: { type: "base64", data: base64Data.data, media_type: (_g = (_f = (_e = part.toolResponse) == null ? void 0 : _e.output) == null ? void 0 : _f.contentType) != null ? _g : base64Data.contentType } } : { type: "text", text: isString ? (_h = part.toolResponse) == null ? void 0 : _h.output : JSON.stringify((_i = part.toolResponse) == null ? void 0 : _i.output) }; } function toAnthropicMessageContent(part) { var _a, _b; if (part.text) { return { type: "text", text: part.text }; } if (part.media) { const { data, contentType } = (_a = extractDataFromBase64Url(part.media.url)) != null ? _a : {}; if (!data) { throw Error( `Invalid genkit part media provided to toAnthropicMessageContent: ${JSON.stringify( part.media )}.` ); } return { type: "image", source: { type: "base64", data, // @ts-expect-error TODO: improve these types media_type: (_b = part.media.contentType) != null ? _b : contentType } }; } if (part.toolRequest) { return { type: "tool_use", id: part.toolRequest.ref, name: part.toolRequest.name, input: part.toolRequest.input }; } if (part.toolResponse) { return { type: "tool_result", tool_use_id: part.toolResponse.ref, content: [toAnthropicToolResponseContent(part)] }; } throw Error( `Unsupported genkit part fields encountered for current message role: ${JSON.stringify( part )}.` ); } function toAnthropicMessages(messages) { var _a, _b, _c; const system = ((_a = messages[0]) == null ? void 0 : _a.role) === "system" ? (_c = (_b = messages[0].content) == null ? void 0 : _b[0]) == null ? void 0 : _c.text : void 0; const messagesToIterate = system ? messages.slice(1) : messages; const anthropicMsgs = []; for (const message of messagesToIterate) { const msg = new import_genkit.Message(message); const content = msg.content.map(toAnthropicMessageContent); const toolMessageType = content.find( (c) => c.type === "tool_use" || c.type === "tool_result" ); const role = toAnthropicRole(message.role, toolMessageType == null ? void 0 : toolMessageType.type); anthropicMsgs.push({ role, content }); } return { system, messages: anthropicMsgs }; } function toAnthropicTool(tool) { return { name: tool.name, description: tool.description, input_schema: tool.inputSchema }; } function fromAnthropicContentBlock(contentBlock) { return contentBlock.type === "tool_use" ? { toolRequest: { ref: contentBlock.id, name: contentBlock.name, input: contentBlock.input } } : { text: contentBlock.text }; } function fromAnthropicContentBlockChunk(event) { if (event.type !== "content_block_start" && event.type !== "content_block_delta") { return; } const eventField = event.type === "content_block_start" ? "content_block" : "delta"; return ["text", "text_delta"].includes(event[eventField].type) ? { text: event[eventField].text } : { toolRequest: { ref: event[eventField].id, name: event[eventField].name, input: event[eventField].input } }; } function fromAnthropicStopReason(reason) { switch (reason) { case "max_tokens": return "length"; case "end_turn": // fall through case "stop_sequence": // fall through case "tool_use": return "stop"; case null: return "unknown"; default: return "other"; } } function fromAnthropicResponse(response) { return { candidates: [ { index: 0, finishReason: fromAnthropicStopReason(response.stop_reason), message: { role: "model", content: response.content.map(fromAnthropicContentBlock) } } ], usage: { inputTokens: response.usage.input_tokens, outputTokens: response.usage.output_tokens }, custom: response }; } function toAnthropicRequestBody(modelName, request, stream, cacheSystemPrompt) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m; const model = SUPPORTED_CLAUDE_MODELS[modelName]; if (!model) throw new Error(`Unsupported model: ${modelName}`); const { system, messages } = toAnthropicMessages(request.messages); const mappedModelName = (_c = (_b = (_a = request.config) == null ? void 0 : _a.version) != null ? _b : model.version) != null ? _c : modelName; const body = { system: cacheSystemPrompt ? [ { type: "text", text: system, // @ts-expect-error cache_control is in beta cache_control: { type: "ephemeral" } } ] : system, messages, tools: (_d = request.tools) == null ? void 0 : _d.map(toAnthropicTool), max_tokens: (_f = (_e = request.config) == null ? void 0 : _e.maxOutputTokens) != null ? _f : 4096, model: mappedModelName, top_k: (_g = request.config) == null ? void 0 : _g.topK, top_p: (_h = request.config) == null ? void 0 : _h.topP, temperature: (_i = request.config) == null ? void 0 : _i.temperature, stop_sequences: (_j = request.config) == null ? void 0 : _j.stopSequences, metadata: (_k = request.config) == null ? void 0 : _k.metadata, tool_choice: (_l = request.config) == null ? void 0 : _l.tool_choice, stream }; if (((_m = request.output) == null ? void 0 : _m.format) && request.output.format !== "text") { throw new Error( `Only text output format is supported for Claude models currently` ); } for (const key in body) { if (!body[key] || Array.isArray(body[key]) && !body[key].length) delete body[key]; } return body; } function claudeRunner(name, client, cacheSystemPrompt) { return (request, streamingCallback) => __async(this, null, function* () { let response; const body = toAnthropicRequestBody( name, request, !!streamingCallback, cacheSystemPrompt ); if (streamingCallback) { const stream = client.messages.stream(body); try { for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield iter.next()).done; more = false) { const chunk = temp.value; const c = fromAnthropicContentBlockChunk(chunk); if (c) { streamingCallback({ index: 0, content: [c] }); } } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && (yield temp.call(iter)); } finally { if (error) throw error[0]; } } response = yield stream.finalMessage(); } else { response = yield client.messages.create(body); } return fromAnthropicResponse(response); }); } function claudeModel(ai, name, client, cacheSystemPrompt) { const modelId = `anthropic/${name}`; const model = SUPPORTED_CLAUDE_MODELS[name]; if (!model) throw new Error(`Unsupported model: ${name}`); return ai.defineModel( __spreadProps(__spreadValues({ name: modelId }, model.info), { configSchema: model.configSchema }), claudeRunner(name, client, cacheSystemPrompt) ); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AnthropicConfigSchema, SUPPORTED_CLAUDE_MODELS, claude35Haiku, claude35Sonnet, claude37Sonnet, claude3Haiku, claude3Opus, claude3Sonnet, claudeModel, claudeRunner, fromAnthropicContentBlockChunk, fromAnthropicResponse, fromAnthropicStopReason, toAnthropicMessageContent, toAnthropicMessages, toAnthropicRequestBody, toAnthropicRole, toAnthropicTool, toAnthropicToolResponseContent }); //# sourceMappingURL=claude.js.map