mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-08 22:08:03 -05:00
refactor: extract message conversion logic to toMessages method in VertexAI client
- Extract message conversion into dedicated `toMessages` helper method - Add proper role handling for system, user, and assistant messages - Prepend system content to first user message per Anthropic format - Enforce user/assistant message alternation with placeholder messages - Skip empty messages during conversion processing - Concatenate multiple text blocks in response output - Add validation for empty message arrays before sending - Handle edge case when only system content is provided
This commit is contained in:
@@ -3,6 +3,7 @@ package vertexai
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/anthropics/anthropic-sdk-go"
|
||||
"github.com/anthropics/anthropic-sdk-go/vertex"
|
||||
@@ -74,9 +75,9 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o
|
||||
}
|
||||
|
||||
// Convert chat messages to Anthropic format
|
||||
anthropicMessages := make([]anthropic.MessageParam, len(msgs))
|
||||
for i, msg := range msgs {
|
||||
anthropicMessages[i] = anthropic.NewUserMessage(anthropic.NewTextBlock(msg.Content))
|
||||
anthropicMessages := c.toMessages(msgs)
|
||||
if len(anthropicMessages) == 0 {
|
||||
return "", fmt.Errorf("no valid messages to send")
|
||||
}
|
||||
|
||||
// Create the request
|
||||
@@ -92,11 +93,18 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o
|
||||
}
|
||||
|
||||
// Extract text from response
|
||||
if len(response.Content) > 0 {
|
||||
return response.Content[0].Text, nil
|
||||
var textParts []string
|
||||
for _, block := range response.Content {
|
||||
if block.Type == "text" && block.Text != "" {
|
||||
textParts = append(textParts, block.Text)
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no content in response")
|
||||
if len(textParts) == 0 {
|
||||
return "", fmt.Errorf("no content in response")
|
||||
}
|
||||
|
||||
return strings.Join(textParts, ""), nil
|
||||
}
|
||||
|
||||
func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.ChatOptions, channel chan string) error {
|
||||
@@ -109,9 +117,9 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha
|
||||
ctx := context.Background()
|
||||
|
||||
// Convert chat messages to Anthropic format
|
||||
anthropicMessages := make([]anthropic.MessageParam, len(msgs))
|
||||
for i, msg := range msgs {
|
||||
anthropicMessages[i] = anthropic.NewUserMessage(anthropic.NewTextBlock(msg.Content))
|
||||
anthropicMessages := c.toMessages(msgs)
|
||||
if len(anthropicMessages) == 0 {
|
||||
return fmt.Errorf("no valid messages to send")
|
||||
}
|
||||
|
||||
// Create streaming request
|
||||
@@ -133,6 +141,70 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha
|
||||
return stream.Err()
|
||||
}
|
||||
|
||||
func (c *Client) toMessages(msgs []*chat.ChatCompletionMessage) []anthropic.MessageParam {
|
||||
// Convert messages to Anthropic format with proper role handling
|
||||
// - System messages become part of the first user message
|
||||
// - Messages must alternate user/assistant
|
||||
// - Skip empty messages
|
||||
|
||||
var anthropicMessages []anthropic.MessageParam
|
||||
var systemContent string
|
||||
|
||||
isFirstUserMessage := true
|
||||
lastRoleWasUser := false
|
||||
|
||||
for _, msg := range msgs {
|
||||
if strings.TrimSpace(msg.Content) == "" {
|
||||
continue // Skip empty messages
|
||||
}
|
||||
|
||||
switch msg.Role {
|
||||
case chat.ChatMessageRoleSystem:
|
||||
// Accumulate system content to prepend to first user message
|
||||
if systemContent != "" {
|
||||
systemContent += "\\n" + msg.Content
|
||||
} else {
|
||||
systemContent = msg.Content
|
||||
}
|
||||
case chat.ChatMessageRoleUser:
|
||||
userContent := msg.Content
|
||||
if isFirstUserMessage && systemContent != "" {
|
||||
userContent = systemContent + "\\n\\n" + userContent
|
||||
isFirstUserMessage = false
|
||||
}
|
||||
if lastRoleWasUser {
|
||||
// Enforce alternation: add a minimal assistant message
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewAssistantMessage(anthropic.NewTextBlock("Okay.")))
|
||||
}
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewUserMessage(anthropic.NewTextBlock(userContent)))
|
||||
lastRoleWasUser = true
|
||||
case chat.ChatMessageRoleAssistant:
|
||||
// If first message is assistant and we have system content, prepend user message
|
||||
if isFirstUserMessage && systemContent != "" {
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewUserMessage(anthropic.NewTextBlock(systemContent)))
|
||||
lastRoleWasUser = true
|
||||
isFirstUserMessage = false
|
||||
} else if !lastRoleWasUser && len(anthropicMessages) > 0 {
|
||||
// Enforce alternation: add a minimal user message
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewUserMessage(anthropic.NewTextBlock("Hi")))
|
||||
lastRoleWasUser = true
|
||||
}
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewAssistantMessage(anthropic.NewTextBlock(msg.Content)))
|
||||
lastRoleWasUser = false
|
||||
default:
|
||||
// Other roles are ignored for Anthropic's message structure
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If only system content was provided, create a user message with it
|
||||
if len(anthropicMessages) == 0 && systemContent != "" {
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewUserMessage(anthropic.NewTextBlock(systemContent)))
|
||||
}
|
||||
|
||||
return anthropicMessages
|
||||
}
|
||||
|
||||
func (c *Client) NeedsRawMode(modelName string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user