package pricing import "strings" // 价格单位:美元 / 1M tokens type ModelPrice struct { InputPer1M float64 OutputPer1M float64 } var catalog = map[string]ModelPrice{ "gpt-4o": {InputPer1M: 2.5, OutputPer1M: 10}, "gpt-4o-mini": {InputPer1M: 0.15, OutputPer1M: 0.6}, "gpt-4-turbo": {InputPer1M: 10, OutputPer1M: 30}, "gpt-3.5-turbo": {InputPer1M: 0.5, OutputPer1M: 1.5}, "claude-3-5-sonnet": {InputPer1M: 3, OutputPer1M: 15}, "claude-3-5-haiku": {InputPer1M: 0.8, OutputPer1M: 4}, "claude-3-opus": {InputPer1M: 15, OutputPer1M: 75}, "text-embedding-3-small": {InputPer1M: 0.02, OutputPer1M: 0}, "text-embedding-3-large": {InputPer1M: 0.13, OutputPer1M: 0}, "text-embedding-ada-002": {InputPer1M: 0.1, OutputPer1M: 0}, "bge-reranker-v2-m3": {InputPer1M: 0.1, OutputPer1M: 0}, "rerank-english-v3.0": {InputPer1M: 2.0, OutputPer1M: 0}, "rerank-multilingual-v3.0": {InputPer1M: 2.0, OutputPer1M: 0}, } func Estimate(model string, tokensIn, tokensOut int, endpoint string) float64 { if strings.Contains(endpoint, "embeddings") || strings.Contains(endpoint, "rerank") { tokensOut = 0 } price, ok := lookup(model) if !ok { // fallback: average small model pricing price = ModelPrice{InputPer1M: 0.5, OutputPer1M: 1.5} } inCost := float64(tokensIn) / 1_000_000 * price.InputPer1M outCost := float64(tokensOut) / 1_000_000 * price.OutputPer1M return inCost + outCost } func lookup(model string) (ModelPrice, bool) { if p, ok := catalog[model]; ok { return p, true } // strip provider prefix if i := strings.LastIndex(model, "/"); i >= 0 { if p, ok := catalog[model[i+1:]]; ok { return p, true } } // prefix match for k, v := range catalog { if strings.HasPrefix(model, k) { return v, true } } return ModelPrice{}, false } func ListCatalog() map[string]ModelPrice { out := make(map[string]ModelPrice, len(catalog)) for k, v := range catalog { out[k] = v } return out }