Files
ttstd-infinite-canvas/backend/internal/service/price_validation.go
ahyang a23e399ccf fix: 支持零价系统渠道模型分发 (#303)
* docs(spec): 模型计费 - 记录零价免费模型设计

* fix(billing): 模型定价 - 支持零价免费模型

* fix(config): 系统模型目录 - 支持零价模型
2026-08-24 21:32:56 +08:00

81 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import "infinite-canvas/backend/internal/model"
// ValidateChannelModelPrice 校验渠道模型价格配置的有效性
// 根据 billingMode 检查必要的价格字段是否已配置
func ValidateChannelModelPrice(billingMode string, capability string, protocol model.ChannelInterfaceType, unitPrice, inputPrice, outputPrice, cachedPrice int64) bool {
switch billingMode {
case "fixed_request":
// 固定价格模式:0 表示免费,负数无效。
return unitPrice >= 0
case "per_second":
// 按秒计费:0 表示免费,负数无效。
return unitPrice >= 0
case "token":
if capability == "video" {
return protocol == model.ChannelInterfaceVolcengineArkVideo && inputPrice >= 0 && outputPrice >= 0 && cachedPrice >= 0
}
if capability != "" && capability != "text" {
return false
}
// 文本模型:所有 Token 价格为 0 时表示免费。
return inputPrice >= 0 && outputPrice >= 0 && cachedPrice >= 0
default:
return false
}
}
// ValidatePriceTierPrice 校验价格档的价格配置有效性
func ValidatePriceTierPrice(tier *model.ChannelModelPriceTier, capability string, protocol model.ChannelInterfaceType) bool {
if tier == nil {
return false
}
return ValidateChannelModelPrice(tier.BillingMode, capability, protocol, tier.UnitPriceMicrocredits, tier.InputTokenPriceMicrocredits, tier.OutputTokenPriceMicrocredits, tier.CachedTokenPriceMicrocredits)
}
// ComputePriceConfigured 根据价格内容计算 PriceConfigured 标志
// 不再允许手动设置 PriceConfigured,必须由价格字段派生
func ComputePriceConfigured(billingMode string, capability string, protocol model.ChannelInterfaceType, unitPrice, inputPrice, outputPrice, cachedPrice int64) bool {
return ValidateChannelModelPrice(billingMode, capability, protocol, unitPrice, inputPrice, outputPrice, cachedPrice)
}
// ComputeTierPriceConfigured 计算价格档的 PriceConfigured 标志
func ComputeTierPriceConfigured(tier *model.ChannelModelPriceTier, capability string, protocol model.ChannelInterfaceType) bool {
if tier == nil {
return false
}
return ComputePriceConfigured(tier.BillingMode, capability, protocol, tier.UnitPriceMicrocredits, tier.InputTokenPriceMicrocredits, tier.OutputTokenPriceMicrocredits, tier.CachedTokenPriceMicrocredits)
}
// HasValidPrice 检查渠道模型是否有有效价格
// 对于有价格档的模型,检查是否至少有一个启用且价格有效的价格档
func HasValidPrice(channelModel *model.ChannelModel) bool {
if channelModel == nil {
return false
}
// 如果有价格档,检查价格档
if len(channelModel.PriceTiers) > 0 {
for _, tier := range channelModel.PriceTiers {
if tier.Enabled && tier.PriceConfigured && ValidatePriceTierPrice(&tier, channelModel.Capability, channelModel.Protocol) {
return true
}
}
return false
}
// 否则检查模型级别的价格
return channelModel.PriceConfigured && ValidateChannelModelPrice(channelModel.BillingMode, channelModel.Capability, channelModel.Protocol, channelModel.UnitPriceMicrocredits, channelModel.InputTokenPriceMicrocredits, channelModel.OutputTokenPriceMicrocredits, channelModel.CachedTokenPriceMicrocredits)
}
// ValidateLogicalModelPrice 校验前台模型的价格配置
func ValidateLogicalModelPrice(pricePolicy string, billingMode string, unitPrice, inputPrice, outputPrice, cachedPrice int64) bool {
if pricePolicy == "channel" {
// 跟随渠道价格,不需要校验前台价格
return true
}
// 统一定价模式,按 billingMode 校验
return ValidateChannelModelPrice(billingMode, "", "", unitPrice, inputPrice, outputPrice, cachedPrice)
}