diff --git a/dto/openai_request.go b/dto/openai_request.go index fd0bed0ea4c4..da6074afcf84 100644 --- a/dto/openai_request.go +++ b/dto/openai_request.go @@ -849,6 +849,7 @@ type OpenAIResponsesRequest struct { MaxOutputTokens *uint `json:"max_output_tokens,omitempty"` TopLogProbs *int `json:"top_logprobs,omitempty"` Metadata json.RawMessage `json:"metadata,omitempty"` + Moderation json.RawMessage `json:"moderation,omitempty"` ParallelToolCalls json.RawMessage `json:"parallel_tool_calls,omitempty"` PreviousResponseID string `json:"previous_response_id,omitempty"` Reasoning *Reasoning `json:"reasoning,omitempty"` @@ -859,6 +860,7 @@ type OpenAIResponsesRequest struct { // This field is allowed by default and can be disabled via channel setting disable_store. Store json.RawMessage `json:"store,omitempty"` PromptCacheKey json.RawMessage `json:"prompt_cache_key,omitempty"` + PromptCacheOptions json.RawMessage `json:"prompt_cache_options,omitempty"` PromptCacheRetention json.RawMessage `json:"prompt_cache_retention,omitempty"` // SafetyIdentifier carries client identity for policy abuse detection. // This field is filtered by default and can be enabled via channel setting allow_safety_identifier. diff --git a/dto/openai_response.go b/dto/openai_response.go index e503f5f91c69..8d60c2a91992 100644 --- a/dto/openai_response.go +++ b/dto/openai_response.go @@ -254,6 +254,7 @@ type OpenAIVideoResponse struct { type InputTokenDetails struct { CachedTokens int `json:"cached_tokens"` + CacheWriteTokens int `json:"cache_write_tokens,omitempty"` CachedCreationTokens int `json:"cached_creation_tokens,omitempty"` TextTokens int `json:"text_tokens"` AudioTokens int `json:"audio_tokens"` diff --git a/dto/openai_responses_compaction_request.go b/dto/openai_responses_compaction_request.go index 7ea584ca322e..28f8635bf422 100644 --- a/dto/openai_responses_compaction_request.go +++ b/dto/openai_responses_compaction_request.go @@ -10,10 +10,12 @@ import ( ) type OpenAIResponsesCompactionRequest struct { - Model string `json:"model"` - Input json.RawMessage `json:"input,omitempty"` - Instructions json.RawMessage `json:"instructions,omitempty"` - PreviousResponseID string `json:"previous_response_id,omitempty"` + Model string `json:"model"` + Input json.RawMessage `json:"input,omitempty"` + Instructions json.RawMessage `json:"instructions,omitempty"` + PromptCacheOptions json.RawMessage `json:"prompt_cache_options,omitempty"` + PromptCacheRetention json.RawMessage `json:"prompt_cache_retention,omitempty"` + PreviousResponseID string `json:"previous_response_id,omitempty"` } func (r *OpenAIResponsesCompactionRequest) GetTokenCountMeta() *types.TokenCountMeta { diff --git a/relay/channel/claude/relay-claude.go b/relay/channel/claude/relay-claude.go index 0ba31b1b9baa..9cb3fc3732b6 100644 --- a/relay/channel/claude/relay-claude.go +++ b/relay/channel/claude/relay-claude.go @@ -617,6 +617,7 @@ func buildOpenAIStyleUsageFromClaudeUsage(usage *dto.Usage) dto.Usage { usage.ClaudeCacheCreation1hTokens, ) cacheCreationTokens := cacheCreationTokensForOpenAIUsage(usage) + clone.PromptTokensDetails.CacheWriteTokens = cacheCreationTokens totalInputTokens := usage.PromptTokens + usage.PromptTokensDetails.CachedTokens + cacheCreationTokens clone.PromptTokens = totalInputTokens clone.InputTokens = totalInputTokens diff --git a/relay/channel/openai/relay_responses.go b/relay/channel/openai/relay_responses.go index 2665b8d027e9..6c6b58d887e6 100644 --- a/relay/channel/openai/relay_responses.go +++ b/relay/channel/openai/relay_responses.go @@ -51,6 +51,7 @@ func OaiResponsesHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http usage.TotalTokens = responsesResponse.Usage.TotalTokens if responsesResponse.Usage.InputTokensDetails != nil { usage.PromptTokensDetails.CachedTokens = responsesResponse.Usage.InputTokensDetails.CachedTokens + usage.PromptTokensDetails.CachedCreationTokens = responsesResponse.Usage.InputTokensDetails.CacheWriteTokens } } if info == nil || info.ResponsesUsageInfo == nil || info.ResponsesUsageInfo.BuiltInTools == nil { @@ -104,6 +105,7 @@ func OaiResponsesStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp } if streamResponse.Response.Usage.InputTokensDetails != nil { usage.PromptTokensDetails.CachedTokens = streamResponse.Response.Usage.InputTokensDetails.CachedTokens + usage.PromptTokensDetails.CachedCreationTokens = streamResponse.Response.Usage.InputTokensDetails.CacheWriteTokens } } if streamResponse.Response.HasImageGenerationCall() { diff --git a/relay/channel/openai/relay_responses_compact.go b/relay/channel/openai/relay_responses_compact.go index 390de8ed6865..e0091339d0dd 100644 --- a/relay/channel/openai/relay_responses_compact.go +++ b/relay/channel/openai/relay_responses_compact.go @@ -37,6 +37,7 @@ func OaiResponsesCompactionHandler(c *gin.Context, resp *http.Response) (*dto.Us usage.TotalTokens = compactResp.Usage.TotalTokens if compactResp.Usage.InputTokensDetails != nil { usage.PromptTokensDetails.CachedTokens = compactResp.Usage.InputTokensDetails.CachedTokens + usage.PromptTokensDetails.CachedCreationTokens = compactResp.Usage.InputTokensDetails.CacheWriteTokens } } diff --git a/relay/responses_handler.go b/relay/responses_handler.go index 010c38bba865..e56cbb58fd55 100644 --- a/relay/responses_handler.go +++ b/relay/responses_handler.go @@ -41,10 +41,12 @@ func ResponsesHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError * responsesReq = req case *dto.OpenAIResponsesCompactionRequest: responsesReq = &dto.OpenAIResponsesRequest{ - Model: req.Model, - Input: req.Input, - Instructions: req.Instructions, - PreviousResponseID: req.PreviousResponseID, + Model: req.Model, + Input: req.Input, + Instructions: req.Instructions, + PromptCacheOptions: req.PromptCacheOptions, + PromptCacheRetention: req.PromptCacheRetention, + PreviousResponseID: req.PreviousResponseID, } default: return types.NewErrorWithStatusCode( diff --git a/service/relayconvert/responses_to_chat.go b/service/relayconvert/responses_to_chat.go index bfa1621189e5..f27d55826ee6 100644 --- a/service/relayconvert/responses_to_chat.go +++ b/service/relayconvert/responses_to_chat.go @@ -150,6 +150,8 @@ func UsageFromResponsesUsage(src *dto.Usage) *dto.Usage { } if src.InputTokensDetails != nil { usage.PromptTokensDetails.CachedTokens = src.InputTokensDetails.CachedTokens + usage.PromptTokensDetails.CacheWriteTokens = src.InputTokensDetails.CacheWriteTokens + usage.PromptTokensDetails.CachedCreationTokens = src.InputTokensDetails.CacheWriteTokens usage.PromptTokensDetails.ImageTokens = src.InputTokensDetails.ImageTokens usage.PromptTokensDetails.AudioTokens = src.InputTokensDetails.AudioTokens } diff --git a/setting/ratio_setting/cache_ratio.go b/setting/ratio_setting/cache_ratio.go index 89d0bfc2c51a..6e874b5bc5f9 100644 --- a/setting/ratio_setting/cache_ratio.go +++ b/setting/ratio_setting/cache_ratio.go @@ -81,6 +81,9 @@ var defaultCacheRatio = map[string]float64{ } var defaultCreateCacheRatio = map[string]float64{ + "gpt-5.6-sol": 1.25, + "gpt-5.6-terra": 1.25, + "gpt-5.6-luna": 1.25, "claude-3-sonnet-20240229": 1.25, "claude-3-opus-20240229": 1.25, "claude-3-haiku-20240307": 1.25,