mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
feat(openai): add ultrafast pricing
Add published GPT-6 Astra and GPT-6.1 Sol rates for short and long context. Expose Ultrafast override bands in the pricing API and editor, with billing and validation coverage. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -260,10 +260,12 @@ impl SettingsService for DefaultSettingsService {
|
||||
PricingChange::Replace(pricing) => {
|
||||
pricing.validate().map_err(AdminError::invalid)?;
|
||||
if command.provider == "xai"
|
||||
&& pricing
|
||||
.bands
|
||||
.keys()
|
||||
.any(|band| matches!(band.as_str(), "image" | "flex" | "long_flex"))
|
||||
&& pricing.bands.keys().any(|band| {
|
||||
matches!(
|
||||
band.as_str(),
|
||||
"image" | "flex" | "long_flex" | "ultrafast" | "long_ultrafast"
|
||||
)
|
||||
})
|
||||
{
|
||||
return Err(AdminError::invalid("xAI 不支持此价格档位"));
|
||||
}
|
||||
|
||||
@@ -100,6 +100,51 @@ async fn client_profile_preview_rejects_unknown_provider_before_loading_settings
|
||||
assert_eq!(error.kind(), AdminErrorKind::Invalid);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pricing_accepts_ultrafast_for_openai_but_rejects_it_for_xai() {
|
||||
for provider in ["openai", "xai"] {
|
||||
let store = Arc::new(PricingSettingsStore::default());
|
||||
let services = super::AdminHarness::new()
|
||||
.settings(store.clone())
|
||||
.provider(super::test_provider(provider))
|
||||
.build()
|
||||
.await;
|
||||
let context = MutationContext {
|
||||
actor: gateway_admin::model::MutationActor::System,
|
||||
request_id: "request-ultrafast-pricing".to_owned(),
|
||||
};
|
||||
for band in ["ultrafast", "long_ultrafast"] {
|
||||
let pricing = serde_json::from_value(serde_json::json!({
|
||||
"multiplierBps": 10000,
|
||||
"bands": {
|
||||
"standard": {"input":"2", "output":"10", "cacheRead":"0.1", "cacheWrite":"2.5"},
|
||||
(band): {"input":"12", "output":"60", "cacheRead":"0.6", "cacheWrite":"15"}
|
||||
}
|
||||
}))
|
||||
.expect("Ultrafast override");
|
||||
let update = UpdatePricing {
|
||||
provider: provider.to_owned(),
|
||||
models: vec!["example-model".to_owned()],
|
||||
change: PricingChange::Replace(pricing),
|
||||
};
|
||||
let result = services
|
||||
.settings()
|
||||
.update_pricing(&context, update.clone())
|
||||
.await;
|
||||
if provider == "openai" {
|
||||
result.expect("OpenAI accepts Ultrafast overrides");
|
||||
assert_eq!(store.updated.lock().unwrap().as_ref(), Some(&update));
|
||||
} else {
|
||||
assert_eq!(
|
||||
result.expect_err("xAI rejects Ultrafast").kind(),
|
||||
AdminErrorKind::Invalid
|
||||
);
|
||||
assert!(store.updated.lock().unwrap().is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pricing_accepts_native_provider_and_rejects_unknown_sync_provider() {
|
||||
let store = Arc::new(PricingSettingsStore::default());
|
||||
|
||||
@@ -69,9 +69,11 @@ impl ModelPriceOverride {
|
||||
band.as_str(),
|
||||
"standard"
|
||||
| "fast"
|
||||
| "ultrafast"
|
||||
| "flex"
|
||||
| "long_standard"
|
||||
| "long_fast"
|
||||
| "long_ultrafast"
|
||||
| "long_flex"
|
||||
| "image"
|
||||
)
|
||||
|
||||
@@ -37,6 +37,19 @@ fn override_validation_rejects_unsupported_bands_and_excessive_multiplier() {
|
||||
assert!(price.validate().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_validation_accepts_ultrafast_bands() {
|
||||
let pricing: ModelPriceOverride = serde_json::from_value(json!({
|
||||
"multiplierBps": 10000,
|
||||
"bands": {
|
||||
"ultrafast": {"input":"12", "output":"60", "cacheRead":"0.6", "cacheWrite":"15"},
|
||||
"long_ultrafast": {"input":"24", "output":"90", "cacheRead":"1.2", "cacheWrite":"30"}
|
||||
}
|
||||
}))
|
||||
.unwrap();
|
||||
assert!(pricing.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_layer_cannot_erase_manual_bands_or_multiplier() {
|
||||
let synced: PricingOverrides = serde_json::from_value(json!({"openai":{"model":{
|
||||
|
||||
@@ -139,9 +139,11 @@ struct ModelPricing {
|
||||
standard: TokenRates,
|
||||
flex: TokenRates,
|
||||
fast: TokenRates,
|
||||
ultrafast: TokenRates,
|
||||
long_standard: TokenRates,
|
||||
long_flex: TokenRates,
|
||||
long_fast: TokenRates,
|
||||
long_ultrafast: TokenRates,
|
||||
cache_write_percent: u32,
|
||||
unpriced_long_context: bool,
|
||||
}
|
||||
@@ -152,9 +154,11 @@ impl ModelPricing {
|
||||
standard: TokenRates::new(input, output, cache_read),
|
||||
flex: TokenRates::ZERO,
|
||||
fast: TokenRates::ZERO,
|
||||
ultrafast: TokenRates::ZERO,
|
||||
long_standard: TokenRates::ZERO,
|
||||
long_flex: TokenRates::ZERO,
|
||||
long_fast: TokenRates::ZERO,
|
||||
long_ultrafast: TokenRates::ZERO,
|
||||
cache_write_percent: 0,
|
||||
unpriced_long_context: false,
|
||||
}
|
||||
@@ -170,6 +174,11 @@ impl ModelPricing {
|
||||
self
|
||||
}
|
||||
|
||||
const fn with_ultrafast(mut self, input: u128, output: u128, cache_read: u128) -> Self {
|
||||
self.ultrafast = TokenRates::new(input, output, cache_read);
|
||||
self
|
||||
}
|
||||
|
||||
const fn with_long(mut self, input: u128, output: u128, cache_read: u128) -> Self {
|
||||
self.long_standard = TokenRates::new(input, output, cache_read);
|
||||
self
|
||||
@@ -185,6 +194,11 @@ impl ModelPricing {
|
||||
self
|
||||
}
|
||||
|
||||
const fn with_long_ultrafast(mut self, input: u128, output: u128, cache_read: u128) -> Self {
|
||||
self.long_ultrafast = TokenRates::new(input, output, cache_read);
|
||||
self
|
||||
}
|
||||
|
||||
const fn with_cache_write(mut self, percent: u32) -> Self {
|
||||
self.cache_write_percent = percent;
|
||||
self
|
||||
@@ -206,9 +220,11 @@ impl ModelPricing {
|
||||
(PricingTier::Standard, false) => self.standard,
|
||||
(PricingTier::Flex, false) => self.flex,
|
||||
(PricingTier::Fast, false) => self.fast,
|
||||
(PricingTier::Ultrafast, false) => self.ultrafast,
|
||||
(PricingTier::Standard, true) => self.long_standard,
|
||||
(PricingTier::Flex, true) => self.long_flex,
|
||||
(PricingTier::Fast, true) => self.long_fast,
|
||||
(PricingTier::Ultrafast, true) => self.long_ultrafast,
|
||||
};
|
||||
rates.is_configured().then_some(rates)
|
||||
}
|
||||
@@ -219,6 +235,7 @@ enum PricingTier {
|
||||
Standard,
|
||||
Flex,
|
||||
Fast,
|
||||
Ultrafast,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@@ -230,6 +247,7 @@ struct PricingRule {
|
||||
// 价格来源:https://developers.openai.com/api/docs/pricing
|
||||
// 只登记已核验的常规价格及服务档位;临时优惠不写入内置价目
|
||||
// 原有规则于 2026-09-09 核验,GPT-6.1 Sol 于 2026-09-29 核验,其余新增型号见对应条目
|
||||
// Astra 与 GPT-6.1 Sol 的 Ultrafast 档位于 2026-10-12 对照官方价目表核验
|
||||
// 已按 https://developers.openai.com/api/docs/deprecations 核验至 2026-09-13,
|
||||
// 移除已关闭的型号;仅宣布弃用但尚未到关闭日期的型号继续保留
|
||||
const PRICING_RULES: &[PricingRule] = &[
|
||||
@@ -241,9 +259,11 @@ const PRICING_RULES: &[PricingRule] = &[
|
||||
.with_cache_write(125)
|
||||
.with_flex(50_000, 250_000, 5_000)
|
||||
.with_fast(200_000, 1_000_000, 20_000)
|
||||
.with_ultrafast(600_000, 3_000_000, 60_000)
|
||||
.with_long(200_000, 750_000, 20_000)
|
||||
.with_long_flex(100_000, 375_000, 10_000)
|
||||
.with_long_fast(400_000, 1_500_000, 40_000),
|
||||
.with_long_fast(400_000, 1_500_000, 40_000)
|
||||
.with_long_ultrafast(1_200_000, 4_500_000, 120_000),
|
||||
},
|
||||
PricingRule {
|
||||
model: "gpt-6.1-sol",
|
||||
@@ -251,9 +271,11 @@ const PRICING_RULES: &[PricingRule] = &[
|
||||
.with_cache_write(125)
|
||||
.with_flex(10_000, 50_000, 500)
|
||||
.with_fast(40_000, 200_000, 2_000)
|
||||
.with_ultrafast(120_000, 600_000, 6_000)
|
||||
.with_long(40_000, 150_000, 2_000)
|
||||
.with_long_flex(20_000, 75_000, 1_000)
|
||||
.with_long_fast(80_000, 300_000, 4_000),
|
||||
.with_long_fast(80_000, 300_000, 4_000)
|
||||
.with_long_ultrafast(240_000, 900_000, 12_000),
|
||||
},
|
||||
// https://developers.openai.com/api/docs/models/gpt-6-sol,核验日期 2026-09-24
|
||||
PricingRule {
|
||||
@@ -608,6 +630,7 @@ fn effective_rates(
|
||||
PricingTier::Standard => "long_standard",
|
||||
PricingTier::Fast => "long_fast",
|
||||
PricingTier::Flex => "long_flex",
|
||||
PricingTier::Ultrafast => "long_ultrafast",
|
||||
};
|
||||
let uses_long = long_context
|
||||
&& (default.is_some_and(|p| p.long_standard.is_configured() || p.unpriced_long_context)
|
||||
@@ -616,9 +639,11 @@ fn effective_rates(
|
||||
(PricingTier::Standard, false) => "standard",
|
||||
(PricingTier::Fast, false) => "fast",
|
||||
(PricingTier::Flex, false) => "flex",
|
||||
(PricingTier::Ultrafast, false) => "ultrafast",
|
||||
(PricingTier::Standard, true) => "long_standard",
|
||||
(PricingTier::Fast, true) => "long_fast",
|
||||
(PricingTier::Flex, true) => "long_flex",
|
||||
(PricingTier::Ultrafast, true) => "long_ultrafast",
|
||||
};
|
||||
if let Some(rates) = custom.and_then(|p| p.bands.get(band)) {
|
||||
return Some((
|
||||
@@ -656,9 +681,11 @@ pub(crate) fn pricing_catalog()
|
||||
let bands = [
|
||||
("standard", pricing.standard),
|
||||
("fast", pricing.fast),
|
||||
("ultrafast", pricing.ultrafast),
|
||||
("flex", pricing.flex),
|
||||
("long_standard", pricing.long_standard),
|
||||
("long_fast", pricing.long_fast),
|
||||
("long_ultrafast", pricing.long_ultrafast),
|
||||
("long_flex", pricing.long_flex),
|
||||
]
|
||||
.into_iter()
|
||||
@@ -891,6 +918,7 @@ fn pricing_tier(service_tier: Option<&str>) -> Option<PricingTier> {
|
||||
None | Some("default" | "standard") => Some(PricingTier::Standard),
|
||||
Some("flex") => Some(PricingTier::Flex),
|
||||
Some("fast" | "priority") => Some(PricingTier::Fast),
|
||||
Some("ultrafast") => Some(PricingTier::Ultrafast),
|
||||
Some(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,12 +412,31 @@ async fn copying_builtin_prices_keeps_cache_read_and_write_fallback_costs() {
|
||||
"gpt-6-sol",
|
||||
"gpt-6-luna",
|
||||
] {
|
||||
let usage = OpenAiBillingUsage::new(100, 10, 20, 15);
|
||||
let inherited = openai_billing_breakdown(model, usage, None).unwrap();
|
||||
let copied =
|
||||
openai_billing_breakdown_with_override(model, usage, None, Some(&prices[model]))
|
||||
let ultrafast_supported = matches!(model, "gpt-6-astra" | "gpt-6.1-sol");
|
||||
for band in ["ultrafast", "long_ultrafast"] {
|
||||
assert_eq!(prices[model].bands.contains_key(band), ultrafast_supported);
|
||||
}
|
||||
for tier in [None, Some("ultrafast")] {
|
||||
if tier.is_some() && !ultrafast_supported {
|
||||
continue;
|
||||
}
|
||||
for input in [100, 272_001] {
|
||||
let usage = OpenAiBillingUsage::new(input, 10, 20, 15);
|
||||
let inherited = openai_billing_breakdown(model, usage, tier).unwrap();
|
||||
let copied = openai_billing_breakdown_with_override(
|
||||
model,
|
||||
usage,
|
||||
tier,
|
||||
Some(&prices[model]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(inherited.total_amount(), copied.total_amount(), "{model}");
|
||||
assert_eq!(
|
||||
inherited.total_amount(),
|
||||
copied.total_amount(),
|
||||
"{model} {tier:?} {input}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1205,6 +1205,8 @@ fn billing_should_follow_requested_tier_independently_of_response_tier() {
|
||||
for (requested, actual, expected) in [
|
||||
(Some("priority"), Some("default"), Some(2_000_000_000)),
|
||||
(Some("fast"), Some("default"), Some(2_000_000_000)),
|
||||
(Some("ultrafast"), Some("default"), Some(6_000_000_000)),
|
||||
(Some("ultrafast"), None, Some(6_000_000_000)),
|
||||
(Some("auto"), Some("fast"), None),
|
||||
(Some("default"), Some("flex"), Some(1_000_000_000)),
|
||||
(Some("flex"), Some("priority"), Some(500_000_000)),
|
||||
@@ -1213,6 +1215,7 @@ fn billing_should_follow_requested_tier_independently_of_response_tier() {
|
||||
(Some("default"), Some("future"), Some(1_000_000_000)),
|
||||
(Some("future"), Some("default"), None),
|
||||
(None, Some("priority"), Some(1_000_000_000)),
|
||||
(None, Some("ultrafast"), Some(1_000_000_000)),
|
||||
(None, None, Some(1_000_000_000)),
|
||||
] {
|
||||
assert_eq!(
|
||||
@@ -1230,7 +1233,11 @@ fn billing_should_add_file_and_web_search_fees_without_tier_markup() {
|
||||
{"type": "file_search_call", "id": "fs_2", "status": "completed"},
|
||||
{"type": "web_search_call", "id": "ws_1", "status": "completed", "action": {"type": "search"}}
|
||||
]);
|
||||
for (tier, expected) in [("default", 1_150_000_000), ("fast", 2_150_000_000)] {
|
||||
for (tier, expected) in [
|
||||
("default", 1_150_000_000),
|
||||
("fast", 2_150_000_000),
|
||||
("ultrafast", 6_150_000_000),
|
||||
] {
|
||||
assert_eq!(
|
||||
pricing_response_cost(
|
||||
Some(tier),
|
||||
|
||||
@@ -136,6 +136,48 @@ fn new_gpt_6_models_should_use_published_prices_across_tiers_and_context_boundar
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ultrafast_billing_uses_published_prices_across_the_context_boundary() {
|
||||
// 每档依次核对每百万 Token 的输入、缓存读取、缓存写入和输出价格
|
||||
for (model, input, expected, total) in [
|
||||
("gpt-6-astra", 272_000, ["60", "6", "75", "300"], "16.32057"),
|
||||
(
|
||||
"gpt-6-astra",
|
||||
272_001,
|
||||
["120", "12", "150", "450"],
|
||||
"32.64051",
|
||||
),
|
||||
(
|
||||
"gpt-6.1-sol",
|
||||
272_000,
|
||||
["12", "0.6", "15", "60"],
|
||||
"3.264102",
|
||||
),
|
||||
(
|
||||
"gpt-6.1-sol",
|
||||
272_001,
|
||||
["24", "1.2", "30", "90"],
|
||||
"6.528078",
|
||||
),
|
||||
] {
|
||||
let breakdown =
|
||||
openai_billing_breakdown(model, billing_usage(input, 5, 20, 10), Some("ultrafast"))
|
||||
.expect("published Ultrafast pricing");
|
||||
let prices = [
|
||||
breakdown.input_price_per_million(),
|
||||
breakdown.cache_read_price_per_million(),
|
||||
breakdown.cache_write_price_per_million(),
|
||||
breakdown.output_price_per_million(),
|
||||
]
|
||||
.map(|price| price.amount().canonical());
|
||||
assert_eq!(prices, expected, "{model} {input}");
|
||||
assert_eq!(breakdown.total_amount().amount().canonical(), total);
|
||||
assert_eq!(breakdown.service_tier(), Some("ultrafast"));
|
||||
assert_eq!(breakdown.multiplier_percent(), 600);
|
||||
assert_eq!(breakdown.long_context_billing_applied(), input > 272_000);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn billing_breakdown_should_preserve_input_output_and_cache_components() {
|
||||
let breakdown = openai_billing_breakdown("gpt-5.6-sol", billing_usage(100, 5, 20, 10), None)
|
||||
@@ -405,7 +447,12 @@ fn billing_should_not_inherit_prices_for_unknown_models_or_tiers() {
|
||||
("gpt-5.6-cyber", 1, Some("fast")),
|
||||
("gpt-5.3-codex", 1, Some("flex")),
|
||||
("gpt-6-astra", 1, Some("auto")),
|
||||
("gpt-6-astra", 1, Some("ultrafast")),
|
||||
("gpt-6-astra", 1, Some("future")),
|
||||
("gpt-6-sol", 1, Some("ultrafast")),
|
||||
("gpt-6-sol", 272_001, Some("ultrafast")),
|
||||
("gpt-6-luna", 1, Some("ultrafast")),
|
||||
("gpt-6-luna", 272_001, Some("ultrafast")),
|
||||
("gpt-5.4", 1, Some("ultrafast")),
|
||||
] {
|
||||
assert!(
|
||||
openai_billing_breakdown(model, billing_usage(input, 1, 0, 0), tier).is_none(),
|
||||
@@ -906,29 +953,31 @@ fn custom_price_has_exact_cache_and_multiplier_math() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_custom_long_priority_band_does_not_require_a_long_standard_band() {
|
||||
let pricing = serde_json::from_value(json!({"multiplierBps":10000,"bands":{
|
||||
"standard":{"input":"2","output":"10","cacheRead":"0","cacheWrite":"0"},
|
||||
"long_fast":{"input":"8","output":"40","cacheRead":"0","cacheWrite":"0"}
|
||||
}}))
|
||||
.unwrap();
|
||||
let result = openai_billing_breakdown_with_override(
|
||||
"custom-model",
|
||||
billing_usage(300_000, 0, 0, 0),
|
||||
Some("priority"),
|
||||
Some(&pricing),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(result.total_amount().amount().canonical(), "2.4");
|
||||
assert_eq!(result.standard_amount().amount().canonical(), "0.6");
|
||||
assert!(result.long_context_billing_applied());
|
||||
fn a_custom_long_tier_does_not_require_a_long_standard_band() {
|
||||
for (tier, band) in [("priority", "long_fast"), ("ultrafast", "long_ultrafast")] {
|
||||
let pricing = serde_json::from_value(json!({"multiplierBps":10000,"bands":{
|
||||
"standard":{"input":"2","output":"10","cacheRead":"0","cacheWrite":"0"},
|
||||
(band):{"input":"8","output":"40","cacheRead":"0","cacheWrite":"0"}
|
||||
}}))
|
||||
.unwrap();
|
||||
let result = openai_billing_breakdown_with_override(
|
||||
"custom-model",
|
||||
billing_usage(300_000, 0, 0, 0),
|
||||
Some(tier),
|
||||
Some(&pricing),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(result.total_amount().amount().canonical(), "2.4");
|
||||
assert_eq!(result.standard_amount().amount().canonical(), "0.6");
|
||||
assert!(result.long_context_billing_applied());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplier_only_preserves_builtin_tiers_and_unknown_models_remain_unknown() {
|
||||
let custom: ModelPriceOverride =
|
||||
serde_json::from_value(json!({"multiplierBps":20000,"bands":{}})).unwrap();
|
||||
for tier in [None, Some("priority"), Some("flex")] {
|
||||
for tier in [None, Some("priority"), Some("flex"), Some("ultrafast")] {
|
||||
for input in [100, 272_001] {
|
||||
let usage = billing_usage(input, 10, 20, 5);
|
||||
let original = openai_billing_breakdown("gpt-6-astra", usage, tier).unwrap();
|
||||
|
||||
+3
-2
@@ -1536,9 +1536,10 @@ Guardian 以 `subagent_kind` 或 `client_metadata.x-openai-subagent` 值 `guardi
|
||||
每个档位包含四个非负十进制字符串:`input`、`output`、`cacheRead`、`cacheWrite`,单位 USD / 百万
|
||||
Token,范围 0~1000000、最多四位小数。`"0"` 表示免费,缺少整个档位表示继承;不能只缺少部分单价
|
||||
|
||||
`bands` 可用键为 `standard`、`fast`、`flex`、`long_standard`、`long_fast`、`long_flex`、`image`。
|
||||
`bands` 可用键为 `standard`、`fast`、`ultrafast`、`flex`、`long_standard`、`long_fast`、`long_ultrafast`、`long_flex`、`image`。
|
||||
OpenAI 长上下文为输入超过 272000 Token,xAI 为输入达到 200000 Token;仍按 Provider 支持的
|
||||
模型与服务档位判断是否能估算。xAI 不接受 `flex`、`long_flex`、`image`。图像端点的 `standard`
|
||||
模型与服务档位判断是否能估算。OpenAI 内置 Ultrafast 价目覆盖 `gpt-6-astra` 与 `gpt-6.1-sol`。
|
||||
xAI 不接受 `flex`、`long_flex`、`ultrafast`、`long_ultrafast`、`image`。图像端点的 `standard`
|
||||
用于文本输入,`image` 用于图像 Token;不能用文本输出单价替代图像输出单价。用量无法完整拆分时不估算
|
||||
|
||||
`multiplierBps` 为 0~1000000 的整数,10000 表示 1 倍、0 表示本地估算为零,最大 100 倍。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { RequestOptions } from '../../request'
|
||||
import request from '../../request'
|
||||
|
||||
export type PriceBand = 'standard' | 'fast' | 'flex' | 'long_standard' | 'long_fast' | 'long_flex' | 'image'
|
||||
export type PriceBand = 'standard' | 'fast' | 'ultrafast' | 'flex' | 'long_standard' | 'long_fast' | 'long_ultrafast' | 'long_flex' | 'image'
|
||||
|
||||
export interface TokenPrices {
|
||||
input: string
|
||||
|
||||
@@ -32,7 +32,7 @@ const priceMode = computed({
|
||||
const bandOptions = computed(() => bands
|
||||
.filter(band => props.row?.base.bands.image
|
||||
? ['standard', 'image'].includes(band.value)
|
||||
: props.provider !== 'xai' || !['flex', 'long_flex', 'image'].includes(band.value))
|
||||
: props.provider !== 'xai' || !['flex', 'long_flex', 'ultrafast', 'long_ultrafast', 'image'].includes(band.value))
|
||||
.map(band => ({ ...band, label: band.value === 'standard' && props.row?.base.bands.image ? '文本 Token' : band.label })))
|
||||
|
||||
watch(open, (value) => {
|
||||
|
||||
@@ -3,9 +3,11 @@ import type { ModelPricing, PriceBand, PricingCatalog, TokenPrices } from '@/api
|
||||
export const bands: { value: PriceBand, label: string }[] = [
|
||||
{ value: 'standard', label: '标准' },
|
||||
{ value: 'fast', label: 'Priority / Fast' },
|
||||
{ value: 'ultrafast', label: 'Ultrafast' },
|
||||
{ value: 'flex', label: 'Flex' },
|
||||
{ value: 'long_standard', label: '长上下文 · 标准' },
|
||||
{ value: 'long_fast', label: '长上下文 · Priority' },
|
||||
{ value: 'long_ultrafast', label: '长上下文 · Ultrafast' },
|
||||
{ value: 'long_flex', label: '长上下文 · Flex' },
|
||||
{ value: 'image', label: '图像 Token' },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user