feat: claude web search tool 计费
This commit is contained in:
@@ -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"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 收费
|
||||||
|
|||||||
Reference in New Issue
Block a user