fix(api): Use RawMessage for nested polymorphic JSON in OpenAI request input (#207)

Signed-off-by: Richard Palethorpe <io@richiejp.com>
This commit is contained in:
Richard Palethorpe
2025-06-10 16:50:49 +01:00
committed by GitHub
parent a0a9299cda
commit 13e0f12c1b

View File

@@ -1,11 +1,16 @@
package types package types
import "github.com/sashabaranov/go-openai" import (
"encoding/json"
"github.com/mudler/LocalAGI/pkg/xlog"
"github.com/sashabaranov/go-openai"
)
// RequestBody represents the request body structure for the OpenAI API // RequestBody represents the request body structure for the OpenAI API
type RequestBody struct { type RequestBody struct {
Model string `json:"model"` Model string `json:"model"`
Input interface{} `json:"input"` Input json.RawMessage `json:"input"`
InputText string `json:"input_text"` InputText string `json:"input_text"`
InputMessages []InputMessage `json:"input_messages"` InputMessages []InputMessage `json:"input_messages"`
Include []string `json:"include,omitempty"` Include []string `json:"include,omitempty"`
@@ -26,17 +31,34 @@ type RequestBody struct {
} }
func (r *RequestBody) SetInputByType() { func (r *RequestBody) SetInputByType() {
switch input := r.Input.(type) { xlog.Debug("[Parse Request] Set input type", "input", string(r.Input))
var inputText string
if err := json.Unmarshal(r.Input, &inputText); err == nil {
r.InputText = inputText
return
}
var inputMessages []InputMessage
if err := json.Unmarshal(r.Input, &inputMessages); err != nil {
xlog.Warn("[Parse Request] Input type not recognized", "input", string(r.Input))
return
}
for _, i := range inputMessages {
switch content := i.Content.(type) {
case []ContentItem:
i.ContentItems = content
case string: case string:
r.InputText = input i.ContentText = content
case []any: default:
for _, i := range input { xlog.Warn("[Parse Request] Input content type not recognized", "content", content)
switch i := i.(type) { }
case InputMessage:
r.InputMessages = append(r.InputMessages, i) r.InputMessages = append(r.InputMessages, i)
} }
}
} xlog.Debug("[Parse Request] Input messages parsed", "messages", r.InputMessages)
} }
func (r *RequestBody) ToChatCompletionMessages() []openai.ChatCompletionMessage { func (r *RequestBody) ToChatCompletionMessages() []openai.ChatCompletionMessage {
@@ -45,7 +67,15 @@ func (r *RequestBody) ToChatCompletionMessages() []openai.ChatCompletionMessage
for _, m := range r.InputMessages { for _, m := range r.InputMessages {
content := []openai.ChatMessagePart{} content := []openai.ChatMessagePart{}
oneImageWasFound := false oneImageWasFound := false
for _, c := range m.Content {
if m.ContentText != "" {
content = append(content, openai.ChatMessagePart{
Type: "text",
Text: m.ContentText,
})
}
for _, c := range m.ContentItems {
switch c.Type { switch c.Type {
case "text": case "text":
content = append(content, openai.ChatMessagePart{ content = append(content, openai.ChatMessagePart{
@@ -163,7 +193,9 @@ type ResponseBody struct {
// InputMessage represents a user input message // InputMessage represents a user input message
type InputMessage struct { type InputMessage struct {
Role string `json:"role"` Role string `json:"role"`
Content []ContentItem `json:"content"` Content any `json:"content"`
ContentText string `json:"content_text"`
ContentItems []ContentItem `json:"content_items"`
} }
// ContentItem represents an item in a content array // ContentItem represents an item in a content array