diff --git a/web/src/components/table/LogsTable.js b/web/src/components/table/LogsTable.js
index 88992452..ad28992e 100644
--- a/web/src/components/table/LogsTable.js
+++ b/web/src/components/table/LogsTable.js
@@ -1,4 +1,4 @@
-import React, { useContext, useEffect, useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
API,
@@ -19,7 +19,8 @@ import {
renderNumber,
renderQuota,
stringToColor,
- getLogOther
+ getLogOther,
+ renderModelTag
} from '../../helpers';
import {
@@ -39,18 +40,14 @@ import {
Typography,
Divider,
Input,
- DatePicker,
+ DatePicker
} from '@douyinfe/semi-ui';
import { ITEMS_PER_PAGE } from '../../constants';
import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph';
import {
- IconRefresh,
IconSetting,
- IconEyeOpened,
IconSearch,
- IconCoinMoneyStroked,
- IconPulse,
- IconTypograph,
+ IconForward
} from '@douyinfe/semi-icons';
const { Text } = Typography;
@@ -202,19 +199,12 @@ const LogsTable = () => {
other?.upstream_model_name &&
other?.upstream_model_name !== '';
if (!modelMapped) {
- return (
- {
- copyText(event, record.model_name).then((r) => { });
- }}
- >
- {' '}
- {record.model_name}{' '}
-
- );
+ return renderModelTag(record.model_name, {
+ color: stringToColor(record.model_name),
+ onClick: (event) => {
+ copyText(event, record.model_name).then((r) => { });
+ }
+ });
} else {
return (
<>
@@ -223,48 +213,35 @@ const LogsTable = () => {
content={
- {
- copyText(event, record.model_name).then((r) => { });
- }}
- >
- {t('请求并计费模型')} {record.model_name}{' '}
-
- {
- copyText(event, other.upstream_model_name).then(
- (r) => { },
- );
- }}
- >
- {t('实际模型')} {other.upstream_model_name}{' '}
-
+
+ {t('请求并计费模型')}:
+ {renderModelTag(record.model_name, {
+ color: stringToColor(record.model_name),
+ onClick: (event) => {
+ copyText(event, record.model_name).then((r) => { });
+ }
+ })}
+
+
+ {t('实际模型')}:
+ {renderModelTag(other.upstream_model_name, {
+ color: stringToColor(other.upstream_model_name),
+ onClick: (event) => {
+ copyText(event, other.upstream_model_name).then((r) => { });
+ }
+ })}
+
}
>
- {
+ {renderModelTag(record.model_name, {
+ color: stringToColor(record.model_name),
+ onClick: (event) => {
copyText(event, record.model_name).then((r) => { });
- }}
- suffixIcon={
-
- }
- >
- {' '}
- {record.model_name}{' '}
-
+ },
+ suffixIcon:
+ })}
>
diff --git a/web/src/components/table/ModelPricing.js b/web/src/components/table/ModelPricing.js
index d3d4459d..a7955c2c 100644
--- a/web/src/components/table/ModelPricing.js
+++ b/web/src/components/table/ModelPricing.js
@@ -1,5 +1,5 @@
import React, { useContext, useEffect, useRef, useMemo, useState } from 'react';
-import { API, copy, showError, showInfo, showSuccess } from '../../helpers/index.js';
+import { API, copy, showError, showInfo, showSuccess, getModelCategories } from '../../helpers/index.js';
import { useTranslation } from 'react-i18next';
import {
@@ -28,7 +28,6 @@ import {
} from '@douyinfe/semi-icons';
import { UserContext } from '../../context/User/index.js';
import { AlertCircle } from 'lucide-react';
-import { MODEL_CATEGORIES } from '../../constants/index.js';
const ModelPricing = () => {
const { t } = useTranslation();
@@ -321,7 +320,7 @@ const ModelPricing = () => {
refresh().then();
}, []);
- const modelCategories = MODEL_CATEGORIES(t);
+ const modelCategories = getModelCategories(t);
const renderArrow = (items, pos, handleArrowClick) => {
const style = {
diff --git a/web/src/constants/index.js b/web/src/constants/index.js
index 9538a7dc..f92e2b19 100644
--- a/web/src/constants/index.js
+++ b/web/src/constants/index.js
@@ -2,5 +2,4 @@ export * from './channel.constants';
export * from './user.constants';
export * from './toast.constants';
export * from './common.constant';
-export * from './model.constants';
export * from './playground.constants';
diff --git a/web/src/constants/model.constants.js b/web/src/constants/model.constants.js
deleted file mode 100644
index f9002cea..00000000
--- a/web/src/constants/model.constants.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import {
- OpenAI,
- Claude,
- Gemini,
- Moonshot,
- Zhipu,
- Qwen,
- DeepSeek,
- Minimax,
- Wenxin,
- Spark,
- Midjourney,
- Hunyuan,
- Cohere,
- Cloudflare,
- Ai360,
- Yi,
- Jina,
- Mistral,
- XAI,
- Ollama,
- Doubao,
-} from '@lobehub/icons';
-
-export const MODEL_CATEGORIES = (t) => ({
- all: {
- label: t('全部模型'),
- icon: null,
- filter: () => true
- },
- openai: {
- label: 'OpenAI',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('gpt') ||
- model.model_name.toLowerCase().includes('dall-e') ||
- model.model_name.toLowerCase().includes('whisper') ||
- model.model_name.toLowerCase().includes('tts') ||
- model.model_name.toLowerCase().includes('text-') ||
- model.model_name.toLowerCase().includes('babbage') ||
- model.model_name.toLowerCase().includes('davinci') ||
- model.model_name.toLowerCase().includes('curie') ||
- model.model_name.toLowerCase().includes('ada')
- },
- anthropic: {
- label: 'Anthropic',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('claude')
- },
- gemini: {
- label: 'Gemini',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('gemini')
- },
- moonshot: {
- label: 'Moonshot',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('moonshot')
- },
- zhipu: {
- label: t('智谱'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('chatglm') ||
- model.model_name.toLowerCase().includes('glm-')
- },
- qwen: {
- label: t('通义千问'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('qwen')
- },
- deepseek: {
- label: 'DeepSeek',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('deepseek')
- },
- minimax: {
- label: 'MiniMax',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('abab')
- },
- baidu: {
- label: t('文心一言'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('ernie')
- },
- xunfei: {
- label: t('讯飞星火'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('spark')
- },
- midjourney: {
- label: 'Midjourney',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('mj_')
- },
- tencent: {
- label: t('腾讯混元'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('hunyuan')
- },
- cohere: {
- label: 'Cohere',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('command')
- },
- cloudflare: {
- label: 'Cloudflare',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('@cf/')
- },
- ai360: {
- label: t('360智脑'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('360')
- },
- yi: {
- label: t('零一万物'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('yi')
- },
- jina: {
- label: 'Jina',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('jina')
- },
- mistral: {
- label: 'Mistral AI',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('mistral')
- },
- xai: {
- label: 'xAI',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('grok')
- },
- llama: {
- label: 'Llama',
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('llama')
- },
- doubao: {
- label: t('豆包'),
- icon: ,
- filter: (model) => model.model_name.toLowerCase().includes('doubao')
- }
-});
\ No newline at end of file
diff --git a/web/src/helpers/render.js b/web/src/helpers/render.js
index c8302feb..72374ef6 100644
--- a/web/src/helpers/render.js
+++ b/web/src/helpers/render.js
@@ -2,6 +2,328 @@ import i18next from 'i18next';
import { Modal, Tag, Typography } from '@douyinfe/semi-ui';
import { copy, isMobile, showSuccess } from './utils';
import { visit } from 'unist-util-visit';
+import {
+ OpenAI,
+ Claude,
+ Gemini,
+ Moonshot,
+ Zhipu,
+ Qwen,
+ DeepSeek,
+ Minimax,
+ Wenxin,
+ Spark,
+ Midjourney,
+ Hunyuan,
+ Cohere,
+ Cloudflare,
+ Ai360,
+ Yi,
+ Jina,
+ Mistral,
+ XAI,
+ Ollama,
+ Doubao,
+} from '@lobehub/icons';
+
+// 获取模型分类
+export const getModelCategories = (() => {
+ let categoriesCache = null;
+ let lastLocale = null;
+
+ return (t) => {
+ const currentLocale = i18next.language;
+ if (categoriesCache && lastLocale === currentLocale) {
+ return categoriesCache;
+ }
+
+ categoriesCache = {
+ all: {
+ label: t('全部模型'),
+ icon: null,
+ filter: () => true
+ },
+ openai: {
+ label: 'OpenAI',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('gpt') ||
+ model.model_name.toLowerCase().includes('dall-e') ||
+ model.model_name.toLowerCase().includes('whisper') ||
+ model.model_name.toLowerCase().includes('tts') ||
+ model.model_name.toLowerCase().includes('text-') ||
+ model.model_name.toLowerCase().includes('babbage') ||
+ model.model_name.toLowerCase().includes('davinci') ||
+ model.model_name.toLowerCase().includes('curie') ||
+ model.model_name.toLowerCase().includes('ada')
+ },
+ anthropic: {
+ label: 'Anthropic',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('claude')
+ },
+ gemini: {
+ label: 'Gemini',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('gemini')
+ },
+ moonshot: {
+ label: 'Moonshot',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('moonshot')
+ },
+ zhipu: {
+ label: t('智谱'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('chatglm') ||
+ model.model_name.toLowerCase().includes('glm-')
+ },
+ qwen: {
+ label: t('通义千问'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('qwen')
+ },
+ deepseek: {
+ label: 'DeepSeek',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('deepseek')
+ },
+ minimax: {
+ label: 'MiniMax',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('abab')
+ },
+ baidu: {
+ label: t('文心一言'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('ernie')
+ },
+ xunfei: {
+ label: t('讯飞星火'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('spark')
+ },
+ midjourney: {
+ label: 'Midjourney',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('mj_')
+ },
+ tencent: {
+ label: t('腾讯混元'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('hunyuan')
+ },
+ cohere: {
+ label: 'Cohere',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('command')
+ },
+ cloudflare: {
+ label: 'Cloudflare',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('@cf/')
+ },
+ ai360: {
+ label: t('360智脑'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('360')
+ },
+ yi: {
+ label: t('零一万物'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('yi')
+ },
+ jina: {
+ label: 'Jina',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('jina')
+ },
+ mistral: {
+ label: 'Mistral AI',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('mistral')
+ },
+ xai: {
+ label: 'xAI',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('grok')
+ },
+ llama: {
+ label: 'Llama',
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('llama')
+ },
+ doubao: {
+ label: t('豆包'),
+ icon: ,
+ filter: (model) => model.model_name.toLowerCase().includes('doubao')
+ }
+ };
+
+ lastLocale = currentLocale;
+ return categoriesCache;
+ };
+})();
+
+// 颜色列表
+const colors = [
+ 'amber',
+ 'blue',
+ 'cyan',
+ 'green',
+ 'grey',
+ 'indigo',
+ 'light-blue',
+ 'lime',
+ 'orange',
+ 'pink',
+ 'purple',
+ 'red',
+ 'teal',
+ 'violet',
+ 'yellow',
+];
+
+// 基础10色色板 (N ≤ 10)
+const baseColors = [
+ '#1664FF', // 主色
+ '#1AC6FF',
+ '#FF8A00',
+ '#3CC780',
+ '#7442D4',
+ '#FFC400',
+ '#304D77',
+ '#B48DEB',
+ '#009488',
+ '#FF7DDA',
+];
+
+// 扩展20色色板 (10 < N ≤ 20)
+const extendedColors = [
+ '#1664FF',
+ '#B2CFFF',
+ '#1AC6FF',
+ '#94EFFF',
+ '#FF8A00',
+ '#FFCE7A',
+ '#3CC780',
+ '#B9EDCD',
+ '#7442D4',
+ '#DDC5FA',
+ '#FFC400',
+ '#FAE878',
+ '#304D77',
+ '#8B959E',
+ '#B48DEB',
+ '#EFE3FF',
+ '#009488',
+ '#59BAA8',
+ '#FF7DDA',
+ '#FFCFEE',
+];
+
+// 模型颜色映射
+export const modelColorMap = {
+ 'dall-e': 'rgb(147,112,219)', // 深紫色
+ // 'dall-e-2': 'rgb(147,112,219)', // 介于紫色和蓝色之间的色调
+ 'dall-e-3': 'rgb(153,50,204)', // 介于紫罗兰和洋红之间的色调
+ 'gpt-3.5-turbo': 'rgb(184,227,167)', // 浅绿色
+ // 'gpt-3.5-turbo-0301': 'rgb(131,220,131)', // 亮绿色
+ 'gpt-3.5-turbo-0613': 'rgb(60,179,113)', // 海洋绿
+ 'gpt-3.5-turbo-1106': 'rgb(32,178,170)', // 浅海洋绿
+ 'gpt-3.5-turbo-16k': 'rgb(149,252,206)', // 淡橙色
+ 'gpt-3.5-turbo-16k-0613': 'rgb(119,255,214)', // 淡桃
+ 'gpt-3.5-turbo-instruct': 'rgb(175,238,238)', // 粉蓝色
+ 'gpt-4': 'rgb(135,206,235)', // 天蓝色
+ // 'gpt-4-0314': 'rgb(70,130,180)', // 钢蓝色
+ 'gpt-4-0613': 'rgb(100,149,237)', // 矢车菊蓝
+ 'gpt-4-1106-preview': 'rgb(30,144,255)', // 道奇蓝
+ 'gpt-4-0125-preview': 'rgb(2,177,236)', // 深天蓝
+ 'gpt-4-turbo-preview': 'rgb(2,177,255)', // 深天蓝
+ 'gpt-4-32k': 'rgb(104,111,238)', // 中紫色
+ // 'gpt-4-32k-0314': 'rgb(90,105,205)', // 暗灰蓝色
+ 'gpt-4-32k-0613': 'rgb(61,71,139)', // 暗蓝灰色
+ 'gpt-4-all': 'rgb(65,105,225)', // 皇家蓝
+ 'gpt-4-gizmo-*': 'rgb(0,0,255)', // 纯蓝色
+ 'gpt-4-vision-preview': 'rgb(25,25,112)', // 午夜蓝
+ 'text-ada-001': 'rgb(255,192,203)', // 粉红色
+ 'text-babbage-001': 'rgb(255,160,122)', // 浅珊瑚色
+ 'text-curie-001': 'rgb(219,112,147)', // 苍紫罗兰色
+ // 'text-davinci-002': 'rgb(199,21,133)', // 中紫罗兰红色
+ 'text-davinci-003': 'rgb(219,112,147)', // 苍紫罗兰色(与Curie相同,表示同一个系列)
+ 'text-davinci-edit-001': 'rgb(255,105,180)', // 热粉色
+ 'text-embedding-ada-002': 'rgb(255,182,193)', // 浅粉红
+ 'text-embedding-v1': 'rgb(255,174,185)', // 浅粉红色(略有区别)
+ 'text-moderation-latest': 'rgb(255,130,171)', // 强粉色
+ 'text-moderation-stable': 'rgb(255,160,122)', // 浅珊瑚色(与Babbage相同,表示同一类功能)
+ 'tts-1': 'rgb(255,140,0)', // 深橙色
+ 'tts-1-1106': 'rgb(255,165,0)', // 橙色
+ 'tts-1-hd': 'rgb(255,215,0)', // 金色
+ 'tts-1-hd-1106': 'rgb(255,223,0)', // 金黄色(略有区别)
+ 'whisper-1': 'rgb(245,245,220)', // 米色
+ 'claude-3-opus-20240229': 'rgb(255,132,31)', // 橙红色
+ 'claude-3-sonnet-20240229': 'rgb(253,135,93)', // 橙色
+ 'claude-3-haiku-20240307': 'rgb(255,175,146)', // 浅橙色
+ 'claude-2.1': 'rgb(255,209,190)', // 浅橙色(略有区别)
+};
+
+export function modelToColor(modelName) {
+ // 1. 如果模型在预定义的 modelColorMap 中,使用预定义颜色
+ if (modelColorMap[modelName]) {
+ return modelColorMap[modelName];
+ }
+
+ // 2. 生成一个稳定的数字作为索引
+ let hash = 0;
+ for (let i = 0; i < modelName.length; i++) {
+ hash = (hash << 5) - hash + modelName.charCodeAt(i);
+ hash = hash & hash; // Convert to 32-bit integer
+ }
+ hash = Math.abs(hash);
+
+ // 3. 根据模型名称长度选择不同的色板
+ const colorPalette = modelName.length > 10 ? extendedColors : baseColors;
+
+ // 4. 使用hash值选择颜色
+ const index = hash % colorPalette.length;
+ return colorPalette[index];
+}
+
+export function stringToColor(str) {
+ let sum = 0;
+ for (let i = 0; i < str.length; i++) {
+ sum += str.charCodeAt(i);
+ }
+ let i = sum % colors.length;
+ return colors[i];
+}
+
+// 渲染带有模型图标的标签
+export function renderModelTag(modelName, options = {}) {
+ const { color, size = 'large', shape = 'circle', onClick, suffixIcon } = options;
+
+ const categories = getModelCategories(i18next.t);
+ let icon = null;
+
+ for (const [key, category] of Object.entries(categories)) {
+ if (key !== 'all' && category.filter({ model_name: modelName })) {
+ icon = category.icon;
+ break;
+ }
+ }
+
+ return (
+
+ {modelName}
+
+ );
+}
export function renderText(text, limit) {
if (text.length > limit) {
@@ -800,137 +1122,6 @@ export function renderQuotaWithPrompt(quota, digits) {
return '';
}
-const colors = [
- 'amber',
- 'blue',
- 'cyan',
- 'green',
- 'grey',
- 'indigo',
- 'light-blue',
- 'lime',
- 'orange',
- 'pink',
- 'purple',
- 'red',
- 'teal',
- 'violet',
- 'yellow',
-];
-
-// 基础10色色板 (N ≤ 10)
-const baseColors = [
- '#1664FF', // 主色
- '#1AC6FF',
- '#FF8A00',
- '#3CC780',
- '#7442D4',
- '#FFC400',
- '#304D77',
- '#B48DEB',
- '#009488',
- '#FF7DDA',
-];
-
-// 扩展20色色板 (10 < N ≤ 20)
-const extendedColors = [
- '#1664FF',
- '#B2CFFF',
- '#1AC6FF',
- '#94EFFF',
- '#FF8A00',
- '#FFCE7A',
- '#3CC780',
- '#B9EDCD',
- '#7442D4',
- '#DDC5FA',
- '#FFC400',
- '#FAE878',
- '#304D77',
- '#8B959E',
- '#B48DEB',
- '#EFE3FF',
- '#009488',
- '#59BAA8',
- '#FF7DDA',
- '#FFCFEE',
-];
-
-export const modelColorMap = {
- 'dall-e': 'rgb(147,112,219)', // 深紫色
- // 'dall-e-2': 'rgb(147,112,219)', // 介于紫色和蓝色之间的色调
- 'dall-e-3': 'rgb(153,50,204)', // 介于紫罗兰和洋红之间的色调
- 'gpt-3.5-turbo': 'rgb(184,227,167)', // 浅绿色
- // 'gpt-3.5-turbo-0301': 'rgb(131,220,131)', // 亮绿色
- 'gpt-3.5-turbo-0613': 'rgb(60,179,113)', // 海洋绿
- 'gpt-3.5-turbo-1106': 'rgb(32,178,170)', // 浅海洋绿
- 'gpt-3.5-turbo-16k': 'rgb(149,252,206)', // 淡橙色
- 'gpt-3.5-turbo-16k-0613': 'rgb(119,255,214)', // 淡桃
- 'gpt-3.5-turbo-instruct': 'rgb(175,238,238)', // 粉蓝色
- 'gpt-4': 'rgb(135,206,235)', // 天蓝色
- // 'gpt-4-0314': 'rgb(70,130,180)', // 钢蓝色
- 'gpt-4-0613': 'rgb(100,149,237)', // 矢车菊蓝
- 'gpt-4-1106-preview': 'rgb(30,144,255)', // 道奇蓝
- 'gpt-4-0125-preview': 'rgb(2,177,236)', // 深天蓝
- 'gpt-4-turbo-preview': 'rgb(2,177,255)', // 深天蓝
- 'gpt-4-32k': 'rgb(104,111,238)', // 中紫色
- // 'gpt-4-32k-0314': 'rgb(90,105,205)', // 暗灰蓝色
- 'gpt-4-32k-0613': 'rgb(61,71,139)', // 暗蓝灰色
- 'gpt-4-all': 'rgb(65,105,225)', // 皇家蓝
- 'gpt-4-gizmo-*': 'rgb(0,0,255)', // 纯蓝色
- 'gpt-4-vision-preview': 'rgb(25,25,112)', // 午夜蓝
- 'text-ada-001': 'rgb(255,192,203)', // 粉红色
- 'text-babbage-001': 'rgb(255,160,122)', // 浅珊瑚色
- 'text-curie-001': 'rgb(219,112,147)', // 苍紫罗兰色
- // 'text-davinci-002': 'rgb(199,21,133)', // 中紫罗兰红色
- 'text-davinci-003': 'rgb(219,112,147)', // 苍紫罗兰色(与Curie相同,表示同一个系列)
- 'text-davinci-edit-001': 'rgb(255,105,180)', // 热粉色
- 'text-embedding-ada-002': 'rgb(255,182,193)', // 浅粉红
- 'text-embedding-v1': 'rgb(255,174,185)', // 浅粉红色(略有区别)
- 'text-moderation-latest': 'rgb(255,130,171)', // 强粉色
- 'text-moderation-stable': 'rgb(255,160,122)', // 浅珊瑚色(与Babbage相同,表示同一类功能)
- 'tts-1': 'rgb(255,140,0)', // 深橙色
- 'tts-1-1106': 'rgb(255,165,0)', // 橙色
- 'tts-1-hd': 'rgb(255,215,0)', // 金色
- 'tts-1-hd-1106': 'rgb(255,223,0)', // 金黄色(略有区别)
- 'whisper-1': 'rgb(245,245,220)', // 米色
- 'claude-3-opus-20240229': 'rgb(255,132,31)', // 橙红色
- 'claude-3-sonnet-20240229': 'rgb(253,135,93)', // 橙色
- 'claude-3-haiku-20240307': 'rgb(255,175,146)', // 浅橙色
- 'claude-2.1': 'rgb(255,209,190)', // 浅橙色(略有区别)
-};
-
-export function modelToColor(modelName) {
- // 1. 如果模型在预定义的 modelColorMap 中,使用预定义颜色
- if (modelColorMap[modelName]) {
- return modelColorMap[modelName];
- }
-
- // 2. 生成一个稳定的数字作为索引
- let hash = 0;
- for (let i = 0; i < modelName.length; i++) {
- hash = (hash << 5) - hash + modelName.charCodeAt(i);
- hash = hash & hash; // Convert to 32-bit integer
- }
- hash = Math.abs(hash);
-
- // 3. 根据模型名称长度选择不同的色板
- const colorPalette = modelName.length > 10 ? extendedColors : baseColors;
-
- // 4. 使用hash值选择颜色
- const index = hash % colorPalette.length;
- return colorPalette[index];
-}
-
-export function stringToColor(str) {
- let sum = 0;
- for (let i = 0; i < str.length; i++) {
- sum += str.charCodeAt(i);
- }
- let i = sum % colors.length;
- return colors[i];
-}
-
export function renderClaudeModelPrice(
inputTokens,
completionTokens,