@lobehub/chat 1.26.0 → 1.26.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 +25 -0
- package/package.json +1 -1
- package/src/prompts/plugin/index.test.ts +42 -0
- package/src/prompts/plugin/index.ts +9 -0
- package/src/prompts/plugin/tools.test.ts +109 -0
- package/src/prompts/plugin/tools.ts +28 -0
- package/src/services/__tests__/__snapshots__/chat.test.ts.snap +10 -14
- package/src/services/__tests__/chat.test.ts +18 -26
- package/src/store/tool/selectors/tool.ts +13 -18
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.26.1](https://github.com/lobehub/lobe-chat/compare/v1.26.0...v1.26.1)
|
6
|
+
|
7
|
+
<sup>Released on **2024-10-27**</sup>
|
8
|
+
|
9
|
+
#### ♻ Code Refactoring
|
10
|
+
|
11
|
+
- **misc**: Refactor the plugin prompts to xml format.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Code refactoring
|
19
|
+
|
20
|
+
- **misc**: Refactor the plugin prompts to xml format, closes [#4520](https://github.com/lobehub/lobe-chat/issues/4520) ([49be146](https://github.com/lobehub/lobe-chat/commit/49be146))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
## [Version 1.26.0](https://github.com/lobehub/lobe-chat/compare/v1.25.3...v1.26.0)
|
6
31
|
|
7
32
|
<sup>Released on **2024-10-27**</sup>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.26.
|
3
|
+
"version": "1.26.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",
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { Tool } from '@/prompts/plugin/tools';
|
2
|
+
|
3
|
+
import { pluginPrompts } from './index';
|
4
|
+
|
5
|
+
describe('pluginPrompts', () => {
|
6
|
+
it('should generate plugin prompts with tools', () => {
|
7
|
+
const tools: Tool[] = [
|
8
|
+
{
|
9
|
+
name: 'tool1',
|
10
|
+
identifier: 'id1',
|
11
|
+
apis: [
|
12
|
+
{
|
13
|
+
name: 'api1',
|
14
|
+
desc: 'API 1',
|
15
|
+
},
|
16
|
+
],
|
17
|
+
},
|
18
|
+
];
|
19
|
+
|
20
|
+
const expected = `<plugins_info>
|
21
|
+
<tools>
|
22
|
+
<description>The tools you can use below</description>
|
23
|
+
<tool name="tool1" identifier="id1">
|
24
|
+
|
25
|
+
<api name="api1">API 1</api>
|
26
|
+
</tool>
|
27
|
+
</tools>
|
28
|
+
</plugins_info>`;
|
29
|
+
|
30
|
+
expect(pluginPrompts({ tools })).toBe(expected);
|
31
|
+
});
|
32
|
+
|
33
|
+
it('should generate plugin prompts without tools', () => {
|
34
|
+
const tools: Tool[] = [];
|
35
|
+
|
36
|
+
const expected = `<plugins_info>
|
37
|
+
|
38
|
+
</plugins_info>`;
|
39
|
+
|
40
|
+
expect(pluginPrompts({ tools })).toBe(expected);
|
41
|
+
});
|
42
|
+
});
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
2
|
+
|
3
|
+
import { Tool, apiPrompt, toolPrompt, toolsPrompts } from './tools';
|
4
|
+
|
5
|
+
describe('Prompt Generation Utils', () => {
|
6
|
+
// 测试 apiPrompt 函数
|
7
|
+
describe('apiPrompt', () => {
|
8
|
+
it('should generate correct api prompt', () => {
|
9
|
+
const api = {
|
10
|
+
name: 'testApi',
|
11
|
+
desc: 'Test API Description',
|
12
|
+
};
|
13
|
+
|
14
|
+
expect(apiPrompt(api)).toBe(`<api name="testApi">Test API Description</api>`);
|
15
|
+
});
|
16
|
+
});
|
17
|
+
|
18
|
+
// 测试 toolPrompt 函数
|
19
|
+
describe('toolPrompt', () => {
|
20
|
+
it('should generate tool prompt with system role', () => {
|
21
|
+
const tool: Tool = {
|
22
|
+
name: 'testTool',
|
23
|
+
identifier: 'test-id',
|
24
|
+
systemRole: 'Test System Role',
|
25
|
+
apis: [
|
26
|
+
{
|
27
|
+
name: 'api1',
|
28
|
+
desc: 'API 1 Description',
|
29
|
+
},
|
30
|
+
],
|
31
|
+
};
|
32
|
+
|
33
|
+
const expected = `<tool name="testTool" identifier="test-id">
|
34
|
+
<tool_instructions>Test System Role</tool_instructions>
|
35
|
+
<api name="api1">API 1 Description</api>
|
36
|
+
</tool>`;
|
37
|
+
|
38
|
+
expect(toolPrompt(tool)).toBe(expected);
|
39
|
+
});
|
40
|
+
|
41
|
+
it('should generate tool prompt without system role', () => {
|
42
|
+
const tool: Tool = {
|
43
|
+
name: 'testTool',
|
44
|
+
identifier: 'test-id',
|
45
|
+
apis: [
|
46
|
+
{
|
47
|
+
name: 'api1',
|
48
|
+
desc: 'API 1 Description',
|
49
|
+
},
|
50
|
+
],
|
51
|
+
};
|
52
|
+
|
53
|
+
const expected = `<tool name="testTool" identifier="test-id">
|
54
|
+
|
55
|
+
<api name="api1">API 1 Description</api>
|
56
|
+
</tool>`;
|
57
|
+
|
58
|
+
expect(toolPrompt(tool)).toBe(expected);
|
59
|
+
});
|
60
|
+
});
|
61
|
+
|
62
|
+
// 测试 toolsPrompts 函数
|
63
|
+
describe('toolsPrompts', () => {
|
64
|
+
it('should generate tools prompts with multiple tools', () => {
|
65
|
+
const tools: Tool[] = [
|
66
|
+
{
|
67
|
+
name: 'tool1',
|
68
|
+
identifier: 'id1',
|
69
|
+
apis: [
|
70
|
+
{
|
71
|
+
name: 'api1',
|
72
|
+
desc: 'API 1',
|
73
|
+
},
|
74
|
+
],
|
75
|
+
},
|
76
|
+
{
|
77
|
+
name: 'tool2',
|
78
|
+
identifier: 'id2',
|
79
|
+
apis: [
|
80
|
+
{
|
81
|
+
name: 'api2',
|
82
|
+
desc: 'API 2',
|
83
|
+
},
|
84
|
+
],
|
85
|
+
},
|
86
|
+
];
|
87
|
+
|
88
|
+
const expected = `<tools>
|
89
|
+
<description>The tools you can use below</description>
|
90
|
+
<tool name="tool1" identifier="id1">
|
91
|
+
|
92
|
+
<api name="api1">API 1</api>
|
93
|
+
</tool>
|
94
|
+
<tool name="tool2" identifier="id2">
|
95
|
+
|
96
|
+
<api name="api2">API 2</api>
|
97
|
+
</tool>
|
98
|
+
</tools>`;
|
99
|
+
|
100
|
+
expect(toolsPrompts(tools)).toBe(expected);
|
101
|
+
});
|
102
|
+
|
103
|
+
it('should generate tools prompts with empty tools array', () => {
|
104
|
+
const tools: Tool[] = [];
|
105
|
+
|
106
|
+
expect(toolsPrompts(tools)).toBe('');
|
107
|
+
});
|
108
|
+
});
|
109
|
+
});
|
@@ -0,0 +1,28 @@
|
|
1
|
+
export interface API {
|
2
|
+
desc: string;
|
3
|
+
name: string;
|
4
|
+
}
|
5
|
+
export interface Tool {
|
6
|
+
apis: API[];
|
7
|
+
identifier: string;
|
8
|
+
name?: string;
|
9
|
+
systemRole?: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
export const apiPrompt = (api: API) => `<api name="${api.name}">${api.desc}</api>`;
|
13
|
+
|
14
|
+
export const toolPrompt = (tool: Tool) =>
|
15
|
+
`<tool name="${tool.name}" identifier="${tool.identifier}">
|
16
|
+
${tool.systemRole ? `<tool_instructions>${tool.systemRole}</tool_instructions>` : ''}
|
17
|
+
${tool.apis.map((api) => apiPrompt(api)).join('\n')}
|
18
|
+
</tool>`;
|
19
|
+
|
20
|
+
export const toolsPrompts = (tools: Tool[]) => {
|
21
|
+
const hasTools = tools.length > 0;
|
22
|
+
if (!hasTools) return '';
|
23
|
+
|
24
|
+
return `<tools>
|
25
|
+
<description>The tools you can use below</description>
|
26
|
+
${tools.map((tool) => toolPrompt(tool)).join('\n')}
|
27
|
+
</tools>`;
|
28
|
+
};
|
@@ -4,13 +4,11 @@ exports[`ChatService > createAssistantMessage > with tools messages > work with
|
|
4
4
|
{
|
5
5
|
"messages": [
|
6
6
|
{
|
7
|
-
"content": "
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Whenever a description of an image is given, use lobe-image-designer to create the images and then summarize the prompts used to generate the images in plain text. If the user does not ask for a specific number of images, default to creating four captions to send to lobe-image-designer that are written to be as diverse as possible.
|
7
|
+
"content": "<plugins_info>
|
8
|
+
<tools>
|
9
|
+
<description>The tools you can use below</description>
|
10
|
+
<tool name="DALL·E 3" identifier="lobe-image-designer">
|
11
|
+
<tool_instructions>Whenever a description of an image is given, use lobe-image-designer to create the images and then summarize the prompts used to generate the images in plain text. If the user does not ask for a specific number of images, default to creating four captions to send to lobe-image-designer that are written to be as diverse as possible.
|
14
12
|
|
15
13
|
All captions sent to lobe-image-designer must abide by the following policies:
|
16
14
|
|
@@ -33,13 +31,11 @@ Whenever a description of an image is given, use lobe-image-designer to create t
|
|
33
31
|
- If any creative professional or studio is named, substitute the name with a description of their style that does not reference any specific people, or delete the reference if they are unknown. DO NOT refer to the artist or studio's style.
|
34
32
|
|
35
33
|
The prompt must intricately describe every part of the image in concrete, objective detail. THINK about what the end goal of the description is, and extrapolate that to what would make satisfying images.
|
36
|
-
All descriptions sent to lobe-image-designer should be a paragraph of text that is extremely descriptive and detailed. Each should be more than 3 sentences long
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
Create images from a text-only prompt.",
|
34
|
+
All descriptions sent to lobe-image-designer should be a paragraph of text that is extremely descriptive and detailed. Each should be more than 3 sentences long.</tool_instructions>
|
35
|
+
<api name="lobe-image-designer____text2image____builtin">Create images from a text-only prompt.</api>
|
36
|
+
</tool>
|
37
|
+
</tools>
|
38
|
+
</plugins_info>",
|
43
39
|
"role": "system",
|
44
40
|
},
|
45
41
|
{
|
@@ -296,19 +296,15 @@ describe('ChatService', () => {
|
|
296
296
|
],
|
297
297
|
messages: [
|
298
298
|
{
|
299
|
-
content:
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
#### seo____getData
|
310
|
-
|
311
|
-
Get data from users`,
|
299
|
+
content: `<plugins_info>
|
300
|
+
<tools>
|
301
|
+
<description>The tools you can use below</description>
|
302
|
+
<tool name="SEO" identifier="seo">
|
303
|
+
<tool_instructions>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.</tool_instructions>
|
304
|
+
<api name="seo____getData">Get data from users</api>
|
305
|
+
</tool>
|
306
|
+
</tools>
|
307
|
+
</plugins_info>`,
|
312
308
|
role: 'system',
|
313
309
|
},
|
314
310
|
{ content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n', role: 'user' },
|
@@ -405,19 +401,15 @@ Get data from users`,
|
|
405
401
|
{
|
406
402
|
content: `system
|
407
403
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
#### seo____getData
|
419
|
-
|
420
|
-
Get data from users`,
|
404
|
+
<plugins_info>
|
405
|
+
<tools>
|
406
|
+
<description>The tools you can use below</description>
|
407
|
+
<tool name="SEO" identifier="seo">
|
408
|
+
<tool_instructions>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.</tool_instructions>
|
409
|
+
<api name="seo____getData">Get data from users</api>
|
410
|
+
</tool>
|
411
|
+
</tools>
|
412
|
+
</plugins_info>`,
|
421
413
|
role: 'system',
|
422
414
|
},
|
423
415
|
{ content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n', role: 'user' },
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
2
2
|
import { uniqBy } from 'lodash-es';
|
3
3
|
|
4
|
+
import { pluginPrompts } from '@/prompts/plugin';
|
4
5
|
import { MetaData } from '@/types/meta';
|
5
6
|
import { ChatCompletionTool } from '@/types/openai/chat';
|
6
7
|
import { LobeToolMeta } from '@/types/tool/tool';
|
@@ -37,32 +38,26 @@ const enabledSystemRoles =
|
|
37
38
|
.installedPluginManifestList(s)
|
38
39
|
.concat(s.builtinTools.map((b) => b.manifest as LobeChatPluginManifest))
|
39
40
|
// 如果存在 enabledPlugins,那么只启用 enabledPlugins 中的插件
|
40
|
-
.filter((m) => tools.includes(m
|
41
|
+
.filter((m) => m && tools.includes(m.identifier))
|
41
42
|
.map((manifest) => {
|
42
|
-
if (!manifest) return '';
|
43
|
-
|
44
43
|
const meta = manifest.meta || {};
|
45
44
|
|
46
45
|
const title = pluginHelpers.getPluginTitle(meta) || manifest.identifier;
|
47
46
|
const systemRole = manifest.systemRole || pluginHelpers.getPluginDesc(meta);
|
48
47
|
|
49
|
-
|
50
|
-
.map((m) =>
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
})
|
60
|
-
.filter(Boolean);
|
48
|
+
return {
|
49
|
+
apis: manifest.api.map((m) => ({
|
50
|
+
desc: m.description,
|
51
|
+
name: genToolCallingName(manifest.identifier, m.name, manifest.type),
|
52
|
+
})),
|
53
|
+
identifier: manifest.identifier,
|
54
|
+
name: title,
|
55
|
+
systemRole,
|
56
|
+
};
|
57
|
+
});
|
61
58
|
|
62
59
|
if (toolsSystemRole.length > 0) {
|
63
|
-
return
|
64
|
-
.filter(Boolean)
|
65
|
-
.join('\n\n');
|
60
|
+
return pluginPrompts({ tools: toolsSystemRole });
|
66
61
|
}
|
67
62
|
|
68
63
|
return '';
|