增加2.5模型调用

This commit is contained in:
andy committed 2026-09-23 15:10:13 +08:00
1 parent 3f29ba716a
commit be655b6569
32 files changed
+1075 -56

No files matched your search

+26
View File
@@ -23,6 +23,8 @@ func DefaultBillingPriceRules() []PriceRule {
rules := []PriceRule{
{ID: "base-volcengine-jimeng-seedream46", Provider: "volcengine-visual", Capability: "image.generate", ReqKey: "jimeng_seedream46_cvtob", Unit: UnitImage, StandardUnitPriceFen: 20, Note: "即梦4.6公开资源包基准。", Source: catalogSource("https://www.volcengine.com/activity/jimeng")},
{ID: "base-evolink-gpt-image-2", Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2", Unit: UnitImage, StandardUnitPriceFen: 34, Note: "medium / 1K / 1:1 / 无参考图基准。", Source: catalogSource("https://evolink.ai/zh/gpt-image-2"), Dimensions: evolinkDimensions()},
evolink25PriceRule("gpt-image-2.5-flare", "https://evolink.ai/gpt-image-2-5"),
evolink25PriceRule("gpt-image-2.5-sunburst", "https://evolink.ai/zh/gpt-image-2-5-sunburst"),
{ID: "base-bailian-wan27-image-pro", Provider: "bailian", Capability: "image.generate", ReqKey: "wan2.7-image-pro", Unit: UnitImage, StandardUnitPriceFen: 50, Source: catalogSource("https://help.aliyun.com/zh/model-studio/wan2-7-image-pro")},
{ID: "base-seedream-5-0-pro", Provider: "seedream", Capability: "image.generate", ReqKey: Seedream50ProModel, Unit: UnitImage, StandardUnitPriceFen: 30, Note: "基础生图:1K/1.5K ¥0.30,2K ¥0.60;首张输入图免费,额外输入图 ¥0.02/张。", Source: catalogSource("https://docs.volcengine.com/docs/82379/1544106?lang=zh"), Dimensions: seedreamDimensions()},
{ID: "base-seedream-5-0-pro-layers", Provider: "seedream", Capability: "image.generate", ReqKey: Seedream50ProModel, Unit: UnitImage, StandardUnitPriceFen: 15, Conditions: Conditions{"layerDecomposition": true}, Priority: 10, Note: "图层拆分:≤261万像素 ¥0.15/张,>261万像素 ¥0.30/张;最多预留底图加16个图层,完成后按每张实际像素结算。", Source: catalogSource("https://docs.volcengine.com/docs/82379/1544106?lang=zh"), Dimensions: seedreamDimensions()},
@@ -86,6 +88,30 @@ func evolinkDimensions() []ParameterDimension {
}
}
func evolink25PriceRule(model, sourceURL string) PriceRule {
dimensions := evolinkDimensions()
dimensions[0] = ParameterDimension{
Key: "quality", Label: "生成质量", BaselineValue: "medium", DefaultValue: "medium",
Tiers: []ParameterTier{
{Value: "low", Label: "快速", StandardFactor: 4.0 / 9, MarkupMultiplier: DefaultBillingMarkupMultiplier, Enabled: true},
{Value: "medium", Label: "标准", StandardFactor: 1, MarkupMultiplier: DefaultBillingMarkupMultiplier, Enabled: true},
{Value: "high", Label: "精细", StandardFactor: 35.0 / 9, MarkupMultiplier: DefaultBillingMarkupMultiplier, Enabled: true},
},
}
// This integration exposes only 1K. Do not inherit Image 2's 2K/4K estimates.
dimensions[1].Tiers = dimensions[1].Tiers[:1]
dimensions[2].Tiers = append(dimensions[2].Tiers, ParameterTier{Value: "other", Match: map[string]any{}, StandardFactor: 1, MarkupMultiplier: DefaultBillingMarkupMultiplier, Enabled: true})
return PriceRule{
ID: "base-evolink-" + model, Provider: "evolink", Capability: "image.generate", ReqKey: model,
Unit: UnitImage, StandardUnitPriceFen: 9, Dimensions: dimensions,
Note: "1K 基础输出估算:low/medium/high 成本为 ¥0.04/¥0.09/¥0.35;输入费用未单独加收,非上游实际 token 账单。",
Source: map[string]any{
"url": sourceURL, "observedAt": "2026-09-23", "currency": "USD", "unitPrice": 0.012, "fxRate": 7.2,
"basis": "1024×1024、无参考图输出费用估算:low 约 $0.0053,medium 约 $0.012,high 约 $0.0474;人民币标准成本向上取整到分。参考图和提示词会影响上游实扣。",
},
}
}
// NormalizeBillingParameters derives quote inputs from the persisted generation
// payload. Explicit parameters are retained only as a fallback for values the
// payload does not carry.
+18 -16
View File
@@ -5,22 +5,24 @@ import "testing"
func TestDefaultBillingPriceRulesFreezeOfficialCatalogMatchKeys(t *testing.T) {
rules := DefaultBillingPriceRules()
want := map[string]bool{
"base-volcengine-jimeng-seedream46": false,
"base-evolink-gpt-image-2": false,
"base-bailian-wan27-image-pro": false,
"base-seedream-5-0-pro": false,
"base-seedream-5-0-pro-layers": false,
"base-bailian-wan27-i2v-720p": false,
"base-bailian-wan27-i2v-1080p": false,
"base-seedance-2-0-480p": false,
"base-seedance-2-0-720p": false,
"base-seedance-2-0-1080p": false,
"base-seedance-2-0-4k": false,
"base-seedance-2-5-480p": false,
"base-seedance-2-5-720p": false,
"base-seedance-2-5-1080p": false,
"base-minimax-h3-768p": false,
"base-minimax-h3-2k": false,
"base-volcengine-jimeng-seedream46": false,
"base-evolink-gpt-image-2": false,
"base-evolink-gpt-image-2.5-flare": false,
"base-evolink-gpt-image-2.5-sunburst": false,
"base-bailian-wan27-image-pro": false,
"base-seedream-5-0-pro": false,
"base-seedream-5-0-pro-layers": false,
"base-bailian-wan27-i2v-720p": false,
"base-bailian-wan27-i2v-1080p": false,
"base-seedance-2-0-480p": false,
"base-seedance-2-0-720p": false,
"base-seedance-2-0-1080p": false,
"base-seedance-2-0-4k": false,
"base-seedance-2-5-480p": false,
"base-seedance-2-5-720p": false,
"base-seedance-2-5-1080p": false,
"base-minimax-h3-768p": false,
"base-minimax-h3-2k": false,
}
for _, rule := range rules {
if _, ok := want[rule.ID]; !ok {
@@ -0,0 +1,70 @@
package billing
import (
"context"
"errors"
"testing"
)
func TestEvoLink25QuotesUseIndependentModelAndQualityPrices(t *testing.T) {
catalog := Catalog{Rules: DefaultBillingPriceRules()}
for _, model := range []string{"gpt-image-2.5-flare", "gpt-image-2.5-sunburst"} {
for _, test := range []struct {
quality string
cost, amount int64
}{{"low", 4, 5}, {"medium", 9, 11}, {"high", 35, 42}} {
t.Run(model+"/"+test.quality, func(t *testing.T) {
quote, err := catalog.Quote(QuoteInput{Provider: "evolink", Capability: "image.generate", ReqKey: model, Parameters: Parameters{"quality": test.quality}})
if err != nil {
t.Fatal(err)
}
if quote.PriceRuleID != "base-evolink-"+model || quote.StandardUnitPriceFen != test.cost || quote.AmountFen != test.amount {
t.Fatalf("quote=%+v", quote)
}
})
}
for _, params := range []Parameters{{"quality": "xhigh"}, {"resolution": "2K"}, {"resolution": "4K"}} {
if _, err := catalog.Quote(QuoteInput{Provider: "evolink", Capability: "image.generate", ReqKey: model, Parameters: params}); !errors.Is(err, ErrParameterTier) {
t.Fatalf("unsupported params %v: %v", params, err)
}
}
}
legacy, err := catalog.Quote(QuoteInput{Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2"})
if err != nil || legacy.AmountFen != 41 {
t.Fatalf("legacy quote=%+v, err=%v", legacy, err)
}
}
func TestEvoLink25A4QuoteKeepsModelAndQuality(t *testing.T) {
store := &quoteStoreStub{rules: DefaultBillingPriceRules()}
quote, err := NewService(store, nil).Quote(context.Background(), QuoteCommand{
Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2.5-sunburst",
Payload: map[string]any{"settings": map[string]any{"width": 848.0, "height": 1200.0, "quality": "high", "imageCount": 1.0}},
})
if err != nil {
t.Fatal(err)
}
if quote.AmountFen != 42 || quote.Parameters["aspectRatio"] != "70:99" {
t.Fatalf("quote=%+v", quote)
}
}
func TestEvoLink25QuotesAllSupportedAspectRatios(t *testing.T) {
store := &quoteStoreStub{rules: DefaultBillingPriceRules()}
for _, size := range []string{"1:2", "2:3", "5:4", "21:9", "848x1200"} {
quote, err := NewService(store, nil).Quote(context.Background(), QuoteCommand{
Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2.5-flare",
Payload: map[string]any{"settings": map[string]any{"size": size, "quality": "medium", "imageCount": 1.0}},
})
if err != nil || quote.AmountFen != 11 {
t.Fatalf("size=%s quote=%+v err=%v", size, quote, err)
}
}
quote, err := NewService(store, nil).Quote(context.Background(), QuoteCommand{
Provider: "evolink", Capability: "image.generate", ReqKey: "gpt-image-2.5-flare",
Payload: map[string]any{"settings": map[string]any{"width": 512.0, "height": 1024.0, "quality": "medium"}},
})
if err != nil || quote.AmountFen != 11 || quote.Parameters["aspectRatio"] != "512:1024" {
t.Fatalf("unlisted ratio quote=%+v err=%v", quote, err)
}
}