UNPKG

@arizeai/phoenix-client

Version:

A client for the Phoenix API

123 lines 4.53 kB
import { assertUnreachable } from "../../../utils/assertUnreachable.js"; import { safelyStringifyJSON } from "../../../utils/safelyStringifyJSON.js"; import { openAIMessageRoleSchema, } from "../openai/messageSchemas.js"; import { anthropicMessagePartSchema, } from "./messagePartSchemas.js"; import { anthropicMessageSchema } from "./messageSchemas.js"; import { anthropicToolCallSchema } from "./toolCallSchemas.js"; import { anthropicToolChoiceSchema } from "./toolChoiceSchemas.js"; import { anthropicToolDefinitionSchema } from "./toolSchemas.js"; import invariant from "tiny-invariant"; /* * Conversion Functions * * These follow a hub-and-spoke model where OpenAI is the hub format. * All conversions between different formats go through OpenAI as an intermediate step. */ export const anthropicMessagePartToOpenAI = anthropicMessagePartSchema.transform((anthropic) => { const type = anthropic.type; switch (type) { case "text": return { type: "text", text: anthropic.text, }; case "image": return { type: "image_url", image_url: { url: anthropic.source.data }, }; case "tool_use": return null; case "tool_result": return null; default: return assertUnreachable(type); } }); /** * Spoke → Hub: Convert an Anthropic message to OpenAI format */ export const anthropicMessageToOpenAI = anthropicMessageSchema.transform((anthropic) => { let role = openAIMessageRoleSchema.parse(anthropic.role); if (Array.isArray(anthropic.content) && anthropic.content.some((part) => part.type === "tool_result")) { role = "tool"; } const initialContentArray = typeof anthropic.content === "string" ? [{ type: "text", text: anthropic.content }] : anthropic.content; const toolCallParts = initialContentArray.filter((part) => part.type === "tool_use"); const nonToolCallParts = initialContentArray.filter((part) => part.type !== "tool_use"); invariant(role === "user" || role === "assistant", `Unexpected anthropic role: ${role}`); switch (role) { case "assistant": { const content = nonToolCallParts .map((part) => anthropicMessagePartToOpenAI.parse(part)) .filter((part) => part !== null && part.type === "text"); return { role: "assistant", tool_calls: toolCallParts.length > 0 ? toolCallParts.map((tc) => anthropicToolCallToOpenAI.parse(tc)) : undefined, content, }; } case "user": { const content = nonToolCallParts .map((part) => anthropicMessagePartToOpenAI.parse(part)) .filter((part) => part !== null); return { role: "user", content, }; } default: return assertUnreachable(role); } }); /** * Parse incoming object as an Anthropic tool call and immediately convert to OpenAI format */ export const anthropicToolCallToOpenAI = anthropicToolCallSchema.transform((anthropic) => ({ type: "function", id: anthropic.id, function: { name: anthropic.name, arguments: typeof anthropic.input === "string" ? anthropic.input : (safelyStringifyJSON(anthropic.input).json ?? ""), }, })); /** * Parse incoming object as an Anthropic tool choice and immediately convert to OpenAI format */ export const anthropicToolChoiceToOpenAI = anthropicToolChoiceSchema.transform((anthropic) => { switch (anthropic.type) { case "any": return "required"; case "auto": return "auto"; case "tool": if (!anthropic.name) { return "auto"; } return { type: "function", function: { name: anthropic.name }, }; default: return "auto"; } }); /** * Parse incoming object as an Anthropic tool call and immediately convert to OpenAI format */ export const anthropicToolDefinitionToOpenAI = anthropicToolDefinitionSchema.transform((anthropic) => ({ type: "function", function: { name: anthropic.name, description: anthropic.description, parameters: anthropic.input_schema, }, })); //# sourceMappingURL=converters.js.map