package proxy import "testing" func TestComputeCost(t *testing.T) { // 标准三价:输入 0.5 / 输出 1.5 / 缓存读 0.05($/M) const ( inPrice = 0.5 outPrice = 1.5 cchPrice = 0.05 ) tests := []struct { name string upstreamProto string input int output int cacheRead int cacheCreation int inP float64 outP float64 cchP float64 want float64 }{ { // OpenAI:prompt 含缓存读,需扣减:(11000−10000)×0.5 + 10000×0.05 + 500×1.5 name: "openai prompt includes cache read", upstreamProto: "chat", input: 11000, output: 500, cacheRead: 10000, inP: inPrice, outP: outPrice, cchP: cchPrice, want: (1000*inPrice + 10000*cchPrice + 500*outPrice) / 1e6, }, { // Anthropic:input 不含缓存;缓存写按输入价 ×1.25 name: "anthropic cache write at 1.25x input price", upstreamProto: "messages", input: 1000, output: 500, cacheRead: 10000, cacheCreation: 2000, inP: inPrice, outP: outPrice, cchP: cchPrice, want: (1000*inPrice + 10000*cchPrice + 2000*inPrice*1.25 + 500*outPrice) / 1e6, }, { // Anthropic 口径不得扣减缓存读(否则这里非缓存输入会算成负数) name: "anthropic does not subtract cache read", upstreamProto: "messages", input: 100, output: 0, cacheRead: 1000, inP: inPrice, outP: outPrice, cchP: cchPrice, want: (100*inPrice + 1000*cchPrice) / 1e6, }, { // OpenAI 异常数据:cached > prompt 时非缓存输入钳制为 0,不出现负费用 name: "openai clamps negative uncached input", upstreamProto: "responses", input: 100, output: 0, cacheRead: 5000, inP: inPrice, outP: outPrice, cchP: cchPrice, want: (5000 * cchPrice) / 1e6, }, { // 未配置价格时费用为 0 name: "no prices no cost", upstreamProto: "messages", input: 1000, output: 1000, cacheRead: 1000, cacheCreation: 1000, want: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := ComputeCost(tt.upstreamProto, tt.input, tt.output, tt.cacheRead, tt.cacheCreation, tt.inP, tt.outP, tt.cchP) if diff := got - tt.want; diff > 1e-12 || diff < -1e-12 { t.Fatalf("ComputeCost(%q, in=%d, out=%d, cr=%d, cw=%d) = %v, want %v", tt.upstreamProto, tt.input, tt.output, tt.cacheRead, tt.cacheCreation, got, tt.want) } }) } }