@lobehub/lobehub 2.0.0-next.14 → 2.0.0-next.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/.github/workflows/desktop-pr-build.yml +6 -6
  2. package/.github/workflows/release-desktop-beta.yml +4 -4
  3. package/.github/workflows/release.yml +1 -2
  4. package/.github/workflows/test.yml +4 -5
  5. package/.nvmrc +1 -1
  6. package/CHANGELOG.md +42 -0
  7. package/apps/desktop/tsconfig.json +0 -1
  8. package/changelog/v1.json +14 -0
  9. package/docs/self-hosting/advanced/feature-flags.mdx +0 -1
  10. package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +0 -1
  11. package/e2e/tsconfig.json +0 -1
  12. package/package.json +58 -58
  13. package/packages/types/src/serverConfig.ts +2 -6
  14. package/packages/web-crawler/tsconfig.json +0 -1
  15. package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -8
  16. package/src/app/[variants]/(main)/(mobile)/me/(home)/features/UserBanner.tsx +3 -6
  17. package/src/app/[variants]/(main)/labs/components/LabCard.tsx +3 -1
  18. package/src/app/[variants]/(main)/settings/provider/detail/azure/index.tsx +5 -7
  19. package/src/components/InvalidAPIKey/APIKeyForm/Bedrock.tsx +8 -13
  20. package/src/config/featureFlags/schema.test.ts +0 -2
  21. package/src/config/featureFlags/schema.ts +0 -6
  22. package/src/config/modelProviders/ai21.ts +1 -16
  23. package/src/config/modelProviders/ai302.ts +1 -128
  24. package/src/config/modelProviders/ai360.ts +1 -32
  25. package/src/config/modelProviders/anthropic.ts +1 -71
  26. package/src/config/modelProviders/azure.ts +1 -51
  27. package/src/config/modelProviders/baichuan.ts +1 -57
  28. package/src/config/modelProviders/bedrock.ts +1 -276
  29. package/src/config/modelProviders/cloudflare.ts +1 -64
  30. package/src/config/modelProviders/deepseek.ts +1 -19
  31. package/src/config/modelProviders/fireworksai.ts +1 -174
  32. package/src/config/modelProviders/giteeai.ts +1 -135
  33. package/src/config/modelProviders/github.ts +1 -254
  34. package/src/config/modelProviders/google.ts +1 -130
  35. package/src/config/modelProviders/groq.ts +1 -119
  36. package/src/config/modelProviders/higress.ts +1 -1713
  37. package/src/config/modelProviders/huggingface.ts +1 -54
  38. package/src/config/modelProviders/hunyuan.ts +1 -83
  39. package/src/config/modelProviders/infiniai.ts +1 -74
  40. package/src/config/modelProviders/internlm.ts +1 -20
  41. package/src/config/modelProviders/mistral.ts +1 -95
  42. package/src/config/modelProviders/modelscope.ts +1 -27
  43. package/src/config/modelProviders/moonshot.ts +1 -29
  44. package/src/config/modelProviders/novita.ts +1 -105
  45. package/src/config/modelProviders/ollama.ts +1 -325
  46. package/src/config/modelProviders/openai.ts +1 -242
  47. package/src/config/modelProviders/openrouter.ts +1 -240
  48. package/src/config/modelProviders/perplexity.ts +1 -45
  49. package/src/config/modelProviders/ppio.ts +1 -152
  50. package/src/config/modelProviders/qiniu.ts +1 -18
  51. package/src/config/modelProviders/qwen.ts +1 -245
  52. package/src/config/modelProviders/search1api.ts +1 -34
  53. package/src/config/modelProviders/sensenova.ts +1 -69
  54. package/src/config/modelProviders/siliconcloud.ts +1 -417
  55. package/src/config/modelProviders/spark.ts +1 -59
  56. package/src/config/modelProviders/stepfun.ts +1 -98
  57. package/src/config/modelProviders/taichu.ts +1 -18
  58. package/src/config/modelProviders/togetherai.ts +1 -274
  59. package/src/config/modelProviders/upstage.ts +1 -28
  60. package/src/config/modelProviders/wenxin.ts +1 -140
  61. package/src/config/modelProviders/xai.ts +1 -38
  62. package/src/config/modelProviders/zeroone.ts +1 -81
  63. package/src/config/modelProviders/zhipu.ts +1 -108
  64. package/src/helpers/isCanUseFC.ts +0 -8
  65. package/src/hooks/useEnabledChatModels.ts +0 -8
  66. package/src/hooks/useModelContextWindowTokens.ts +0 -8
  67. package/src/hooks/useModelHasContextWindowToken.ts +1 -10
  68. package/src/hooks/useModelSupportFiles.ts +1 -11
  69. package/src/hooks/useModelSupportReasoning.ts +1 -11
  70. package/src/hooks/useModelSupportToolUse.ts +1 -11
  71. package/src/hooks/useModelSupportVision.ts +1 -11
  72. package/src/layout/AuthProvider/Clerk/index.tsx +2 -16
  73. package/src/server/globalConfig/index.ts +0 -23
  74. package/src/server/routers/lambda/config/__snapshots__/index.test.ts.snap +175 -12
  75. package/src/server/routers/lambda/config/index.test.ts +36 -28
  76. package/src/services/chat/chat.test.ts +12 -0
  77. package/src/services/chat/helper.ts +7 -31
  78. package/src/services/models.ts +2 -11
  79. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +41 -14
  80. package/src/store/global/store.ts +1 -7
  81. package/src/store/user/initialState.ts +1 -7
  82. package/src/store/user/selectors.ts +1 -5
  83. package/src/store/user/slices/common/action.ts +5 -4
  84. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  85. package/src/store/user/slices/settings/selectors/keyVaults.ts +21 -0
  86. package/src/store/user/store.ts +0 -3
  87. package/src/tools/web-browsing/Render/Search/ConfigForm/Form.tsx +1 -1
  88. package/tsconfig.json +0 -1
  89. package/packages/utils/src/_deprecated/__snapshots__/parseModels.test.ts.snap +0 -104
  90. package/packages/utils/src/_deprecated/parseModels.test.ts +0 -287
  91. package/packages/utils/src/_deprecated/parseModels.ts +0 -165
  92. package/src/hooks/_header.ts +0 -23
  93. package/src/server/globalConfig/_deprecated.test.ts +0 -92
  94. package/src/server/globalConfig/_deprecated.ts +0 -41
  95. package/src/store/global/actions/clientDb.ts +0 -67
  96. package/src/store/user/slices/modelList/__snapshots__/action.test.ts.snap +0 -12
  97. package/src/store/user/slices/modelList/action.test.ts +0 -359
  98. package/src/store/user/slices/modelList/action.ts +0 -223
  99. package/src/store/user/slices/modelList/initialState.ts +0 -15
  100. package/src/store/user/slices/modelList/reducers/customModelCard.test.ts +0 -204
  101. package/src/store/user/slices/modelList/reducers/customModelCard.ts +0 -64
  102. package/src/store/user/slices/modelList/selectors/index.ts +0 -3
  103. package/src/store/user/slices/modelList/selectors/keyVaults.test.ts +0 -201
  104. package/src/store/user/slices/modelList/selectors/keyVaults.ts +0 -50
  105. package/src/store/user/slices/modelList/selectors/modelConfig.test.ts +0 -219
  106. package/src/store/user/slices/modelList/selectors/modelConfig.ts +0 -95
  107. package/src/store/user/slices/modelList/selectors/modelProvider.test.ts +0 -138
  108. package/src/store/user/slices/modelList/selectors/modelProvider.ts +0 -170
@@ -1,219 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { UserStore } from '@/store/user';
4
- import { merge } from '@/utils/merge';
5
-
6
- import { UserState } from '../../../initialState';
7
- import { UserSettingsState, initialSettingsState } from '../../settings/initialState';
8
- import { modelConfigSelectors } from './modelConfig';
9
-
10
- describe('modelConfigSelectors', () => {
11
- describe('isProviderEnabled', () => {
12
- it('should return true if provider is enabled', () => {
13
- const s = merge(initialSettingsState, {
14
- settings: {
15
- languageModel: {
16
- ollama: { enabled: true },
17
- },
18
- },
19
- } as UserSettingsState) as unknown as UserStore;
20
-
21
- expect(modelConfigSelectors.isProviderEnabled('ollama')(s)).toBe(true);
22
- });
23
-
24
- it('should return false if provider is not enabled', () => {
25
- const s = merge(initialSettingsState, {
26
- settings: {
27
- languageModel: {
28
- perplexity: { enabled: false },
29
- },
30
- },
31
- } as UserSettingsState) as unknown as UserStore;
32
-
33
- expect(modelConfigSelectors.isProviderEnabled('perplexity')(s)).toBe(false);
34
- });
35
-
36
- it('should follow the user settings if provider is in the whitelist', () => {
37
- const s = merge(initialSettingsState, {
38
- settings: {
39
- languageModel: {
40
- ollama: { enabled: false },
41
- },
42
- },
43
- } as UserSettingsState) as unknown as UserStore;
44
-
45
- expect(modelConfigSelectors.isProviderEnabled('ollama')(s)).toBe(false);
46
- });
47
-
48
- it('ollama should be enabled by default', () => {
49
- const s = merge(initialSettingsState, {
50
- settings: {
51
- languageModel: {},
52
- },
53
- } as UserSettingsState) as unknown as UserStore;
54
- expect(modelConfigSelectors.isProviderEnabled('ollama')(s)).toBe(true);
55
- });
56
- });
57
-
58
- describe('isProviderFetchOnClient', () => {
59
- // The next 4 case are base on the rules on https://github.com/lobehub/lobe-chat/pull/2753
60
- it('client fetch should disabled on default', () => {
61
- const s = merge(initialSettingsState, {
62
- settings: {
63
- keyVaults: {
64
- azure: {
65
- endpoint: 'endpoint',
66
- apiKey: 'apikey',
67
- },
68
- },
69
- },
70
- } as UserSettingsState) as unknown as UserStore;
71
- expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(false);
72
- });
73
-
74
- it('client fetch should disabled if no apikey or endpoint provided even user set it enabled', () => {
75
- const s = merge(initialSettingsState, {
76
- settings: {
77
- languageModel: {
78
- azure: { fetchOnClient: true },
79
- },
80
- },
81
- } as UserSettingsState) as unknown as UserStore;
82
- expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(false);
83
- });
84
-
85
- it('client fetch should enable if only endpoint provided', () => {
86
- const s = merge(initialSettingsState, {
87
- settings: {
88
- languageModel: {
89
- azure: { fetchOnClient: false },
90
- },
91
- keyVaults: {
92
- azure: { endpoint: 'https://example.com' },
93
- },
94
- },
95
- } as UserSettingsState) as unknown as UserStore;
96
- expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(true);
97
- });
98
-
99
- it('client fetch should control by user when a apikey or endpoint provided', () => {
100
- const s = merge(initialSettingsState, {
101
- settings: {
102
- languageModel: {
103
- azure: { fetchOnClient: true },
104
- },
105
- keyVaults: {
106
- azure: { apiKey: 'some-key' },
107
- },
108
- },
109
- } as UserSettingsState) as unknown as UserStore;
110
- expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(true);
111
- });
112
-
113
- // Qwen provider not work in browser request. Please skip this case if it work in future.
114
- // Issue: https://github.com/lobehub/lobe-chat/issues/3108
115
- // PR: https://github.com/lobehub/lobe-chat/pull/3133
116
- it('client fecth should be disabled if provider is disable browser request', () => {
117
- const s = merge(initialSettingsState, {
118
- settings: {
119
- languageModel: {
120
- qwen: { fetchOnClient: true },
121
- },
122
- keyVaults: {
123
- qwen: {
124
- apiKey: 'apikey',
125
- },
126
- },
127
- },
128
- } as UserSettingsState) as unknown as UserStore;
129
- expect(modelConfigSelectors.isAutoFetchModelsEnabled('qwen')(s)).toBe(false);
130
- });
131
- });
132
-
133
- describe('getCustomModelCardById', () => {
134
- it('should return the custom model card with the given id and provider', () => {
135
- const s = merge(initialSettingsState, {
136
- settings: {
137
- languageModel: {
138
- perplexity: {
139
- customModelCards: [
140
- { id: 'custom-model-1', displayName: 'Custom Model 1' },
141
- { id: 'custom-model-2', displayName: 'Custom Model 2' },
142
- ],
143
- },
144
- },
145
- },
146
- } as UserSettingsState) as unknown as UserStore;
147
-
148
- const customModelCard = modelConfigSelectors.getCustomModelCard({
149
- id: 'custom-model-2',
150
- provider: 'perplexity',
151
- })(s);
152
-
153
- expect(customModelCard).toEqual({ id: 'custom-model-2', displayName: 'Custom Model 2' });
154
- });
155
-
156
- it('should return undefined if no custom model card is found with the given id and provider', () => {
157
- const s = merge(initialSettingsState, {
158
- settings: {
159
- languageModel: {
160
- perplexity: {
161
- customModelCards: [{ id: 'custom-model-1', displayName: 'Custom Model 1' }],
162
- },
163
- },
164
- },
165
- } as UserSettingsState) as unknown as UserStore;
166
-
167
- const customModelCard = modelConfigSelectors.getCustomModelCard({
168
- id: 'nonexistent-model',
169
- provider: 'perplexity',
170
- })(s);
171
-
172
- expect(customModelCard).toBeUndefined();
173
- });
174
- });
175
-
176
- describe('currentEditingCustomModelCard', () => {
177
- it('should return the custom model card that is currently being edited', () => {
178
- const s = merge(initialSettingsState, {
179
- settings: {
180
- languageModel: {
181
- perplexity: {
182
- customModelCards: [
183
- { id: 'custom-model-1', displayName: 'Custom Model 1' },
184
- { id: 'custom-model-2', displayName: 'Custom Model 2' },
185
- ],
186
- },
187
- },
188
- },
189
- editingCustomCardModel: {
190
- id: 'custom-model-2',
191
- provider: 'perplexity',
192
- },
193
- } as UserState) as unknown as UserStore;
194
-
195
- const currentEditingModelCard = modelConfigSelectors.currentEditingCustomModelCard(s);
196
-
197
- expect(currentEditingModelCard).toEqual({
198
- id: 'custom-model-2',
199
- displayName: 'Custom Model 2',
200
- });
201
- });
202
-
203
- it('should return undefined if no custom model card is currently being edited', () => {
204
- const s = merge(initialSettingsState, {
205
- settings: {
206
- languageModel: {
207
- perplexity: {
208
- customModelCards: [{ id: 'custom-model-1', displayName: 'Custom Model 1' }],
209
- },
210
- },
211
- },
212
- } as UserSettingsState) as unknown as UserStore;
213
-
214
- const currentEditingModelCard = modelConfigSelectors.currentEditingCustomModelCard(s);
215
-
216
- expect(currentEditingModelCard).toBeUndefined();
217
- });
218
- });
219
- });
@@ -1,95 +0,0 @@
1
- import { isProviderDisableBrowserRequest } from '@/config/modelProviders';
2
- import { isDesktop } from '@/const/version';
3
- import { UserStore } from '@/store/user';
4
- import { GlobalLLMProviderKey } from '@/types/user/settings';
5
-
6
- import { currentLLMSettings, getProviderConfigById } from '../../settings/selectors/settings';
7
- import { keyVaultsConfigSelectors } from './keyVaults';
8
-
9
- const isProviderEnabled = (provider: GlobalLLMProviderKey) => (s: UserStore) =>
10
- getProviderConfigById(provider)(s)?.enabled || false;
11
-
12
- const providerWhitelist = new Set(['ollama', 'lmstudio']);
13
- /**
14
- * @description The conditions to enable client fetch
15
- * 1. If no baseUrl and apikey input, force on Server.
16
- * 2. If only contains baseUrl, force on Client
17
- * 3. Follow the user settings.
18
- * 4. On Server, by default.
19
- */
20
- const isProviderFetchOnClient = (provider: GlobalLLMProviderKey | string) => (s: UserStore) => {
21
- const config = getProviderConfigById(provider)(s);
22
-
23
- // if is desktop, force on Server.
24
- if (isDesktop) return false;
25
-
26
- // If the provider already disable browser request in model config, force on Server.
27
- if (isProviderDisableBrowserRequest(provider)) return false;
28
-
29
- // If the provider in the whitelist, follow the user settings
30
- if (providerWhitelist.has(provider) && typeof config?.fetchOnClient !== 'undefined')
31
- return config?.fetchOnClient;
32
-
33
- // 1. If no baseUrl and apikey input, force on Server.
34
- const isProviderEndpointNotEmpty =
35
- keyVaultsConfigSelectors.isProviderEndpointNotEmpty(provider)(s);
36
- const isProviderApiKeyNotEmpty = keyVaultsConfigSelectors.isProviderApiKeyNotEmpty(provider)(s);
37
- if (!isProviderEndpointNotEmpty && !isProviderApiKeyNotEmpty) return false;
38
-
39
- // 2. If only contains baseUrl, force on Client
40
- if (isProviderEndpointNotEmpty && !isProviderApiKeyNotEmpty) return true;
41
-
42
- // 3. Follow the user settings.
43
- if (typeof config?.fetchOnClient !== 'undefined') return config?.fetchOnClient;
44
-
45
- // 4. On Server, by default.
46
- return false;
47
- };
48
-
49
- const getCustomModelCard =
50
- ({ id, provider }: { id?: string; provider?: string }) =>
51
- (s: UserStore) => {
52
- if (!provider) return;
53
-
54
- const config = getProviderConfigById(provider)(s);
55
-
56
- return config?.customModelCards?.find((m) => m.id === id);
57
- };
58
-
59
- const currentEditingCustomModelCard = (s: UserStore) => {
60
- if (!s.editingCustomCardModel) return;
61
- const { id, provider } = s.editingCustomCardModel;
62
-
63
- return getCustomModelCard({ id, provider })(s);
64
- };
65
-
66
- const isAutoFetchModelsEnabled =
67
- (provider: GlobalLLMProviderKey) =>
68
- (s: UserStore): boolean => {
69
- return getProviderConfigById(provider)(s)?.autoFetchModelLists || false;
70
- };
71
-
72
- const openAIConfig = (s: UserStore) => currentLLMSettings(s).openai;
73
- const bedrockConfig = (s: UserStore) => currentLLMSettings(s).bedrock;
74
- const ollamaConfig = (s: UserStore) => currentLLMSettings(s).ollama;
75
- const azureConfig = (s: UserStore) => currentLLMSettings(s).azure;
76
- const cloudflareConfig = (s: UserStore) => currentLLMSettings(s).cloudflare;
77
-
78
- const isAzureEnabled = (s: UserStore) => currentLLMSettings(s).azure.enabled;
79
-
80
- export const modelConfigSelectors = {
81
- azureConfig,
82
- bedrockConfig,
83
- cloudflareConfig,
84
-
85
- currentEditingCustomModelCard,
86
- getCustomModelCard,
87
-
88
- isAutoFetchModelsEnabled,
89
- isAzureEnabled,
90
- isProviderEnabled,
91
- isProviderFetchOnClient,
92
-
93
- ollamaConfig,
94
- openAIConfig,
95
- };
@@ -1,138 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { merge } from '@/utils/merge';
4
-
5
- import { UserState, initialState } from '../../../initialState';
6
- import { UserStore, useUserStore } from '../../../store';
7
- import { getDefaultModeProviderById, modelProviderSelectors } from './modelProvider';
8
-
9
- describe('modelProviderSelectors', () => {
10
- describe('getDefaultModeProviderById', () => {
11
- it('should return the correct ModelProviderCard when provider ID matches', () => {
12
- const s = merge(initialState, {}) as unknown as UserStore;
13
-
14
- const result = getDefaultModeProviderById('openai')(s);
15
- expect(result).not.toBeUndefined();
16
- });
17
-
18
- it('should return undefined when provider ID does not exist', () => {
19
- const s = merge(initialState, {}) as unknown as UserStore;
20
- const result = getDefaultModeProviderById('nonExistingProvider')(s);
21
- expect(result).toBeUndefined();
22
- });
23
- });
24
-
25
- describe('getModelCardsById', () => {
26
- it('should return model cards including custom model cards', () => {
27
- const s = merge(initialState, {
28
- settings: {
29
- languageModel: {
30
- perplexity: {
31
- customModelCards: [{ id: 'custom-model', displayName: 'Custom Model' }],
32
- },
33
- },
34
- },
35
- } as UserState) as unknown as UserStore;
36
-
37
- const modelCards = modelProviderSelectors.getModelCardsById('perplexity')(s);
38
-
39
- expect(modelCards).toContainEqual({
40
- id: 'custom-model',
41
- displayName: 'Custom Model',
42
- isCustom: true,
43
- });
44
- });
45
- });
46
-
47
- describe('defaultEnabledProviderModels', () => {
48
- it('should return undefined for a non-existing provider', () => {
49
- const s = merge(initialState, {}) as unknown as UserStore;
50
-
51
- const result = modelProviderSelectors.getDefaultEnabledModelsById('nonExistingProvider')(s);
52
- expect(result).toBeUndefined();
53
- });
54
- });
55
- describe('modelEnabledVision', () => {
56
- it('should return true if the model has vision ability', () => {
57
- const hasAbility = modelProviderSelectors.isModelEnabledVision('gpt-4-vision-preview')(
58
- useUserStore.getState(),
59
- );
60
- expect(hasAbility).toBeTruthy();
61
- });
62
-
63
- it('should return false if the model does not have vision ability', () => {
64
- const hasAbility = modelProviderSelectors.isModelEnabledVision('some-other-model')(
65
- useUserStore.getState(),
66
- );
67
-
68
- expect(hasAbility).toBeFalsy();
69
- });
70
-
71
- it('should return false if the model include vision in id', () => {
72
- const hasAbility = modelProviderSelectors.isModelEnabledVision('some-other-model-vision')(
73
- useUserStore.getState(),
74
- );
75
-
76
- expect(hasAbility).toBeTruthy();
77
- });
78
- });
79
-
80
- describe('modelEnabledFiles', () => {
81
- it('should return false if the model does not have file ability', () => {
82
- const enabledFiles = modelProviderSelectors.isModelEnabledFiles('gpt-4-vision-preview')(
83
- useUserStore.getState(),
84
- );
85
- expect(enabledFiles).toBeFalsy();
86
- });
87
-
88
- it.skip('should return true if the model has file ability', () => {
89
- const enabledFiles = modelProviderSelectors.isModelEnabledFiles('gpt-4-all')(
90
- useUserStore.getState(),
91
- );
92
- expect(enabledFiles).toBeTruthy();
93
- });
94
- });
95
-
96
- describe('modelHasMaxToken', () => {
97
- it('should return true if the model is in the list of models that show tokens', () => {
98
- const show = modelProviderSelectors.isModelHasMaxToken('gpt-3.5-turbo')(
99
- useUserStore.getState(),
100
- );
101
- expect(show).toBeTruthy();
102
- });
103
-
104
- it('should return false if the model is not in the list of models that show tokens', () => {
105
- const show = modelProviderSelectors.isModelHasMaxToken('some-other-model')(
106
- useUserStore.getState(),
107
- );
108
- expect(show).toBe(false);
109
- });
110
- });
111
-
112
- describe('modelMaxToken', () => {
113
- it('should return the correct token count for a model with specified tokens', () => {
114
- const model1Tokens = modelProviderSelectors.modelMaxToken('gpt-3.5-turbo')(
115
- useUserStore.getState(),
116
- );
117
-
118
- expect(model1Tokens).toEqual(16385);
119
- });
120
-
121
- it('should return 0 for a model without a specified token count', () => {
122
- // 测试未指定tokens属性的模型的tokens值,期望为0
123
- const tokens = modelProviderSelectors.modelMaxToken('chat-bison-001')(
124
- useUserStore.getState(),
125
- );
126
- expect(tokens).toEqual(0);
127
- });
128
-
129
- it('should return 0 for a non-existing model', () => {
130
- // 测试一个不存在的模型的tokens值,期望为0
131
- const tokens = modelProviderSelectors.modelMaxToken('nonExistingModel')(
132
- useUserStore.getState(),
133
- );
134
-
135
- expect(tokens).toEqual(0);
136
- });
137
- });
138
- });
@@ -1,170 +0,0 @@
1
- import type {
2
- ChatModelCard,
3
- EnabledProviderWithModels,
4
- GlobalLLMProviderKey,
5
- ModelProviderCard,
6
- } from '@lobechat/types';
7
- import { ServerModelProviderConfig } from '@lobechat/types';
8
- import { uniqBy } from 'lodash-es';
9
-
10
- import { filterEnabledModels } from '@/config/modelProviders';
11
- import type { UserStore } from '@/store/user';
12
-
13
- import { currentSettings, getProviderConfigById } from '../../settings/selectors/settings';
14
-
15
- /**
16
- * get the server side model cards
17
- */
18
- const serverProviderModelCards =
19
- (provider: GlobalLLMProviderKey) =>
20
- (s: UserStore): ChatModelCard[] | undefined => {
21
- const config = s.serverLanguageModel?.[provider] as ServerModelProviderConfig | undefined;
22
-
23
- if (!config) return;
24
-
25
- return config.serverModelCards;
26
- };
27
-
28
- const remoteProviderModelCards =
29
- (provider: GlobalLLMProviderKey) =>
30
- (s: UserStore): ChatModelCard[] | undefined => {
31
- const cards = currentSettings(s).languageModel?.[provider]?.remoteModelCards as
32
- | ChatModelCard[]
33
- | undefined;
34
-
35
- if (!cards) return;
36
-
37
- return cards;
38
- };
39
-
40
- const isProviderEnabled = (provider: GlobalLLMProviderKey) => (s: UserStore) =>
41
- getProviderConfigById(provider)(s)?.enabled || false;
42
-
43
- // Default Model Provider List
44
-
45
- /**
46
- * define all the model list of providers
47
- */
48
- const defaultModelProviderList = (s: UserStore): ModelProviderCard[] => s.defaultModelProviderList;
49
-
50
- export const getDefaultModeProviderById = (provider: string) => (s: UserStore) =>
51
- defaultModelProviderList(s).find((s) => s.id === provider);
52
-
53
- /**
54
- * get the default enabled models for a provider
55
- * it's a default enabled model list by Lobe Chat
56
- * e.g. openai is ['gpt-4o-mini','gpt-4o','gpt-4-turbo']
57
- */
58
- const getDefaultEnabledModelsById = (provider: string) => (s: UserStore) => {
59
- const modelProvider = getDefaultModeProviderById(provider)(s);
60
-
61
- if (modelProvider) return filterEnabledModels(modelProvider);
62
-
63
- return undefined;
64
- };
65
-
66
- const getDefaultModelCardById = (id: string) => (s: UserStore) => {
67
- const list = defaultModelProviderList(s);
68
-
69
- return list.flatMap((i) => i.chatModels).find((m) => m.id === id);
70
- };
71
-
72
- // Model Provider List
73
-
74
- const getModelCardsById =
75
- (provider: string) =>
76
- (s: UserStore): ChatModelCard[] => {
77
- const builtinCards = getDefaultModeProviderById(provider)(s)?.chatModels || [];
78
-
79
- const userCards = (getProviderConfigById(provider)(s)?.customModelCards || []).map((model) => ({
80
- ...model,
81
- isCustom: true,
82
- }));
83
-
84
- return uniqBy([...userCards, ...builtinCards], 'id');
85
- };
86
-
87
- const getEnableModelsById = (provider: string) => (s: UserStore) => {
88
- if (!getProviderConfigById(provider)(s)?.enabledModels) return;
89
-
90
- return getProviderConfigById(provider)(s)?.enabledModels?.filter(Boolean);
91
- };
92
-
93
- const modelProviderList = (s: UserStore): ModelProviderCard[] => s.modelProviderList;
94
-
95
- const modelProviderListForModelSelect = (s: UserStore): EnabledProviderWithModels[] =>
96
- modelProviderList(s)
97
- .filter((s) => s.enabled)
98
- .map((provider) => ({
99
- ...provider,
100
- children: provider.chatModels
101
- .filter((model) => model.enabled)
102
- .map((m) => ({
103
- abilities: {
104
- functionCall: m.functionCall,
105
- vision: m.vision,
106
- },
107
- contextWindowTokens: m.contextWindowTokens,
108
- displayName: m.displayName,
109
- id: m.id,
110
- })),
111
- source: 'builtin',
112
- }));
113
-
114
- const getModelCardById = (id: string, provider?: GlobalLLMProviderKey) => (s: UserStore) => {
115
- const list = modelProviderList(s);
116
-
117
- return list
118
- .filter((i) => !provider || i.id === provider)
119
- .flatMap((i) => i.chatModels)
120
- .find((m) => m.id === id);
121
- };
122
-
123
- const isModelEnabledFunctionCall = (id: string) => (s: UserStore) =>
124
- getModelCardById(id)(s)?.functionCall || false;
125
-
126
- // vision model white list, these models will change the content from string to array
127
- // refs: https://github.com/lobehub/lobe-chat/issues/790
128
- const isModelEnabledVision = (id: string) => (s: UserStore) =>
129
- getModelCardById(id)(s)?.vision || id.includes('vision');
130
-
131
- const isModelEnabledReasoning = (id: string) => (s: UserStore) =>
132
- getModelCardById(id)(s)?.reasoning || false;
133
-
134
- const isModelEnabledFiles = (id: string) => (s: UserStore) => getModelCardById(id)(s)?.files;
135
-
136
- const isModelEnabledUpload = (id: string) => (s: UserStore) =>
137
- isModelEnabledVision(id)(s) || isModelEnabledFiles(id)(s);
138
-
139
- const isModelHasMaxToken = (id: string) => (s: UserStore) =>
140
- typeof getModelCardById(id)(s)?.contextWindowTokens !== 'undefined';
141
-
142
- const modelMaxToken = (id: string) => (s: UserStore) =>
143
- getModelCardById(id)(s)?.contextWindowTokens || 0;
144
-
145
- export const modelProviderSelectors = {
146
- defaultModelProviderList,
147
- getDefaultEnabledModelsById,
148
- getDefaultModelCardById,
149
-
150
- getEnableModelsById,
151
- getModelCardById,
152
-
153
- getModelCardsById,
154
- isModelEnabledFiles,
155
- isModelEnabledFunctionCall,
156
- isModelEnabledReasoning,
157
- isModelEnabledUpload,
158
- isModelEnabledVision,
159
- isModelHasMaxToken,
160
-
161
- isProviderEnabled,
162
-
163
- modelMaxToken,
164
- modelProviderList,
165
-
166
- modelProviderListForModelSelect,
167
-
168
- remoteProviderModelCards,
169
- serverProviderModelCards,
170
- };