@lobehub/chat 1.2.14 → 1.3.1
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/CHANGELOG.md +42 -0
- package/docs/usage/tools-calling/groq.zh-CN.mdx +172 -4
- package/package.json +1 -1
- package/src/app/(main)/settings/llm/ProviderList/providers.tsx +7 -0
- package/src/app/api/chat/agentRuntime.ts +7 -0
- package/src/app/api/chat/google/route.test.ts +6 -1
- package/src/app/api/chat/google/route.ts +18 -3
- package/src/components/ModelIcon/index.tsx +2 -0
- package/src/components/ModelProviderIcon/index.tsx +5 -0
- package/src/components/ModelTag/ModelIcon.tsx +2 -0
- package/src/config/llm.ts +6 -0
- package/src/config/modelProviders/index.ts +4 -0
- package/src/config/modelProviders/taichu.ts +21 -0
- package/src/const/settings/llm.ts +5 -0
- package/src/features/Conversation/Error/APIKeyForm/ProviderAvatar.tsx +5 -0
- package/src/libs/agent-runtime/AgentRuntime.ts +7 -0
- package/src/libs/agent-runtime/taichu/index.test.ts +255 -0
- package/src/libs/agent-runtime/taichu/index.ts +10 -0
- package/src/libs/agent-runtime/types/type.ts +1 -0
- package/src/libs/agent-runtime/utils/debugStream.ts +5 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +2 -3
- package/src/server/globalConfig/index.ts +2 -0
- package/src/types/user/settings/keyVaults.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.3.1](https://github.com/lobehub/lobe-chat/compare/v1.3.0...v1.3.1)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-07-09**</sup>
|
|
8
|
+
|
|
9
|
+
<br/>
|
|
10
|
+
|
|
11
|
+
<details>
|
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
13
|
+
|
|
14
|
+
</details>
|
|
15
|
+
|
|
16
|
+
<div align="right">
|
|
17
|
+
|
|
18
|
+
[](#readme-top)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## [Version 1.3.0](https://github.com/lobehub/lobe-chat/compare/v1.2.14...v1.3.0)
|
|
23
|
+
|
|
24
|
+
<sup>Released on **2024-07-09**</sup>
|
|
25
|
+
|
|
26
|
+
#### ✨ Features
|
|
27
|
+
|
|
28
|
+
- **misc**: Add Taichu model provider.
|
|
29
|
+
|
|
30
|
+
<br/>
|
|
31
|
+
|
|
32
|
+
<details>
|
|
33
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
34
|
+
|
|
35
|
+
#### What's improved
|
|
36
|
+
|
|
37
|
+
- **misc**: Add Taichu model provider, closes [#3129](https://github.com/lobehub/lobe-chat/issues/3129) ([a4580e9](https://github.com/lobehub/lobe-chat/commit/a4580e9))
|
|
38
|
+
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
<div align="right">
|
|
42
|
+
|
|
43
|
+
[](#readme-top)
|
|
44
|
+
|
|
45
|
+
</div>
|
|
46
|
+
|
|
5
47
|
### [Version 1.2.14](https://github.com/lobehub/lobe-chat/compare/v1.2.13...v1.2.14)
|
|
6
48
|
|
|
7
49
|
<sup>Released on **2024-07-08**</sup>
|
|
@@ -2,14 +2,182 @@
|
|
|
2
2
|
title: Groq Tool Calling
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# Groq
|
|
5
|
+
# Groq 平台模型 Tools Calling 评测(Llama 3/Mistral)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<Callout type={'info'}>
|
|
8
|
+
由于 Groq 本身不支持 stream,因此 Tools Calling 的调用是普通请求。
|
|
9
|
+
</Callout>
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
Groq 平台的模型 Tools Calling 能力一览:
|
|
12
|
+
|
|
13
|
+
| 模型 | 支持 Tools Calling | 流式 (Stream) | 并发(Parallel) | 简单指令得分 | 复杂指令 |
|
|
14
|
+
| ------------ | ------------------ | --------------- | ---------------- | ------------ | -------- |
|
|
15
|
+
| LLAMA3 70B | ✅ | ❌ | ✅ | 🌟🌟 | 🌟🌟 |
|
|
16
|
+
| LLAMA3 8B | ✅ | ❌ | ✅ | 🌟🌟 | 🌟 |
|
|
17
|
+
| Mixtral-8x7B | ✅ | ❌ | ✅ | ⛔ | 🌟🌟 |
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## LLAMA3 70B
|
|
21
|
+
|
|
22
|
+
### 简单调用指令:天气查询
|
|
23
|
+
|
|
24
|
+
测试指令:指令 ①
|
|
25
|
+
|
|
26
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/a509d3f4-20b5-40a4-a2dc-adf11e1789e8" />
|
|
27
|
+
|
|
28
|
+
从上述视频中可以看到 LLAMA3 70B 支持并发 Tools Calling,可以同时调用多次天气查询。
|
|
29
|
+
|
|
30
|
+
<Image
|
|
31
|
+
alt="LLAMA3 70B 简单指令的 Tools Calling"
|
|
32
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/f9cd0d4d-0e44-4bff-98cc-560f11259a60"
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
37
|
+
|
|
38
|
+
```yml
|
|
39
|
+
[no stream response] 2024-7-8 15:50:40.166
|
|
40
|
+
|
|
41
|
+
{"id":"chatcmpl-ec4b6c0b-1078-4f50-a39c-e58b3b1f9c31","object":"chat.completion","created":1720425030,"model":"llama3-70b-8192","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_v89g","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\":\"杭州\"}"}},{"id":"call_jxwk","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\":\"北京}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":969,"prompt_time":0.224209489,"completion_tokens":68,"completion_time":0.194285714,"total_tokens":1037,"total_time":0.418495203},"system_fingerprint":"fp_87cbfbbc4d","x_groq":{"id":"req_01j28n57x9e78a6bfbn9sdn139"}}
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
</details>
|
|
46
|
+
|
|
47
|
+
### 复杂调用指令:文生图
|
|
48
|
+
|
|
49
|
+
测试指令:指令 ②
|
|
50
|
+
|
|
51
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/b790f5d8-e797-4325-a974-436505b16fba" />
|
|
52
|
+
|
|
53
|
+
<Image
|
|
54
|
+
alt="LLAMA3 70B 复杂指令的 Tools Calling"
|
|
55
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/082170fa-6d09-4602-8e23-eb678024305f"
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
<details>
|
|
59
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
60
|
+
|
|
61
|
+
```yml
|
|
62
|
+
[no stream response] 2024-7-8 18:0:34.811
|
|
63
|
+
|
|
64
|
+
{"id":"chatcmpl-e3b59ca9-1172-4ae2-96c7-3d6997a1f8a8","object":"chat.completion","created":1720432834,"model":"llama3-70b-8192","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_azm9","type":"function","function":{"name":"lobe-image-designer____text2image____builtin","arguments":"{\"prompts\":[\"A small, fluffy, and playful golden retriever puppy with a white patch on its forehead, sitting on a green grass field with a bright blue sky in the background, photo.\",\"A cute, little, brown and white Dalmatian puppy with a red collar, running around in a park with a sunny day, illustration.\",\"A tiny, grey and white Poodle puppy with a pink ribbon, sitting on a white couch with a few toys surrounding it, watercolor painting.\",\"A sweet, small, black and white Chihuahua puppy with a pink bow, lying on a soft, white blanket with a few stuffed animals nearby, oil painting.\"],\"quality\":\"standard\",\"seeds\":[],\"size\":\"1024x1024\",\"style\":\"vivid\"}"}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":2305,"prompt_time":3.027052298,"completion_tokens":246,"completion_time":0.702857143,"total_tokens":2551,"total_time":3.729909441},"system_fingerprint":"fp_7ab5f7e105","x_groq":{"id":"req_01j28wk2q0efvs22qatw7rd0ds"}}
|
|
65
|
+
|
|
66
|
+
POST /api/chat/groq 200 in 17462ms
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
</details>
|
|
10
70
|
|
|
11
71
|
## LLAMA3-8B
|
|
12
72
|
|
|
13
|
-
|
|
73
|
+
### 简单调用指令:天气查询
|
|
74
|
+
|
|
75
|
+
测试指令:指令 ①
|
|
76
|
+
|
|
77
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/8077f432-b5f6-4e68-a311-2aac1d7ea892" />
|
|
78
|
+
|
|
79
|
+
从上述视频中可以看到 LLAMA3-8B 对于天气插件可以正常调用,并获得正确的总结结果。但是它并没有完全 follow 我们的描述指令,没有回答「好的」。
|
|
80
|
+
|
|
81
|
+
<Image
|
|
82
|
+
alt="LLAMA3-8B 简单指令的 Tools Calling"
|
|
83
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/9d553f4e-0818-4f6c-be9d-70da289dd723"
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<details>
|
|
87
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
88
|
+
|
|
89
|
+
```yml
|
|
90
|
+
[no stream response] 2024-7-9 11:33:16.920
|
|
91
|
+
|
|
92
|
+
{"id":"chatcmpl-f3672d59-e91d-4253-af1b-bfc4e0912085","object":"chat.completion","created":1720495996,"model":"llama3-8b-8192","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_rjtk","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\":\"杭州市\"}"}},{"id":"call_7pqh","type":"functi,"function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\":\"北京市\"}"}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":969,"ppt_time":0.145428625,"completion_tokens":128,"completion_time":0.101364747,"total_tokens":1097,"total_time":0.246793372},"system_fingerprint":"fp_33d61fdfc3","x_groq":{"id":"req_01j2artze1exz82nettf2h9066"}}
|
|
93
|
+
|
|
94
|
+
POST /api/chat/groq 200 in 1649ms
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
</details>
|
|
98
|
+
|
|
99
|
+
### 复杂调用指令:文生图
|
|
100
|
+
|
|
101
|
+
测试指令:指令 ②
|
|
102
|
+
|
|
103
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/48dcfb0a-ba03-4eae-951e-37f3645eb9c7" />
|
|
104
|
+
|
|
105
|
+
LLAMA3 8B 在 DallE 的输出场景下,只会输出 1 张图片,而不是像 LLAMA3 70B 一样输出 4 张,意味着在复杂 Tools 指令层面,能力和 GPT 3.5 Turbo 接近,不如 GPT 4。
|
|
106
|
+
|
|
107
|
+
<Image
|
|
108
|
+
alt="LLAMA3 8B 复杂指令的 Tools Calling"
|
|
109
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/b0180793-5934-4296-a569-60fbc70e8262"
|
|
110
|
+
/>
|
|
111
|
+
|
|
112
|
+
<details>
|
|
113
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
114
|
+
|
|
115
|
+
```yml
|
|
116
|
+
[no stream response] 2024-7-9 11:58:27.40
|
|
117
|
+
|
|
118
|
+
{"id":"chatcmpl-3c38f4d2-3424-416c-9fb0-0969d2683959","object":"chat.completion","created":1720497506,"model":"llama3-8b-8192","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_k6xj","type":"function","function":{"name":"lobe-image-designer____text2image____builtin","arguments":"{\"prompts\":[\"Create a watercolor painting of a small white dog with a pink nose, wearing a red collar and sitting on a green grass. The dog's ears should be floppy and its fur should be curly.\"],\"quality\":\"standard\",\"seeds\":[],\"size\":\"1024x1024\",\"style\":\"natural\"}"}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":2282,"prompt_time":0.342335558,"completion_tokens":148,"completion_time":0.118023813,"total_tokens":2430,"total_time":0.460359371},"system_fingerprint":"fp_179b0f92c9","x_groq":{"id":"req_01j2at921tec8aymdq48czcw1y"}}
|
|
119
|
+
|
|
120
|
+
POST /api/chat/groq 200 in 2517ms
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
</details>
|
|
14
124
|
|
|
15
125
|
## Mixtral-8x7B
|
|
126
|
+
|
|
127
|
+
### 简单调用指令:天气查询
|
|
128
|
+
|
|
129
|
+
测试指令:指令 ①
|
|
130
|
+
|
|
131
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/70b887fa-0e16-4ed2-892e-db52dcecf71d" />
|
|
132
|
+
|
|
133
|
+
从上述视频中可以看到 Mixtral-8x7B 对于天气插件的查询输出的参数有问题,导致无法正常调用插件。
|
|
134
|
+
|
|
135
|
+
<Image
|
|
136
|
+
alt="Mixtral-8x7B 简单指令的 Tools Calling"
|
|
137
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/1b7bf28e-fa31-4838-ae92-9100a4bbb71c"
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<details>
|
|
141
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
142
|
+
|
|
143
|
+
```yml
|
|
144
|
+
|
|
145
|
+
[no stream response] 2024-7-8 22:18:19.682
|
|
146
|
+
|
|
147
|
+
{"id":"chatcmpl-9f89d669-5642-48be-b5cd-7a29756800c0","object":"chat.completion","created":1720448299,"model":"mixtral-8x7b-32768","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_719t","type":"function","function":{"name":"realtime-weather____fetchCurrentWeather","arguments":"{\"city\":\"Hangzhou,Beijing\"}"}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":1262,"prompt_time":0.116684046,"completion_tokens":102,"completion_time":0.163113006,"total_tokens":1364,"total_time":0.279797052},"system_fingerprint":"fp_c5f20b5bb1","x_groq":{"id":"req_01j29bbc8xen2s3thp9qen5bys"}}
|
|
148
|
+
|
|
149
|
+
POST /api/chat/groq 200 in 4860ms
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
### 复杂调用指令:文生图
|
|
155
|
+
|
|
156
|
+
测试指令:指令 ②
|
|
157
|
+
|
|
158
|
+
<Video src="https://github.com/lobehub/lobe-chat/assets/28616219/86c4ce08-c634-4a45-8782-c74245eee05b" />
|
|
159
|
+
|
|
160
|
+
非常意外地,Mixtral 8x7B 在文生图的 Tools Calling 的场景下,居然可以正常出图,而且出图的能力基本和 LLAMA3 70B 持平。
|
|
161
|
+
|
|
162
|
+
<Image
|
|
163
|
+
alt="Mixtral-8x7B 复杂指令的 Tools Calling"
|
|
164
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/6e7bc3fa-3bc7-4c23-8f88-f38bb889c594"
|
|
165
|
+
/>
|
|
166
|
+
<Image
|
|
167
|
+
alt="Mixtral-8x7B 复杂指令的 Tools Calling"
|
|
168
|
+
src="https://github.com/lobehub/lobe-chat/assets/28616219/815b2792-adaf-4315-9014-f20531a3978b"
|
|
169
|
+
/>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary>Tools Calling 原始输出:</summary>
|
|
173
|
+
|
|
174
|
+
```yml
|
|
175
|
+
[no stream response] 2024-7-9 12:6:38.11
|
|
176
|
+
|
|
177
|
+
{"id":"chatcmpl-a90069f3-b119-41b9-b8d7-c7f97373529e","object":"chat.completion","created":1720497998,"model":"mixtral-8x7b-32768","choices":[{"index":0,"message":{"role":"assistant","tool_calls":[{"id":"call_hw8t","type":"function","function":{"name":"lobe-image-designer____text2image____builtin","arguments":"{\"prompts\":[\"A colorful and playful illustration of a friendly small dog, looking directly at the viewer with a wagging tail and bright, expressive eyes. The dog's fur is glossy and well-groomed, with a mix of black, white, and brown colors. The background is a lush, green park with a clear blue sky and a few fluffy clouds.\",\"An oil painting of a small, energetic dog in a sunlit park, chasing a frisbee. The dog is a mix of black and white fur, with a distinct brown spot above its left eye. The park features tall trees, providing dappled shade across the grassy landscape. The frisbee is bright orange and stands out against the natural surroundings.\",\"A realistic watercolor painting of a small, fluffy white dog curled up next to a warm fireplace during a cozy winter evening. The dog's eyes are closed in contentment, and a single red bow is tied around its neck. The background includes a plush armchair, a stack of books, and a softly lit room.\",\"A fun and engaging cartoon of a small dog sitting at a café table, enjoying a cup of coffee and a croissant. The dog has a expressive face and a blue scarf around its neck. The café has a vintage, 1920's style and a red awning, with a bustling city background.\"],\"quality\":\"standard\",\"size\":\"1024x1024\",\"style\":\"vivid\"}"}}]},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":2920,"prompt_time":0.228639219,"completion_tokens":465,"completion_time":0.755757988,"total_tokens":3385,"total_time":0.984397207},"system_fingerprint":"fp_c5f20b5bb1","x_groq":{"id":"req_01j2atr155f0nv8rmfk448e2at"}}
|
|
178
|
+
|
|
179
|
+
POST /api/chat/groq 200 in 6216ms
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
</details>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AiMass,
|
|
2
3
|
Anthropic,
|
|
3
4
|
Baichuan,
|
|
4
5
|
Claude,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
PerplexityProviderCard,
|
|
37
38
|
QwenProviderCard,
|
|
38
39
|
StepfunProviderCard,
|
|
40
|
+
TaichuProviderCard,
|
|
39
41
|
TogetherAIProviderCard,
|
|
40
42
|
ZeroOneProviderCard,
|
|
41
43
|
ZhiPuProviderCard,
|
|
@@ -177,6 +179,11 @@ export const useProviderList = (): ProviderItem[] => {
|
|
|
177
179
|
docUrl: urlJoin(BASE_DOC_URL, 'baichuan'),
|
|
178
180
|
title: <Baichuan.Combine size={ 20 } type={ 'color' } />,
|
|
179
181
|
},
|
|
182
|
+
{
|
|
183
|
+
...TaichuProviderCard,
|
|
184
|
+
docUrl: urlJoin(BASE_DOC_URL, 'taichu'),
|
|
185
|
+
title: <AiMass.Combine size={ 28 } type={ 'color' } />,
|
|
186
|
+
},
|
|
180
187
|
],
|
|
181
188
|
[azureProvider, ollamaProvider, ollamaProvider, bedrockProvider],
|
|
182
189
|
);
|
|
@@ -177,6 +177,13 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
|
|
|
177
177
|
|
|
178
178
|
const apiKey = apiKeyManager.pick(payload?.apiKey || BAICHUAN_API_KEY);
|
|
179
179
|
|
|
180
|
+
return { apiKey };
|
|
181
|
+
}
|
|
182
|
+
case ModelProvider.Taichu: {
|
|
183
|
+
const { TAICHU_API_KEY } = getLLMConfig();
|
|
184
|
+
|
|
185
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || TAICHU_API_KEY);
|
|
186
|
+
|
|
180
187
|
return { apiKey };
|
|
181
188
|
}
|
|
182
189
|
}
|
|
@@ -15,7 +15,12 @@ describe('Configuration tests', () => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('should contain specific regions in preferredRegion', () => {
|
|
18
|
-
expect(preferredRegion).not.contain(['
|
|
18
|
+
expect(preferredRegion).not.contain(['hkg1']);
|
|
19
|
+
expect(preferredRegion).not.contain(['dub1']);
|
|
20
|
+
expect(preferredRegion).not.contain(['cdg1']);
|
|
21
|
+
expect(preferredRegion).not.contain(['fra1']);
|
|
22
|
+
expect(preferredRegion).not.contain(['lhr1']);
|
|
23
|
+
expect(preferredRegion).not.contain(['arn1']);
|
|
19
24
|
});
|
|
20
25
|
});
|
|
21
26
|
|
|
@@ -13,8 +13,23 @@ import { POST as UniverseRoute } from '../[provider]/route';
|
|
|
13
13
|
// so if you want to use with proxy, you need comment the code below
|
|
14
14
|
export const runtime = 'edge';
|
|
15
15
|
|
|
16
|
-
// due to Gemini-1.5-pro is not available in Hong Kong
|
|
17
|
-
//
|
|
18
|
-
|
|
16
|
+
// due to Gemini-1.5-pro is not available in Hong Kong, we need to set the preferred region to exclude "Hong Kong (hkg1)".
|
|
17
|
+
// the paid service of the Gemini API is required in the following regions until 8 July 2024. The free service is not available. Therefore, the regions is temporarily disabled.
|
|
18
|
+
// regions include Dublin (dub1, Ireland), Paris (cdg1, France), Frankfurt (fra1, Germany), London (lhr1, UK), and Stockholm (arn1, Sweden).
|
|
19
|
+
// refs: https://ai.google.dev/gemini-api/docs/available-regions
|
|
20
|
+
export const preferredRegion = [
|
|
21
|
+
'icn1',
|
|
22
|
+
'sin1',
|
|
23
|
+
'hnd1',
|
|
24
|
+
'kix1',
|
|
25
|
+
'bom1',
|
|
26
|
+
'cpt1',
|
|
27
|
+
'pdx1',
|
|
28
|
+
'cle1',
|
|
29
|
+
'syd1',
|
|
30
|
+
'iad1',
|
|
31
|
+
'sfo1',
|
|
32
|
+
'gru1',
|
|
33
|
+
];
|
|
19
34
|
|
|
20
35
|
export const POST = async (req: Request) => UniverseRoute(req, { params: { provider: 'google' } });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AiMass,
|
|
2
3
|
Adobe,
|
|
3
4
|
Ai21,
|
|
4
5
|
Aws,
|
|
@@ -66,6 +67,7 @@ const ModelIcon = memo<ModelProviderIconProps>(({ model: originModel, size = 12
|
|
|
66
67
|
if (model.includes('command')) return <Cohere.Avatar size={size} />;
|
|
67
68
|
if (model.includes('dbrx')) return <Dbrx.Avatar size={size} />;
|
|
68
69
|
if (model.includes('step')) return <Stepfun.Avatar size={size} />;
|
|
70
|
+
if (model.includes('taichu')) return <AiMass.Avatar size={size} />;
|
|
69
71
|
|
|
70
72
|
// below: To be supported in providers, move up if supported
|
|
71
73
|
if (model.includes('baichuan'))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AiMass,
|
|
2
3
|
Anthropic,
|
|
3
4
|
Azure,
|
|
4
5
|
Baichuan,
|
|
@@ -119,6 +120,10 @@ const ModelProviderIcon = memo<ModelProviderIconProps>(({ provider }) => {
|
|
|
119
120
|
return <Baichuan size={20} />;
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
case ModelProvider.Taichu: {
|
|
124
|
+
return <AiMass size={20} />;
|
|
125
|
+
}
|
|
126
|
+
|
|
122
127
|
default: {
|
|
123
128
|
return null;
|
|
124
129
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AdobeFirefly,
|
|
3
3
|
Ai21,
|
|
4
|
+
AiMass,
|
|
4
5
|
Aws,
|
|
5
6
|
Azure,
|
|
6
7
|
Baichuan,
|
|
@@ -61,6 +62,7 @@ const ModelIcon = memo<ModelIconProps>(({ model, size = 12 }) => {
|
|
|
61
62
|
if (model.startsWith('openchat')) return <OpenChat size={size} />;
|
|
62
63
|
if (model.includes('command')) return <Cohere size={size} />;
|
|
63
64
|
if (model.includes('dbrx')) return <Dbrx size={size} />;
|
|
65
|
+
if (model.includes('taichu')) return <AiMass size={size} />;
|
|
64
66
|
|
|
65
67
|
// below: To be supported in providers, move up if supported
|
|
66
68
|
if (model.includes('baichuan')) return <Baichuan size={size} />;
|
package/src/config/llm.ts
CHANGED
|
@@ -85,6 +85,9 @@ export const getLLMConfig = () => {
|
|
|
85
85
|
|
|
86
86
|
ENABLED_BAICHUAN: z.boolean(),
|
|
87
87
|
BAICHUAN_API_KEY: z.string().optional(),
|
|
88
|
+
|
|
89
|
+
ENABLED_TAICHU: z.boolean(),
|
|
90
|
+
TAICHU_API_KEY: z.string().optional(),
|
|
88
91
|
},
|
|
89
92
|
runtimeEnv: {
|
|
90
93
|
API_KEY_SELECT_MODE: process.env.API_KEY_SELECT_MODE,
|
|
@@ -161,6 +164,9 @@ export const getLLMConfig = () => {
|
|
|
161
164
|
|
|
162
165
|
ENABLED_BAICHUAN: !!process.env.BAICHUAN_API_KEY,
|
|
163
166
|
BAICHUAN_API_KEY: process.env.BAICHUAN_API_KEY,
|
|
167
|
+
|
|
168
|
+
ENABLED_TAICHU: !!process.env.TAICHU_API_KEY,
|
|
169
|
+
TAICHU_API_KEY: process.env.TAICHU_API_KEY,
|
|
164
170
|
},
|
|
165
171
|
});
|
|
166
172
|
};
|
|
@@ -16,6 +16,7 @@ import OpenRouterProvider from './openrouter';
|
|
|
16
16
|
import PerplexityProvider from './perplexity';
|
|
17
17
|
import QwenProvider from './qwen';
|
|
18
18
|
import StepfunProvider from './stepfun';
|
|
19
|
+
import TaichuProvider from './taichu';
|
|
19
20
|
import TogetherAIProvider from './togetherai';
|
|
20
21
|
import ZeroOneProvider from './zeroone';
|
|
21
22
|
import ZhiPuProvider from './zhipu';
|
|
@@ -39,6 +40,7 @@ export const LOBE_DEFAULT_MODEL_LIST: ChatModelCard[] = [
|
|
|
39
40
|
ZeroOneProvider.chatModels,
|
|
40
41
|
StepfunProvider.chatModels,
|
|
41
42
|
BaichuanProvider.chatModels,
|
|
43
|
+
TaichuProvider.chatModels,
|
|
42
44
|
].flat();
|
|
43
45
|
|
|
44
46
|
export const DEFAULT_MODEL_PROVIDER_LIST = [
|
|
@@ -61,6 +63,7 @@ export const DEFAULT_MODEL_PROVIDER_LIST = [
|
|
|
61
63
|
ZhiPuProvider,
|
|
62
64
|
StepfunProvider,
|
|
63
65
|
BaichuanProvider,
|
|
66
|
+
TaichuProvider,
|
|
64
67
|
];
|
|
65
68
|
|
|
66
69
|
export const filterEnabledModels = (provider: ModelProviderCard) => {
|
|
@@ -83,6 +86,7 @@ export { default as OpenRouterProviderCard } from './openrouter';
|
|
|
83
86
|
export { default as PerplexityProviderCard } from './perplexity';
|
|
84
87
|
export { default as QwenProviderCard } from './qwen';
|
|
85
88
|
export { default as StepfunProviderCard } from './stepfun';
|
|
89
|
+
export { default as TaichuProviderCard } from './taichu';
|
|
86
90
|
export { default as TogetherAIProviderCard } from './togetherai';
|
|
87
91
|
export { default as ZeroOneProviderCard } from './zeroone';
|
|
88
92
|
export { default as ZhiPuProviderCard } from './zhipu';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ModelProviderCard } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
// ref https://ai-maas.wair.ac.cn/#/doc
|
|
4
|
+
const Taichu: ModelProviderCard = {
|
|
5
|
+
chatModels: [
|
|
6
|
+
{
|
|
7
|
+
description: '语言大模型',
|
|
8
|
+
displayName: 'Taichu-2.0',
|
|
9
|
+
enabled: true,
|
|
10
|
+
functionCall: false,
|
|
11
|
+
id: 'taichu_llm',
|
|
12
|
+
tokens: 32_768,
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
checkModel: 'taichu_llm',
|
|
16
|
+
id: 'taichu',
|
|
17
|
+
modelList: { showModelFetcher: true },
|
|
18
|
+
name: 'Taichu',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default Taichu;
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
PerplexityProviderCard,
|
|
15
15
|
QwenProviderCard,
|
|
16
16
|
StepfunProviderCard,
|
|
17
|
+
TaichuProviderCard,
|
|
17
18
|
TogetherAIProviderCard,
|
|
18
19
|
ZeroOneProviderCard,
|
|
19
20
|
ZhiPuProviderCard,
|
|
@@ -87,6 +88,10 @@ export const DEFAULT_LLM_CONFIG: UserModelProviderConfig = {
|
|
|
87
88
|
enabled: false,
|
|
88
89
|
enabledModels: filterEnabledModels(StepfunProviderCard),
|
|
89
90
|
},
|
|
91
|
+
taichu: {
|
|
92
|
+
enabled: false,
|
|
93
|
+
enabledModels: filterEnabledModels(TaichuProviderCard),
|
|
94
|
+
},
|
|
90
95
|
togetherai: {
|
|
91
96
|
enabled: false,
|
|
92
97
|
enabledModels: filterEnabledModels(TogetherAIProviderCard),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AiMass,
|
|
2
3
|
Anthropic,
|
|
3
4
|
Baichuan,
|
|
4
5
|
DeepSeek,
|
|
@@ -81,6 +82,10 @@ const ProviderAvatar = memo<ProviderAvatarProps>(({ provider }) => {
|
|
|
81
82
|
return <Stepfun color={Stepfun.colorPrimary} size={56} />;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
case ModelProvider.Taichu: {
|
|
86
|
+
return <AiMass.Color size={56} />;
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
case ModelProvider.TogetherAI: {
|
|
85
90
|
return <Together color={Together.colorPrimary} size={56} />;
|
|
86
91
|
}
|
|
@@ -19,6 +19,7 @@ import { LobeOpenRouterAI } from './openrouter';
|
|
|
19
19
|
import { LobePerplexityAI } from './perplexity';
|
|
20
20
|
import { LobeQwenAI } from './qwen';
|
|
21
21
|
import { LobeStepfunAI } from './stepfun';
|
|
22
|
+
import { LobeTaichuAI } from './taichu';
|
|
22
23
|
import { LobeTogetherAI } from './togetherai';
|
|
23
24
|
import {
|
|
24
25
|
ChatCompetitionOptions,
|
|
@@ -118,6 +119,7 @@ class AgentRuntime {
|
|
|
118
119
|
perplexity: Partial<ClientOptions>;
|
|
119
120
|
qwen: Partial<ClientOptions>;
|
|
120
121
|
stepfun: Partial<ClientOptions>;
|
|
122
|
+
taichu: Partial<ClientOptions>;
|
|
121
123
|
togetherai: Partial<ClientOptions>;
|
|
122
124
|
zeroone: Partial<ClientOptions>;
|
|
123
125
|
zhipu: Partial<ClientOptions>;
|
|
@@ -226,6 +228,11 @@ class AgentRuntime {
|
|
|
226
228
|
runtimeModel = new LobeBaichuanAI(params.baichuan ?? {});
|
|
227
229
|
break
|
|
228
230
|
}
|
|
231
|
+
|
|
232
|
+
case ModelProvider.Taichu: {
|
|
233
|
+
runtimeModel = new LobeTaichuAI(params.taichu ?? {});
|
|
234
|
+
break
|
|
235
|
+
}
|
|
229
236
|
}
|
|
230
237
|
|
|
231
238
|
return new AgentRuntime(runtimeModel);
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import OpenAI from 'openai';
|
|
3
|
+
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ChatStreamCallbacks,
|
|
7
|
+
LobeOpenAICompatibleRuntime,
|
|
8
|
+
ModelProvider,
|
|
9
|
+
} from '@/libs/agent-runtime';
|
|
10
|
+
|
|
11
|
+
import * as debugStreamModule from '../utils/debugStream';
|
|
12
|
+
import { LobeTaichuAI } from './index';
|
|
13
|
+
|
|
14
|
+
const provider = ModelProvider.Taichu;
|
|
15
|
+
const defaultBaseURL = 'https://ai-maas.wair.ac.cn/maas/v1';
|
|
16
|
+
|
|
17
|
+
const bizErrorType = 'ProviderBizError';
|
|
18
|
+
const invalidErrorType = 'InvalidProviderAPIKey';
|
|
19
|
+
|
|
20
|
+
// Mock the console.error to avoid polluting test output
|
|
21
|
+
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
22
|
+
|
|
23
|
+
let instance: LobeOpenAICompatibleRuntime;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
instance = new LobeTaichuAI({ apiKey: 'test' });
|
|
27
|
+
|
|
28
|
+
// 使用 vi.spyOn 来模拟 chat.completions.create 方法
|
|
29
|
+
vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(
|
|
30
|
+
new ReadableStream() as any,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
vi.clearAllMocks();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('LobeTaichuAI', () => {
|
|
39
|
+
describe('init', () => {
|
|
40
|
+
it('should correctly initialize with an API key', async () => {
|
|
41
|
+
const instance = new LobeTaichuAI({ apiKey: 'test_api_key' });
|
|
42
|
+
expect(instance).toBeInstanceOf(LobeTaichuAI);
|
|
43
|
+
expect(instance.baseURL).toEqual(defaultBaseURL);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('chat', () => {
|
|
48
|
+
describe('Error', () => {
|
|
49
|
+
it('should return OpenAIBizError with an openai error response when OpenAI.APIError is thrown', async () => {
|
|
50
|
+
// Arrange
|
|
51
|
+
const apiError = new OpenAI.APIError(
|
|
52
|
+
400,
|
|
53
|
+
{
|
|
54
|
+
status: 400,
|
|
55
|
+
error: {
|
|
56
|
+
message: 'Bad Request',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
'Error message',
|
|
60
|
+
{},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
|
|
64
|
+
|
|
65
|
+
// Act
|
|
66
|
+
try {
|
|
67
|
+
await instance.chat({
|
|
68
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
69
|
+
model: 'Taichu4',
|
|
70
|
+
temperature: 0,
|
|
71
|
+
});
|
|
72
|
+
} catch (e) {
|
|
73
|
+
expect(e).toEqual({
|
|
74
|
+
endpoint: defaultBaseURL,
|
|
75
|
+
error: {
|
|
76
|
+
error: { message: 'Bad Request' },
|
|
77
|
+
status: 400,
|
|
78
|
+
},
|
|
79
|
+
errorType: bizErrorType,
|
|
80
|
+
provider,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should throw AgentRuntimeError with NoOpenAIAPIKey if no apiKey is provided', async () => {
|
|
86
|
+
try {
|
|
87
|
+
new LobeTaichuAI({});
|
|
88
|
+
} catch (e) {
|
|
89
|
+
expect(e).toEqual({ errorType: invalidErrorType });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should return OpenAIBizError with the cause when OpenAI.APIError is thrown with cause', async () => {
|
|
94
|
+
// Arrange
|
|
95
|
+
const errorInfo = {
|
|
96
|
+
stack: 'abc',
|
|
97
|
+
cause: {
|
|
98
|
+
message: 'api is undefined',
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
|
|
102
|
+
|
|
103
|
+
vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
|
|
104
|
+
|
|
105
|
+
// Act
|
|
106
|
+
try {
|
|
107
|
+
await instance.chat({
|
|
108
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
109
|
+
model: 'Taichu4',
|
|
110
|
+
temperature: 0,
|
|
111
|
+
});
|
|
112
|
+
} catch (e) {
|
|
113
|
+
expect(e).toEqual({
|
|
114
|
+
endpoint: defaultBaseURL,
|
|
115
|
+
error: {
|
|
116
|
+
cause: { message: 'api is undefined' },
|
|
117
|
+
stack: 'abc',
|
|
118
|
+
},
|
|
119
|
+
errorType: bizErrorType,
|
|
120
|
+
provider,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should return OpenAIBizError with an cause response with desensitize Url', async () => {
|
|
126
|
+
// Arrange
|
|
127
|
+
const errorInfo = {
|
|
128
|
+
stack: 'abc',
|
|
129
|
+
cause: { message: 'api is undefined' },
|
|
130
|
+
};
|
|
131
|
+
const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
|
|
132
|
+
|
|
133
|
+
instance = new LobeTaichuAI({
|
|
134
|
+
apiKey: 'test',
|
|
135
|
+
|
|
136
|
+
baseURL: 'https://api.abc.com/v1',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
|
|
140
|
+
|
|
141
|
+
// Act
|
|
142
|
+
try {
|
|
143
|
+
await instance.chat({
|
|
144
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
145
|
+
model: 'Taichu4',
|
|
146
|
+
temperature: 0,
|
|
147
|
+
});
|
|
148
|
+
} catch (e) {
|
|
149
|
+
expect(e).toEqual({
|
|
150
|
+
endpoint: 'https://api.***.com/v1',
|
|
151
|
+
error: {
|
|
152
|
+
cause: { message: 'api is undefined' },
|
|
153
|
+
stack: 'abc',
|
|
154
|
+
},
|
|
155
|
+
errorType: bizErrorType,
|
|
156
|
+
provider,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should throw an InvalidTaichuAPIKey error type on 401 status code', async () => {
|
|
162
|
+
// Mock the API call to simulate a 401 error
|
|
163
|
+
const error = new Error('Unauthorized') as any;
|
|
164
|
+
error.status = 401;
|
|
165
|
+
vi.mocked(instance['client'].chat.completions.create).mockRejectedValue(error);
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
await instance.chat({
|
|
169
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
170
|
+
model: 'Taichu4',
|
|
171
|
+
temperature: 0,
|
|
172
|
+
});
|
|
173
|
+
} catch (e) {
|
|
174
|
+
// Expect the chat method to throw an error with InvalidTaichuAPIKey
|
|
175
|
+
expect(e).toEqual({
|
|
176
|
+
endpoint: defaultBaseURL,
|
|
177
|
+
error: new Error('Unauthorized'),
|
|
178
|
+
errorType: invalidErrorType,
|
|
179
|
+
provider,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should return AgentRuntimeError for non-OpenAI errors', async () => {
|
|
185
|
+
// Arrange
|
|
186
|
+
const genericError = new Error('Generic Error');
|
|
187
|
+
|
|
188
|
+
vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(genericError);
|
|
189
|
+
|
|
190
|
+
// Act
|
|
191
|
+
try {
|
|
192
|
+
await instance.chat({
|
|
193
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
194
|
+
model: 'Taichu4',
|
|
195
|
+
temperature: 0,
|
|
196
|
+
});
|
|
197
|
+
} catch (e) {
|
|
198
|
+
expect(e).toEqual({
|
|
199
|
+
endpoint: defaultBaseURL,
|
|
200
|
+
errorType: 'AgentRuntimeError',
|
|
201
|
+
provider,
|
|
202
|
+
error: {
|
|
203
|
+
name: genericError.name,
|
|
204
|
+
cause: genericError.cause,
|
|
205
|
+
message: genericError.message,
|
|
206
|
+
stack: genericError.stack,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('DEBUG', () => {
|
|
214
|
+
it('should call debugStream and return StreamingTextResponse when DEBUG_TAICHU_CHAT_COMPLETION is 1', async () => {
|
|
215
|
+
// Arrange
|
|
216
|
+
const mockProdStream = new ReadableStream() as any; // 模拟的 prod 流
|
|
217
|
+
const mockDebugStream = new ReadableStream({
|
|
218
|
+
start(controller) {
|
|
219
|
+
controller.enqueue('Debug stream content');
|
|
220
|
+
controller.close();
|
|
221
|
+
},
|
|
222
|
+
}) as any;
|
|
223
|
+
mockDebugStream.toReadableStream = () => mockDebugStream; // 添加 toReadableStream 方法
|
|
224
|
+
|
|
225
|
+
// 模拟 chat.completions.create 返回值,包括模拟的 tee 方法
|
|
226
|
+
(instance['client'].chat.completions.create as Mock).mockResolvedValue({
|
|
227
|
+
tee: () => [mockProdStream, { toReadableStream: () => mockDebugStream }],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// 保存原始环境变量值
|
|
231
|
+
const originalDebugValue = process.env.DEBUG_TAICHU_CHAT_COMPLETION;
|
|
232
|
+
|
|
233
|
+
// 模拟环境变量
|
|
234
|
+
process.env.DEBUG_TAICHU_CHAT_COMPLETION = '1';
|
|
235
|
+
vi.spyOn(debugStreamModule, 'debugStream').mockImplementation(() => Promise.resolve());
|
|
236
|
+
|
|
237
|
+
// 执行测试
|
|
238
|
+
// 运行你的测试函数,确保它会在条件满足时调用 debugStream
|
|
239
|
+
// 假设的测试函数调用,你可能需要根据实际情况调整
|
|
240
|
+
await instance.chat({
|
|
241
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
242
|
+
model: 'Taichu4',
|
|
243
|
+
stream: true,
|
|
244
|
+
temperature: 0,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// 验证 debugStream 被调用
|
|
248
|
+
expect(debugStreamModule.debugStream).toHaveBeenCalled();
|
|
249
|
+
|
|
250
|
+
// 恢复原始环境变量值
|
|
251
|
+
process.env.DEBUG_TAICHU_CHAT_COMPLETION = originalDebugValue;
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ModelProvider } from '../types';
|
|
2
|
+
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';
|
|
3
|
+
|
|
4
|
+
export const LobeTaichuAI = LobeOpenAICompatibleFactory({
|
|
5
|
+
baseURL: 'https://ai-maas.wair.ac.cn/maas/v1',
|
|
6
|
+
debug: {
|
|
7
|
+
chatCompletion: () => process.env.DEBUG_TAICHU_CHAT_COMPLETION === '1',
|
|
8
|
+
},
|
|
9
|
+
provider: ModelProvider.Taichu,
|
|
10
|
+
});
|
|
@@ -8,7 +8,7 @@ import { LobeRuntimeAI } from '../../BaseAI';
|
|
|
8
8
|
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../../error';
|
|
9
9
|
import { ChatCompetitionOptions, ChatCompletionErrorPayload, ChatStreamPayload } from '../../types';
|
|
10
10
|
import { AgentRuntimeError } from '../createError';
|
|
11
|
-
import { debugStream } from '../debugStream';
|
|
11
|
+
import { debugResponse, debugStream } from '../debugStream';
|
|
12
12
|
import { desensitizeUrl } from '../desensitizeUrl';
|
|
13
13
|
import { handleOpenAIError } from '../handleOpenAIError';
|
|
14
14
|
import { StreamingResponse } from '../response';
|
|
@@ -106,8 +106,7 @@ export const LobeOpenAICompatibleFactory = ({
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (debug?.chatCompletion?.()) {
|
|
109
|
-
|
|
110
|
-
console.log(JSON.stringify(response) + '\n');
|
|
109
|
+
debugResponse(response);
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
const stream = this.transformResponseToStream(response as unknown as OpenAI.ChatCompletion);
|
|
@@ -35,6 +35,7 @@ export const getServerGlobalConfig = () => {
|
|
|
35
35
|
ENABLED_QWEN,
|
|
36
36
|
ENABLED_STEPFUN,
|
|
37
37
|
ENABLED_BAICHUAN,
|
|
38
|
+
ENABLED_TAICHU,
|
|
38
39
|
|
|
39
40
|
ENABLED_AZURE_OPENAI,
|
|
40
41
|
AZURE_MODEL_LIST,
|
|
@@ -109,6 +110,7 @@ export const getServerGlobalConfig = () => {
|
|
|
109
110
|
|
|
110
111
|
stepfun: { enabled: ENABLED_STEPFUN },
|
|
111
112
|
|
|
113
|
+
taichu: { enabled: ENABLED_TAICHU },
|
|
112
114
|
togetherai: {
|
|
113
115
|
enabled: ENABLED_TOGETHERAI,
|
|
114
116
|
enabledModels: extractEnabledModels(TOGETHERAI_MODEL_LIST),
|
|
@@ -34,6 +34,7 @@ export interface UserKeyVaults {
|
|
|
34
34
|
perplexity?: OpenAICompatibleKeyVault;
|
|
35
35
|
qwen?: OpenAICompatibleKeyVault;
|
|
36
36
|
stepfun?: OpenAICompatibleKeyVault;
|
|
37
|
+
taichu?: OpenAICompatibleKeyVault;
|
|
37
38
|
togetherai?: OpenAICompatibleKeyVault;
|
|
38
39
|
zeroone?: OpenAICompatibleKeyVault;
|
|
39
40
|
zhipu?: OpenAICompatibleKeyVault;
|