|
|
@@ -30,7 +30,7 @@ import {
|
|
|
Dify,
|
|
|
Coze,
|
|
|
SiliconCloud,
|
|
|
- FastGPT
|
|
|
+ FastGPT,
|
|
|
} from '@lobehub/icons';
|
|
|
|
|
|
import {
|
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
Gift,
|
|
|
User,
|
|
|
Settings,
|
|
|
- CircleUser
|
|
|
+ CircleUser,
|
|
|
} from 'lucide-react';
|
|
|
|
|
|
// 侧边栏图标颜色映射
|
|
|
@@ -315,7 +315,6 @@ export const getModelCategories = (() => {
|
|
|
};
|
|
|
})();
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 根据渠道类型返回对应的厂商图标
|
|
|
* @param {number} channelType - 渠道类型值
|
|
|
@@ -868,6 +867,30 @@ export function renderQuota(quota, digits = 2) {
|
|
|
return renderNumber(quota);
|
|
|
}
|
|
|
|
|
|
+function isValidGroupRatio(ratio) {
|
|
|
+ return Number.isFinite(ratio) && ratio !== -1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Helper function to get effective ratio and label
|
|
|
+ * @param {number} groupRatio - The default group ratio
|
|
|
+ * @param {number} user_group_ratio - The user-specific group ratio
|
|
|
+ * @returns {Object} - Object containing { ratio, label, useUserGroupRatio }
|
|
|
+ */
|
|
|
+function getEffectiveRatio(groupRatio, user_group_ratio) {
|
|
|
+ const useUserGroupRatio = isValidGroupRatio(user_group_ratio);
|
|
|
+ const ratioLabel = useUserGroupRatio
|
|
|
+ ? i18next.t('专属倍率')
|
|
|
+ : i18next.t('分组倍率');
|
|
|
+ const effectiveRatio = useUserGroupRatio ? user_group_ratio : groupRatio;
|
|
|
+
|
|
|
+ return {
|
|
|
+ ratio: effectiveRatio,
|
|
|
+ label: ratioLabel,
|
|
|
+ useUserGroupRatio: useUserGroupRatio
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
export function renderModelPrice(
|
|
|
inputTokens,
|
|
|
completionTokens,
|
|
|
@@ -875,6 +898,7 @@ export function renderModelPrice(
|
|
|
modelPrice = -1,
|
|
|
completionRatio,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheTokens = 0,
|
|
|
cacheRatio = 1.0,
|
|
|
image = false,
|
|
|
@@ -890,13 +914,17 @@ export function renderModelPrice(
|
|
|
audioInputTokens = 0,
|
|
|
audioInputPrice = 0,
|
|
|
) {
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
+
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t(
|
|
|
- '模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}',
|
|
|
+ '模型价格:${{price}} * {{ratioType}}:{{ratio}} = ${{total}}',
|
|
|
{
|
|
|
price: modelPrice,
|
|
|
ratio: groupRatio,
|
|
|
total: modelPrice * groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
},
|
|
|
);
|
|
|
} else {
|
|
|
@@ -1033,11 +1061,12 @@ export function renderModelPrice(
|
|
|
|
|
|
// 构建输出部分描述
|
|
|
const outputDesc = i18next.t(
|
|
|
- '输出 {{completion}} tokens / 1M tokens * ${{compPrice}}) * 分组倍率 {{ratio}}',
|
|
|
+ '输出 {{completion}} tokens / 1M tokens * ${{compPrice}}) * {{ratioType}} {{ratio}}',
|
|
|
{
|
|
|
completion: completionTokens,
|
|
|
compPrice: completionRatioPrice,
|
|
|
ratio: groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
},
|
|
|
);
|
|
|
|
|
|
@@ -1045,23 +1074,25 @@ export function renderModelPrice(
|
|
|
const extraServices = [
|
|
|
webSearch && webSearchCallCount > 0
|
|
|
? i18next.t(
|
|
|
- ' + Web搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}',
|
|
|
- {
|
|
|
- count: webSearchCallCount,
|
|
|
- price: webSearchPrice,
|
|
|
- ratio: groupRatio,
|
|
|
- },
|
|
|
- )
|
|
|
+ ' + Web搜索 {{count}}次 / 1K 次 * ${{price}} * {{ratioType}} {{ratio}}',
|
|
|
+ {
|
|
|
+ count: webSearchCallCount,
|
|
|
+ price: webSearchPrice,
|
|
|
+ ratio: groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
+ },
|
|
|
+ )
|
|
|
: '',
|
|
|
fileSearch && fileSearchCallCount > 0
|
|
|
? i18next.t(
|
|
|
- ' + 文件搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}',
|
|
|
- {
|
|
|
- count: fileSearchCallCount,
|
|
|
- price: fileSearchPrice,
|
|
|
- ratio: groupRatio,
|
|
|
- },
|
|
|
- )
|
|
|
+ ' + 文件搜索 {{count}}次 / 1K 次 * ${{price}} * {{ratioType}} {{ratio}}',
|
|
|
+ {
|
|
|
+ count: fileSearchCallCount,
|
|
|
+ price: fileSearchPrice,
|
|
|
+ ratio: groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
+ },
|
|
|
+ )
|
|
|
: '',
|
|
|
].join('');
|
|
|
|
|
|
@@ -1091,16 +1122,12 @@ export function renderLogContent(
|
|
|
user_group_ratio,
|
|
|
image = false,
|
|
|
imageRatio = 1.0,
|
|
|
- useUserGroupRatio = undefined,
|
|
|
webSearch = false,
|
|
|
webSearchCallCount = 0,
|
|
|
fileSearch = false,
|
|
|
fileSearchCallCount = 0,
|
|
|
) {
|
|
|
- const ratioLabel = useUserGroupRatio
|
|
|
- ? i18next.t('专属倍率')
|
|
|
- : i18next.t('分组倍率');
|
|
|
- const ratio = useUserGroupRatio ? user_group_ratio : groupRatio;
|
|
|
+ const { ratio, label: ratioLabel, useUserGroupRatio: useUserGroupRatio } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t('模型价格 ${{price}},{{ratioType}} {{ratio}}', {
|
|
|
@@ -1149,14 +1176,18 @@ export function renderModelPriceSimple(
|
|
|
modelRatio,
|
|
|
modelPrice = -1,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheTokens = 0,
|
|
|
cacheRatio = 1.0,
|
|
|
image = false,
|
|
|
imageRatio = 1.0,
|
|
|
) {
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
if (modelPrice !== -1) {
|
|
|
- return i18next.t('价格:${{price}} * 分组:{{ratio}}', {
|
|
|
+ return i18next.t('价格:${{price}} * {{ratioType}}:{{ratio}}', {
|
|
|
price: modelPrice,
|
|
|
+ ratioType: ratioLabel,
|
|
|
ratio: groupRatio,
|
|
|
});
|
|
|
} else {
|
|
|
@@ -1191,8 +1222,9 @@ export function renderModelPriceSimple(
|
|
|
},
|
|
|
);
|
|
|
} else {
|
|
|
- return i18next.t('模型: {{ratio}} * 分组: {{groupRatio}}', {
|
|
|
+ return i18next.t('模型: {{ratio}} * {{ratioType}}:{{groupRatio}}', {
|
|
|
ratio: modelRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
groupRatio: groupRatio,
|
|
|
});
|
|
|
}
|
|
|
@@ -1210,17 +1242,21 @@ export function renderAudioModelPrice(
|
|
|
audioRatio,
|
|
|
audioCompletionRatio,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheTokens = 0,
|
|
|
cacheRatio = 1.0,
|
|
|
) {
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
// 1 ratio = $0.002 / 1K tokens
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t(
|
|
|
- '模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}',
|
|
|
+ '模型价格:${{price}} * {{ratioType}}:{{ratio}} = ${{total}}',
|
|
|
{
|
|
|
price: modelPrice,
|
|
|
ratio: groupRatio,
|
|
|
total: modelPrice * groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
},
|
|
|
);
|
|
|
} else {
|
|
|
@@ -1245,10 +1281,10 @@ export function renderAudioModelPrice(
|
|
|
let audioPrice =
|
|
|
(audioInputTokens / 1000000) * inputRatioPrice * audioRatio * groupRatio +
|
|
|
(audioCompletionTokens / 1000000) *
|
|
|
- inputRatioPrice *
|
|
|
- audioRatio *
|
|
|
- audioCompletionRatio *
|
|
|
- groupRatio;
|
|
|
+ inputRatioPrice *
|
|
|
+ audioRatio *
|
|
|
+ audioCompletionRatio *
|
|
|
+ groupRatio;
|
|
|
let price = textPrice + audioPrice;
|
|
|
return (
|
|
|
<>
|
|
|
@@ -1304,27 +1340,27 @@ export function renderAudioModelPrice(
|
|
|
<p>
|
|
|
{cacheTokens > 0
|
|
|
? i18next.t(
|
|
|
- '文字提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
|
|
- {
|
|
|
- nonCacheInput: inputTokens - cacheTokens,
|
|
|
- cacheInput: cacheTokens,
|
|
|
- cachePrice: inputRatioPrice * cacheRatio,
|
|
|
- price: inputRatioPrice,
|
|
|
- completion: completionTokens,
|
|
|
- compPrice: completionRatioPrice,
|
|
|
- total: textPrice.toFixed(6),
|
|
|
- },
|
|
|
- )
|
|
|
+ '文字提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
|
|
+ {
|
|
|
+ nonCacheInput: inputTokens - cacheTokens,
|
|
|
+ cacheInput: cacheTokens,
|
|
|
+ cachePrice: inputRatioPrice * cacheRatio,
|
|
|
+ price: inputRatioPrice,
|
|
|
+ completion: completionTokens,
|
|
|
+ compPrice: completionRatioPrice,
|
|
|
+ total: textPrice.toFixed(6),
|
|
|
+ },
|
|
|
+ )
|
|
|
: i18next.t(
|
|
|
- '文字提示 {{input}} tokens / 1M tokens * ${{price}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
|
|
- {
|
|
|
- input: inputTokens,
|
|
|
- price: inputRatioPrice,
|
|
|
- completion: completionTokens,
|
|
|
- compPrice: completionRatioPrice,
|
|
|
- total: textPrice.toFixed(6),
|
|
|
- },
|
|
|
- )}
|
|
|
+ '文字提示 {{input}} tokens / 1M tokens * ${{price}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
|
|
+ {
|
|
|
+ input: inputTokens,
|
|
|
+ price: inputRatioPrice,
|
|
|
+ completion: completionTokens,
|
|
|
+ compPrice: completionRatioPrice,
|
|
|
+ total: textPrice.toFixed(6),
|
|
|
+ },
|
|
|
+ )}
|
|
|
</p>
|
|
|
<p>
|
|
|
{i18next.t(
|
|
|
@@ -1374,12 +1410,14 @@ export function renderClaudeModelPrice(
|
|
|
modelPrice = -1,
|
|
|
completionRatio,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheTokens = 0,
|
|
|
cacheRatio = 1.0,
|
|
|
cacheCreationTokens = 0,
|
|
|
cacheCreationRatio = 1.0,
|
|
|
) {
|
|
|
- const ratioLabel = false ? i18next.t('专属倍率') : i18next.t('分组倍率');
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t(
|
|
|
@@ -1461,33 +1499,35 @@ export function renderClaudeModelPrice(
|
|
|
<p>
|
|
|
{cacheTokens > 0 || cacheCreationTokens > 0
|
|
|
? i18next.t(
|
|
|
- '提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 缓存创建 {{cacheCreationInput}} tokens / 1M tokens * ${{cacheCreationPrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
|
|
- {
|
|
|
- nonCacheInput: nonCachedTokens,
|
|
|
- cacheInput: cacheTokens,
|
|
|
- cacheRatio: cacheRatio,
|
|
|
- cacheCreationInput: cacheCreationTokens,
|
|
|
- cacheCreationRatio: cacheCreationRatio,
|
|
|
- cachePrice: cacheRatioPrice,
|
|
|
- cacheCreationPrice: cacheCreationRatioPrice,
|
|
|
- price: inputRatioPrice,
|
|
|
- completion: completionTokens,
|
|
|
- compPrice: completionRatioPrice,
|
|
|
- ratio: groupRatio,
|
|
|
- total: price.toFixed(6),
|
|
|
- },
|
|
|
- )
|
|
|
+ '提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 缓存创建 {{cacheCreationInput}} tokens / 1M tokens * ${{cacheCreationPrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * {{ratioType}} {{ratio}} = ${{total}}',
|
|
|
+ {
|
|
|
+ nonCacheInput: nonCachedTokens,
|
|
|
+ cacheInput: cacheTokens,
|
|
|
+ cacheRatio: cacheRatio,
|
|
|
+ cacheCreationInput: cacheCreationTokens,
|
|
|
+ cacheCreationRatio: cacheCreationRatio,
|
|
|
+ cachePrice: cacheRatioPrice,
|
|
|
+ cacheCreationPrice: cacheCreationRatioPrice,
|
|
|
+ price: inputRatioPrice,
|
|
|
+ completion: completionTokens,
|
|
|
+ compPrice: completionRatioPrice,
|
|
|
+ ratio: groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
+ total: price.toFixed(6),
|
|
|
+ },
|
|
|
+ )
|
|
|
: i18next.t(
|
|
|
- '提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
|
|
- {
|
|
|
- input: inputTokens,
|
|
|
- price: inputRatioPrice,
|
|
|
- completion: completionTokens,
|
|
|
- compPrice: completionRatioPrice,
|
|
|
- ratio: groupRatio,
|
|
|
- total: price.toFixed(6),
|
|
|
- },
|
|
|
- )}
|
|
|
+ '提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * {{ratioType}} {{ratio}} = ${{total}}',
|
|
|
+ {
|
|
|
+ input: inputTokens,
|
|
|
+ price: inputRatioPrice,
|
|
|
+ completion: completionTokens,
|
|
|
+ compPrice: completionRatioPrice,
|
|
|
+ ratio: groupRatio,
|
|
|
+ ratioType: ratioLabel,
|
|
|
+ total: price.toFixed(6),
|
|
|
+ },
|
|
|
+ )}
|
|
|
</p>
|
|
|
<p>{i18next.t('仅供参考,以实际扣费为准')}</p>
|
|
|
</article>
|
|
|
@@ -1501,10 +1541,12 @@ export function renderClaudeLogContent(
|
|
|
completionRatio,
|
|
|
modelPrice = -1,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheRatio = 1.0,
|
|
|
cacheCreationRatio = 1.0,
|
|
|
) {
|
|
|
- const ratioLabel = false ? i18next.t('专属倍率') : i18next.t('分组倍率');
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t('模型价格 ${{price}},{{ratioType}} {{ratio}}', {
|
|
|
@@ -1531,12 +1573,14 @@ export function renderClaudeModelPriceSimple(
|
|
|
modelRatio,
|
|
|
modelPrice = -1,
|
|
|
groupRatio,
|
|
|
+ user_group_ratio,
|
|
|
cacheTokens = 0,
|
|
|
cacheRatio = 1.0,
|
|
|
cacheCreationTokens = 0,
|
|
|
cacheCreationRatio = 1.0,
|
|
|
) {
|
|
|
- const ratioLabel = false ? i18next.t('专属倍率') : i18next.t('分组');
|
|
|
+ const { ratio: effectiveGroupRatio, label: ratioLabel } = getEffectiveRatio(groupRatio, user_group_ratio);
|
|
|
+ groupRatio = effectiveGroupRatio;
|
|
|
|
|
|
if (modelPrice !== -1) {
|
|
|
return i18next.t('价格:${{price}} * {{ratioType}}:{{ratio}}', {
|