@lobehub/chat 0.123.1 → 0.123.3
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.
- package/.env.example +3 -3
- package/CHANGELOG.md +50 -0
- package/Dockerfile +1 -1
- package/README.md +7 -9
- package/README.zh-CN.md +7 -9
- package/docs/Deployment/Environment-Variable.md +3 -2
- package/docs/Deployment/Environment-Variable.zh-CN.md +3 -2
- package/locales/ar/common.json +1 -0
- package/locales/de-DE/common.json +1 -0
- package/locales/en-US/common.json +1 -0
- package/locales/es-ES/common.json +1 -0
- package/locales/fr-FR/common.json +1 -0
- package/locales/it-IT/common.json +1 -0
- package/locales/ja-JP/common.json +1 -0
- package/locales/ko-KR/common.json +1 -0
- package/locales/nl-NL/common.json +1 -0
- package/locales/pl-PL/common.json +1 -0
- package/locales/pt-BR/common.json +1 -0
- package/locales/ru-RU/common.json +1 -0
- package/locales/tr-TR/common.json +1 -0
- package/locales/vi-VN/common.json +1 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-TW/common.json +1 -0
- package/package.json +3 -1
- package/src/app/api/chat/[provider]/route.ts +7 -5
- package/src/app/api/chat/auth.ts +13 -2
- package/src/app/api/chat/google/route.ts +1 -1
- package/src/app/api/errorResponse.ts +9 -11
- package/src/components/ModelProviderIcon/index.tsx +4 -1
- package/src/components/ModelSelect/index.tsx +8 -2
- package/src/config/modelProviders/openai.ts +3 -0
- package/src/const/auth.ts +1 -0
- package/src/features/Conversation/Error/index.tsx +2 -7
- package/src/layout/GlobalLayout/Locale.tsx +1 -0
- package/src/libs/agent-runtime/error.ts +3 -4
- package/src/libs/agent-runtime/types/type.ts +1 -1
- package/src/libs/agent-runtime/utils/createError.ts +1 -1
- package/src/locales/default/common.ts +1 -0
- package/src/services/_auth.ts +3 -29
- package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +1 -0
- package/src/store/global/slices/settings/selectors/modelProvider.test.ts +57 -0
- package/src/store/global/slices/settings/selectors/modelProvider.ts +19 -17
- package/src/utils/jwt.test.ts +26 -0
- package/src/utils/jwt.ts +37 -0
package/.env.example
CHANGED
|
@@ -40,13 +40,13 @@ OPENAI_API_KEY=sk-xxxxxxxxx
|
|
|
40
40
|
#ZHIPU_API_KEY=xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxx
|
|
41
41
|
|
|
42
42
|
########################################
|
|
43
|
-
|
|
43
|
+
########### Google AI Service ##########
|
|
44
44
|
########################################
|
|
45
45
|
|
|
46
|
-
#GOOGLE_API_KEY=
|
|
46
|
+
#GOOGLE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
47
47
|
|
|
48
48
|
########################################
|
|
49
|
-
|
|
49
|
+
######### AWS Bedrock Service ##########
|
|
50
50
|
########################################
|
|
51
51
|
|
|
52
52
|
#AWS_REGION=us-east-1
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.123.3](https://github.com/lobehub/lobe-chat/compare/v0.123.2...v0.123.3)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-02-06**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix non-https `crypto.subtile` missing error.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix non-https `crypto.subtile` missing error, closes [#1238](https://github.com/lobehub/lobe-chat/issues/1238) ([1750d0b](https://github.com/lobehub/lobe-chat/commit/1750d0b))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.123.2](https://github.com/lobehub/lobe-chat/compare/v0.123.1...v0.123.2)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-02-06**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Fix docker build.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Fix docker build, closes [#1231](https://github.com/lobehub/lobe-chat/issues/1231) ([e180722](https://github.com/lobehub/lobe-chat/commit/e180722))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 0.123.1](https://github.com/lobehub/lobe-chat/compare/v0.123.0...v0.123.1)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2024-02-05**</sup>
|
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -193,7 +193,7 @@ e-commerce platform data access, and various third-party services.
|
|
|
193
193
|
| [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | Get realtime crypto price, BTC, ETH, BNB, and the latest insights.The latest coin news and airdrop opportunities.<br/>`crypto` `btc` `eth` `bnb` |
|
|
194
194
|
| [Bilibili](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | Dive into Bilibili's vast content with features like keyword video search, replay access, interactive danmaku, trending video recommendations, and hot-search insights, all at your fingertips.<br/>`video` `bilibili` `search` |
|
|
195
195
|
|
|
196
|
-
> 📊 Total plugins: [<kbd>**
|
|
196
|
+
> 📊 Total plugins: [<kbd>**61**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
|
|
197
197
|
|
|
198
198
|
<!-- PLUGIN LIST -->
|
|
199
199
|
|
|
@@ -225,14 +225,12 @@ Our marketplace is not just a showcase platform but also a collaborative space.
|
|
|
225
225
|
|
|
226
226
|
<!-- AGENT LIST -->
|
|
227
227
|
|
|
228
|
-
| Recent Submits
|
|
229
|
-
|
|
|
230
|
-
| [Database Expert](https://chat-preview.lobehub.com/market?agent=dba)<br/><sup>By **[xuzhen1994](https://github.com/xuzhen1994)** on **2024-02-03**</sup>
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
| [
|
|
234
|
-
| [SagePathfinder](https://chat-preview.lobehub.com/market?agent=sage-pathfinder)<br/><sup>By **[Ajasra](https://github.com/Ajasra)** on **2024-01-31**</sup> | Expert in personal growth coaching with a focus on stoicism, deep reflection, and strategic questioning.<br/>`personal-growth` `coaching` `reflection` `goal-setting` `well-being` |
|
|
235
|
-
| [Variable Naming Master](https://chat-preview.lobehub.com/market?agent=variable-naming-assistant)<br/><sup>By **[undefinedZNN](https://github.com/undefinedZNN)** on **2024-01-31**</sup> | Master the art of programming variable naming, providing multiple suggestions and explaining their usage scenarios.<br/>`variable-naming` `programming` `suggestions` |
|
|
228
|
+
| Recent Submits | Description |
|
|
229
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
230
|
+
| [Database Expert](https://chat-preview.lobehub.com/market?agent=dba)<br/><sup>By **[xuzhen1994](https://github.com/xuzhen1994)** on **2024-02-03**</sup> | Provides professional advice on database design paradigms, index optimization, query performance tuning, data security, backup and recovery.<br/>`database` `dba` `mysql` `clickhouse` `doris` `mongo-db` `oracle` |
|
|
231
|
+
| [Presentation Wizard](https://chat-preview.lobehub.com/market?agent=word)<br/><sup>By **[MYSeaIT](https://github.com/MYSeaIT)** on **2024-02-03**</sup> | App Presentation Maker Bot for Word: Assists in creating impressive and professional app presentations in Microsoft Word.<br/>`app-presentation` `microsoft-word` `bot` `assistance` `template` |
|
|
232
|
+
| [SagePathfinder](https://chat-preview.lobehub.com/market?agent=sage-pathfinder)<br/><sup>By **[Ajasra](https://github.com/Ajasra)** on **2024-01-31**</sup> | Expert in personal growth coaching with a focus on stoicism, deep reflection, and strategic questioning.<br/>`personal-growth` `coaching` `reflection` `goal-setting` `well-being` |
|
|
233
|
+
| [Variable Naming Master](https://chat-preview.lobehub.com/market?agent=variable-naming-assistant)<br/><sup>By **[undefinedZNN](https://github.com/undefinedZNN)** on **2024-01-31**</sup> | Master the art of programming variable naming, providing multiple suggestions and explaining their usage scenarios.<br/>`variable-naming` `programming` `suggestions` |
|
|
236
234
|
|
|
237
235
|
> 📊 Total agents: [<kbd>**149**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
238
236
|
|
package/README.zh-CN.md
CHANGED
|
@@ -177,7 +177,7 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
|
|
|
177
177
|
| [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | 获取实时加密货币价格,BTC,ETH,BNB 和最新见解。最新的币新闻和空投机会。<br/>`加密货币` `btc` `eth` `bnb` |
|
|
178
178
|
| [哔哩哔哩](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | 通过关键词视频搜索、回放访问、互动弹幕、热门视频推荐和热搜洞察等功能,深入体验哔哩哔哩丰富的内容,尽在您的指尖。<br/>`视频` `哔哩哔哩` `搜索` |
|
|
179
179
|
|
|
180
|
-
> 📊 Total plugins: [<kbd>**
|
|
180
|
+
> 📊 Total plugins: [<kbd>**61**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
|
|
181
181
|
|
|
182
182
|
<!-- PLUGIN LIST -->
|
|
183
183
|
|
|
@@ -205,14 +205,12 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
|
|
|
205
205
|
|
|
206
206
|
<!-- AGENT LIST -->
|
|
207
207
|
|
|
208
|
-
| 最近新增
|
|
209
|
-
|
|
|
210
|
-
| [数据库专家](https://chat-preview.lobehub.com/market?agent=dba)<br/><sup>By **[xuzhen1994](https://github.com/xuzhen1994)** on **2024-02-03**</sup>
|
|
211
|
-
|
|
|
212
|
-
|
|
|
213
|
-
| [
|
|
214
|
-
| [SagePathfinder](https://chat-preview.lobehub.com/market?agent=sage-pathfinder)<br/><sup>By **[Ajasra](https://github.com/Ajasra)** on **2024-01-31**</sup> | 专注于斯多葛主义、深度反思和战略性提问的个人成长教练专家。<br/>`个人成长` `教练` `反思` `目标设定` `幸福感` |
|
|
215
|
-
| [变量命名大师](https://chat-preview.lobehub.com/market?agent=variable-naming-assistant)<br/><sup>By **[undefinedZNN](https://github.com/undefinedZNN)** on **2024-01-31**</sup> | 精通编程变量命名,提供多个建议并解释使用场景。<br/>`变量命名` `编程` `建议` |
|
|
208
|
+
| 最近新增 | 助手说明 |
|
|
209
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
210
|
+
| [数据库专家](https://chat-preview.lobehub.com/market?agent=dba)<br/><sup>By **[xuzhen1994](https://github.com/xuzhen1994)** on **2024-02-03**</sup> | 提供关于数据库设计范式、索引优化、查询性能调优、数据安全、备份与恢复等方面的专业建议<br/>`数据库` `dba` `mysql` `clickhouse` `doris` `mongo-db` `oracle` |
|
|
211
|
+
| [演示向导](https://chat-preview.lobehub.com/market?agent=word)<br/><sup>By **[MYSeaIT](https://github.com/MYSeaIT)** on **2024-02-03**</sup> | Word 应用演示制作机器人:帮助在 Microsoft Word 中创建令人印象深刻和专业的应用程序演示。<br/>`应用程序演示` `微软-word` `机器人` `辅助` `模板` |
|
|
212
|
+
| [SagePathfinder](https://chat-preview.lobehub.com/market?agent=sage-pathfinder)<br/><sup>By **[Ajasra](https://github.com/Ajasra)** on **2024-01-31**</sup> | 专注于斯多葛主义、深度反思和战略性提问的个人成长教练专家。<br/>`个人成长` `教练` `反思` `目标设定` `幸福感` |
|
|
213
|
+
| [变量命名大师](https://chat-preview.lobehub.com/market?agent=variable-naming-assistant)<br/><sup>By **[undefinedZNN](https://github.com/undefinedZNN)** on **2024-01-31**</sup> | 精通编程变量命名,提供多个建议并解释使用场景。<br/>`变量命名` `编程` `建议` |
|
|
216
214
|
|
|
217
215
|
> 📊 Total agents: [<kbd>**149**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
218
216
|
|
|
@@ -8,7 +8,6 @@ LobeChat provides additional configuration options during deployment, which can
|
|
|
8
8
|
- [`ACCESS_CODE`](#access_code)
|
|
9
9
|
- [Model Service Providers](#model-service-providers)
|
|
10
10
|
- [OpenAI](#openai)
|
|
11
|
-
- [`CUSTOM_MODELS`](#custom_models)
|
|
12
11
|
- [Azure OpenAI](#azure-openai)
|
|
13
12
|
- [Zhipu AI](#zhipu-ai)
|
|
14
13
|
- [Google AI](#google-ai)
|
|
@@ -62,7 +61,7 @@ Related discussions:
|
|
|
62
61
|
- [Reasons for errors when using third-party interfaces](https://github.com/lobehub/lobe-chat/discussions/734)
|
|
63
62
|
- [No response when filling in the proxy server address for chatting](https://github.com/lobehub/lobe-chat/discussions/1065)
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
#### `CUSTOM_MODELS`
|
|
66
65
|
|
|
67
66
|
- Type: Optional
|
|
68
67
|
- Description: Used to control the model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model, separated by commas.
|
|
@@ -71,6 +70,8 @@ Related discussions:
|
|
|
71
70
|
|
|
72
71
|
The above example adds `qwen-7b-chat` and `glm-6b` to the model list, removes `gpt-3.5-turbo` from the list, and displays the model name `gpt-4-0125-preview` as `gpt-4-turbo`. If you want to disable all models first and then enable specific models, you can use `-all,+gpt-3.5-turbo`, which means only `gpt-3.5-turbo` will be enabled.
|
|
73
72
|
|
|
73
|
+
You can find all current model names in [modelProviders](https://github.com/lobehub/lobe-chat/tree/main/src/config/modelProviders).
|
|
74
|
+
|
|
74
75
|
### Azure OpenAI
|
|
75
76
|
|
|
76
77
|
If you need to use Azure OpenAI to provide model services, you can refer to the [Deploy with Azure OpenAI](Deploy-with-Azure-OpenAI.zh-CN.md) section for detailed steps. Here are the environment variables related to Azure OpenAI.
|
|
@@ -8,7 +8,6 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
|
|
|
8
8
|
- [`ACCESS_CODE`](#access_code)
|
|
9
9
|
- [模型服务商](#模型服务商)
|
|
10
10
|
- [OpenAI](#openai)
|
|
11
|
-
- [`CUSTOM_MODELS`](#custom_models)
|
|
12
11
|
- [Azure OpenAI](#azure-openai)
|
|
13
12
|
- [智谱 AI](#智谱-ai)
|
|
14
13
|
- [Google AI](#google-ai)
|
|
@@ -62,7 +61,7 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
|
|
|
62
61
|
- [使用第三方接口报错的原因](https://github.com/lobehub/lobe-chat/discussions/734)
|
|
63
62
|
- [代理服务器地址填了聊天没任何反应](https://github.com/lobehub/lobe-chat/discussions/1065)
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
#### `CUSTOM_MODELS`
|
|
66
65
|
|
|
67
66
|
- 类型:可选
|
|
68
67
|
- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。
|
|
@@ -71,6 +70,8 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
|
|
|
71
70
|
|
|
72
71
|
上面示例表示增加 `qwen-7b-chat` 和 `glm-6b` 到模型列表,而从列表中删除 `gpt-3.5-turbo`,并将 `gpt-4-0125-preview` 模型名字展示为 `gpt-4-turbo`。如果你想先禁用所有模型,再启用指定模型,可以使用 `-all,+gpt-3.5-turbo`,则表示仅启用 `gpt-3.5-turbo`。
|
|
73
72
|
|
|
73
|
+
你可以在 [modelProviders](https://github.com/lobehub/lobe-chat/tree/main/src/config/modelProviders) 查找到当前的所有模型名。
|
|
74
|
+
|
|
74
75
|
### Azure OpenAI
|
|
75
76
|
|
|
76
77
|
如果你需要使用 Azure OpenAI 来提供模型服务,可以查阅 [使用 Azure OpenAI 部署](Deploy-with-Azure-OpenAI.zh-CN.md) 章节查看详细步骤,这里将列举和 Azure OpenAI 相关的环境变量。
|
package/locales/ar/common.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "نموذج مخصص، يدعم الوظائف والتعرف على الرؤية، يرجى التحقق من قدرة النموذج على القيام بذلك وفقًا للحالة الفعلية",
|
|
5
|
+
"file": "يدعم هذا النموذج قراءة وتعرف على الملفات المرفقة",
|
|
5
6
|
"functionCall": "يدعم هذا النموذج استدعاء الوظائف",
|
|
6
7
|
"tokens": "هذا النموذج يدعم حتى {{tokens}} رموز في جلسة واحدة",
|
|
7
8
|
"vision": "يدعم هذا النموذج التعرف على الرؤية"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Benutzerdefiniertes Modell, das standardmäßig sowohl Funktionsaufrufe als auch visuelle Erkennung unterstützt. Bitte überprüfen Sie die Verfügbarkeit dieser Fähigkeiten basierend auf den tatsächlichen Anforderungen.",
|
|
5
|
+
"file": "Dieses Modell unterstützt das Hochladen von Dateien zur Erkennung.",
|
|
5
6
|
"functionCall": "Dieses Modell unterstützt Funktionsaufrufe (Function Call).",
|
|
6
7
|
"tokens": "Dieses Modell unterstützt maximal {{tokens}} Tokens pro einzelner Sitzung.",
|
|
7
8
|
"vision": "Dieses Modell unterstützt visuelle Erkennung."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Custom model, by default, supports both function call and visual recognition. Please verify the availability of the above capabilities based on actual situations.",
|
|
5
|
+
"file": "This model supports file upload for reading and recognition",
|
|
5
6
|
"functionCall": "This model supports function call.",
|
|
6
7
|
"tokens": "This model supports a maximum of {{tokens}} tokens per session.",
|
|
7
8
|
"vision": "This model supports visual recognition."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Modelo personalizado: admite tanto la llamada de funciones como el reconocimiento visual. Por favor, verifique la disponibilidad de estas capacidades según sea necesario.",
|
|
5
|
+
"file": "Este modelo admite la carga y reconocimiento de archivos",
|
|
5
6
|
"functionCall": "Este modelo admite la llamada de funciones (Function Call).",
|
|
6
7
|
"tokens": "Este modelo admite un máximo de {{tokens}} tokens por sesión.",
|
|
7
8
|
"vision": "Este modelo admite el reconocimiento visual."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Modèle personnalisé, par défaut prend en charge à la fois l'appel de fonction et la reconnaissance visuelle. Veuillez vérifier la disponibilité de ces capacités selon les besoins réels.",
|
|
5
|
+
"file": "Ce modèle prend en charge la lecture et la reconnaissance de fichiers",
|
|
5
6
|
"functionCall": "Ce modèle prend en charge l'appel de fonction (Function Call).",
|
|
6
7
|
"tokens": "Ce modèle prend en charge jusqu'à {{tokens}} jetons par session.",
|
|
7
8
|
"vision": "Ce modèle prend en charge la reconnaissance visuelle."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Modello personalizzato, di default supporta sia la chiamata di funzioni che il riconoscimento visivo. Si prega di verificare l'effettiva disponibilità di tali funzionalità in base alle esigenze specifiche.",
|
|
5
|
+
"file": "Questo modello supporta il caricamento e il riconoscimento dei file",
|
|
5
6
|
"functionCall": "Questo modello supporta la chiamata di funzioni (Function Call)",
|
|
6
7
|
"tokens": "Questo modello supporta un massimo di {{tokens}} token per singola sessione",
|
|
7
8
|
"vision": "Questo modello supporta il riconoscimento visivo"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "カスタムモデル、デフォルトでは関数呼び出しとビジョン認識の両方をサポートしています。上記の機能の有効性を実際の状況で検証してください。",
|
|
5
|
+
"file": "このモデルはファイルのアップロードと認識をサポートしています",
|
|
5
6
|
"functionCall": "このモデルは関数呼び出し(Function Call)をサポートしています。",
|
|
6
7
|
"tokens": "このモデルは1つのセッションあたり最大{{tokens}}トークンをサポートしています。",
|
|
7
8
|
"vision": "このモデルはビジョン認識をサポートしています。"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "사용자 정의 모델, 기본적으로 함수 호출 및 시각 인식을 모두 지원하며, 상기 기능의 가용성을 실제로 확인하십시오",
|
|
5
|
+
"file": "이 모델은 파일 업로드를 지원하여 인식할 수 있습니다.",
|
|
5
6
|
"functionCall": "이 모델은 함수 호출을 지원합니다",
|
|
6
7
|
"tokens": "이 모델은 단일 세션당 최대 {{tokens}} 토큰을 지원합니다",
|
|
7
8
|
"vision": "이 모델은 시각 인식을 지원합니다"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Aangepast model, standaard ingesteld om zowel functieoproep als visuele herkenning te ondersteunen. Verifieer de beschikbaarheid van deze mogelijkheden op basis van de werkelijke situatie.",
|
|
5
|
+
"file": "Dit model ondersteunt het uploaden van bestanden voor lezen en herkenning",
|
|
5
6
|
"functionCall": "Dit model ondersteunt functieoproep (Function Call).",
|
|
6
7
|
"tokens": "Dit model ondersteunt maximaal {{tokens}} tokens per sessie.",
|
|
7
8
|
"vision": "Dit model ondersteunt visuele herkenning."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Niestandardowy model, domyślnie obsługujący zarówno wywołania funkcji, jak i rozpoznawanie wizualne. Proszę zweryfikować możliwość użycia tych funkcji w praktyce.",
|
|
5
|
+
"file": "Ten model obsługuje wczytywanie plików i rozpoznawanie",
|
|
5
6
|
"functionCall": "Ten model obsługuje wywołania funkcji (Function Call).",
|
|
6
7
|
"tokens": "Ten model obsługuje maksymalnie {{tokens}} tokenów w pojedynczej sesji.",
|
|
7
8
|
"vision": "Ten model obsługuje rozpoznawanie wizualne."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Modelo personalizado, suporta chamadas de função e reconhecimento visual. Por favor, verifique a disponibilidade dessas capacidades de acordo com a situação real.",
|
|
5
|
+
"file": "Este modelo suporta o carregamento de arquivos para leitura e reconhecimento",
|
|
5
6
|
"functionCall": "Este modelo suporta chamadas de função (Function Call)",
|
|
6
7
|
"tokens": "Este modelo suporta no máximo {{tokens}} tokens por sessão",
|
|
7
8
|
"vision": "Este modelo suporta reconhecimento visual"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Пользовательская модель. По умолчанию поддерживает как вызов функций, так и визуальное распознавание. Пожалуйста, проверьте возможность использования указанных функций в вашем конкретном случае.",
|
|
5
|
+
"file": "Эта модель поддерживает загрузку файлов для чтения и распознавания",
|
|
5
6
|
"functionCall": "Эта модель поддерживает вызов функций (Function Call).",
|
|
6
7
|
"tokens": "Эта модель поддерживает до {{tokens}} токенов в одной сессии.",
|
|
7
8
|
"vision": "Эта модель поддерживает визуальное распознавание."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Özel model, varsayılan olarak hem fonksiyon çağrısını hem de görüntü tanımayı destekler, lütfen yukarıdaki yeteneklerin kullanılabilirliğini doğrulayın",
|
|
5
|
+
"file": "Bu model dosya yükleme ve tanıma desteği sağlar",
|
|
5
6
|
"functionCall": "Bu model fonksiyon çağrısını destekler (Function Call)",
|
|
6
7
|
"tokens": "Bu model, tek bir oturumda en fazla {{tokens}} Token'ı destekler",
|
|
7
8
|
"vision": "Bu model görüntü tanımı destekler"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"ModelSelect": {
|
|
3
3
|
"featureTag": {
|
|
4
4
|
"custom": "Chọn mô hình tùy chỉnh, mặc định hỗ trợ cả cuộc gọi hàm và nhận diện thị giác, vui lòng xác minh khả năng sử dụng của các tính năng trên dựa trên tình hình thực tế",
|
|
5
|
+
"file": "Mô hình này hỗ trợ tải lên tệp để đọc và nhận dạng",
|
|
5
6
|
"functionCall": "Mô hình này hỗ trợ cuộc gọi hàm (Function Call)",
|
|
6
7
|
"tokens": "Mô hình này hỗ trợ tối đa {{tokens}} Tokens cho mỗi phiên",
|
|
7
8
|
"vision": "Mô hình này hỗ trợ nhận diện thị giác"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.123.
|
|
3
|
+
"version": "0.123.3",
|
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"@lobehub/tts": "latest",
|
|
85
85
|
"@lobehub/ui": "latest",
|
|
86
86
|
"@vercel/analytics": "^1",
|
|
87
|
+
"ahooks": "^3",
|
|
87
88
|
"ai": "^2",
|
|
88
89
|
"antd": "^5",
|
|
89
90
|
"antd-style": "^3",
|
|
@@ -144,6 +145,7 @@
|
|
|
144
145
|
"@lobehub/lint": "latest",
|
|
145
146
|
"@next/bundle-analyzer": "^14",
|
|
146
147
|
"@next/eslint-plugin-next": "^14",
|
|
148
|
+
"@peculiar/webcrypto": "^1.4.5",
|
|
147
149
|
"@testing-library/jest-dom": "^6",
|
|
148
150
|
"@testing-library/react": "^14",
|
|
149
151
|
"@types/chroma-js": "^2",
|
|
@@ -40,11 +40,13 @@ export const POST = async (req: Request, { params }: { params: { provider: strin
|
|
|
40
40
|
} catch (e) {
|
|
41
41
|
// if catch the error, just return it
|
|
42
42
|
const err = e as AgentInitErrorPayload;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
return createErrorResponse(
|
|
44
|
+
(err.errorType || ChatErrorType.InternalServerError) as ILobeAgentRuntimeErrorType,
|
|
45
|
+
{
|
|
46
|
+
error: err.error || e,
|
|
47
|
+
provider: params.provider,
|
|
48
|
+
},
|
|
49
|
+
);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
// ============ 2. create chat completion ============ //
|
package/src/app/api/chat/auth.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { importJWK, jwtVerify } from 'jose';
|
|
2
2
|
|
|
3
3
|
import { getServerConfig } from '@/config/server';
|
|
4
|
-
import { JWTPayload, JWT_SECRET_KEY } from '@/const/auth';
|
|
4
|
+
import { JWTPayload, JWT_SECRET_KEY, NON_HTTP_PREFIX } from '@/const/auth';
|
|
5
5
|
import { AgentRuntimeError } from '@/libs/agent-runtime';
|
|
6
6
|
import { ChatErrorType } from '@/types/fetch';
|
|
7
7
|
|
|
8
|
-
export const getJWTPayload = async (token: string) => {
|
|
8
|
+
export const getJWTPayload = async (token: string): Promise<JWTPayload> => {
|
|
9
|
+
//如果是 HTTP 协议发起的请求,直接解析 token
|
|
10
|
+
// 这是一个非常 hack 的解决方案,未来要找更好的解决方案来处理这个问题
|
|
11
|
+
// refs: https://github.com/lobehub/lobe-chat/pull/1238
|
|
12
|
+
if (token.startsWith(NON_HTTP_PREFIX)) {
|
|
13
|
+
const jwtParts = token.split('.');
|
|
14
|
+
|
|
15
|
+
const payload = jwtParts[1];
|
|
16
|
+
|
|
17
|
+
return JSON.parse(atob(payload));
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
const encoder = new TextEncoder();
|
|
10
21
|
const secretKey = await crypto.subtle.digest('SHA-256', encoder.encode(JWT_SECRET_KEY));
|
|
11
22
|
|
|
@@ -63,7 +63,7 @@ export const POST = async (req: Request) => {
|
|
|
63
63
|
// if catch the error, just return it
|
|
64
64
|
const err = e as AgentInitErrorPayload;
|
|
65
65
|
|
|
66
|
-
return createErrorResponse(err.
|
|
66
|
+
return createErrorResponse(err.errorType as ILobeAgentRuntimeErrorType, {
|
|
67
67
|
error: err.error,
|
|
68
68
|
provider: 'google',
|
|
69
69
|
});
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { consola } from 'consola';
|
|
2
|
-
|
|
3
1
|
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime';
|
|
4
|
-
import {
|
|
2
|
+
import { ErrorResponse, ErrorType } from '@/types/fetch';
|
|
5
3
|
|
|
6
4
|
const getStatus = (errorType: ILobeAgentRuntimeErrorType | ErrorType) => {
|
|
5
|
+
// InvalidAccessCode / InvalidAzureAPIKey / InvalidOpenAIAPIKey / InvalidZhipuAPIKey ....
|
|
6
|
+
if (errorType.toString().includes('Invalid')) return 401;
|
|
7
|
+
|
|
7
8
|
switch (errorType) {
|
|
8
|
-
|
|
9
|
-
case AgentRuntimeErrorType.NoOpenAIAPIKey:
|
|
10
|
-
case AgentRuntimeErrorType.InvalidAzureAPIKey:
|
|
11
|
-
case AgentRuntimeErrorType.InvalidBedrockCredentials:
|
|
12
|
-
case AgentRuntimeErrorType.InvalidZhipuAPIKey:
|
|
13
|
-
case AgentRuntimeErrorType.InvalidGoogleAPIKey: {
|
|
9
|
+
// TODO: Need to refactor to Invalid OpenAI API Key
|
|
10
|
+
case AgentRuntimeErrorType.NoOpenAIAPIKey: {
|
|
14
11
|
return 401;
|
|
15
12
|
}
|
|
16
13
|
|
|
@@ -38,7 +35,8 @@ const getStatus = (errorType: ILobeAgentRuntimeErrorType | ErrorType) => {
|
|
|
38
35
|
return 475;
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
|
-
|
|
38
|
+
|
|
39
|
+
return errorType as number;
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
export const createErrorResponse = (
|
|
@@ -50,7 +48,7 @@ export const createErrorResponse = (
|
|
|
50
48
|
const data: ErrorResponse = { body, errorType };
|
|
51
49
|
|
|
52
50
|
if (typeof statusCode !== 'number' || statusCode < 200 || statusCode > 599) {
|
|
53
|
-
|
|
51
|
+
console.error(
|
|
54
52
|
`current StatusCode: \`${statusCode}\` .`,
|
|
55
53
|
'Please go to `./src/app/api/errorResponse.ts` to defined the statusCode.',
|
|
56
54
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Icon, Tooltip } from '@lobehub/ui';
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
|
-
import { LucideEye, ToyBrick } from 'lucide-react';
|
|
3
|
+
import { LucideEye, LucidePaperclip, ToyBrick } from 'lucide-react';
|
|
4
4
|
import numeral from 'numeral';
|
|
5
5
|
import { rgba } from 'polished';
|
|
6
6
|
import { memo } from 'react';
|
|
@@ -72,6 +72,13 @@ export const ModelItemRender = memo<ModelItemRenderProps>(({ showInfoTag = true,
|
|
|
72
72
|
|
|
73
73
|
{showInfoTag && (
|
|
74
74
|
<Flexbox gap={4} horizontal>
|
|
75
|
+
{model.files && (
|
|
76
|
+
<Tooltip placement={'right'} title={t('ModelSelect.featureTag.file')}>
|
|
77
|
+
<div className={cx(styles.tag, styles.tagGreen)}>
|
|
78
|
+
<Icon icon={LucidePaperclip} />
|
|
79
|
+
</div>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
)}
|
|
75
82
|
{model.vision && (
|
|
76
83
|
<Tooltip placement={'right'} title={t('ModelSelect.featureTag.vision')}>
|
|
77
84
|
<div className={cx(styles.tag, styles.tagGreen)}>
|
|
@@ -90,7 +97,6 @@ export const ModelItemRender = memo<ModelItemRenderProps>(({ showInfoTag = true,
|
|
|
90
97
|
</div>
|
|
91
98
|
</Tooltip>
|
|
92
99
|
)}
|
|
93
|
-
|
|
94
100
|
{model.tokens && (
|
|
95
101
|
<Tooltip
|
|
96
102
|
overlayStyle={{ maxWidth: 'unset' }}
|
|
@@ -29,6 +29,7 @@ const OpenAI: ModelProviderCard = {
|
|
|
29
29
|
tokens: 4096,
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
|
+
displayName: 'GPT-3.5 Turbo 16K',
|
|
32
33
|
hidden: true,
|
|
33
34
|
id: 'gpt-3.5-turbo-16k',
|
|
34
35
|
tokens: 16_385,
|
|
@@ -65,12 +66,14 @@ const OpenAI: ModelProviderCard = {
|
|
|
65
66
|
vision: true,
|
|
66
67
|
},
|
|
67
68
|
{
|
|
69
|
+
displayName: 'GPT-4 Turbo Preview (1106)',
|
|
68
70
|
functionCall: true,
|
|
69
71
|
hidden: true,
|
|
70
72
|
id: 'gpt-4-1106-preview',
|
|
71
73
|
tokens: 128_000,
|
|
72
74
|
},
|
|
73
75
|
{
|
|
76
|
+
displayName: 'GPT-4',
|
|
74
77
|
functionCall: true,
|
|
75
78
|
hidden: true,
|
|
76
79
|
id: 'gpt-4',
|
package/src/const/auth.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const getErrorAlertConfig = (
|
|
|
17
17
|
errorType?: IPluginErrorType | ILobeAgentRuntimeErrorType | ErrorType,
|
|
18
18
|
): AlertProps | undefined => {
|
|
19
19
|
// OpenAIBizError / ZhipuBizError / GoogleBizError / ...
|
|
20
|
-
if (typeof errorType === 'string' && errorType.includes('Biz'))
|
|
20
|
+
if (typeof errorType === 'string' && (errorType.includes('Biz') || errorType.includes('Invalid')))
|
|
21
21
|
return {
|
|
22
22
|
extraDefaultExpand: true,
|
|
23
23
|
extraIsolate: true,
|
|
@@ -31,12 +31,7 @@ export const getErrorAlertConfig = (
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
case
|
|
35
|
-
case ChatErrorType.InvalidAccessCode:
|
|
36
|
-
case AgentRuntimeErrorType.NoOpenAIAPIKey:
|
|
37
|
-
case AgentRuntimeErrorType.InvalidBedrockCredentials:
|
|
38
|
-
case AgentRuntimeErrorType.InvalidGoogleAPIKey:
|
|
39
|
-
case AgentRuntimeErrorType.InvalidZhipuAPIKey: {
|
|
34
|
+
case ChatErrorType.InvalidAccessCode: {
|
|
40
35
|
return {
|
|
41
36
|
extraDefaultExpand: true,
|
|
42
37
|
extraIsolate: true,
|
|
@@ -33,6 +33,7 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang }) => {
|
|
|
33
33
|
const [lang, setLang] = useState(defaultLang);
|
|
34
34
|
|
|
35
35
|
const { data: locale } = useSWR(['antd-locale', lang], ([, key]) => getAntdLocale(key), {
|
|
36
|
+
dedupingInterval: 0,
|
|
36
37
|
revalidateOnFocus: false,
|
|
37
38
|
});
|
|
38
39
|
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
-
|
|
3
2
|
// ******* Runtime Biz Error ******* //
|
|
4
3
|
export const AgentRuntimeErrorType = {
|
|
5
4
|
AgentRuntimeError: 'AgentRuntimeError', // Agent Runtime 模块运行时错误
|
|
6
5
|
LocationNotSupportError: 'LocationNotSupportError',
|
|
7
6
|
|
|
8
|
-
OpenAIBizError: 'OpenAIBizError',
|
|
7
|
+
OpenAIBizError: 'OpenAIBizError',
|
|
9
8
|
|
|
10
9
|
NoOpenAIAPIKey: 'NoOpenAIAPIKey',
|
|
11
10
|
|
|
12
11
|
InvalidAzureAPIKey: 'InvalidAzureAPIKey',
|
|
13
|
-
AzureBizError: 'AzureBizError',
|
|
12
|
+
AzureBizError: 'AzureBizError',
|
|
14
13
|
|
|
15
14
|
InvalidZhipuAPIKey: 'InvalidZhipuAPIKey',
|
|
16
15
|
ZhipuBizError: 'ZhipuBizError',
|
|
@@ -19,7 +18,7 @@ export const AgentRuntimeErrorType = {
|
|
|
19
18
|
GoogleBizError: 'GoogleBizError',
|
|
20
19
|
|
|
21
20
|
InvalidBedrockCredentials: 'InvalidBedrockCredentials',
|
|
22
|
-
BedrockBizError: 'BedrockBizError',
|
|
21
|
+
BedrockBizError: 'BedrockBizError',
|
|
23
22
|
} as const;
|
|
24
23
|
|
|
25
24
|
export type ILobeAgentRuntimeErrorType =
|
package/src/services/_auth.ts
CHANGED
|
@@ -1,34 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { JWTPayload, JWT_SECRET_KEY, LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
|
|
1
|
+
import { JWTPayload, LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
|
|
4
2
|
import { ModelProvider } from '@/libs/agent-runtime';
|
|
5
3
|
import { useGlobalStore } from '@/store/global';
|
|
6
4
|
import { modelProviderSelectors, settingsSelectors } from '@/store/global/selectors';
|
|
7
|
-
|
|
8
|
-
const createJWT = async (payload: JWTPayload) => {
|
|
9
|
-
// 将AccessCode转换成适合作为密钥的格式,例如使用SHA-256进行哈希
|
|
10
|
-
const encoder = new TextEncoder();
|
|
11
|
-
const secretKey = await crypto.subtle.digest('SHA-256', encoder.encode(JWT_SECRET_KEY));
|
|
12
|
-
|
|
13
|
-
// 将密钥导入为JWK格式
|
|
14
|
-
const jwkSecretKey = await importJWK(
|
|
15
|
-
{
|
|
16
|
-
k: Buffer.from(secretKey).toString('base64'),
|
|
17
|
-
kty: 'oct',
|
|
18
|
-
},
|
|
19
|
-
'HS256',
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
// 获取当前时间戳
|
|
23
|
-
const now = Math.floor(Date.now() / 1000);
|
|
24
|
-
|
|
25
|
-
// 创建JWT
|
|
26
|
-
return new SignJWT(payload as Record<string, any>)
|
|
27
|
-
.setProtectedHeader({ alg: 'HS256' })
|
|
28
|
-
.setIssuedAt(now) // 设置JWT的iat(签发时间)声明
|
|
29
|
-
.setExpirationTime(now + 100) // 设置 JWT 的 exp(过期时间)为 100 s
|
|
30
|
-
.sign(jwkSecretKey);
|
|
31
|
-
};
|
|
5
|
+
import { createJWT } from '@/utils/jwt';
|
|
32
6
|
|
|
33
7
|
const getProviderAuthPayload = (provider: string) => {
|
|
34
8
|
switch (provider) {
|
|
@@ -81,7 +55,7 @@ const getProviderAuthPayload = (provider: string) => {
|
|
|
81
55
|
const createAuthTokenWithPayload = async (payload = {}) => {
|
|
82
56
|
const accessCode = settingsSelectors.password(useGlobalStore.getState());
|
|
83
57
|
|
|
84
|
-
return await createJWT({ accessCode, ...payload });
|
|
58
|
+
return await createJWT<JWTPayload>({ accessCode, ...payload });
|
|
85
59
|
};
|
|
86
60
|
|
|
87
61
|
interface AuthParams {
|
|
@@ -23,6 +23,62 @@ describe('modelProviderSelectors', () => {
|
|
|
23
23
|
expect(result).toMatchSnapshot();
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
it('should work correct with gpt-4', () => {
|
|
27
|
+
const s = merge(initialSettingsState, {
|
|
28
|
+
serverConfig: {
|
|
29
|
+
customModelName:
|
|
30
|
+
'-all,+gpt-3.5-turbo-1106,+gpt-3.5-turbo,+gpt-3.5-turbo-16k,+gpt-4,+gpt-4-32k,+gpt-4-1106-preview,+gpt-4-vision-preview',
|
|
31
|
+
},
|
|
32
|
+
}) as unknown as GlobalStore;
|
|
33
|
+
|
|
34
|
+
const result = modelProviderSelectors.modelSelectList(s).filter((r) => r.enabled);
|
|
35
|
+
|
|
36
|
+
expect(result[0].chatModels).toEqual([
|
|
37
|
+
{
|
|
38
|
+
displayName: 'GPT-3.5 Turbo (1106)',
|
|
39
|
+
functionCall: true,
|
|
40
|
+
id: 'gpt-3.5-turbo-1106',
|
|
41
|
+
tokens: 16385,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
description: 'GPT 3.5 Turbo,适用于各种文本生成和理解任务',
|
|
45
|
+
displayName: 'GPT-3.5 Turbo',
|
|
46
|
+
functionCall: true,
|
|
47
|
+
id: 'gpt-3.5-turbo',
|
|
48
|
+
tokens: 4096,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
displayName: 'GPT-3.5 Turbo 16K',
|
|
52
|
+
id: 'gpt-3.5-turbo-16k',
|
|
53
|
+
tokens: 16385,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
displayName: 'GPT-4',
|
|
57
|
+
functionCall: true,
|
|
58
|
+
id: 'gpt-4',
|
|
59
|
+
tokens: 8192,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
displayName: 'gpt-4-32k',
|
|
63
|
+
functionCall: true,
|
|
64
|
+
id: 'gpt-4-32k',
|
|
65
|
+
tokens: 32768,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
displayName: 'GPT-4 Turbo Preview (1106)',
|
|
69
|
+
functionCall: true,
|
|
70
|
+
id: 'gpt-4-1106-preview',
|
|
71
|
+
tokens: 128000,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
description: 'GPT-4 视觉预览版,支持视觉任务',
|
|
75
|
+
displayName: 'GPT-4 Turbo Vision (Preview)',
|
|
76
|
+
id: 'gpt-4-vision-preview',
|
|
77
|
+
tokens: 128000,
|
|
78
|
+
vision: true,
|
|
79
|
+
},
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
26
82
|
it('duplicate naming model', () => {
|
|
27
83
|
const s = merge(initialSettingsState, {
|
|
28
84
|
serverConfig: {},
|
|
@@ -67,6 +123,7 @@ describe('modelProviderSelectors', () => {
|
|
|
67
123
|
const result = modelProviderSelectors.modelSelectList(s).filter((r) => r.enabled);
|
|
68
124
|
|
|
69
125
|
expect(result[0].chatModels.find((o) => o.id === 'gpt-4-1106-preview')).toEqual({
|
|
126
|
+
displayName: 'GPT-4 Turbo Preview (1106)',
|
|
70
127
|
functionCall: true,
|
|
71
128
|
id: 'gpt-4-1106-preview',
|
|
72
129
|
tokens: 128000,
|
|
@@ -52,29 +52,31 @@ const processChatModels = (modelConfig: ReturnType<typeof parseModelString>): Ch
|
|
|
52
52
|
|
|
53
53
|
return produce(chatModels, (draft) => {
|
|
54
54
|
// 处理添加或替换逻辑
|
|
55
|
-
for (const
|
|
56
|
-
//
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
if (
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
if
|
|
64
|
-
|
|
65
|
-
if (
|
|
55
|
+
for (const toAddModel of modelConfig.add) {
|
|
56
|
+
// first try to find the model in LOBE_DEFAULT_MODEL_LIST to confirm if it is a known model
|
|
57
|
+
const knownModel = LOBE_DEFAULT_MODEL_LIST.find((model) => model.id === toAddModel.id);
|
|
58
|
+
|
|
59
|
+
// if the model is known, update it based on the known model
|
|
60
|
+
if (knownModel) {
|
|
61
|
+
const modelInList = draft.find((model) => model.id === toAddModel.id);
|
|
62
|
+
|
|
63
|
+
// if the model is already in chatModels, update it
|
|
64
|
+
if (modelInList) {
|
|
65
|
+
if (modelInList.hidden) delete modelInList.hidden;
|
|
66
|
+
if (toAddModel.displayName) modelInList.displayName = toAddModel.displayName;
|
|
66
67
|
} else {
|
|
67
|
-
//
|
|
68
|
+
// if the model is not in chatModels, add it
|
|
68
69
|
draft.push({
|
|
69
|
-
...
|
|
70
|
-
displayName:
|
|
70
|
+
...knownModel,
|
|
71
|
+
displayName: toAddModel.displayName || knownModel.displayName || knownModel.id,
|
|
72
|
+
hidden: undefined,
|
|
71
73
|
});
|
|
72
74
|
}
|
|
73
75
|
} else {
|
|
74
|
-
//
|
|
76
|
+
// if the model is not in LOBE_DEFAULT_MODEL_LIST, add it as a new custom model
|
|
75
77
|
draft.push({
|
|
76
|
-
...
|
|
77
|
-
displayName:
|
|
78
|
+
...toAddModel,
|
|
79
|
+
displayName: toAddModel.displayName || toAddModel.id,
|
|
78
80
|
functionCall: true,
|
|
79
81
|
isCustom: true,
|
|
80
82
|
vision: true,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { NON_HTTP_PREFIX } from '@/const/auth';
|
|
4
|
+
|
|
5
|
+
import { createJWT } from './jwt';
|
|
6
|
+
|
|
7
|
+
describe('createJWT', () => {
|
|
8
|
+
it('should create a JWT token', async () => {
|
|
9
|
+
const payload = { test: 'test' };
|
|
10
|
+
const token = await createJWT(payload);
|
|
11
|
+
expect(token).toBeTruthy();
|
|
12
|
+
});
|
|
13
|
+
it('should return a token with NON_HTTP_PREFIX when crypto.subtle does not exist', async () => {
|
|
14
|
+
const originalCryptoSubtle = crypto.subtle;
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
crypto['subtle'] = undefined;
|
|
17
|
+
|
|
18
|
+
const payload = { test: 'test' };
|
|
19
|
+
const token = await createJWT(payload);
|
|
20
|
+
|
|
21
|
+
expect(token.startsWith(NON_HTTP_PREFIX)).toBeTruthy();
|
|
22
|
+
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
crypto['subtle'] = originalCryptoSubtle;
|
|
25
|
+
});
|
|
26
|
+
});
|
package/src/utils/jwt.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SignJWT, importJWK } from 'jose';
|
|
2
|
+
|
|
3
|
+
import { JWT_SECRET_KEY, NON_HTTP_PREFIX } from '@/const/auth';
|
|
4
|
+
|
|
5
|
+
export const createJWT = async <T>(payload: T) => {
|
|
6
|
+
const now = Math.floor(Date.now() / 1000);
|
|
7
|
+
const duration = 100; // 100s
|
|
8
|
+
|
|
9
|
+
const encoder = new TextEncoder();
|
|
10
|
+
|
|
11
|
+
// fix the issue that crypto.subtle is not available in non-HTTPS environment
|
|
12
|
+
// refs: https://github.com/lobehub/lobe-chat/pull/1238
|
|
13
|
+
if (!crypto.subtle) {
|
|
14
|
+
const buffer = encoder.encode(JSON.stringify(payload));
|
|
15
|
+
|
|
16
|
+
return `${NON_HTTP_PREFIX}.${Buffer.from(buffer).toString('base64')}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// create a secret key
|
|
20
|
+
const secretKey = await crypto.subtle.digest('SHA-256', encoder.encode(JWT_SECRET_KEY));
|
|
21
|
+
|
|
22
|
+
// get the JWK from the secret key
|
|
23
|
+
const jwkSecretKey = await importJWK(
|
|
24
|
+
{
|
|
25
|
+
k: Buffer.from(secretKey).toString('base64'),
|
|
26
|
+
kty: 'oct',
|
|
27
|
+
},
|
|
28
|
+
'HS256',
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// 创建JWT
|
|
32
|
+
return new SignJWT(payload as Record<string, any>)
|
|
33
|
+
.setProtectedHeader({ alg: 'HS256' })
|
|
34
|
+
.setIssuedAt(now) // 设置JWT的iat(签发时间)声明
|
|
35
|
+
.setExpirationTime(now + duration) // 设置 JWT 的 exp(过期时间)为 100 s
|
|
36
|
+
.sign(jwkSecretKey);
|
|
37
|
+
};
|