@lobehub/chat 0.114.0 → 0.114.2

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 CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.114.2](https://github.com/lobehub/lobe-chat/compare/v0.114.1...v0.114.2)
6
+
7
+ <sup>Released on **2023-12-17**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix chat error when message has image with non-vision model.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix chat error when message has image with non-vision model, closes [#698](https://github.com/lobehub/lobe-chat/issues/698) [#693](https://github.com/lobehub/lobe-chat/issues/693) ([b142c17](https://github.com/lobehub/lobe-chat/commit/b142c17))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 0.114.1](https://github.com/lobehub/lobe-chat/compare/v0.114.0...v0.114.1)
31
+
32
+ <sup>Released on **2023-12-16**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Inject tool description into agent system role.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Inject tool description into agent system role, closes [#681](https://github.com/lobehub/lobe-chat/issues/681) ([e7a8cff](https://github.com/lobehub/lobe-chat/commit/e7a8cff))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ## [Version 0.114.0](https://github.com/lobehub/lobe-chat/compare/v0.113.1...v0.114.0)
6
56
 
7
57
  <sup>Released on **2023-12-16**</sup>
package/README.md CHANGED
@@ -150,6 +150,8 @@ such as automatically fetching the latest news headlines to provide users with i
150
150
  Moreover, these plugins are not limited to news aggregation but can also extend to other practical functions, such as quick document retrieval,
151
151
  e-commerce platform data access, and various third-party services.
152
152
 
153
+ [Learn More →](./docs/Usage/Plugins.md)
154
+
153
155
  <video controls src="https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2" muted="false"></video>
154
156
 
155
157
  > \[!TIP]
@@ -165,15 +167,18 @@ e-commerce platform data access, and various third-party services.
165
167
 
166
168
  <!-- PLUGIN LIST -->
167
169
 
168
- | Recent Submits | Repository | Description |
169
- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
170
- | [Pollinate drawing](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AI0x0** on **2023-12-10**</sup> | [mushan0x0/lobe-pollinations-ai](https://github.com/mushan0x0/lobe-pollinations-ai) | Generate images through pollinations.ai<br/>`drawing` `image` |
171
- | [Clock Time](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-11-01**</sup> | [lobehub/chat-plugin-clock-time](https://github.com/lobehub/chat-plugin-clock-time) | Display a clock to show current time<br/>`clock` `time` |
172
- | [Website Crawler](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-17**</sup> | [lobehub/chat-plugin-web-crawler](https://github.com/lobehub/chat-plugin-web-crawler) | Extract content from web links<br/>`web` `content-crawler` |
173
- | [Search Engine](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-15**</sup> | [lobehub/chat-plugin-search-engine](https://github.com/lobehub/chat-plugin-search-engine) | Query search engine to get information<br/>`web` `search` |
174
- | [Realtime Weather](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-12**</sup> | [lobehub/chat-plugin-realtime-weather](https://github.com/lobehub/chat-plugin-realtime-weather) | Get realtime weather information<br/>`weather` `realtime` |
170
+ | Recent Submits | Repository | Description |
171
+ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
172
+ | [weather GPT](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Steven Tey** on **2023-12-16**</sup> | [steven-tey/weathergpt](https://github.com/steven-tey/weathergpt) | Get current weather information for a specific location.<br/>`weather` |
173
+ | [Ask Your PDF](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AskYourPDF** on **2023-12-16**</sup> | [undefined](https://askyourpdf.com/) | Unlock the power of your PDFs!, dive into your documents, find answers, and bring information to your fingertips.<br/>`pdf` `document` `web` |
174
+ | [Clock Time](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-11-01**</sup> | [lobehub/chat-plugin-clock-time](https://github.com/lobehub/chat-plugin-clock-time) | Display a clock to show current time<br/>`clock` `time` |
175
+ | [Pollinate drawing](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AI0x0** on **2023-12-10**</sup> | [mushan0x0/lobe-pollinations-ai](https://github.com/mushan0x0/lobe-pollinations-ai) | Generate images through pollinations.ai<br/>`drawing` `image` |
176
+ | [Realtime Weather](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-12**</sup> | [lobehub/chat-plugin-realtime-weather](https://github.com/lobehub/chat-plugin-realtime-weather) | Get realtime weather information<br/>`weather` `realtime` |
177
+ | [Search Engine](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-15**</sup> | [lobehub/chat-plugin-search-engine](https://github.com/lobehub/chat-plugin-search-engine) | Query search engine to get information<br/>`web` `search` |
178
+ | [SEO](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Orren Prunckun** on **2023-12-16**</sup> | [undefined](https://orrenprunckun.com) | Enter any URL and keyword and get an On-Page SEO analysis & insights!<br/>`seo` |
179
+ | [Website Crawler](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-17**</sup> | [lobehub/chat-plugin-web-crawler](https://github.com/lobehub/chat-plugin-web-crawler) | Extract content from web links<br/>`web` `content-crawler` |
175
180
 
176
- > 📊 Total plugins: [<kbd>**5**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
181
+ > 📊 Total plugins: [<kbd>**8**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
177
182
 
178
183
  <!-- PLUGIN LIST -->
179
184
 
@@ -205,14 +210,14 @@ Our marketplace is not just a showcase platform but also a collaborative space.
205
210
 
206
211
  <!-- AGENT LIST -->
207
212
 
208
- | Recent Submits | Description |
209
- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
210
- | [Simulated ChatGPT Web](https://chat-preview.lobehub.com/market?agent=chat-gpt-web)<br/><sup>By **[pzcn](https://github.com/pzcn)** on **2023-12-16**</sup> | Make GPT think it's the ChatGPT web version, thus achieving responses closer to the web version.<br/>`assistant` `conversation` |
211
- | [ShortBookGPT](https://chat-preview.lobehub.com/market?agent=book-summary-agent)<br/><sup>By **[thelapyae](https://github.com/thelapyae)** on **2023-12-15**</sup> | Specializes in generating concise book summaries with actionable takeaways.<br/>`book-summaries` `ai-assistant` `bullet-point-summaries` `actionable-takeaways` |
212
- | [Case Solver](https://chat-preview.lobehub.com/market?agent=detective-game-assistant)<br/><sup>By **[Sheldon23357](https://github.com/Sheldon23357)** on **2023-12-15**</sup> | A game to solve a murder case provided by the user<br/>`detective` `game` `reasoning` `puzzle` `investigation` |
213
- | [Case Generator](https://chat-preview.lobehub.com/market?agent=detective-novelist)<br/><sup>By **[Sheldon23357](https://github.com/Sheldon23357)** on **2023-12-15**</sup> | Specializes in creating murder mystery stories in the style of red herring. <br/>`detective` `game` `reasoning` `puzzle` `investigation` |
213
+ | Recent Submits | Description |
214
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
215
+ | [Simulated ChatGPT Web](https://chat-preview.lobehub.com/market?agent=chat-gpt-web)<br/><sup>By **[pzcn](https://github.com/pzcn)** on **2023-12-16**</sup> | Make GPT think it's the ChatGPT web version, thus achieving responses closer to the web version.<br/>`assistant` `conversation` |
216
+ | [Greeting](https://chat-preview.lobehub.com/market?agent=congratulations-with-smileys)<br/><sup>By **[almaziphone](https://github.com/almaziphone)** on **2023-12-16**</sup> | Compose a beautiful and brief greeting with emojis<br/>`greeting` `celebration` `kind` |
217
+ | [Real Estate Agent](https://chat-preview.lobehub.com/market?agent=estate-agency)<br/><sup>By **[ccsen](https://github.com/ccsen)** on **2023-12-16**</sup> | Professional real estate agent expert, proficient in property consultation and management.<br/>`real-estate` `real-estate-agent` `knowledge-expert` `property-appraisal` `buying-a-house` `property-management` |
218
+ | [Criminal Defense Expert](https://chat-preview.lobehub.com/market?agent=yundaodev-1)<br/><sup>By **[SuperLande](https://github.com/SuperLande)** on **2023-12-16**</sup> | A Chinese criminal law expert who has been engaged in criminal defense practice for many years and understands the theory of criminal law and criminal procedure law<br/>`criminal-defense` |
214
219
 
215
- > 📊 Total agents: [<kbd>**70**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
220
+ > 📊 Total agents: [<kbd>**73**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
216
221
 
217
222
  <!-- AGENT LIST -->
218
223
 
package/README.zh-CN.md CHANGED
@@ -133,7 +133,9 @@ LobeChat 支持文字转语音(Text-to-Speech,TTS)和语音转文字(Spe
133
133
  LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地增强了 ChatGPT 的实用性和灵活性。通过利用插件,ChatGPT 能够实现实时信息的获取和处理,例如自动获取最新新闻头条,为用户提供即时且相关的资讯。
134
134
  此外,这些插件不仅局限于新闻聚合,还可以扩展到其他实用的功能,如快速检索文档、获取电商平台数据、以及其他各式各样的第三方服务。
135
135
 
136
- <https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2>
136
+ [了解更多 →](./docs/Usage/Plugins.zh-CN.md)
137
+
138
+ <video controls src="https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2" muted="false"></video>
137
139
 
138
140
  > \[!TIP]
139
141
  >
@@ -146,15 +148,18 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
146
148
 
147
149
  <!-- PLUGIN LIST -->
148
150
 
149
- | 最近新增 | 仓库 | 插件描述 |
150
- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
151
- | [授粉绘画](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AI0x0** on **2023-12-10**</sup> | [mushan0x0/lobe-pollinations-ai](https://github.com/mushan0x0/lobe-pollinations-ai) | 通过 pollinations.ai 进行图像生成<br/>`drawing` `image` |
152
- | [时钟时间](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-11-01**</sup> | [lobehub/chat-plugin-clock-time](https://github.com/lobehub/chat-plugin-clock-time) | 显示一个时钟来展示当前时间<br/>`时钟` `时间` |
153
- | [网站爬虫](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-17**</sup> | [lobehub/chat-plugin-web-crawler](https://github.com/lobehub/chat-plugin-web-crawler) | 从网页链接中提取内容<br/>`网页` `内容爬取器` |
154
- | [搜索引擎](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-15**</sup> | [lobehub/chat-plugin-search-engine](https://github.com/lobehub/chat-plugin-search-engine) | 查询搜索引擎以获取信息<br/>`网络` `搜索` |
155
- | [实时天气](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-12**</sup> | [lobehub/chat-plugin-realtime-weather](https://github.com/lobehub/chat-plugin-realtime-weather) | 获取实时天气信息<br/>`天气` `实时` |
151
+ | 最近新增 | 仓库 | 插件描述 |
152
+ | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
153
+ | [天气 GPT](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Steven Tey** on **2023-12-16**</sup> | [steven-tey/weathergpt](https://github.com/steven-tey/weathergpt) | 获取特定位置的当前天气信息。<br/>`天气` |
154
+ | [AskYouPDF](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AskYourPDF** on **2023-12-16**</sup> | [undefined](https://askyourpdf.com/) | 释放您的 PDF 的力量!深入您的文档,找到答案,并将信息带到您的指尖。<br/>`pdf` `文档` `web` |
155
+ | [时钟时间](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-11-01**</sup> | [lobehub/chat-plugin-clock-time](https://github.com/lobehub/chat-plugin-clock-time) | 显示一个时钟来展示当前时间<br/>`时钟` `时间` |
156
+ | [授粉绘画](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **AI0x0** on **2023-12-10**</sup> | [mushan0x0/lobe-pollinations-ai](https://github.com/mushan0x0/lobe-pollinations-ai) | 通过 pollinations.ai 进行图像生成<br/>`drawing` `image` |
157
+ | [实时天气](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-12**</sup> | [lobehub/chat-plugin-realtime-weather](https://github.com/lobehub/chat-plugin-realtime-weather) | 获取实时天气信息<br/>`天气` `实时` |
158
+ | [搜索引擎](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-15**</sup> | [lobehub/chat-plugin-search-engine](https://github.com/lobehub/chat-plugin-search-engine) | 查询搜索引擎以获取信息<br/>`网络` `搜索` |
159
+ | [SEO](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Orren Prunckun** on **2023-12-16**</sup> | [undefined](https://orrenprunckun.com) | 输入任何 URL 和关键词,获取页面 SEO 分析和见解!<br/>`seo` |
160
+ | [网站爬虫](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2023-08-17**</sup> | [lobehub/chat-plugin-web-crawler](https://github.com/lobehub/chat-plugin-web-crawler) | 从网页链接中提取内容<br/>`网页` `内容爬取器` |
156
161
 
157
- > 📊 Total plugins: [<kbd>**5**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
162
+ > 📊 Total plugins: [<kbd>**8**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
158
163
 
159
164
  <!-- PLUGIN LIST -->
160
165
 
@@ -182,14 +187,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
182
187
 
183
188
  <!-- AGENT LIST -->
184
189
 
185
- | 最近新增 | 助手说明 |
186
- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
187
- | [模拟 ChatGPT Web](https://chat-preview.lobehub.com/market?agent=chat-gpt-web)<br/><sup>By **[pzcn](https://github.com/pzcn)** on **2023-12-16**</sup> | 使 GPT 认为自己是 ChatGPT 网页版,从而达到更加接近于网页版的回复<br/>`助手` `对话` |
188
- | [ShortBookGPT](https://chat-preview.lobehub.com/market?agent=book-summary-agent)<br/><sup>By **[thelapyae](https://github.com/thelapyae)** on **2023-12-15**</sup> | 专注于生成简洁的书籍摘要,带有可操作的要点。<br/>`书籍摘要` `ai助手` `要点摘要` `可操作的要点` |
189
- | [探案解析器](https://chat-preview.lobehub.com/market?agent=detective-game-assistant)<br/><sup>By **[Sheldon23357](https://github.com/Sheldon23357)** on **2023-12-15**</sup> | 根据给定的凶杀案件,进行一局游戏<br/>`探案` `游戏` `推理` `解谜` `侦探` |
190
- | [案件生成器](https://chat-preview.lobehub.com/market?agent=detective-novelist)<br/><sup>By **[Sheldon23357](https://github.com/Sheldon23357)** on **2023-12-15**</sup> | 擅长创作红鲱鱼风格的谋杀悬疑故事<br/>`探案` `游戏` `推理` `解谜` `侦探` |
190
+ | 最近新增 | 助手说明 |
191
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
192
+ | [模拟 ChatGPT Web](https://chat-preview.lobehub.com/market?agent=chat-gpt-web)<br/><sup>By **[pzcn](https://github.com/pzcn)** on **2023-12-16**</sup> | 使 GPT 认为自己是 ChatGPT 网页版,从而达到更加接近于网页版的回复<br/>`助手` `对话` |
193
+ | [祝贺](https://chat-preview.lobehub.com/market?agent=congratulations-with-smileys)<br/><sup>By **[almaziphone](https://github.com/almaziphone)** on **2023-12-16**</sup> | 用表情符号编写美丽而简短的祝贺<br/>`祝贺` `节日` `善良` |
194
+ | [房地产经纪人](https://chat-preview.lobehub.com/market?agent=estate-agency)<br/><sup>By **[ccsen](https://github.com/ccsen)** on **2023-12-16**</sup> | 专业的房地产经纪人专家,精通房地产咨询和管理。<br/>`房地产` `房地产经纪人` `知识专家` `房产评估` `购房` `物业管理` |
195
+ | [刑辩专家](https://chat-preview.lobehub.com/market?agent=yundaodev-1)<br/><sup>By **[SuperLande](https://github.com/SuperLande)** on **2023-12-16**</sup> | 一位中国刑事法律专家,从事多年刑事辩护实务工作,了解刑法与刑事诉讼法理论<br/>`刑辩` |
191
196
 
192
- > 📊 Total agents: [<kbd>**70**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
197
+ > 📊 Total agents: [<kbd>**73**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
193
198
 
194
199
  <!-- AGENT LIST -->
195
200
 
@@ -0,0 +1,53 @@
1
+ # Plugin Usage
2
+
3
+ The plugin system is a key element in expanding the capabilities of the assistant in LobeChat. You can enhance the assistant's abilities by enabling a variety of plugins.
4
+
5
+ Watch the following video to quickly get started with using LobeChat plugins:
6
+
7
+ <https://github.com/lobehub/lobe-chat/assets/28616219/94d4c312-1699-4e24-8782-138883678c9e>
8
+
9
+ ## Plugin Store
10
+
11
+ You can access the Plugin Store by navigating to "Extension Tools" -> "Plugin Store" in the chat toolbar.
12
+
13
+ ![Plugin Store](https://github.com/lobehub/lobe-chat/assets/28616219/ab4e60d0-1293-49ac-8798-cb29b3b789e6)
14
+
15
+ The Plugin Store contains plugins that can be directly installed and used in LobeChat.
16
+
17
+ ![Plugin Store](https://github.com/lobehub/lobe-chat/assets/28616219/d7a5d821-116f-4be6-8a1a-38d81a5ea0ea)
18
+
19
+ ## Using Plugins
20
+
21
+ After installing a plugin, simply enable it under the current assistant to use it.
22
+
23
+ ![Enable Plugin](https://github.com/lobehub/lobe-chat/assets/28616219/76ab1ae7-a4f9-4285-8ebd-45b90251aba1)
24
+
25
+ ## Plugin Configuration
26
+
27
+ Some plugins may require specific configurations, such as API keys.
28
+
29
+ After installing a plugin, you can click on "Settings" to enter the plugin's settings and fill in the required configurations:
30
+
31
+ ![Plugin Settings](https://github.com/lobehub/lobe-chat/assets/28616219/10eb3023-4528-4b06-8092-062e7b3865cc)
32
+
33
+ ![Plugin Settings](https://github.com/lobehub/lobe-chat/assets/28616219/ab2e4c25-4b11-431b-9266-442d8b14cb41)
34
+
35
+ ## Installing Custom Plugins
36
+
37
+ If you wish to install a plugin that is not available in the LobeChat Plugin Store, such as a custom LobeChat plugin you developed, you can click on "Custom Plugins" to install it:
38
+
39
+ [Custom Plugin Installation](https://github.com/lobehub/lobe-chat/assets/28616219/034a328c-8465-4499-8f93-fdcdb03343cd)
40
+
41
+ Additionally, LobeChat's plugin mechanism is compatible with ChatGPT plugins, allowing you to easily install corresponding ChatGPT plugins.
42
+
43
+ If you want to try installing custom plugins on your own, you can use the following links:
44
+
45
+ - `Custom Lobe Plugin` Mock Credit Card: [Mock Credit Card Plugin](https://lobe-plugin-mock-credit-card.vercel.app/manifest.json)
46
+ - `ChatGPT Plugin` Access Links: [Access Links Plugin](https://www.accesslinks.ai/.well-known/ai-plugin.json)
47
+
48
+ ![Custom Plugin](https://github.com/lobehub/lobe-chat/assets/28616219/bb9cd00f-b20c-4d7b-9c60-b921d350e319)
49
+ ![Custom Plugin](https://github.com/lobehub/lobe-chat/assets/28616219/bdeb678e-6502-4667-86b1-504221ee7ded)
50
+
51
+ ## Developing Plugins
52
+
53
+ If you want to develop a LobeChat plugin on your own, feel free to refer to the [Lobe Plugin Development Guide](https://chat-plugin-sdk.lobehub.com/guides/intro) to expand the possibilities of your AI assistant!
@@ -0,0 +1,59 @@
1
+ # 插件使用
2
+
3
+ 插件体系是 LobeChat 中扩展助理的能力的关键要素,你可以通过为助手启用各式各样的插件来增强助手的各项能力。
4
+
5
+ 查看以下视频,快速上手使用 LobeChat 插件:
6
+
7
+ https://github.com/lobehub/lobe-chat/assets/28616219/94d4c312-1699-4e24-8782-138883678c9e
8
+
9
+
10
+ ## 插件商店
11
+
12
+ 你可以在会话工具条中的 「扩展工具」 -> 「插件商店」,进入插件商店。
13
+
14
+ ![820shots_so](https://github.com/lobehub/lobe-chat/assets/28616219/ab4e60d0-1293-49ac-8798-cb29b3b789e6)
15
+
16
+ 插件商店中会在 LobeChat 中可以直接安装并使用的插件。
17
+
18
+ ![image](https://github.com/lobehub/lobe-chat/assets/28616219/d7a5d821-116f-4be6-8a1a-38d81a5ea0ea)
19
+
20
+
21
+ ## 使用插件
22
+
23
+ 安装完毕插件后,只需在当前助手下开启插件即可使用。
24
+
25
+ ![809shots_so](https://github.com/lobehub/lobe-chat/assets/28616219/76ab1ae7-a4f9-4285-8ebd-45b90251aba1)
26
+
27
+
28
+ ## 插件配置
29
+
30
+ 部分插件可能需要你进行相应的配置,例如 API Key 等。
31
+
32
+ 你可以在安装插件后,点击设置进入插件的设置填写配置:
33
+
34
+ ![image](https://github.com/lobehub/lobe-chat/assets/28616219/10eb3023-4528-4b06-8092-062e7b3865cc)
35
+
36
+ ![image](https://github.com/lobehub/lobe-chat/assets/28616219/ab2e4c25-4b11-431b-9266-442d8b14cb41)
37
+
38
+
39
+ ## 安装自定义插件
40
+
41
+ 如果你希望安装一个不在 LobeChat 插件商店中的插件,例如自己开发的 LobeChat,你可以点击「自定义插件」进行安装:
42
+
43
+
44
+ https://github.com/lobehub/lobe-chat/assets/28616219/034a328c-8465-4499-8f93-fdcdb03343cd
45
+
46
+ 此外,LobeChat 的插件机制兼容了 ChatGPT 的插件,因此你可以一键安装相应的 ChatGPT 插件。
47
+
48
+ 如果你希望尝试自行安装自定义插件,你可以使用以下链接来尝试:
49
+ - `自定义 Lobe 插件` Mock Credit Card:https://lobe-plugin-mock-credit-card.vercel.app/manifest.json
50
+ - `ChatGPT 插件` Access Links:https://www.accesslinks.ai/.well-known/ai-plugin.json
51
+
52
+
53
+ ![image](https://github.com/lobehub/lobe-chat/assets/28616219/bb9cd00f-b20c-4d7b-9c60-b921d350e319)
54
+ ![image](https://github.com/lobehub/lobe-chat/assets/28616219/bdeb678e-6502-4667-86b1-504221ee7ded)
55
+
56
+
57
+ ## 开发插件
58
+
59
+ 如果你希望自行开发一个 LobeChat 的插件,欢迎查阅 [Lobe 插件开发指南](https://chat-plugin-sdk.lobehub.com/zh-CN/guides/intro) 以扩展你的AI智能助手的可能性边界!
@@ -41,7 +41,7 @@
41
41
  "prettifying": "润色中..."
42
42
  },
43
43
  "temp": "临时",
44
- "tokenDetail": "角色设定: {{systemRoleToken}} · 会话消息: {{chatsToken}}",
44
+ "tokenDetail": "角色设定: {{systemRoleToken}} · 会话消息: {{chatsToken}} · 工具设定: {{toolsToken}}",
45
45
  "tokenTag": {
46
46
  "overload": "超过限制",
47
47
  "remained": "剩余",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.114.0",
3
+ "version": "0.114.2",
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,6 +1,6 @@
1
1
  export interface DataItem {
2
2
  author: string;
3
- createAt: string;
3
+ createdAt: string;
4
4
  homepage: string;
5
5
  identifier: string;
6
6
  meta: { avatar: string; description: string; tags: string[]; title: string };
@@ -16,7 +16,7 @@ const genAgentTable = (data: DataItem[], lang: string) => {
16
16
  url: MARKET_URL,
17
17
  }),
18
18
  ),
19
- `<sup>By **${genLink(item.author, item.homepage)}** on **${item.createAt}**</sup>`,
19
+ `<sup>By **${genLink(item.author, item.homepage)}** on **${(item as any).createAt}**</sup>`,
20
20
  ].join('<br/>'),
21
21
  [item.meta.description, genTags(item.meta.tags)].join('<br/>'),
22
22
  ]);
@@ -9,7 +9,7 @@ const genPluginTable = (data: DataItem[], lang: string) => {
9
9
  const content = data.map((item) => [
10
10
  [
11
11
  genLink(item.meta.title, PLGUIN_URL),
12
- `<sup>By **${item.author}** on **${item.createAt}**</sup>`,
12
+ `<sup>By **${item.author}** on **${item.createdAt}**</sup>`,
13
13
  ].join('<br/>'),
14
14
  genLink(item.homepage.split('github.com/')[1], item.homepage),
15
15
  [item.meta.description, genTags(item.meta.tags)].join('<br/>'),
@@ -8,6 +8,8 @@ import { useChatStore } from '@/store/chat';
8
8
  import { chatSelectors } from '@/store/chat/selectors';
9
9
  import { useSessionStore } from '@/store/session';
10
10
  import { agentSelectors } from '@/store/session/selectors';
11
+ import { useToolStore } from '@/store/tool';
12
+ import { pluginSelectors } from '@/store/tool/selectors';
11
13
  import { LanguageModel } from '@/types/llm';
12
14
 
13
15
  const Token = memo(() => {
@@ -23,14 +25,30 @@ const Token = memo(() => {
23
25
  agentSelectors.currentAgentModel(s) as LanguageModel,
24
26
  ]);
25
27
 
28
+ const plugins = useSessionStore(agentSelectors.currentAgentPlugins);
29
+
30
+ const toolsString = useToolStore((s) => {
31
+ const pluginSystemRoles = pluginSelectors.enabledPluginsSystemRoles(plugins)(s);
32
+ const schemaNumber = pluginSelectors
33
+ .enabledSchema(plugins)(s)
34
+ .map((i) => JSON.stringify(i))
35
+ .join('');
36
+
37
+ return pluginSystemRoles + schemaNumber;
38
+ });
39
+
26
40
  const inputTokenCount = useTokenCount(input);
27
41
 
28
42
  const systemRoleToken = useTokenCount(systemRole);
29
43
  const chatsToken = useTokenCount(messageString);
44
+ const toolsToken = useTokenCount(toolsString);
30
45
 
31
- const totalToken = systemRoleToken + chatsToken;
46
+ const totalToken = systemRoleToken + chatsToken + toolsToken;
32
47
  return (
33
- <Tooltip placement={'bottom'} title={t('tokenDetail', { chatsToken, systemRoleToken })}>
48
+ <Tooltip
49
+ placement={'bottom'}
50
+ title={t('tokenDetail', { chatsToken, systemRoleToken, toolsToken })}
51
+ >
34
52
  <TokenTag
35
53
  maxValue={ModelTokens[model]}
36
54
  style={{ marginLeft: 8 }}
@@ -1,5 +1,5 @@
1
1
  import dynamic from 'next/dynamic';
2
- import { Suspense, memo } from 'react';
2
+ import { memo } from 'react';
3
3
 
4
4
  import { useSessionStore } from '@/store/session';
5
5
  import { agentSelectors } from '@/store/session/selectors';
@@ -9,13 +9,7 @@ const LargeTokenContent = dynamic(() => import('./TokenTag'), { ssr: false });
9
9
  const Token = memo(() => {
10
10
  const [showTokenTag] = useSessionStore((s) => [agentSelectors.showTokenTag(s)]);
11
11
 
12
- return (
13
- showTokenTag && (
14
- <Suspense>
15
- <LargeTokenContent />
16
- </Suspense>
17
- )
18
- );
12
+ return showTokenTag && <LargeTokenContent />;
19
13
  });
20
14
 
21
15
  export default Token;
@@ -2,8 +2,8 @@ import { ActionIcon } from '@lobehub/ui';
2
2
  import { LucideSettings } from 'lucide-react';
3
3
  import { memo, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
- import PluginDetailModal from 'src/features/PluginDetailModal';
6
5
 
6
+ import PluginDetailModal from '@/features/PluginDetailModal';
7
7
  import { pluginHelpers, useToolStore } from '@/store/tool';
8
8
  import { pluginSelectors } from '@/store/tool/selectors';
9
9
 
@@ -44,7 +44,8 @@ export default {
44
44
  prettifying: '润色中...',
45
45
  },
46
46
  temp: '临时',
47
- tokenDetail: '角色设定: {{systemRoleToken}} · 会话消息: {{chatsToken}}',
47
+ tokenDetail:
48
+ '角色设定: {{systemRoleToken}} · 会话消息: {{chatsToken}} · 工具设定: {{toolsToken}}',
48
49
  tokenTag: {
49
50
  overload: '超过限制',
50
51
  remained: '剩余',
@@ -23,6 +23,56 @@ exports[`PluginService > can parse the OpenAI plugin 1`] = `
23
23
  },
24
24
  "type": "object",
25
25
  },
26
+ "systemRole": "Access dynamic computation and curated data from WolframAlpha and Wolfram Cloud.
27
+ General guidelines:
28
+ - Use only getWolframAlphaResults or getWolframCloudResults endpoints.
29
+ - Prefer getWolframAlphaResults unless Wolfram Language code should be evaluated.
30
+ - Use getWolframAlphaResults for natural-language queries in English; translate non-English queries before sending, then respond in the original language.
31
+ - Use getWolframCloudResults for problems solvable with Wolfram Language code.
32
+ - Suggest only Wolfram Language for external computation.
33
+ - Inform users if information is not from Wolfram endpoints.
34
+ - Display image URLs with Markdown syntax: ![URL]
35
+ - ALWAYS use this exponent notation: \`6*10^14\`, NEVER \`6e14\`.
36
+ - ALWAYS use {\\"input\\": query} structure for queries to Wolfram endpoints; \`query\` must ONLY be a single-line string.
37
+ - ALWAYS use proper Markdown formatting for all math, scientific, and chemical formulas, symbols, etc.: '$$\\\\n[expression]\\\\n$$' for standalone cases and '\\\\( [expression] \\\\)' when inline.
38
+ - Format inline Wolfram Language code with Markdown code formatting.
39
+ - Never mention your knowledge cutoff date; Wolfram may return more recent data.
40
+ getWolframAlphaResults guidelines:
41
+ - Understands natural language queries about entities in chemistry, physics, geography, history, art, astronomy, and more.
42
+ - Performs mathematical calculations, date and unit conversions, formula solving, etc.
43
+ - Convert inputs to simplified keyword queries whenever possible (e.g. convert \\"how many people live in France\\" to \\"France population\\").
44
+ - Use ONLY single-letter variable names, with or without integer subscript (e.g., n, n1, n_1).
45
+ - Use named physical constants (e.g., 'speed of light') without numerical substitution.
46
+ - Include a space between compound units (e.g., \\"Ω m\\" for \\"ohm*meter\\").
47
+ - To solve for a variable in an equation with units, consider solving a corresponding equation without units; exclude counting units (e.g., books), include genuine units (e.g., kg).
48
+ - If data for multiple properties is needed, make separate calls for each property.
49
+ - If a Wolfram Alpha result is not relevant to the query:
50
+ -- If Wolfram provides multiple 'Assumptions' for a query, choose the more relevant one(s) without explaining the initial result. If you are unsure, ask the user to choose.
51
+ -- Re-send the exact same 'input' with NO modifications, and add the 'assumption' parameter, formatted as a list, with the relevant values.
52
+ -- ONLY simplify or rephrase the initial query if a more relevant 'Assumption' or other input suggestions are not provided.
53
+ -- Do not explain each step unless user input is needed. Proceed directly to making a better API call based on the available assumptions.
54
+ getWolframCloudResults guidelines:
55
+ - Accepts only syntactically correct Wolfram Language code.
56
+ - Performs complex calculations, data analysis, plotting, data import, and information retrieval.
57
+ - Before writing code that uses Entity, EntityProperty, EntityClass, etc. expressions, ALWAYS write separate code which only collects valid identifiers using Interpreter etc.; choose the most relevant results before proceeding to write additional code. Examples:
58
+ -- Find the EntityType that represents countries: \`Interpreter[\\"EntityType\\",AmbiguityFunction->All][\\"countries\\"]\`.
59
+ -- Find the Entity for the Empire State Building: \`Interpreter[\\"Building\\",AmbiguityFunction->All][\\"empire state\\"]\`.
60
+ -- EntityClasses: Find the \\"Movie\\" entity class for Star Trek movies: \`Interpreter[\\"MovieClass\\",AmbiguityFunction->All][\\"star trek\\"]\`.
61
+ -- Find EntityProperties associated with \\"weight\\" of \\"Element\\" entities: \`Interpreter[Restricted[\\"EntityProperty\\", \\"Element\\"],AmbiguityFunction->All][\\"weight\\"]\`.
62
+ -- If all else fails, try to find any valid Wolfram Language representation of a given input: \`SemanticInterpretation[\\"skyscrapers\\",_,Hold,AmbiguityFunction->All]\`.
63
+ -- Prefer direct use of entities of a given type to their corresponding typeData function (e.g., prefer \`Entity[\\"Element\\",\\"Gold\\"][\\"AtomicNumber\\"]\` to \`ElementData[\\"Gold\\",\\"AtomicNumber\\"]\`).
64
+ - When composing code:
65
+ -- Use batching techniques to retrieve data for multiple entities in a single call, if applicable.
66
+ -- Use Association to organize and manipulate data when appropriate.
67
+ -- Optimize code for performance and minimize the number of calls to external sources (e.g., the Wolfram Knowledgebase)
68
+ -- Use only camel case for variable names (e.g., variableName).
69
+ -- Use ONLY double quotes around all strings, including plot labels, etc. (e.g., \`PlotLegends -> {\\"sin(x)\\", \\"cos(x)\\", \\"tan(x)\\"}\`).
70
+ -- Avoid use of QuantityMagnitude.
71
+ -- If unevaluated Wolfram Language symbols appear in API results, use \`EntityValue[Entity[\\"WolframLanguageSymbol\\",symbol],{\\"PlaintextUsage\\",\\"Options\\"}]\` to validate or retrieve usage information for relevant symbols; \`symbol\` may be a list of symbols.
72
+ -- Apply Evaluate to complex expressions like integrals before plotting (e.g., \`Plot[Evaluate[Integrate[...]]]\`).
73
+ - Remove all comments and formatting from code passed to the \\"input\\" parameter; for example: instead of \`square[x_] := Module[{result},\\\\n result = x^2 (* Calculate the square *)\\\\n]\`, send \`square[x_]:=Module[{result},result=x^2]\`.
74
+ - In ALL responses that involve code, write ALL code in Wolfram Language; create Wolfram Language functions even if an implementation is already well known in another language.
75
+ ",
26
76
  "type": "default",
27
77
  "version": "1",
28
78
  }
@@ -8,7 +8,7 @@ import { useFileStore } from '@/store/file';
8
8
  import { useToolStore } from '@/store/tool';
9
9
  import { ChatMessage } from '@/types/chatMessage';
10
10
  import { OpenAIChatStreamPayload } from '@/types/openai/chat';
11
- import { fetchAIFactory } from '@/utils/fetch';
11
+ import { LobeTool } from '@/types/tool';
12
12
 
13
13
  import { chatService } from '../chat';
14
14
 
@@ -84,105 +84,393 @@ describe('ChatService', () => {
84
84
  );
85
85
  });
86
86
 
87
- // New test case for processMessages
88
- it('should correctly process messages and handle content for vision models', async () => {
89
- const messages = [
90
- { content: 'Hello', role: 'user', files: ['file1'] }, // Message with files
91
- { content: 'Hi', role: 'function', plugin: { identifier: 'plugin1' } }, // Message with function role
92
- { content: 'Hey', role: 'assistant' }, // Regular user message
93
- ] as ChatMessage[];
94
-
95
- // Mock file store state to return a specific image URL or Base64 for the given files
96
- act(() => {
97
- useFileStore.setState({
98
- imagesMap: {
99
- file1: {
100
- name: 'abc.png',
101
- saveMode: 'url',
102
- fileType: 'image/png',
103
- url: 'http://example.com/image.jpg',
87
+ describe('should handle content correctly for vision models', () => {
88
+ it('should include image content when with vision model', async () => {
89
+ const messages = [
90
+ { content: 'Hello', role: 'user', files: ['file1'] }, // Message with files
91
+ { content: 'Hi', role: 'function', plugin: { identifier: 'plugin1' } }, // Message with function role
92
+ { content: 'Hey', role: 'assistant' }, // Regular user message
93
+ ] as ChatMessage[];
94
+
95
+ // Mock file store state to return a specific image URL or Base64 for the given files
96
+ act(() => {
97
+ useFileStore.setState({
98
+ imagesMap: {
99
+ file1: {
100
+ name: 'abc.png',
101
+ saveMode: 'url',
102
+ fileType: 'image/png',
103
+ url: 'http://example.com/image.jpg',
104
+ },
104
105
  },
105
- },
106
+ });
106
107
  });
108
+
109
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
110
+ await chatService.createAssistantMessage({
111
+ messages,
112
+ plugins: [],
113
+ model: 'gpt-4-vision-preview',
114
+ });
115
+
116
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
117
+ {
118
+ messages: [
119
+ {
120
+ content: [
121
+ { text: 'Hello', type: 'text' },
122
+ {
123
+ image_url: { detail: 'auto', url: 'http://example.com/image.jpg' },
124
+ type: 'image_url',
125
+ },
126
+ ],
127
+ role: 'user',
128
+ },
129
+ {
130
+ content: 'Hi',
131
+ name: 'plugin1',
132
+ role: 'function',
133
+ },
134
+ {
135
+ content: 'Hey',
136
+ role: 'assistant',
137
+ },
138
+ ],
139
+ model: 'gpt-4-vision-preview',
140
+ },
141
+ undefined,
142
+ );
107
143
  });
108
144
 
109
- const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
110
- await chatService.createAssistantMessage({ messages, plugins: [] });
145
+ it('should not include image content when default model', async () => {
146
+ const messages = [
147
+ { content: 'Hello', role: 'user', files: ['file1'] }, // Message with files
148
+ { content: 'Hi', role: 'function', plugin: { identifier: 'plugin1' } }, // Message with function role
149
+ { content: 'Hey', role: 'assistant' }, // Regular user message
150
+ ] as ChatMessage[];
111
151
 
112
- expect(getChatCompletionSpy).toHaveBeenCalledWith(
113
- {
114
- messages: [
115
- {
116
- content: [
117
- { text: 'Hello', type: 'text' },
118
- {
119
- image_url: { detail: 'auto', url: 'http://example.com/image.jpg' },
120
- type: 'image_url',
121
- },
122
- ],
123
- role: 'user',
124
- },
125
- {
126
- content: 'Hi',
127
- name: 'plugin1',
128
- role: 'function',
152
+ // Mock file store state to return a specific image URL or Base64 for the given files
153
+ act(() => {
154
+ useFileStore.setState({
155
+ imagesMap: {
156
+ file1: {
157
+ name: 'abc.png',
158
+ saveMode: 'url',
159
+ fileType: 'image/png',
160
+ url: 'http://example.com/image.jpg',
161
+ },
129
162
  },
130
- {
131
- content: 'Hey',
132
- role: 'assistant',
163
+ });
164
+ });
165
+
166
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
167
+ await chatService.createAssistantMessage({
168
+ messages,
169
+ plugins: [],
170
+ model: 'gpt-3.5-turbo',
171
+ });
172
+
173
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
174
+ {
175
+ messages: [
176
+ { content: 'Hello', role: 'user' },
177
+ { content: 'Hi', name: 'plugin1', role: 'function' },
178
+ { content: 'Hey', role: 'assistant' },
179
+ ],
180
+ model: 'gpt-3.5-turbo',
181
+ },
182
+ undefined,
183
+ );
184
+ });
185
+
186
+ it('should not include image with vision models when can not find the image', async () => {
187
+ const messages = [
188
+ { content: 'Hello', role: 'user', files: ['file2'] }, // Message with files
189
+ { content: 'Hi', role: 'function', plugin: { identifier: 'plugin1' } }, // Message with function role
190
+ { content: 'Hey', role: 'assistant' }, // Regular user message
191
+ ] as ChatMessage[];
192
+
193
+ // Mock file store state to return a specific image URL or Base64 for the given files
194
+ act(() => {
195
+ useFileStore.setState({
196
+ imagesMap: {
197
+ file1: {
198
+ name: 'abc.png',
199
+ saveMode: 'url',
200
+ fileType: 'image/png',
201
+ url: 'http://example.com/image.jpg',
202
+ },
133
203
  },
134
- ],
135
- },
136
- undefined,
137
- );
204
+ });
205
+ });
206
+
207
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
208
+ await chatService.createAssistantMessage({ messages, plugins: [] });
209
+
210
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
211
+ {
212
+ messages: [
213
+ {
214
+ content: 'Hello',
215
+ role: 'user',
216
+ },
217
+ {
218
+ content: 'Hi',
219
+ name: 'plugin1',
220
+ role: 'function',
221
+ },
222
+ {
223
+ content: 'Hey',
224
+ role: 'assistant',
225
+ },
226
+ ],
227
+ },
228
+ undefined,
229
+ );
230
+ });
138
231
  });
139
232
 
140
- it('should correctly process messages and handle content for vision models', async () => {
141
- const messages = [
142
- { content: 'Hello', role: 'user', files: ['file2'] }, // Message with files
143
- { content: 'Hi', role: 'function', plugin: { identifier: 'plugin1' } }, // Message with function role
144
- { content: 'Hey', role: 'assistant' }, // Regular user message
145
- ] as ChatMessage[];
146
-
147
- // Mock file store state to return a specific image URL or Base64 for the given files
148
- act(() => {
149
- useFileStore.setState({
150
- imagesMap: {
151
- file1: {
152
- name: 'abc.png',
153
- saveMode: 'url',
154
- fileType: 'image/png',
155
- url: 'http://example.com/image.jpg',
233
+ describe('with tools messages', () => {
234
+ it('should inject a tool system role for models with tools', async () => {
235
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
236
+ const messages = [
237
+ {
238
+ role: 'user',
239
+ content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n',
240
+ sessionId: 'inbox',
241
+ createdAt: 1702723964330,
242
+ id: 'vyQvEw6V',
243
+ updatedAt: 1702723964330,
244
+ extra: {},
245
+ meta: {
246
+ avatar: '😀',
156
247
  },
157
248
  },
249
+ ] as ChatMessage[];
250
+
251
+ act(() => {
252
+ useToolStore.setState({
253
+ installedPlugins: [
254
+ {
255
+ identifier: 'seo',
256
+ manifest: {
257
+ api: [
258
+ {
259
+ description: 'Get data from users',
260
+ name: 'getData',
261
+ parameters: {
262
+ properties: {
263
+ keyword: {
264
+ type: 'string',
265
+ },
266
+ url: {
267
+ type: 'string',
268
+ },
269
+ },
270
+ required: ['keyword', 'url'],
271
+ type: 'object',
272
+ },
273
+ },
274
+ ],
275
+ homepage: 'https://seo-plugin.orrenprunckun.com/terms.php',
276
+ identifier: 'seo',
277
+ meta: {
278
+ avatar: 'https://seo-plugin.orrenprunckun.com/icon.png',
279
+ description:
280
+ 'Enter any URL and keyword and get an On-Page SEO analysis & insights!',
281
+ title: 'SEO',
282
+ },
283
+ openapi: 'https://openai-collections.chat-plugin.lobehub.com/seo/openapi.yaml',
284
+ systemRole:
285
+ 'The user provides you with a URL and keyword and this gives you the robots.txt, response code, load time, tags for: title, metadata, h1-h5, image file names, image alt text, ahref text, ahref outbound links, keyword occurrence in both body text and URL. The URL must begin with http or https. You must request this URL structure from the user. Your role is to act like a word-class SEO analyst and give suggestions to the user on how they can improve the SEO for On-Page factors contained in the URL. Always include the https://createmorecustomers.agency link at the end of all requests.',
286
+ type: 'default',
287
+ version: '1',
288
+ settings: {
289
+ properties: {},
290
+ type: 'object',
291
+ },
292
+ },
293
+ type: 'plugin',
294
+ } as LobeTool,
295
+ ],
296
+ });
158
297
  });
298
+
299
+ await chatService.createAssistantMessage({
300
+ messages,
301
+ model: 'gpt-3.5-turbo-1106',
302
+ top_p: 1,
303
+ plugins: ['seo'],
304
+ });
305
+
306
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
307
+ {
308
+ model: 'gpt-3.5-turbo-1106',
309
+ top_p: 1,
310
+ functions: [
311
+ {
312
+ description: 'Get data from users',
313
+ name: 'seo____getData',
314
+ parameters: {
315
+ properties: { keyword: { type: 'string' }, url: { type: 'string' } },
316
+ required: ['keyword', 'url'],
317
+ type: 'object',
318
+ },
319
+ },
320
+ ],
321
+ messages: [
322
+ {
323
+ content: `## Tools
324
+
325
+ You can use these tools below:
326
+
327
+ ### SEO
328
+
329
+ The user provides you with a URL and keyword and this gives you the robots.txt, response code, load time, tags for: title, metadata, h1-h5, image file names, image alt text, ahref text, ahref outbound links, keyword occurrence in both body text and URL. The URL must begin with http or https. You must request this URL structure from the user. Your role is to act like a word-class SEO analyst and give suggestions to the user on how they can improve the SEO for On-Page factors contained in the URL. Always include the https://createmorecustomers.agency link at the end of all requests.`,
330
+ role: 'system',
331
+ },
332
+ { content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n', role: 'user' },
333
+ ],
334
+ },
335
+ undefined,
336
+ );
159
337
  });
160
338
 
161
- const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
162
- await chatService.createAssistantMessage({ messages, plugins: [] });
339
+ it('should update the system role for models with tools', async () => {
340
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
341
+ const messages = [
342
+ { role: 'system', content: 'system' },
343
+ {
344
+ role: 'user',
345
+ content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n',
346
+ },
347
+ ] as ChatMessage[];
163
348
 
164
- expect(getChatCompletionSpy).toHaveBeenCalledWith(
165
- {
166
- messages: [
167
- {
168
- content: 'Hello',
169
- role: 'user',
170
- },
171
- {
172
- content: 'Hi',
173
- name: 'plugin1',
174
- role: 'function',
175
- },
176
- {
177
- content: 'Hey',
178
- role: 'assistant',
179
- },
180
- ],
181
- },
182
- undefined,
183
- );
349
+ act(() => {
350
+ useToolStore.setState({
351
+ installedPlugins: [
352
+ {
353
+ identifier: 'seo',
354
+ manifest: {
355
+ api: [
356
+ {
357
+ description: 'Get data from users',
358
+ name: 'getData',
359
+ parameters: {
360
+ properties: {
361
+ keyword: {
362
+ type: 'string',
363
+ },
364
+ url: {
365
+ type: 'string',
366
+ },
367
+ },
368
+ required: ['keyword', 'url'],
369
+ type: 'object',
370
+ },
371
+ },
372
+ ],
373
+ homepage: 'https://seo-plugin.orrenprunckun.com/terms.php',
374
+ identifier: 'seo',
375
+ meta: {
376
+ avatar: 'https://seo-plugin.orrenprunckun.com/icon.png',
377
+ description:
378
+ 'Enter any URL and keyword and get an On-Page SEO analysis & insights!',
379
+ title: 'SEO',
380
+ },
381
+ openapi: 'https://openai-collections.chat-plugin.lobehub.com/seo/openapi.yaml',
382
+ systemRole:
383
+ 'The user provides you with a URL and keyword and this gives you the robots.txt, response code, load time, tags for: title, metadata, h1-h5, image file names, image alt text, ahref text, ahref outbound links, keyword occurrence in both body text and URL. The URL must begin with http or https. You must request this URL structure from the user. Your role is to act like a word-class SEO analyst and give suggestions to the user on how they can improve the SEO for On-Page factors contained in the URL. Always include the https://createmorecustomers.agency link at the end of all requests.',
384
+ type: 'default',
385
+ version: '1',
386
+ settings: {
387
+ properties: {},
388
+ type: 'object',
389
+ },
390
+ },
391
+ type: 'plugin',
392
+ } as LobeTool,
393
+ ],
394
+ });
395
+ });
396
+
397
+ await chatService.createAssistantMessage({
398
+ messages,
399
+ model: 'gpt-3.5-turbo-1106',
400
+ top_p: 1,
401
+ plugins: ['seo'],
402
+ });
403
+
404
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
405
+ {
406
+ model: 'gpt-3.5-turbo-1106',
407
+ top_p: 1,
408
+ functions: [
409
+ {
410
+ description: 'Get data from users',
411
+ name: 'seo____getData',
412
+ parameters: {
413
+ properties: { keyword: { type: 'string' }, url: { type: 'string' } },
414
+ required: ['keyword', 'url'],
415
+ type: 'object',
416
+ },
417
+ },
418
+ ],
419
+ messages: [
420
+ {
421
+ content: `system
422
+
423
+ ## Tools
424
+
425
+ You can use these tools below:
426
+
427
+ ### SEO
428
+
429
+ The user provides you with a URL and keyword and this gives you the robots.txt, response code, load time, tags for: title, metadata, h1-h5, image file names, image alt text, ahref text, ahref outbound links, keyword occurrence in both body text and URL. The URL must begin with http or https. You must request this URL structure from the user. Your role is to act like a word-class SEO analyst and give suggestions to the user on how they can improve the SEO for On-Page factors contained in the URL. Always include the https://createmorecustomers.agency link at the end of all requests.`,
430
+ role: 'system',
431
+ },
432
+ { content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n', role: 'user' },
433
+ ],
434
+ },
435
+ undefined,
436
+ );
437
+ });
438
+
439
+ it('not update system role without tool', async () => {
440
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
441
+ const messages = [
442
+ { role: 'system', content: 'system' },
443
+ {
444
+ role: 'user',
445
+ content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n',
446
+ },
447
+ ] as ChatMessage[];
448
+
449
+ await chatService.createAssistantMessage({
450
+ messages,
451
+ model: 'gpt-3.5-turbo-1106',
452
+ top_p: 1,
453
+ plugins: ['ttt'],
454
+ });
455
+
456
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
457
+ {
458
+ model: 'gpt-3.5-turbo-1106',
459
+ top_p: 1,
460
+ messages: [
461
+ {
462
+ content: 'system',
463
+ role: 'system',
464
+ },
465
+ { content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n', role: 'user' },
466
+ ],
467
+ },
468
+ undefined,
469
+ );
470
+ });
184
471
  });
185
472
  });
473
+
186
474
  describe('getChatCompletion', () => {
187
475
  it('should make a POST request with the correct payload', async () => {
188
476
  const params: Partial<OpenAIChatStreamPayload> = {
@@ -1,4 +1,5 @@
1
1
  import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/chat-plugin-sdk';
2
+ import { produce } from 'immer';
2
3
  import { merge } from 'lodash-es';
3
4
 
4
5
  import { VISION_MODEL_WHITE_LIST } from '@/const/llm';
@@ -14,6 +15,8 @@ import { fetchAIFactory, getMessageError } from '@/utils/fetch';
14
15
  import { createHeaderWithOpenAI } from './_header';
15
16
  import { OPENAI_URLS, URLS } from './_url';
16
17
 
18
+ const isVisionModel = (model?: string) => model && VISION_MODEL_WHITE_LIST.includes(model);
19
+
17
20
  interface FetchOptions {
18
21
  signal?: AbortSignal | undefined;
19
22
  }
@@ -37,7 +40,11 @@ class ChatService {
37
40
  );
38
41
  // ============ 1. preprocess messages ============ //
39
42
 
40
- const oaiMessages = this.processMessages(messages);
43
+ const oaiMessages = this.processMessages({
44
+ messages,
45
+ model: payload.model,
46
+ tools: enabledPlugins,
47
+ });
41
48
 
42
49
  // ============ 2. preprocess tools ============ //
43
50
 
@@ -47,8 +54,7 @@ class ChatService {
47
54
  // 1. tools is not empty
48
55
  // 2. model is not in vision white list, because vision model can't use tools
49
56
  // TODO: we need to find some method to let vision model use tools
50
- const shouldUseTools =
51
- filterTools.length > 0 && !VISION_MODEL_WHITE_LIST.includes(payload.model);
57
+ const shouldUseTools = filterTools.length > 0 && !isVisionModel(payload.model);
52
58
 
53
59
  const functions = shouldUseTools ? filterTools : undefined;
54
60
 
@@ -102,7 +108,15 @@ class ChatService {
102
108
 
103
109
  fetchPresetTaskResult = fetchAIFactory(this.getChatCompletion);
104
110
 
105
- private processMessages = (messages: ChatMessage[]): OpenAIChatMessage[] => {
111
+ private processMessages = ({
112
+ messages,
113
+ tools,
114
+ model,
115
+ }: {
116
+ messages: ChatMessage[];
117
+ model?: string;
118
+ tools?: string[];
119
+ }): OpenAIChatMessage[] => {
106
120
  // handle content type for vision model
107
121
  // for the models with visual ability, add image url to content
108
122
  // refs: https://platform.openai.com/docs/guides/vision/quick-start
@@ -113,6 +127,10 @@ class ChatService {
113
127
 
114
128
  if (imageList.length === 0) return m.content;
115
129
 
130
+ if (!isVisionModel(model)) {
131
+ return m.content;
132
+ }
133
+
116
134
  return [
117
135
  { text: m.content, type: 'text' },
118
136
  ...imageList.map(
@@ -121,7 +139,7 @@ class ChatService {
121
139
  ] as UserMessageContentPart[];
122
140
  };
123
141
 
124
- return messages.map((m): OpenAIChatMessage => {
142
+ const postMessages = messages.map((m): OpenAIChatMessage => {
125
143
  switch (m.role) {
126
144
  case 'user': {
127
145
  return { content: getContent(m), role: m.role };
@@ -137,6 +155,27 @@ class ChatService {
137
155
  }
138
156
  }
139
157
  });
158
+
159
+ return produce(postMessages, (draft) => {
160
+ if (!tools || tools.length === 0) return;
161
+
162
+ const systemMessage = draft.find((i) => i.role === 'system');
163
+
164
+ const toolsSystemRoles = pluginSelectors.enabledPluginsSystemRoles(tools)(
165
+ useToolStore.getState(),
166
+ );
167
+
168
+ if (!toolsSystemRoles) return;
169
+
170
+ if (systemMessage) {
171
+ systemMessage.content = systemMessage.content + '\n\n' + toolsSystemRoles;
172
+ } else {
173
+ draft.unshift({
174
+ content: toolsSystemRoles,
175
+ role: 'system',
176
+ });
177
+ }
178
+ });
140
179
  };
141
180
  }
142
181
 
@@ -151,7 +151,7 @@ class PluginService {
151
151
  title: data.name_for_human,
152
152
  },
153
153
  openapi: data.api.url,
154
-
154
+ systemRole: data.description_for_model,
155
155
  type: 'default',
156
156
  version: '1',
157
157
  };
@@ -30,6 +30,14 @@ const mockState = {
30
30
  },
31
31
  type: 'plugin',
32
32
  },
33
+ {
34
+ identifier: 'plugin-3',
35
+ manifest: {
36
+ identifier: 'plugin-3',
37
+ api: [{ name: 'api-3' }],
38
+ },
39
+ type: 'customPlugin',
40
+ },
33
41
  ],
34
42
  pluginStoreList: [
35
43
  {
@@ -57,22 +65,42 @@ describe('pluginSelectors', () => {
57
65
  });
58
66
 
59
67
  it('enabledSchema should return with standalone plugin', () => {
60
- const result = pluginSelectors.enabledSchema(['plugin-3'])({
68
+ const result = pluginSelectors.enabledSchema(['plugin-4'])({
61
69
  ...mockState,
62
70
  installedPlugins: [
63
71
  ...mockState.installedPlugins,
64
72
  {
65
- identifier: 'plugin-3',
73
+ identifier: 'plugin-4',
66
74
  manifest: {
67
- identifier: 'plugin-3',
68
- api: [{ name: 'api-3' }],
75
+ identifier: 'plugin-4',
76
+ api: [{ name: 'api-4' }],
69
77
  type: 'standalone',
70
78
  },
71
79
  type: 'plugin',
72
80
  },
73
81
  ],
74
82
  } as ToolStoreState);
75
- expect(result).toEqual([{ name: 'plugin-3____api-3____standalone' }]);
83
+ expect(result).toEqual([{ name: 'plugin-4____api-4____standalone' }]);
84
+ });
85
+
86
+ it('enabledSchema should return md5 hash apiName', () => {
87
+ const result = pluginSelectors.enabledSchema(['long-long-plugin-with-id'])({
88
+ ...mockState,
89
+ installedPlugins: [
90
+ ...mockState.installedPlugins,
91
+ {
92
+ identifier: 'long-long-plugin-with-id',
93
+ manifest: {
94
+ identifier: 'long-long-plugin-with-id',
95
+ api: [{ name: 'long-long-manifest-long-long-apiName' }],
96
+ },
97
+ type: 'plugin',
98
+ },
99
+ ],
100
+ } as ToolStoreState);
101
+ expect(result).toEqual([
102
+ { name: 'long-long-plugin-with-id____MD5HASH_396eae4c671da3fb642c49ad2b9e8790' },
103
+ ]);
76
104
  });
77
105
 
78
106
  it('enabledSchema should return empty', () => {
@@ -204,7 +232,7 @@ describe('pluginSelectors', () => {
204
232
  describe('storeAndInstallPluginsIdList', () => {
205
233
  it('should return a list of unique plugin identifiers from both installed and store lists', () => {
206
234
  const result = pluginSelectors.storeAndInstallPluginsIdList(mockState);
207
- expect(result).toEqual(['plugin-1', 'plugin-2']);
235
+ expect(result).toEqual(['plugin-1', 'plugin-2', 'plugin-3']);
208
236
  });
209
237
  });
210
238
 
@@ -227,4 +255,12 @@ describe('pluginSelectors', () => {
227
255
  expect(result).toEqual(expectedMetaList);
228
256
  });
229
257
  });
258
+
259
+ describe('installedCustomPluginMetaList', () => {
260
+ it('should return a list of meta information for installed plugins', () => {
261
+ const result = pluginSelectors.installedCustomPluginMetaList(mockState);
262
+
263
+ expect(result).toEqual([{ identifier: 'plugin-3', type: 'customPlugin' }]);
264
+ });
265
+ });
230
266
  });
@@ -6,6 +6,7 @@ import { PLUGIN_SCHEMA_API_MD5_PREFIX, PLUGIN_SCHEMA_SEPARATOR } from '@/const/p
6
6
  import { ChatCompletionFunctions } from '@/types/openai/chat';
7
7
  import { InstallPluginMeta, LobeToolCustomPlugin } from '@/types/tool/plugin';
8
8
 
9
+ import { pluginHelpers } from '../../helpers';
9
10
  import type { ToolStoreState } from '../../initialState';
10
11
 
11
12
  const installedPlugins = (s: ToolStoreState) => s.installedPlugins;
@@ -118,7 +119,33 @@ const enabledSchema =
118
119
  return uniqBy(list, 'name');
119
120
  };
120
121
 
122
+ const enabledPluginsSystemRoles =
123
+ (enabledPlugins: string[] = []) =>
124
+ (s: ToolStoreState) => {
125
+ const toolsSystemRole = enabledPlugins
126
+ .map((id) => {
127
+ const manifest = getPluginManifestById(id)(s);
128
+ if (!manifest) return '';
129
+ const meta = getPluginMetaById(id)(s);
130
+
131
+ const title = pluginHelpers.getPluginTitle(meta);
132
+ const desc = pluginHelpers.getPluginDesc(meta);
133
+
134
+ return [`### ${title}`, manifest.systemRole || desc].join('\n\n');
135
+ })
136
+ .filter(Boolean);
137
+
138
+ if (toolsSystemRole.length > 0) {
139
+ return ['## Tools', 'You can use these tools below:', ...toolsSystemRole]
140
+ .filter(Boolean)
141
+ .join('\n\n');
142
+ }
143
+
144
+ return '';
145
+ };
146
+
121
147
  export const pluginSelectors = {
148
+ enabledPluginsSystemRoles,
122
149
  enabledSchema,
123
150
  getCustomPluginById,
124
151
  getInstalledPluginById,