- 新增 ComputeCost:OpenAI 系 prompt 含缓存读需扣减(异常数据钳制为 0); Anthropic input_tokens 不含缓存,按原值计费,缓存写按输入价 ×1.25(原实现误用输出价) - recordUsage 传入上游协议(用量语义跟随解析它的上游响应,而非客户端协议) - 补充单元测试覆盖两种协议口径与边界情况
76 lines
2.4 KiB
Go
76 lines
2.4 KiB
Go
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)
|
||
}
|
||
})
|
||
}
|
||
}
|