Skip to content

Commit

Permalink
📝 docs: 添加插件开发中文文档
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Sep 3, 2023
1 parent 7e69398 commit 7ec0050
Showing 1 changed file with 241 additions and 0 deletions.
241 changes: 241 additions & 0 deletions docs/plugin-development.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
# LobeChat 插件开发

## 插件构成

一个 LobeChat 的插件由以下几个部分组成:

1. **插件索引**:用于展示插件的基本信息,包括插件名称、描述、作者、版本、插件描述清单的链接,官方的插件索引地址:[lobe-chat-plugins](https://github.com/lobehub/lobe-chat-plugins)。若想上架插件到官方插件市场,需要[提交 PR](https://github.com/lobehub/lobe-chat-plugins/pulls) 到该仓库;
2. **插件描述清单 (manifest)**:用于描述插件的功能实现,包含了插件的服务端描述、前端展示信息、版本号等。关于 manifest 的详细介绍,详见 [manifest][manifest-docs-url]
3. **插件服务**:用于实现插件描述清单中所描述的服务端和前端模块,分别如下:
- **服务端**:需要实现 manifest 中描述的 `api` 部分的接口能力;
- **前端 UI**(可选):需要实现 manifest 中描述的 `ui` 部分的界面,该界面将会在插件消息中透出,进而实现比文本更加丰富地信息展示方式。

## 自定义插件流程

插件开发需要将插件集成进 LobeChat 中,因此本部分将会介绍如何在 LobeChat 中添加和使用一个自定义插件。

### 1. 创建并启动插件项目

你需要先在本地创建一个插件项目,可以使用我们准备好的 [lobe-chat-plugin-template][lobe-chat-plugin-template-url] 模板;

```bash
$ git clone https://github.com/lobehub/chat-plugin-template.git
$ cd chat-plugin-template
$ npm i
$ npm run dev
```

当出现 `ready started server on 0.0.0.0:3400, url: http://localhost:3400` 时,说明插件服务已经在本地启动成功。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265259526-9ef25272-4312-429b-93bc-a95515727ed3.png)

### 2. 在 LobeChat 角色设置中添加本地插件

接下来进入到 LobeChat 中,创建一个新的助手,并进入它的会话设置页:

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265259643-1a9cc34a-76f3-4ccf-928b-129654670efd.png)

点击「插件列表」右侧的「添加」按钮,打开自定义插件添加弹窗:

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265259748-2ef6a244-39bb-483c-b359-f156ffcbe1a4.png)

在 「插件描述文件 Url 地址」中填入 `http://localhost:3400/manifest-dev.json` ,这是我们本地启动的插件描述清单地址。

此时,你应该可以看到看到插件的标识符一栏已经被自动识别为 `chat-plugin-template`。接下来你需要填写剩下的表单字段(只有标题必填),然后点击「保存」按钮,即可完成自定义插件添加。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265259964-59f4906d-ae2e-4ec0-8b43-db36871d0869.png)

完成添加后,即可在插件列表中看到刚刚添加的插件,如果需要修改插件的配置,可以点击「设置」按钮进行修改。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265260093-a0363c74-0b5b-48dd-b103-2db6b4a8262e.png)

### 3. 会话测试插件功能

接来下我们需要测试下这个自定义插件的功能是否正常。

点击「返回」按钮回到会话区,然后向助手发送消息:「我应该穿什么? 」此时助手将会尝试向你询问,了解你的性别与当前的心情。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265260291-f0aa0e7c-0ffb-486c-a834-08e73d49896f.png)

当回答完毕后,助手将会发起插件的调用,根据你的性别、心情,从服务端获取推荐的衣服数据,并推送给你。最后基于这些信息做一轮文本总结。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265260461-c22ae797-2809-464b-96fc-d0c020f4807b.png)

当完成这些操作后,你已经了解了添加自定义插件,并在 LobeChat 中使用的基础流程。

## 本地插件开发

在上述流程中,我们已经了解插件的添加和使用的方式。由于使用不影响到插件本身的开发,因此接下来重点介绍自定义插件开发的过程。

### manifest

manifest 聚合了插件功能如何实现的所有信息。一个插件核心的描述信息为 `api``ui`,它描述了插件的服务端接口能力与前端渲染的界面地址。

以我们提供的模板为例,介绍 manifest:

```json
{
"api": [
{
"url": "http://localhost:3400/api/clothes",
"name": "recommendClothes",
"description": "根据用户的心情,给用户推荐他有的衣服",
"parameters": {
"properties": {
"mood": {
"description": "用户当前的心情,可选值有:开心(happy), 难过(sad),生气 (anger),害怕(fear),惊喜( surprise),厌恶 (disgust)",
"enums": ["happy", "sad", "anger", "fear", "surprise", "disgust"],
"type": "string"
},
"gender": {
"type": "string",
"enum": ["man", "woman"],
"description": "对话用户的性别,需要询问用户后才知道这个信息"
}
},
"required": ["mood", "gender"],
"type": "object"
}
}
],
"gateway": "http://localhost:3400/api/gateway",
"identifier": "chat-plugin-template",
"ui": {
"url": "http://localhost:3400",
"height": 200
},
"version": "1"
}
```

在这份 manifest 中,主要包含了以下几个部分:

1. `identifier`:这是插件的唯一标识符,用来区分不同的插件,这个字段需要全局唯一。
2. `api`:这是一个数组,包含了插件所提供的所有 API 接口信息。每个接口都包含了url、name、description和 parameters 字段。其中 `description``parameters` 两个字段,将会作为 [Function Call](https://sspai.com/post/81986)`functions` 参数发送给 gpt, parameters 需要符合 [JSON Schema](https://json-schema.org/) 规范。 在这个例子中,api 接口名为 `recommendClothes` ,这个接口的功能是根据用户的心情和性别来推荐衣服。接口的参数包括用户的心情和性别,这两个参数都是必需的。
3. `ui`:这个字段包含了插件的用户界面信息,指明了 LobeChat 从哪个地址加载插件的前端界面。由于 LobeChat 插件界面加载是基于 iframe 实现的,因此可以按需指定插件界面的高度、宽度。
4. `gateway`:这个字段指定了 LobeChat 查询 api 接口的网关。LobeChat 默认的插件网关是云端服务,而自定义插件的请求需要发送给本地服务的,因此通过在 manifest 中指定网关,LobeChat 将会直接请求这个地址,进而访问到本地的插件服务。
5. `version`:这是插件的版本号,现阶段暂时没有作用,非必填项;

其中,`api``ui`是这份 manifest 的核心字段。`api`字段定义了插件的功能,`ui`字段定义了插件的用户界面。这两个字段是插件能够正常工作的关键。

关于 manifest 的详细介绍,参见:[manifest][manifest-docs-url]

接下来,你可以根据自己的需求,修改插件的描述清单,声明自己想要实现的功能。

### 项目结构

[lobe-chat-plugin-template][lobe-chat-plugin-template-url] 这个模板项目使用了 Next.js 作为开发框架,它的核心目录结构如下:

```
➜ chat-plugin-template
.
├── public
│ └── manifest-dev.json # 描述清单文件
├── src
│ └── pages
│ │ ├── api # nextjs 服务端文件夹
│ │ │ ├── clothes.ts # recommendClothes 接口实现
│ │ │ └── gateway.ts # 本地插件代理网关
│ │ └── index.tsx # 前端展示界面
```

当然,模板使用 Next.js 作为开发框架,只是因为我们熟悉 Next.js,并且开发方便。你可以使用任何你熟悉的开发框架与开发语言,只要能够实现 manifest 中描述的功能即可。

同时也欢迎贡献更多框架与语言的插件模板。

### 服务端

服务端实现没有太多需要讲解的,只需要实现 manifest 中描述的 api 接口即可。在模板中,我们使用了 vercel 的 [Edge Runtime](https://nextjs.org/docs/pages/api-reference/edge) 作为服务,免去运维成本。

#### api 实现

针对 Edge Runtime ,我们在 `@lobehub/chat-plugin-sdk` 提供了 `createErrorResponse` 方法,用于快速返回错误响应。目前提供的错误类型详见:[PluginErrorType][plugin-error-type-url]

```ts
export default async (req: Request) => {
if (req.method !== 'POST') return createErrorResponse(PluginErrorType.MethodNotAllowed);

const { gender, mood } = (await req.json()) as RequestData;

const clothes = gender === 'man' ? manClothes : womanClothes;

const result: ResponseData = {
clothes: clothes[mood] || [],
mood,
today: Date.now(),
};

return new Response(JSON.stringify(result));
};
```

#### gateway

由于 LobeChat 默认的插件网关是云端服务( <https://chat.lobehub.com/api/plugins> ),云端服务通过 manifest 上的 api 地址发送请求,以解决跨域问题。

而针对自定义插件,插件的请求需要发送给本地服务的, 因此通过在 manifest 中指定网关 ( <http://localhost:3400/api/gateway> ),LobeChat 将会直接请求该地址。而我们只需要在该地址创建一个网关代理,将请求转发到本地服务即可。

```ts
import { createLobeChatPluginGateway } from '@lobehub/chat-plugins-gateway';

export const config = {
runtime: 'edge',
};

export default async createLobeChatPluginGateway();
```

`@lobehub/chat-plugins-gateway` 包含了 LobeChat 中插件网关的[实现](https://github.com/lobehub/lobe-chat/blob/main/src/pages/api/plugins.api.ts),你可以直接使用该包创建网关,进而让 LobeChat 访问到本地的插件服务。

### 用户界面

对于一个插件而言,用户界面是一个可选项。例如 [「网页内容提取」插件](https://github.com/lobehub/chat-plugin-web-crawler),就没有实现相应的用户界面。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265263241-0e765fdc-3463-4c36-a398-aef177a30df9.png)

如果你希望在插件消息中展示更加丰富的信息,或者包含一些富交互,可以为插件定义一个用户界面。例如下图,则为搜索引擎插件的用户界面。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265263427-9bdc03d5-aa61-4f62-a2ce-88683f3308d8.png)

#### 插件 UI 界面实现

LobeChat 通过 `iframe` + `postMessage` 实现插件 ui 的加载与通信。因此, 插件 UI 的实现方式与普通的网页开发一致,你可以使用任何你熟悉的前端框架与开发语言。

![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/265263653-4ea87abc-249a-49f3-a241-7ed93ddb1ddf.png)

在我们提供的模板中,我们使用了 React + Next.js + antd 作为前端界面框架,你可以在 `src/pages/index.tsx` 中找到用户界面的实现。

其中关于插件通信,我们提供了 `@lobehub/chat-plugin-sdk` 包,用于简化插件与 LobeChat 的通信。你可以通过 `fetchPluginMessage` 方法主动向 LobeChat 获取当前消息的数据。关于该方法的详细介绍,参见:[fetchPluginMessage][fetch-plugin-message-url]

```tsx
import { fetchPluginMessage } from '@lobehub/chat-plugin-sdk';
import { memo, useEffect, useState } from 'react';

import { ResponseData } from '@/type';

const Render = memo(() => {
const [data, setData] = useState<ResponseData>();

useEffect(() => {
// 从 LobeChat 获取当前插件的消息
fetchPluginMessage().then((e: ResponseData) => {
setData(e);
});
}, []);

return <>...</>;
});

export default Render;
```

## 插件部署与发布

当你完成插件的开发后,你可以使用你习惯的方式进行插件的部署。例如使用 vercel ,或者打包成 docker 发布等等。

如果你希望插件被更多人使用,欢迎将你的插件 [提交上架](https://github.com/lobehub/lobe-chat-plugins) 到插件市场。

[manifest-docs-url]: https://github.com/lobehub/chat-plugin-sdk/tree/master/docs/manifest.zh-CN.md
[lobe-chat-plugin-template-url]: https://github.com/lobehub/chat-plugin-template
[plugin-error-type-url]: https://github.com/lobehub/chat-plugin-template
[fetch-plugin-message-url]: https://github.com/lobehub/chat-plugin-template

0 comments on commit 7ec0050

Please sign in to comment.