feat: claude web search tool 计费

This commit is contained in:
creamlike1024
2025-07-15 18:57:22 +08:00
parent 77da33de4f
commit 961bc874d2
4 changed files with 38 additions and 4 deletions

View File

@@ -324,8 +324,13 @@ func (c *ClaudeResponse) GetIndex() int {
} }
type ClaudeUsage struct { type ClaudeUsage struct {
InputTokens int `json:"input_tokens"` InputTokens int `json:"input_tokens"`
CacheCreationInputTokens int `json:"cache_creation_input_tokens"` CacheCreationInputTokens int `json:"cache_creation_input_tokens"`
CacheReadInputTokens int `json:"cache_read_input_tokens"` CacheReadInputTokens int `json:"cache_read_input_tokens"`
OutputTokens int `json:"output_tokens"` OutputTokens int `json:"output_tokens"`
ServerToolUse *ClaudeServerToolUse `json:"server_tool_use"`
}
type ClaudeServerToolUse struct {
WebSearchRequests int `json:"web_search_requests"`
} }

View File

@@ -745,6 +745,10 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
responseData = data responseData = data
} }
if claudeResponse.Usage.ServerToolUse != nil && claudeResponse.Usage.ServerToolUse.WebSearchRequests > 0 {
c.Set("claude_web_search_requests", claudeResponse.Usage.ServerToolUse.WebSearchRequests)
}
common.IOCopyBytesGracefully(c, nil, responseData) common.IOCopyBytesGracefully(c, nil, responseData)
return nil return nil
} }

View File

@@ -382,6 +382,7 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
// openai web search 工具计费 // openai web search 工具计费
var dWebSearchQuota decimal.Decimal var dWebSearchQuota decimal.Decimal
var webSearchPrice float64 var webSearchPrice float64
// response api 格式工具计费
if relayInfo.ResponsesUsageInfo != nil { if relayInfo.ResponsesUsageInfo != nil {
if webSearchTool, exists := relayInfo.ResponsesUsageInfo.BuiltInTools[dto.BuildInToolWebSearchPreview]; exists && webSearchTool.CallCount > 0 { if webSearchTool, exists := relayInfo.ResponsesUsageInfo.BuiltInTools[dto.BuildInToolWebSearchPreview]; exists && webSearchTool.CallCount > 0 {
// 计算 web search 调用的配额 (配额 = 价格 * 调用次数 / 1000 * 分组倍率) // 计算 web search 调用的配额 (配额 = 价格 * 调用次数 / 1000 * 分组倍率)
@@ -404,6 +405,17 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
extraContent += fmt.Sprintf("Web Search 调用 1 次,上下文大小 %s调用花费 %s", extraContent += fmt.Sprintf("Web Search 调用 1 次,上下文大小 %s调用花费 %s",
searchContextSize, dWebSearchQuota.String()) searchContextSize, dWebSearchQuota.String())
} }
// claude web search tool 计费
var dClaudeWebSearchQuota decimal.Decimal
var claudeWebSearchPrice float64
claudeWebSearchCallCount := ctx.GetInt("claude_web_search_requests")
if claudeWebSearchCallCount > 0 {
claudeWebSearchPrice = operation_setting.GetClaudeWebSearchPricePerThousand()
dClaudeWebSearchQuota = decimal.NewFromFloat(claudeWebSearchPrice).
Div(decimal.NewFromInt(1000)).Mul(dGroupRatio).Mul(dQuotaPerUnit).Mul(decimal.NewFromInt(int64(claudeWebSearchCallCount)))
extraContent += fmt.Sprintf("Claude Web Search 调用 %d 次,调用花费 %s",
claudeWebSearchCallCount, dClaudeWebSearchQuota.String())
}
// file search tool 计费 // file search tool 计费
var dFileSearchQuota decimal.Decimal var dFileSearchQuota decimal.Decimal
var fileSearchPrice float64 var fileSearchPrice float64
@@ -527,6 +539,10 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
other["web_search_call_count"] = 1 other["web_search_call_count"] = 1
other["web_search_price"] = webSearchPrice other["web_search_price"] = webSearchPrice
} }
} else if !dClaudeWebSearchQuota.IsZero() {
other["web_search"] = true
other["web_search_call_count"] = claudeWebSearchCallCount
other["web_search_price"] = claudeWebSearchPrice
} }
if !dFileSearchQuota.IsZero() && relayInfo.ResponsesUsageInfo != nil { if !dFileSearchQuota.IsZero() && relayInfo.ResponsesUsageInfo != nil {
if fileSearchTool, exists := relayInfo.ResponsesUsageInfo.BuiltInTools[dto.BuildInToolFileSearch]; exists { if fileSearchTool, exists := relayInfo.ResponsesUsageInfo.BuiltInTools[dto.BuildInToolFileSearch]; exists {

View File

@@ -23,6 +23,15 @@ const (
Gemini20FlashInputAudioPrice = 0.70 Gemini20FlashInputAudioPrice = 0.70
) )
const (
// Claude Web search
ClaudeWebSearchPrice = 10.00
)
func GetClaudeWebSearchPricePerThousand() float64 {
return ClaudeWebSearchPrice
}
func GetWebSearchPricePerThousand(modelName string, contextSize string) float64 { func GetWebSearchPricePerThousand(modelName string, contextSize string) float64 {
// 确定模型类型 // 确定模型类型
// https://platform.openai.com/docs/pricing Web search 价格按模型类型和 search context size 收费 // https://platform.openai.com/docs/pricing Web search 价格按模型类型和 search context size 收费