diff --git a/internal/providers/deepseek.go b/internal/providers/deepseek.go index a9e4070f..098a5cbe 100644 --- a/internal/providers/deepseek.go +++ b/internal/providers/deepseek.go @@ -62,6 +62,9 @@ func (u *deepSeekUsage) ToUnified() *models.Usage { } func (p *DeepSeekProvider) ChatCompletion(ctx context.Context, req *models.UnifiedRequest) (*models.ChatCompletionResponse, error) { + // Ensure English responses — DeepSeek defaults to Chinese for some prompts + ensureEnglish(req) + messagesJSON, err := MessagesToOpenAIJSON(req.Messages) if err != nil { return nil, fmt.Errorf("failed to convert messages: %w", err) @@ -129,6 +132,8 @@ func (p *DeepSeekProvider) ChatCompletion(ctx context.Context, req *models.Unifi } func (p *DeepSeekProvider) ChatCompletionStream(ctx context.Context, req *models.UnifiedRequest) (<-chan *models.ChatCompletionStreamResponse, error) { + ensureEnglish(req) + messagesJSON, err := MessagesToOpenAIJSON(req.Messages) if err != nil { return nil, fmt.Errorf("failed to convert messages: %w", err) diff --git a/internal/providers/helpers.go b/internal/providers/helpers.go index a21250ad..ad8d6c54 100644 --- a/internal/providers/helpers.go +++ b/internal/providers/helpers.go @@ -445,3 +445,19 @@ func StreamGemini(ctx io.ReadCloser, ch chan<- *models.ChatCompletionStreamRespo return nil } + +// ensureEnglish injects a system message instructing the model to respond in +// English when no system prompt is already present. Some providers (e.g. DeepSeek) +// default to Chinese for certain prompts. +func ensureEnglish(req *models.UnifiedRequest) { + if len(req.Messages) > 0 && req.Messages[0].Role == "system" { + return // already has a system prompt, don't interfere + } + enMsg := models.UnifiedMessage{ + Role: "system", + Content: []models.UnifiedContentPart{ + {Type: "text", Text: "You are a helpful assistant. Always respond in English."}, + }, + } + req.Messages = append([]models.UnifiedMessage{enMsg}, req.Messages...) +}