@arizeai/phoenix-client
Version:
A client for the Phoenix API
130 lines • 4.99 kB
JavaScript
import { assertUnreachable } from "../../../utils/assertUnreachable.js";
import { safelyStringifyJSON } from "../../../utils/safelyStringifyJSON.js";
import { jsonSchemaZodSchema } from "../../jsonSchema.js";
import { asToolResultPart, phoenixContentPartSchema, } from "./messagePartSchemas.js";
import { phoenixMessageSchema } from "./messageSchemas.js";
import { phoenixResponseFormatSchema } from "./responseFormatSchema.js";
import { phoenixToolCallSchema } from "./toolCallSchemas.js";
import { phoenixToolChoiceSchema } from "./toolChoiceSchemas.js";
import { phoenixToolDefinitionSchema } from "./toolSchemas.js";
/*
* 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 phoenixMessagePartToOpenAI = phoenixContentPartSchema.transform((part) => {
const type = part.type;
switch (type) {
case "text":
return {
type: "text",
text: part.text,
};
case "tool_call":
return null;
case "tool_result":
return null;
default:
return assertUnreachable(type);
}
});
/**
* Spoke → Hub: Convert a Prompt message to OpenAI format
*/
export const phoenixMessageToOpenAI = phoenixMessageSchema.transform((prompt) => {
const content = typeof prompt.content == "string"
? [{ type: "text", text: prompt.content }]
: prompt.content;
// Special handling for TOOL role messages
if (prompt.role === "tool") {
const toolResult = content
.map((part) => asToolResultPart(part))
.find((part) => !!part);
if (!toolResult) {
throw new Error("TOOL role message must have a ToolResultContentPart");
}
return {
role: "tool",
content: typeof toolResult.tool_result === "string"
? toolResult.tool_result
: safelyStringifyJSON(toolResult.tool_result).json || "",
tool_call_id: toolResult.tool_call_id,
};
}
// Handle other roles
const role = prompt.role;
switch (role) {
case "system":
case "developer":
return {
role: "system",
content: content
.map((part) => phoenixMessagePartToOpenAI.parse(part))
.filter((part) => part !== null && part.type === "text"),
};
case "user":
return {
role: "user",
content: content
.map((part) => phoenixMessagePartToOpenAI.parse(part))
.filter((part) => part !== null && part.type === "text"),
};
case "assistant":
case "ai":
case "model":
return {
role: "assistant",
content: content
.map((part) => phoenixMessagePartToOpenAI.parse(part))
.filter((part) => part !== null && part.type === "text"),
tool_calls: content.some((part) => part.type === "tool_call")
? content
.filter((part) => part.type === "tool_call")
.map((part) => phoenixToolCallToOpenAI.parse(part))
.filter((part) => part !== null)
: undefined,
};
default:
return assertUnreachable(role);
}
});
export const phoenixResponseFormatToOpenAI = phoenixResponseFormatSchema.transform((phoenix) => ({
type: "json_schema",
json_schema: {
name: phoenix.json_schema.name,
description: phoenix.json_schema.description,
schema: jsonSchemaZodSchema.parse(phoenix.json_schema.schema),
},
}));
export const phoenixToolCallToOpenAI = phoenixToolCallSchema.transform((prompt) => ({
type: "function",
id: prompt.tool_call_id,
function: {
...prompt.tool_call,
arguments: typeof prompt.tool_call.arguments === "string"
? prompt.tool_call.arguments
: (safelyStringifyJSON(prompt.tool_call.arguments).json ?? ""),
},
}));
export const phoenixToolDefinitionToOpenAI = phoenixToolDefinitionSchema.transform((phoenix) => ({
type: "function",
function: {
name: phoenix.function.name,
description: phoenix.function.description,
parameters: jsonSchemaZodSchema.parse(phoenix.function.parameters),
},
}));
export const phoenixToolChoiceToOpenAI = phoenixToolChoiceSchema.transform((phoenix) => {
switch (phoenix.type) {
case "none":
return "none";
case "zero_or_more":
return "auto";
case "one_or_more":
return "required";
case "specific_function":
return { type: "function", function: { name: phoenix.function_name } };
}
});
//# sourceMappingURL=converters.js.map