mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 13:09:59 +00:00
fix: unify pricing labels and expand marketplace pricing display
Keep the model pricing editor wording aligned with the new price-based UI while exposing cache, image, and audio pricing in the marketplace so users can see the full configured pricing model.
This commit is contained in:
@@ -25,6 +25,11 @@ type Pricing struct {
|
||||
ModelPrice float64 `json:"model_price"`
|
||||
OwnerBy string `json:"owner_by"`
|
||||
CompletionRatio float64 `json:"completion_ratio"`
|
||||
CacheRatio *float64 `json:"cache_ratio,omitempty"`
|
||||
CreateCacheRatio *float64 `json:"create_cache_ratio,omitempty"`
|
||||
ImageRatio *float64 `json:"image_ratio,omitempty"`
|
||||
AudioRatio *float64 `json:"audio_ratio,omitempty"`
|
||||
AudioCompletionRatio *float64 `json:"audio_completion_ratio,omitempty"`
|
||||
EnableGroup []string `json:"enable_groups"`
|
||||
SupportedEndpointTypes []constant.EndpointType `json:"supported_endpoint_types"`
|
||||
PricingVersion string `json:"pricing_version,omitempty"`
|
||||
@@ -297,12 +302,29 @@ func updatePricing() {
|
||||
pricing.CompletionRatio = ratio_setting.GetCompletionRatio(model)
|
||||
pricing.QuotaType = 0
|
||||
}
|
||||
if cacheRatio, ok := ratio_setting.GetCacheRatio(model); ok {
|
||||
pricing.CacheRatio = &cacheRatio
|
||||
}
|
||||
if createCacheRatio, ok := ratio_setting.GetCreateCacheRatio(model); ok {
|
||||
pricing.CreateCacheRatio = &createCacheRatio
|
||||
}
|
||||
if imageRatio, ok := ratio_setting.GetImageRatio(model); ok {
|
||||
pricing.ImageRatio = &imageRatio
|
||||
}
|
||||
if ratio_setting.ContainsAudioRatio(model) {
|
||||
audioRatio := ratio_setting.GetAudioRatio(model)
|
||||
pricing.AudioRatio = &audioRatio
|
||||
}
|
||||
if ratio_setting.ContainsAudioCompletionRatio(model) {
|
||||
audioCompletionRatio := ratio_setting.GetAudioCompletionRatio(model)
|
||||
pricing.AudioCompletionRatio = &audioCompletionRatio
|
||||
}
|
||||
pricingMap = append(pricingMap, pricing)
|
||||
}
|
||||
|
||||
// 防止大更新后数据不通用
|
||||
if len(pricingMap) > 0 {
|
||||
pricingMap[0].PricingVersion = "82c4a357505fff6fee8462c3f7ec8a645bb95532669cb73b2cabee6a416ec24f"
|
||||
pricingMap[0].PricingVersion = "5a90f2b86c08bd983a9a2e6d66c255f4eaef9c4bc934386d2b6ae84ef0ff1f1f"
|
||||
}
|
||||
|
||||
// 刷新缓存映射,供高并发快速查询
|
||||
|
||||
@@ -20,7 +20,7 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
import React from 'react';
|
||||
import { Card, Avatar, Typography, Table, Tag } from '@douyinfe/semi-ui';
|
||||
import { IconCoinMoneyStroked } from '@douyinfe/semi-icons';
|
||||
import { calculateModelPrice } from '../../../../../helpers';
|
||||
import { calculateModelPrice, getModelPriceItems } from '../../../../../helpers';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
@@ -74,12 +74,7 @@ const ModelPricingTable = ({
|
||||
: modelData?.quota_type === 1
|
||||
? t('按次计费')
|
||||
: '-',
|
||||
inputPrice: modelData?.quota_type === 0 ? priceData.inputPrice : '-',
|
||||
outputPrice:
|
||||
modelData?.quota_type === 0
|
||||
? priceData.completionPrice || priceData.outputPrice
|
||||
: '-',
|
||||
fixedPrice: modelData?.quota_type === 1 ? priceData.price : '-',
|
||||
priceItems: getModelPriceItems(priceData, t),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -126,48 +121,22 @@ const ModelPricingTable = ({
|
||||
},
|
||||
});
|
||||
|
||||
// 根据计费类型添加价格列
|
||||
if (modelData?.quota_type === 0) {
|
||||
// 按量计费
|
||||
columns.push(
|
||||
{
|
||||
title: t('提示'),
|
||||
dataIndex: 'inputPrice',
|
||||
render: (text) => (
|
||||
<>
|
||||
<div className='font-semibold text-orange-600'>{text}</div>
|
||||
<div className='text-xs text-gray-500'>
|
||||
/ {tokenUnit === 'K' ? '1K' : '1M'} tokens
|
||||
columns.push({
|
||||
title: t('价格摘要'),
|
||||
dataIndex: 'priceItems',
|
||||
render: (items) => (
|
||||
<div className='space-y-1'>
|
||||
{items.map((item) => (
|
||||
<div key={item.key}>
|
||||
<div className='font-semibold text-orange-600'>
|
||||
{item.label} {item.value}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('补全'),
|
||||
dataIndex: 'outputPrice',
|
||||
render: (text) => (
|
||||
<>
|
||||
<div className='font-semibold text-orange-600'>{text}</div>
|
||||
<div className='text-xs text-gray-500'>
|
||||
/ {tokenUnit === 'K' ? '1K' : '1M'} tokens
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// 按次计费
|
||||
columns.push({
|
||||
title: t('价格'),
|
||||
dataIndex: 'fixedPrice',
|
||||
render: (text) => (
|
||||
<>
|
||||
<div className='font-semibold text-orange-600'>{text}</div>
|
||||
<div className='text-xs text-gray-500'>/ 次</div>
|
||||
</>
|
||||
),
|
||||
});
|
||||
}
|
||||
<div className='text-xs text-gray-500'>{item.suffix}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
});
|
||||
|
||||
return (
|
||||
<Table
|
||||
|
||||
@@ -264,7 +264,7 @@ const PricingCardView = ({
|
||||
<h3 className='text-lg font-bold text-gray-900 truncate'>
|
||||
{model.model_name}
|
||||
</h3>
|
||||
<div className='flex items-center gap-3 text-xs mt-1'>
|
||||
<div className='flex flex-col gap-1 text-xs mt-1'>
|
||||
{formatPriceInfo(priceData, t)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
renderModelTag,
|
||||
stringToColor,
|
||||
calculateModelPrice,
|
||||
getModelPriceItems,
|
||||
getLobeHubIcon,
|
||||
} from '../../../../../helpers';
|
||||
import {
|
||||
@@ -231,26 +232,18 @@ export const getPricingTableColumns = ({
|
||||
...(isMobile ? {} : { fixed: 'right' }),
|
||||
render: (text, record, index) => {
|
||||
const priceData = getPriceData(record);
|
||||
const priceItems = getModelPriceItems(priceData, t);
|
||||
|
||||
if (priceData.isPerToken) {
|
||||
return (
|
||||
<div className='space-y-1'>
|
||||
<div className='text-gray-700'>
|
||||
{t('输入')} {priceData.inputPrice} / 1{priceData.unitLabel} tokens
|
||||
return (
|
||||
<div className='space-y-1'>
|
||||
{priceItems.map((item) => (
|
||||
<div key={item.key} className='text-gray-700'>
|
||||
{item.label} {item.value}
|
||||
{item.suffix}
|
||||
</div>
|
||||
<div className='text-gray-700'>
|
||||
{t('输出')} {priceData.completionPrice} / 1{priceData.unitLabel}{' '}
|
||||
tokens
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className='text-gray-700'>
|
||||
{t('模型价格')}:{priceData.price}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
134
web/src/helpers/utils.jsx
vendored
134
web/src/helpers/utils.jsx
vendored
@@ -648,20 +648,9 @@ export const calculateModelPrice = ({
|
||||
if (record.quota_type === 0) {
|
||||
// 按量计费
|
||||
const inputRatioPriceUSD = record.model_ratio * 2 * usedGroupRatio;
|
||||
const completionRatioPriceUSD =
|
||||
record.model_ratio * record.completion_ratio * 2 * usedGroupRatio;
|
||||
|
||||
const unitDivisor = tokenUnit === 'K' ? 1000 : 1;
|
||||
const unitLabel = tokenUnit === 'K' ? 'K' : 'M';
|
||||
|
||||
const rawDisplayInput = displayPrice(inputRatioPriceUSD);
|
||||
const rawDisplayCompletion = displayPrice(completionRatioPriceUSD);
|
||||
|
||||
const numInput =
|
||||
parseFloat(rawDisplayInput.replace(/[^0-9.]/g, '')) / unitDivisor;
|
||||
const numCompletion =
|
||||
parseFloat(rawDisplayCompletion.replace(/[^0-9.]/g, '')) / unitDivisor;
|
||||
|
||||
let symbol = '$';
|
||||
if (currency === 'CNY') {
|
||||
symbol = '¥';
|
||||
@@ -678,9 +667,48 @@ export const calculateModelPrice = ({
|
||||
symbol = '¤';
|
||||
}
|
||||
}
|
||||
|
||||
const formatTokenPrice = (priceUSD) => {
|
||||
const rawDisplayPrice = displayPrice(priceUSD);
|
||||
const numericPrice =
|
||||
parseFloat(rawDisplayPrice.replace(/[^0-9.]/g, '')) / unitDivisor;
|
||||
return `${symbol}${numericPrice.toFixed(precision)}`;
|
||||
};
|
||||
|
||||
const hasRatioValue = (value) =>
|
||||
value !== undefined &&
|
||||
value !== null &&
|
||||
value !== '' &&
|
||||
Number.isFinite(Number(value));
|
||||
|
||||
const inputPrice = formatTokenPrice(inputRatioPriceUSD);
|
||||
const audioInputPrice = hasRatioValue(record.audio_ratio)
|
||||
? formatTokenPrice(inputRatioPriceUSD * Number(record.audio_ratio))
|
||||
: null;
|
||||
|
||||
return {
|
||||
inputPrice: `${symbol}${numInput.toFixed(precision)}`,
|
||||
completionPrice: `${symbol}${numCompletion.toFixed(precision)}`,
|
||||
inputPrice,
|
||||
completionPrice: formatTokenPrice(
|
||||
inputRatioPriceUSD * Number(record.completion_ratio),
|
||||
),
|
||||
cachePrice: hasRatioValue(record.cache_ratio)
|
||||
? formatTokenPrice(inputRatioPriceUSD * Number(record.cache_ratio))
|
||||
: null,
|
||||
createCachePrice: hasRatioValue(record.create_cache_ratio)
|
||||
? formatTokenPrice(inputRatioPriceUSD * Number(record.create_cache_ratio))
|
||||
: null,
|
||||
imagePrice: hasRatioValue(record.image_ratio)
|
||||
? formatTokenPrice(inputRatioPriceUSD * Number(record.image_ratio))
|
||||
: null,
|
||||
audioInputPrice,
|
||||
audioOutputPrice:
|
||||
audioInputPrice && hasRatioValue(record.audio_completion_ratio)
|
||||
? formatTokenPrice(
|
||||
inputRatioPriceUSD *
|
||||
Number(record.audio_ratio) *
|
||||
Number(record.audio_completion_ratio),
|
||||
)
|
||||
: null,
|
||||
unitLabel,
|
||||
isPerToken: true,
|
||||
usedGroup,
|
||||
@@ -710,26 +738,76 @@ export const calculateModelPrice = ({
|
||||
};
|
||||
};
|
||||
|
||||
// 格式化价格信息(用于卡片视图)
|
||||
export const formatPriceInfo = (priceData, t) => {
|
||||
export const getModelPriceItems = (priceData, t) => {
|
||||
if (priceData.isPerToken) {
|
||||
return (
|
||||
<>
|
||||
<span style={{ color: 'var(--semi-color-text-1)' }}>
|
||||
{t('输入')} {priceData.inputPrice}/{priceData.unitLabel}
|
||||
</span>
|
||||
<span style={{ color: 'var(--semi-color-text-1)' }}>
|
||||
{t('输出')} {priceData.completionPrice}/{priceData.unitLabel}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
const unitSuffix = ` / 1${priceData.unitLabel} Tokens`;
|
||||
return [
|
||||
{
|
||||
key: 'input',
|
||||
label: t('输入价格'),
|
||||
value: priceData.inputPrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'completion',
|
||||
label: t('补全价格'),
|
||||
value: priceData.completionPrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'cache',
|
||||
label: t('缓存读取价格'),
|
||||
value: priceData.cachePrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'create-cache',
|
||||
label: t('缓存创建价格'),
|
||||
value: priceData.createCachePrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'image',
|
||||
label: t('图片输入价格'),
|
||||
value: priceData.imagePrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'audio-input',
|
||||
label: t('音频输入价格'),
|
||||
value: priceData.audioInputPrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
{
|
||||
key: 'audio-output',
|
||||
label: t('音频补全价格'),
|
||||
value: priceData.audioOutputPrice,
|
||||
suffix: unitSuffix,
|
||||
},
|
||||
].filter((item) => item.value !== null && item.value !== undefined && item.value !== '');
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
key: 'fixed',
|
||||
label: t('模型价格'),
|
||||
value: priceData.price,
|
||||
suffix: ` / ${t('次')}`,
|
||||
},
|
||||
].filter((item) => item.value !== null && item.value !== undefined && item.value !== '');
|
||||
};
|
||||
|
||||
// 格式化价格信息(用于卡片视图)
|
||||
export const formatPriceInfo = (priceData, t) => {
|
||||
const items = getModelPriceItems(priceData, t);
|
||||
return (
|
||||
<>
|
||||
<span style={{ color: 'var(--semi-color-text-1)' }}>
|
||||
{t('模型价格')} {priceData.price}
|
||||
</span>
|
||||
{items.map((item) => (
|
||||
<span key={item.key} style={{ color: 'var(--semi-color-text-1)' }}>
|
||||
{item.label} {item.value}
|
||||
{item.suffix}
|
||||
</span>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
7
web/src/i18n/locales/en.json
vendored
7
web/src/i18n/locales/en.json
vendored
@@ -1398,7 +1398,8 @@
|
||||
"按价格设置": "Set by price",
|
||||
"按倍率类型筛选": "Filter by ratio type",
|
||||
"按倍率设置": "Set by ratio",
|
||||
"按次计费": "Pay per view",
|
||||
"按次": "Per request",
|
||||
"按次计费": "Pay per request",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "Pay as you go",
|
||||
"按顺序替换content中的变量占位符": "Replace variable placeholders in content in order",
|
||||
@@ -1846,7 +1847,7 @@
|
||||
"模板应用失败": "",
|
||||
"模板示例": "Template example",
|
||||
"模糊搜索模型名称": "Fuzzy search model name",
|
||||
"次": "times",
|
||||
"次": "request",
|
||||
"欢迎使用,请完成以下设置以开始使用系统": "Welcome! Please complete the following settings to start using the system",
|
||||
"欧元": "EUR",
|
||||
"正在加载可用部署位置...": "Loading available deployment locations...",
|
||||
@@ -3223,7 +3224,7 @@
|
||||
"扩展价格": "Additional Pricing",
|
||||
"额外价格项": "Additional price items",
|
||||
"补全价格": "Completion Price",
|
||||
"提示缓存价格": "Input Cache Read Price",
|
||||
"缓存读取价格": "Input Cache Read Price",
|
||||
"缓存创建价格": "Input Cache Creation Price",
|
||||
"图片输入价格": "Image Input Price",
|
||||
"音频输入价格": "Audio Input Price",
|
||||
|
||||
7
web/src/i18n/locales/fr.json
vendored
7
web/src/i18n/locales/fr.json
vendored
@@ -1398,7 +1398,8 @@
|
||||
"按价格设置": "Définir par prix",
|
||||
"按倍率类型筛选": "Filtrer par type de ratio",
|
||||
"按倍率设置": "Définir par ratio",
|
||||
"按次计费": "Paiement à la séance",
|
||||
"按次": "Par requête",
|
||||
"按次计费": "Paiement par requête",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Entrez au format : AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "Paiement à l'utilisation",
|
||||
"按顺序替换content中的变量占位符": "Remplacer les espaces réservés de variable dans le contenu dans l'ordre",
|
||||
@@ -1835,7 +1836,7 @@
|
||||
"模板应用失败": "",
|
||||
"模板示例": "Exemple de modèle",
|
||||
"模糊搜索模型名称": "Recherche floue de nom de modèle",
|
||||
"次": "Fois",
|
||||
"次": "requête",
|
||||
"欢迎使用,请完成以下设置以开始使用系统": "Bienvenue, veuillez compléter les paramètres suivants pour commencer à utiliser le système",
|
||||
"欧元": "Euro",
|
||||
"正在加载可用部署位置...": "Loading available deployment locations...",
|
||||
@@ -3192,7 +3193,7 @@
|
||||
"扩展价格": "Prix supplémentaires",
|
||||
"额外价格项": "Éléments de prix supplémentaires",
|
||||
"补全价格": "Prix de complétion",
|
||||
"提示缓存价格": "Prix de lecture du cache d'entrée",
|
||||
"缓存读取价格": "Prix de lecture du cache d'entrée",
|
||||
"缓存创建价格": "Prix de création du cache d'entrée",
|
||||
"图片输入价格": "Prix d'entrée image",
|
||||
"音频输入价格": "Prix d'entrée audio",
|
||||
|
||||
7
web/src/i18n/locales/ja.json
vendored
7
web/src/i18n/locales/ja.json
vendored
@@ -1381,7 +1381,8 @@
|
||||
"按价格设置": "料金設定",
|
||||
"按倍率类型筛选": "倍率タイプで絞り込み",
|
||||
"按倍率设置": "倍率設定",
|
||||
"按次计费": "リクエスト課金",
|
||||
"按次": "リクエストごと",
|
||||
"按次计费": "リクエストごとの課金",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "従量課金",
|
||||
"按顺序替换content中的变量占位符": "content内の変数プレースホルダーを順番に置換します",
|
||||
@@ -1818,7 +1819,7 @@
|
||||
"模板应用失败": "",
|
||||
"模板示例": "テンプレートサンプル",
|
||||
"模糊搜索模型名称": "モデル名であいまい検索",
|
||||
"次": "回",
|
||||
"次": "リクエスト",
|
||||
"欢迎使用,请完成以下设置以开始使用系统": "ようこそ。システムを利用開始するには、以下の設定を完了してください",
|
||||
"欧元": "EUR",
|
||||
"正在加载可用部署位置...": "Loading available deployment locations...",
|
||||
@@ -3173,7 +3174,7 @@
|
||||
"扩展价格": "追加価格",
|
||||
"额外价格项": "追加価格項目",
|
||||
"补全价格": "補完価格",
|
||||
"提示缓存价格": "入力キャッシュ読み取り価格",
|
||||
"缓存读取价格": "入力キャッシュ読み取り価格",
|
||||
"缓存创建价格": "入力キャッシュ作成価格",
|
||||
"图片输入价格": "画像入力価格",
|
||||
"音频输入价格": "音声入力価格",
|
||||
|
||||
7
web/src/i18n/locales/ru.json
vendored
7
web/src/i18n/locales/ru.json
vendored
@@ -1410,7 +1410,8 @@
|
||||
"按价格设置": "Настроить по цене",
|
||||
"按倍率类型筛选": "Фильтровать по типу коэффициента",
|
||||
"按倍率设置": "Настроить по множителю",
|
||||
"按次计费": "Оплата за использование",
|
||||
"按次": "За запрос",
|
||||
"按次计费": "Оплата за запрос",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Введите в формате: AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "Оплата по объему",
|
||||
"按顺序替换content中的变量占位符": "Последовательно заменять переменные-заполнители в content",
|
||||
@@ -1847,7 +1848,7 @@
|
||||
"模板应用失败": "",
|
||||
"模板示例": "Пример шаблона",
|
||||
"模糊搜索模型名称": "Нечеткий поиск по названию модели",
|
||||
"次": "раз",
|
||||
"次": "запрос",
|
||||
"欢迎使用,请完成以下设置以开始使用系统": "Добро пожаловать, пожалуйста, выполните следующие настройки, чтобы начать использовать систему",
|
||||
"欧元": "Евро",
|
||||
"正在加载可用部署位置...": "Loading available deployment locations...",
|
||||
@@ -3206,7 +3207,7 @@
|
||||
"扩展价格": "Дополнительные цены",
|
||||
"额外价格项": "Дополнительные ценовые позиции",
|
||||
"补全价格": "Цена завершения",
|
||||
"提示缓存价格": "Цена чтения входного кеша",
|
||||
"缓存读取价格": "Цена чтения входного кеша",
|
||||
"缓存创建价格": "Цена создания входного кеша",
|
||||
"图片输入价格": "Цена входного изображения",
|
||||
"音频输入价格": "Цена входного аудио",
|
||||
|
||||
7
web/src/i18n/locales/vi.json
vendored
7
web/src/i18n/locales/vi.json
vendored
@@ -1382,7 +1382,8 @@
|
||||
"按价格设置": "Đặt theo giá",
|
||||
"按倍率类型筛选": "Lọc theo loại tỷ lệ",
|
||||
"按倍率设置": "Đặt theo tỷ lệ",
|
||||
"按次计费": "Trả tiền cho mỗi lần xem",
|
||||
"按次": "Theo lượt gọi",
|
||||
"按次计费": "Tính phí theo lượt gọi",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "Trả tiền theo mức sử dụng",
|
||||
"按顺序替换content中的变量占位符": "Thay thế các trình giữ chỗ biến trong nội dung theo thứ tự",
|
||||
@@ -1839,7 +1840,7 @@
|
||||
"模板示例": "Ví dụ mẫu",
|
||||
"模糊匹配": "Khớp mờ",
|
||||
"模糊搜索模型名称": "Tìm kiếm mờ tên mô hình",
|
||||
"次": "lần",
|
||||
"次": "lượt",
|
||||
"欢迎使用,请完成以下设置以开始使用系统": "Chào mừng! Vui lòng hoàn tất các cài đặt sau để bắt đầu sử dụng hệ thống",
|
||||
"欢迎回来": "Chào mừng trở lại",
|
||||
"欢迎回来!": "Chào mừng trở lại!",
|
||||
@@ -3745,7 +3746,7 @@
|
||||
"扩展价格": "Giá mở rộng",
|
||||
"额外价格项": "Mục giá bổ sung",
|
||||
"补全价格": "Giá hoàn thành",
|
||||
"提示缓存价格": "Giá đọc bộ nhớ đệm đầu vào",
|
||||
"缓存读取价格": "Giá đọc bộ nhớ đệm đầu vào",
|
||||
"缓存创建价格": "Giá tạo bộ nhớ đệm đầu vào",
|
||||
"图片输入价格": "Giá đầu vào hình ảnh",
|
||||
"音频输入价格": "Giá đầu vào âm thanh",
|
||||
|
||||
3
web/src/i18n/locales/zh-CN.json
vendored
3
web/src/i18n/locales/zh-CN.json
vendored
@@ -1103,6 +1103,7 @@
|
||||
"按价格设置": "按价格设置",
|
||||
"按倍率类型筛选": "按倍率类型筛选",
|
||||
"按倍率设置": "按倍率设置",
|
||||
"按次": "按次",
|
||||
"按次计费": "按次计费",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式输入:AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "按量计费",
|
||||
@@ -2850,7 +2851,7 @@
|
||||
"扩展价格": "扩展价格",
|
||||
"额外价格项": "额外价格项",
|
||||
"补全价格": "补全价格",
|
||||
"提示缓存价格": "提示缓存价格",
|
||||
"缓存读取价格": "缓存读取价格",
|
||||
"缓存创建价格": "缓存创建价格",
|
||||
"图片输入价格": "图片输入价格",
|
||||
"音频输入价格": "音频输入价格",
|
||||
|
||||
3
web/src/i18n/locales/zh-TW.json
vendored
3
web/src/i18n/locales/zh-TW.json
vendored
@@ -1106,6 +1106,7 @@
|
||||
"按价格设置": "按價格設定",
|
||||
"按倍率类型筛选": "按倍率類型篩選",
|
||||
"按倍率设置": "按倍率設定",
|
||||
"按次": "按次",
|
||||
"按次计费": "按次計費",
|
||||
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式輸入:AccessKey|SecretAccessKey|Region",
|
||||
"按量计费": "按量計費",
|
||||
@@ -2843,7 +2844,7 @@
|
||||
"扩展价格": "擴展價格",
|
||||
"额外价格项": "額外價格項",
|
||||
"补全价格": "補全價格",
|
||||
"提示缓存价格": "提示快取價格",
|
||||
"缓存读取价格": "快取讀取價格",
|
||||
"缓存创建价格": "快取建立價格",
|
||||
"图片输入价格": "圖片輸入價格",
|
||||
"音频输入价格": "音訊輸入價格",
|
||||
|
||||
@@ -491,7 +491,7 @@ export default function ModelPricingEditor({
|
||||
}
|
||||
/>
|
||||
<PriceInput
|
||||
label={t('提示缓存价格')}
|
||||
label={t('缓存读取价格')}
|
||||
value={selectedModel.cachePrice}
|
||||
placeholder={t('输入 $/1M tokens')}
|
||||
onChange={(value) => handleNumericFieldChange('cachePrice', value)}
|
||||
|
||||
Reference in New Issue
Block a user