Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/core/src/llms/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ export type MessageContentTextDetail = {

export type MessageContentImageDetail = {
type: "image_url";
image_url: { url: string };
detail?: "high" | "low" | "auto";
image_url: {
url: string;
detail?: "high" | "low" | "auto";
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not the llamaindex abstraction? We wouldn't want to change the input type, just whatever it gets transformed to

};

export type MessageContentAudioDetail = {
Expand Down
11 changes: 10 additions & 1 deletion packages/providers/openai/src/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,16 @@ export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
}

// Keep other types as is (text, image_url, etc.)
return item;
// return item;
if (item.type === "image_url") {
return {
type: "image_url",
image_url: {
url: item.image_url.url,
detail: item.detail, // This might need to be item.image_url.detail after the type change
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I would leave the type the same so this would be the necessary transform. It might help to add some similar tests for OpenAIResponses to show it working for both

},
};
}
}) as ChatCompletionContentPart[],
} satisfies ChatCompletionUserMessageParam;
}
Expand Down
67 changes: 67 additions & 0 deletions packages/providers/openai/tests/llm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,71 @@ describe("Message Formatting", () => {
expect(OpenAI.toOpenAIMessage(multiToolMessages)).toEqual(expectedOutput);
});
});
describe("Image Detail Formatting", () => {
test("OpenAI formats image messages with detail correctly", () => {
const inputMessages: ChatMessage[] = [
{
role: "user",
content: [
{
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,aGVsbG8=",
detail: "high",
},
},
],
},
];

const expectedOutput = [
{
role: "user",
content: [
{
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,aGVsbG8=",
detail: "high",
},
},
],
},
];

expect(OpenAI.toOpenAIMessage(inputMessages)).toEqual(expectedOutput);
});

test("OpenAI formats image messages without detail correctly", () => {
const inputMessages: ChatMessage[] = [
{
role: "user",
content: [
{
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,aGVsbG8=",
},
},
],
},
];

const expectedOutput = [
{
role: "user",
content: [
{
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,aGVsbG8=",
},
},
],
},
];

expect(OpenAI.toOpenAIMessage(inputMessages)).toEqual(expectedOutput);
});
});
});
32 changes: 32 additions & 0 deletions packages/providers/openai/tests/structure-verify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
console.log("VERIFYING IMAGE DETAIL FIX\n");

// Test the structure change
console.log("OLD STRUCTURE (Broken):");
const oldStructure = {
type: "image_url",
image_url: { url: "data:image/jpeg;base64,test" },
detail: "high", // WRONG: detail at top level
};
console.log(JSON.stringify(oldStructure, null, 2));
console.log("Problem: 'detail' is at top level, OpenAI rejects this\n");

console.log("NEW STRUCTURE (Fixed):");
const newStructure = {
type: "image_url",
image_url: {
url: "data:image/jpeg;base64,test",
detail: "high", // CORRECT: detail inside image_url
},
};
console.log(JSON.stringify(newStructure, null, 2));
console.log("Fixed: 'detail' is inside image_url object\n");

console.log("WHAT YOU CHANGED:");
console.log("In packages/core/src/llms/type.ts:");
console.log("BEFORE: detail?: 'high' | 'low' | 'auto' (at top level)");
console.log(
"AFTER: image_url: { url: string; detail?: 'high' | 'low' | 'auto' }",
);
console.log(" ^-- detail moved inside image_url object");

console.log("\n This matches OpenAI's API requirements!");