diff --git a/relay/adaptor/anthropic/adaptor.go b/relay/adaptor/anthropic/adaptor.go index 44803de4..8dbb20c0 100644 --- a/relay/adaptor/anthropic/adaptor.go +++ b/relay/adaptor/anthropic/adaptor.go @@ -14,6 +14,13 @@ import ( "github.com/songquanpeng/one-api/relay/relaymode" ) +const ( + // NativeAnthropicEndpoint is the endpoint for native Anthropic API + NativeAnthropicEndpoint = "/v1/messages" + // ThirdPartyAnthropicEndpoint is the endpoint for third-party providers supporting Anthropic protocol + ThirdPartyAnthropicEndpoint = "/anthropic/v1/messages" +) + type Adaptor struct { } @@ -24,13 +31,13 @@ func (a *Adaptor) Init(meta *meta.Meta) { func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { // For native Anthropic API if strings.Contains(meta.BaseURL, "api.anthropic.com") { - return fmt.Sprintf("%s/v1/messages", meta.BaseURL), nil + return fmt.Sprintf("%s%s", meta.BaseURL, NativeAnthropicEndpoint), nil } // For third-party providers supporting Anthropic protocol (like DeepSeek) // They typically expose the endpoint at /anthropic/v1/messages baseURL := strings.TrimSuffix(meta.BaseURL, "/") - return fmt.Sprintf("%s/anthropic/v1/messages", baseURL), nil + return fmt.Sprintf("%s%s", baseURL, ThirdPartyAnthropicEndpoint), nil } func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request, meta *meta.Meta) error { diff --git a/relay/adaptor/anthropic/main.go b/relay/adaptor/anthropic/main.go index b0d721bb..a52d97d5 100644 --- a/relay/adaptor/anthropic/main.go +++ b/relay/adaptor/anthropic/main.go @@ -93,9 +93,15 @@ func ConvertRequest(textRequest model.GeneralOpenAIRequest) *Request { if message.Role == "system" && claudeRequest.System.IsEmpty() { // Create a SystemPrompt from the string content systemPrompt := SystemPrompt{} - systemData := []byte(`"` + message.StringContent() + `"`) // Wrap in JSON string quotes - _ = systemPrompt.UnmarshalJSON(systemData) - claudeRequest.System = systemPrompt + systemData, err := json.Marshal(message.StringContent()) // Safely escape string for JSON + if err != nil { + logger.SysError(fmt.Sprintf("Failed to marshal system prompt: %v", err)) + } else { + if err := systemPrompt.UnmarshalJSON(systemData); err != nil { + logger.SysError(fmt.Sprintf("Failed to unmarshal system prompt: %v", err)) + } + claudeRequest.System = systemPrompt + } continue } claudeMessage := Message{ diff --git a/relay/controller/anthropic.go b/relay/controller/anthropic.go index a0c512bc..641eb0f2 100644 --- a/relay/controller/anthropic.go +++ b/relay/controller/anthropic.go @@ -142,6 +142,12 @@ func getAnthropicRequestBody(c *gin.Context, anthropicRequest *anthropic.Request return bytes.NewBuffer(jsonData), nil } +const ( + // CHARS_PER_TOKEN represents the rough character-to-token ratio for Anthropic models + // This is a conservative estimate: approximately 1 token per 4 characters + CHARS_PER_TOKEN = 4 +) + func estimateAnthropicTokens(request *anthropic.Request) int { // Simple token estimation for Anthropic requests // This is a rough estimation, actual implementation might need more sophisticated logic @@ -150,14 +156,14 @@ func estimateAnthropicTokens(request *anthropic.Request) int { // Count tokens in system prompt if !request.System.IsEmpty() { systemText := request.System.String() - totalTokens += len(systemText) / 4 // rough estimate: 1 token per 4 characters + totalTokens += len(systemText) / CHARS_PER_TOKEN // rough estimate: 1 token per 4 characters } // Count tokens in messages for _, message := range request.Messages { for _, content := range message.Content { if content.Type == "text" { - totalTokens += len(content.Text) / 4 + totalTokens += len(content.Text) / CHARS_PER_TOKEN } } }