1- import CUSTOM_MODEL_PRESET from '@src/components/Header/CustomModelDrawer/preset' ;
2- import { getSecretKey } from '@src/store/storage' ;
3- import { getJsonDataFromLocalStorage , setJsonDataToLocalStorage } from '@src/utils/helpers' ;
4- import { LOCAL_STORAGE_KEY } from '@src/utils/types' ;
5- import { checkModelLimit , openAiCompatibleChat } from "./utils" ;
6-
7- const modules = import . meta. glob ( '../assets/img/models/*.*' , { eager : true } ) ;
8-
9- const _iconCache = { } ;
10-
11- let customModels = null ;
12- let normalizedCustomModel = null ;
13-
14- // 辅助函数:解析模型ID,提取 series、name 和 isPro 标志
15- function parseModelId ( id ) {
16- let isPro = false ;
17- let isVendorA = false ;
18- let fullName = id ;
19- if ( id . startsWith ( 'Pro/' ) ) {
20- isPro = true ;
21- fullName = id . replace ( 'Pro/' , '' ) ;
22- }
23- if ( id . startsWith ( 'Vendor-A/' ) ) {
24- isVendorA = true ;
25- fullName = id . replace ( 'Vendor-A/' , '' ) ;
26- }
27- const [ series , ...nameParts ] = fullName . split ( '/' ) ;
28- const name = nameParts . join ( '/' ) ;
29- return { series, name, isPro, isVendorA } ;
30- }
31-
32- const keywordsMap = {
33- 'Qwen' : '阿里云,aliyun,通义千问' ,
34- 'THUDM' : '智谱AI,智谱清言,BigModel,清华大学' ,
35- 'google' : '谷歌,Brad' ,
36- 'meta-llama' : 'Facebook' ,
37- 'internlm' : '书生浦语大模型书生大模型,上海AI实验室,商汤科技,上海人工智能实验室香港中文大学和复旦大学' ,
38- 'mistralai' : '法国欧洲' ,
39- 'deepseek-ai' : '私募巨头幻方量化深度求索' ,
40- '01-ai' : '01万物零一万物李开复' ,
41- 'AIDC-AI' : 'AIDC-AI,阿里云,CoT' ,
42- 'baidu' : '百度,文心一言' ,
43- 'tencent' : '腾讯,Hunyuan' ,
44- 'moonshotai' : '月之暗面,Kimi' ,
45- } ;
46-
47- // 修改后的 textModelOf 函数,统一处理 "Pro/" 前缀
48- const textModelOf = ( id , price , length , needVerify , vision ) => {
49- const { series, name, isPro, isVendorA } = parseModelId ( id ) ;
50- const icon = getModelIcon ( id ) ; // 使用原始id获取图标
51- let keywords = keywordsMap [ series ] ;
52- if ( vision ) {
53- keywords += ',多模态,视觉,图像,VL,vision,image'
54- }
55- if ( isVendorA ) {
56- keywords += ',Vendor-A,国产算力芯片'
57- }
58- const displayName = isPro ? `Pro/${ name } ` : isVendorA ? `Vendor-A/${ name } ` : name ; // 根据 isPro 添加前缀
59- return { id, name : displayName , series, price, length, icon, keywords, needVerify, isPro, isVendorA, vision } ;
60- } ;
61-
62- /**
63- * 获取内置的自定义模型解析函数
64- */
65- function getCustomModelResolveFn ( modelConfig ) {
66- const model = CUSTOM_MODEL_PRESET . find ( item => modelConfig . isOpenAiCompatible ? item . isOpenAiCompatible : item . id === modelConfig . id ) ;
67- // 在标准的函数入参之外,添加上用户配置的数据(内含 apiKey 等东西)
68- return ( ...args ) => model . resolveFn ( modelConfig , ...args ) ;
69- }
70-
71- const VISION_CUSTOM_MODELS = [ 'grok-vision-beta' ] ;
72-
73- export function getCustomModels ( ) {
74- if ( ! customModels ) {
75- customModels = getJsonDataFromLocalStorage ( LOCAL_STORAGE_KEY . USER_CUSTOM_MODELS , [ ] ) ;
76- normalizedCustomModel = customModels . map ( item => {
77- const resolveFn = ( item . paramsMode || item . isOpenAiCompatible )
78- ? getCustomModelResolveFn ( item )
79- : new Function ( `return ${ item . resolveFn } ` ) ( ) ;
80-
81- // 拆分多个模型ID,并处理每个ID
82- return item . ids . split ( ',' ) . map ( id => {
83- const { series, name, isPro } = parseModelId ( id ) ;
84- const icon = item . icon || getModelIcon ( id ) ; // 使用原始id获取图标
85- const displayName = isPro ? `Pro/${ name } ` : name ; // 根据 isPro 添加前缀
86- const vision = VISION_CUSTOM_MODELS . includes ( name ) || item . vision ;
87- return ( {
88- ...item ,
89- vision,
90- keywords : item . keywords || keywordsMap [ series ] ,
91- ids : void 0 , // 移除原始ids字段
92- id,
93- series,
94- name : displayName ,
95- resolveFn,
96- icon,
97- isCustom : true ,
98- isPro
99- } ) ;
100- } ) ;
101- } ) . reduce ( ( acc , cur ) => [ ...acc , ...cur ] , [ ] ) ;
102- }
103- return { raw : customModels , normalized : normalizedCustomModel } ;
104- }
105-
106- export function setCustomModels ( models ) {
107- setJsonDataToLocalStorage ( LOCAL_STORAGE_KEY . USER_CUSTOM_MODELS , models ) ;
108- getCustomModels ( ) ;
109- }
110-
111- // 修改 getModelIcon 函数,确保使用正确的 fullName 获取图标
112- export function getModelIcon ( model ) {
113- if ( ! _iconCache [ model ] ) {
114- const { series } = parseModelId ( model ) ;
115- _iconCache [ model ] = modules [ Object . keys ( modules ) . find ( i => i . includes ( series ) ) ] ?. default ;
116- if ( ! _iconCache [ model ] ) {
117- _iconCache [ model ] = '/logo.svg' ;
118- }
119- }
120- return _iconCache [ model ] ;
121- }
122-
123- /**
124- * 关于模型顺序:
125- * 1. 免费模型在前
126- * 2. 免费模型中,尽量根据模型能力排序,最新最强的在前
127- * 3. 中文模型应排在英文模型前面
128- * 4. Pro 开头的模型为免费模型的付费版本,优先级最低
129- * 5. 新增模型请参考上述规则
130- */
131- const SILICON_MODELS = [
132- textModelOf ( "baidu/ERNIE-4.5-300B-A47B" , 8 , 128 , false ) ,
133- textModelOf ( "tencent/Hunyuan-A13B-Instruct" , 4 , 128 , false ) ,
134- textModelOf ( "moonshotai/Kimi-Dev-72B" , 8 , 128 , false ) ,
135- textModelOf ( "MiniMaxAI/MiniMax-M1-80k" , 16 , 128 , false ) ,
136- textModelOf ( "Tongyi-Zhiwen/QwenLong-L1-32B" , 4 , 128 , false ) ,
137- textModelOf ( "Qwen/Qwen3-235B-A22B" , 10 , 128 , false ) ,
138- textModelOf ( "Qwen/Qwen3-30B-A3B" , 2.8 , 128 , false ) ,
139- textModelOf ( "Qwen/Qwen3-32B" , 4 , 128 , false ) ,
140- textModelOf ( "Qwen/Qwen3-14B" , 2 , 128 , false ) ,
141- textModelOf ( "THUDM/GLM-Z1-32B-0414" , 0.5 , 32 , false ) ,
142- textModelOf ( "THUDM/GLM-4-32B-0414" , 0.5 , 32 , false ) ,
143- textModelOf ( "THUDM/GLM-Z1-9B-0414" , 0 , 32 , false ) ,
144- textModelOf ( "THUDM/GLM-4.1V-9B-Thinking" , 0 , 64 , false ) ,
145- textModelOf ( "THUDM/GLM-4-9B-0414" , 0 , 32 , false ) ,
146- textModelOf ( "Qwen/Qwen2.5-7B-Instruct" , 0 , 32 , false ) ,
147- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Llama-8B" , 0 , 32 , false , false ) ,
148- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B" , 0 , 32 , false , false ) ,
149- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B" , 0 , 32 , false , false ) ,
150- // textModelOf("AIDC-AI/Marco-o1", 0, 32, false),
151- textModelOf ( "THUDM/glm-4-9b-chat" , 0 , 128 , false ) ,
152- textModelOf ( "internlm/internlm2_5-7b-chat" , 0 , 32 , false ) ,
153- textModelOf ( "Qwen/Qwen2.5-Coder-7B-Instruct" , 0 , 32 , false ) ,
154- textModelOf ( "Qwen/Qwen2-7B-Instruct" , 0 , 32 , false ) ,
155- textModelOf ( "THUDM/chatglm3-6b" , 0 , 32 , false ) ,
156- textModelOf ( "Qwen/Qwen2-1.5B-Instruct" , 0 , 32 , false ) ,
157- textModelOf ( "meta-llama/Meta-Llama-3.1-8B-Instruct" , 0 , 32 , true ) ,
158- // textModelOf("meta-llama/Meta-Llama-3-8B-Instruct", 0, 8, true),
159- textModelOf ( "deepseek-ai/DeepSeek-R1" , 16 , 64 , false , false ) ,
160- textModelOf ( "deepseek-ai/DeepSeek-V3" , 8 , 64 , false , false ) ,
161- textModelOf ( "Pro/deepseek-ai/DeepSeek-R1" , 16 , 64 , false , false ) ,
162- textModelOf ( "Pro/deepseek-ai/DeepSeek-V3" , 8 , 64 , false , false ) ,
163- textModelOf ( "Pro/deepseek-ai/DeepSeek-R1-Distill-Llama-8B" , 0.42 , 32 , false , false ) ,
164- textModelOf ( "Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B" , 0.35 , 32 , false , false ) ,
165- textModelOf ( "Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B" , 0.14 , 32 , false , false ) ,
166- textModelOf ( "Qwen/QwQ-32B" , 1.26 , 32 , false , false ) ,
167- textModelOf ( "Qwen/QVQ-72B-Preview" , 9.9 , 32 , false , true ) ,
168- // textModelOf("Tencent/Hunyuan-A52B-Instruct", 21, 32, false),
169- textModelOf ( "Qwen/Qwen2.5-14B-Instruct" , 0.7 , 32 , false ) ,
170- textModelOf ( "internlm/internlm2_5-20b-chat" , 1 , 32 , false ) ,
171- textModelOf ( "Qwen/Qwen2.5-Coder-32B-Instruct" , 1.26 , 32 , false ) ,
172- textModelOf ( "Qwen/Qwen2.5-32B-Instruct" , 1.26 , 32 , false ) ,
173- // textModelOf("Qwen/Qwen2-57B-A14B-Instruct", 1.26, 32, false),
174- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Llama-70B" , 4.13 , 32 , false , false ) ,
175- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B" , 1.26 , 32 , false , false ) ,
176- textModelOf ( "deepseek-ai/DeepSeek-R1-Distill-Qwen-14B" , 0.7 , 32 , false , false ) ,
177-
178- textModelOf ( "deepseek-ai/DeepSeek-V2.5" , 1.33 , 32 , false ) ,
179- textModelOf ( "deepseek-ai/deepseek-vl2" , 0.99 , 4 , false , true ) ,
180- // textModelOf("deepseek-ai/DeepSeek-Coder-V2-Instruct", 1.33, 32, false),
181- textModelOf ( "deepseek-ai/DeepSeek-V2-Chat" , 1.33 , 32 , false ) ,
182- // textModelOf("Qwen/Qwen2.5-Math-72B-Instruct", 4.13, 4, false),
183- textModelOf ( "Qwen/Qwen2.5-72B-Instruct-128K" , 4.13 , 128 , false ) ,
184- textModelOf ( "Qwen/Qwen2.5-72B-Instruct" , 4.13 , 32 , false ) ,
185- // textModelOf("Qwen/Qwen2-72B-Instruct", 4.13, 32, false),
186- // textModelOf("Vendor-A/Qwen/Qwen2.5-72B-Instruct", 1, 32, false),
187- // textModelOf("Vendor-A/Qwen/Qwen2-72B-Instruct", 1, 32, false),
188- // textModelOf("nvidia/Llama-3.1-Nemotron-70B-Instruct", 4.13, 32, true),
189- textModelOf ( "meta-llama/Llama-3.3-70B-Instruct" , 4.13 , 32 , true ) ,
190- textModelOf ( "meta-llama/Meta-Llama-3.1-70B-Instruct" , 4.13 , 32 , true ) ,
191- // textModelOf("meta-llama/Meta-Llama-3-70B-Instruct", 4.13, 8, true),
192- textModelOf ( "meta-llama/Meta-Llama-3.1-405B-Instruct" , 21 , 32 , true ) ,
193- textModelOf ( "Qwen/Qwen2.5-VL-72B-Instruct" , 4.13 , 32 , false , true ) ,
194- // textModelOf("Qwen/Qwen2.5-VL-32B-Instruct", 1.26, 32, false, true),
195- textModelOf ( "Pro/Qwen/Qwen2.5-VL-7B-Instruct" , 0.35 , 32 , false , true ) ,
196- textModelOf ( "Qwen/Qwen2-VL-72B-Instruct" , 4.13 , 32 , false , true ) ,
197- textModelOf ( "OpenGVLab/InternVL2-26B" , 1 , 32 , false , true ) ,
198- textModelOf ( "Pro/OpenGVLab/InternVL2-8B" , 0.35 , 32 , false , true ) ,
199- textModelOf ( "Pro/Qwen/Qwen2-VL-7B-Instruct" , 0.35 , 32 , false , true ) ,
200- textModelOf ( "OpenGVLab/InternVL2-Llama3-76B" , 4.13 , 8 , false , true ) ,
201- textModelOf ( "Pro/Qwen/Qwen2-1.5B-Instruct" , 0.14 , 32 , false ) ,
202- textModelOf ( "Pro/Qwen/Qwen2.5-7B-Instruct" , 0.35 , 32 , false ) ,
203- // textModelOf("Pro/internlm/internlm2_5-7b-chat", 0.35, 32, false),
204- textModelOf ( "Pro/Qwen/Qwen2-7B-Instruct" , 0.35 , 32 , false ) ,
205- // textModelOf("Pro/THUDM/chatglm3-6b", 0.35, 32, false),
206- textModelOf ( "Pro/THUDM/glm-4-9b-chat" , 0.6 , 128 , false ) ,
207- textModelOf ( "Pro/THUDM/GLM-4.1V-9B-Thinking" , 1 , 64 , false ) ,
208- textModelOf ( "Pro/meta-llama/Meta-Llama-3.1-8B-Instruct" , 0.42 , 32 , true ) ,
209- // textModelOf("Pro/meta-llama/Meta-Llama-3-8B-Instruct", 0.42, 8, true),
210- ] ;
211-
212- export function isMixedThinkingModel ( modelId ) {
213- return modelId . includes ( 'Qwen/Qwen3' )
214- }
215-
216- export const SILICON_MODELS_IDS = SILICON_MODELS . map ( item => item . id )
217-
218- export const isSiliconModel = ( modelId ) => {
219- return SILICON_MODELS . some ( item => modelId === item . id )
220- }
221-
222- export function getAllTextModels ( ) {
223- return [
224- ...getCustomModels ( ) . normalized ,
225- ...SILICON_MODELS
226- ] ;
227- }
228-
229- const _visionModelIds = getAllTextModels ( ) . filter ( item => item . vision ) . map ( item => item . id ) ;
230-
231- export function isVisionModel ( modelId ) {
232- return _visionModelIds . includes ( modelId )
233- }
234-
235-
236- const customResolveFns = getAllTextModels ( ) . filter ( item => item . resolveFn ) . reduce ( ( acc , item ) => {
237- acc [ item . id ] = item . resolveFn ;
238- return acc ;
239- } , { } ) ;
240-
241- /**
242- * 获取聊天解析器,根据模型ID选择合适的解析函数
243- */
244- export function getChatResolver ( modelId ) {
245- if ( customResolveFns [ modelId ] ) return customResolveFns [ modelId ] ;
246- return ( ...args ) => {
247- // 硅基模型校验模型限制
248- checkModelLimit ( modelId ) ;
249- return openAiCompatibleChat ( 'https://api.siliconflow.cn/v1' , getSecretKey ( ) , modelId => modelId , ...args ) ;
250- } ;
251- }
252-
253-
254- const imageModelOf = ( id , price ) => {
255- const { series, name, isPro } = parseModelId ( id ) ;
256- const icon = getModelIcon ( id ) ;
257- const displayName = isPro ? `Pro/${ name } ` : name ;
258- return { id, name : displayName , series, price, icon, isPro } ;
259- } ;
260-
261- const IMAGE_MODELS = [
262- imageModelOf ( "black-forest-labs/FLUX.1-dev" , 1 ) ,
263- imageModelOf ( "black-forest-labs/FLUX.1-schnell" , 1 ) ,
264- imageModelOf ( "stabilityai/stable-diffusion-3-5-large" , - 1 ) ,
265- imageModelOf ( "stabilityai/stable-diffusion-xl-base-1.0" , - 1 ) ,
266- // imageModelOf("stabilityai/stable-diffusion-2-1", -1),
267- // 已弃模型
268- // imageModelOf("stabilityai/stable-diffusion-3-medium", -1),
269- // imageModelOf("stabilityai/sd-turbo", -1),
270- // imageModelOf("stabilityai/sdxl-turbo", -1),
271- // imageModelOf("ByteDance/SDXL-Lightning", -1),
272- imageModelOf ( 'Pro/black-forest-labs/FLUX.1-schnell' , 1 )
273- ] ;
274-
275- /**
276- * 判断体验密钥是否可用
277- */
278- export function isLimitedModel ( modelId ) {
279- const IMAGE_LIMITED_MODELS = IMAGE_MODELS . filter ( item => item . price > 0 ) . map ( item => item . id ) ;
280- const TEXT_LIMITED_MODELS = SILICON_MODELS . filter ( item => item . price > 0 ) . map ( item => item . id ) ;
281- return IMAGE_LIMITED_MODELS . includes ( modelId ) || TEXT_LIMITED_MODELS . includes ( modelId ) ;
282- }
283-
284- export function getImageModels ( ) {
285- return [ ...IMAGE_MODELS ] ;
286- }
287-
1+ Hello
0 commit comments