package prompt import ( "encoding/json" "fmt" "regexp" "strings" ) var markdownImagePattern = regexp.MustCompile(`!\[(.*?)\]\((.*?)\)`) func MessagesPrepare(messages []map[string]any) string { type block struct { Role string Text string } processed := make([]block, 0, len(messages)) for _, m := range messages { role, _ := m["role"].(string) text := NormalizeContent(m["content"]) processed = append(processed, block{Role: role, Text: text}) } if len(processed) == 0 { return "" } merged := make([]block, 0, len(processed)) for _, msg := range processed { if len(merged) > 0 && merged[len(merged)-1].Role == msg.Role { merged[len(merged)-1].Text += "\n\n" + msg.Text continue } merged = append(merged, msg) } parts := make([]string, 0, len(merged)) for i, m := range merged { switch m.Role { case "assistant": parts = append(parts, "<|Assistant|>"+m.Text+"<|end▁of▁sentence|>") case "tool": if i > 0 { parts = append(parts, "<|Tool|>"+m.Text) } else { parts = append(parts, m.Text) } case "user", "system": if i > 0 { parts = append(parts, "<|User|>"+m.Text) } else { parts = append(parts, m.Text) } default: parts = append(parts, m.Text) } } out := strings.Join(parts, "") return markdownImagePattern.ReplaceAllString(out, `[${1}](${2})`) } func NormalizeContent(v any) string { if v == nil { return "" } switch x := v.(type) { case string: return x case []any: parts := make([]string, 0, len(x)) for _, item := range x { m, ok := item.(map[string]any) if !ok { continue } typeStr, _ := m["type"].(string) typeStr = strings.ToLower(strings.TrimSpace(typeStr)) if typeStr == "text" || typeStr == "output_text" || typeStr == "input_text" { if txt, ok := m["text"].(string); ok && txt != "" { parts = append(parts, txt) continue } if txt, ok := m["content"].(string); ok && txt != "" { parts = append(parts, txt) } } } return strings.Join(parts, "\n") default: b, err := json.Marshal(v) if err != nil { return fmt.Sprintf("%v", v) } return string(b) } }