Skip to content

Commit de4048e

Browse files
Enable Anthropic's prompt caching (cache_control) for Claude models accessed (#850)
1 parent c875ed1 commit de4048e

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

providers/claude/chat.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,27 @@ func ConvertFromChatOpenai(request *types.ChatCompletionRequest) (*ClaudeRequest
141141
}
142142
}
143143

144+
// 处理 system 字段(支持 cache_control)
144145
systemMessage := ""
145146
mgsLen := len(request.Messages) - 1
146147
isThink := (request.OneOtherArg == "thinking" || request.Reasoning != nil)
147148

149+
// 如果请求中已经有 system 字段(如数组格式带 cache_control),直接使用
150+
if request.System != nil {
151+
claudeRequest.System = request.System
152+
}
153+
154+
// 处理 messages
148155
for index, msg := range request.Messages {
149156
if isThink && index == mgsLen && (msg.Role == types.ChatMessageRoleAssistant || msg.Role == types.ChatMessageRoleSystem) {
150157
msg.Role = types.ChatMessageRoleUser
151158
}
152159

153160
if msg.Role == types.ChatMessageRoleSystem {
154-
systemMessage += msg.StringContent()
161+
// 如果没有预设的 system 字段,从 messages 中提取
162+
if request.System == nil {
163+
systemMessage += msg.StringContent()
164+
}
155165
continue
156166
}
157167
messageContent, err := convertMessageContent(&msg)
@@ -163,7 +173,8 @@ func ConvertFromChatOpenai(request *types.ChatCompletionRequest) (*ClaudeRequest
163173
}
164174
}
165175

166-
if systemMessage != "" {
176+
// 如果没有预设的 system 字段,且从 messages 中提取到了 system message
177+
if request.System == nil && systemMessage != "" {
167178
claudeRequest.System = systemMessage
168179
}
169180

@@ -295,10 +306,15 @@ func convertMessageContent(msg *types.ChatCompletionMessage) (*Message, error) {
295306
openaiContent := msg.ParseContent()
296307
for _, part := range openaiContent {
297308
if part.Type == types.ContentTypeText {
298-
content = append(content, MessageContent{
309+
msgContent := MessageContent{
299310
Type: "text",
300311
Text: part.Text,
301-
})
312+
}
313+
// 传递 cache_control 字段
314+
if msg.CacheControl != nil {
315+
msgContent.CacheControl = msg.CacheControl
316+
}
317+
content = append(content, msgContent)
302318
continue
303319
}
304320
if part.Type == types.ContentTypeImageURL {

types/chat.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type ChatCompletionMessage struct {
5858
Annotations any `json:"annotations,omitempty"`
5959
Image []MultimediaData `json:"image,omitempty"`
6060
Images []ChatMessagePart `json:"images,omitempty"`
61+
CacheControl any `json:"cache_control,omitempty"`
6162
}
6263

6364
func (m ChatCompletionMessage) StringContent() string {
@@ -179,6 +180,7 @@ type FormatJsonSchema struct {
179180
type ChatCompletionRequest struct {
180181
Model string `json:"model" binding:"required"`
181182
Messages []ChatCompletionMessage `json:"messages" binding:"required"`
183+
System any `json:"system,omitempty"`
182184
MaxTokens int `json:"max_tokens,omitempty"`
183185
MaxCompletionTokens int `json:"max_completion_tokens,omitempty"`
184186
Temperature *float64 `json:"temperature,omitempty"`

0 commit comments

Comments
 (0)