Files
ds2api/internal/adapter/openai/message_normalize.go

107 lines
2.3 KiB
Go

package openai
import (
"encoding/json"
"strings"
"ds2api/internal/prompt"
)
func normalizeOpenAIMessagesForPrompt(raw []any, traceID string) []map[string]any {
_ = traceID
out := make([]map[string]any, 0, len(raw))
for _, item := range raw {
msg, ok := item.(map[string]any)
if !ok {
continue
}
role := strings.ToLower(strings.TrimSpace(asString(msg["role"])))
switch role {
case "assistant":
content := normalizeOpenAIContentForPrompt(msg["content"])
if content == "" {
continue
}
out = append(out, map[string]any{
"role": "assistant",
"content": content,
})
case "tool", "function":
content := normalizeOpenAIContentForPrompt(msg["content"])
if content == "" {
content = "null"
}
out = append(out, map[string]any{
"role": "user",
"content": content,
})
case "user", "system", "developer":
out = append(out, map[string]any{
"role": normalizeOpenAIRoleForPrompt(role),
"content": normalizeOpenAIContentForPrompt(msg["content"]),
})
default:
content := normalizeOpenAIContentForPrompt(msg["content"])
if content == "" {
continue
}
if role == "" {
role = "user"
}
out = append(out, map[string]any{
"role": normalizeOpenAIRoleForPrompt(role),
"content": content,
})
}
}
return out
}
func normalizeOpenAIContentForPrompt(v any) string {
return prompt.NormalizeContent(v)
}
func normalizeToolArgumentString(raw string) string {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return ""
}
if looksLikeConcatenatedJSON(trimmed) {
// Keep original payload to avoid silent argument rewrites.
return raw
}
return trimmed
}
func normalizeOpenAIRoleForPrompt(role string) string {
role = strings.ToLower(strings.TrimSpace(role))
if role == "developer" {
return "system"
}
return role
}
func asString(v any) string {
if s, ok := v.(string); ok {
return s
}
return ""
}
func looksLikeConcatenatedJSON(raw string) bool {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return false
}
if strings.Contains(trimmed, "}{") || strings.Contains(trimmed, "][") {
return true
}
dec := json.NewDecoder(strings.NewReader(trimmed))
var first any
if err := dec.Decode(&first); err != nil {
return false
}
var second any
return dec.Decode(&second) == nil
}