diff --git a/core/llm/openaiTypeConverters.ts b/core/llm/openaiTypeConverters.ts index 0a500bc126..e58970ca82 100644 --- a/core/llm/openaiTypeConverters.ts +++ b/core/llm/openaiTypeConverters.ts @@ -19,38 +19,80 @@ export function toChatMessage( tool_call_id: message.toolCallId, }; } - - if (typeof message.content === "string") { - return { - role: message.role, - content: message.content === "" ? " " : message.content, // LM Studio API doesn't accept empty strings - }; - } else if (!message.content.some((item) => item.type !== "text")) { - // If no multi-media is in the message, just send as text - // for compatibility with OpenAI-"compatible" servers - // that don't support multi-media format + if (message.role === "system") { return { - ...message, - content: message.content.map((item) => item.text).join(""), + role: "system", + content: message.content, }; } - const parts = message.content.map((part) => { - const msg: any = { - type: part.type, - text: part.text, - }; - if (part.type === "imageUrl") { - msg.image_url = { ...part.imageUrl, detail: "auto" }; - msg.type = "image_url"; - } - return msg; - }); - - return { - ...message, - content: parts, + let msg: ChatCompletionMessageParam = { + role: message.role, + content: + typeof message.content === "string" + ? message.content === "" + ? " " + : message.content + : !message.content.some((item) => item.type !== "text") + ? message.content.map((item) => item.text).join("") + : message.content.map((part) => { + const msg: any = { + type: part.type, + text: part.text, + }; + if (part.type === "imageUrl") { + msg.image_url = { ...part.imageUrl, detail: "auto" }; + msg.type = "image_url"; + } + return msg; + }), }; + if ( + message.role === "assistant" && + message.toolCalls && + msg.role === "assistant" + ) { + msg.tool_calls = message.toolCalls.map((toolCall) => ({ + id: toolCall.id!, + type: toolCall.type!, + function: { + name: toolCall.function?.name!, + arguments: toolCall.function?.arguments!, + }, + })); + } + return msg; + // if (typeof message.content === "string") { + // return { + // role: message.role, + // content: message.content === "" ? " " : message.content, // LM Studio API doesn't accept empty strings + // }; + // } else if (!message.content.some((item) => item.type !== "text")) { + // // If no multi-media is in the message, just send as text + // // for compatibility with OpenAI-"compatible" servers + // // that don't support multi-media format + // return { + // ...message, + // content: message.content.map((item) => item.text).join(""), + // }; + // } + + // const parts = message.content.map((part) => { + // const msg: any = { + // type: part.type, + // text: part.text, + // }; + // if (part.type === "imageUrl") { + // msg.image_url = { ...part.imageUrl, detail: "auto" }; + // msg.type = "image_url"; + // } + // return msg; + // }); + + // return { + // ...message, + // content: parts, + // }; } export function toChatBody( diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 017ef7a883..93d72751a4 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -11,15 +11,15 @@ export const PROVIDER_TOOL_SUPPORT: Record< return true; } }, - // openai: (model) => { - // if ( - // ["gpt-4", "o1", "chatgpt-4o-latest"].some((part) => - // model.toLowerCase().startsWith(part), - // ) - // ) { - // return true; - // } - // }, + openai: (model) => { + if ( + ["gpt-4", "o1", "chatgpt-4o-latest"].some((part) => + model.toLowerCase().startsWith(part), + ) + ) { + return true; + } + }, // https://ollama.com/search?c=tools ollama: (model) => { if ( diff --git a/gui/src/components/StepContainer/ResponseActions.tsx b/gui/src/components/StepContainer/ResponseActions.tsx index bda0d4a6cd..f016b34749 100644 --- a/gui/src/components/StepContainer/ResponseActions.tsx +++ b/gui/src/components/StepContainer/ResponseActions.tsx @@ -14,7 +14,6 @@ export interface ResponseActionsProps { index: number; onDelete: () => void; item: ChatHistoryItem; - shouldHideActions: boolean; } export default function ResponseActions({ @@ -23,7 +22,6 @@ export default function ResponseActions({ item, isTruncated, onDelete, - shouldHideActions, }: ResponseActionsProps) { const isInEditMode = useAppSelector(selectIsInEditMode); @@ -33,37 +31,33 @@ export default function ResponseActions({ return (