---
title: LobeChat 插件开发指南
description: 学习如何在 LobeChat 中添加和使用自定义插件,包括创建插件项目、在角色设置中添加本地插件、测试插件功能以及插件开发流程和部署。
tags:
- LobeChat
- 插件开发
- 自定义插件
- 插件部署
- 插件发布
- 插件UI
- 插件SDK
---
# 插件开发指南
## 插件构成
一个 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 中添加和使用一个自定义插件。
### 创建并启动插件项目
你需要先在本地创建一个插件项目,可以使用我们准备好的模板 [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` 时,说明插件服务已经在本地启动成功。
### 在 LobeChat 角色设置中添加本地插件
接下来进入到 LobeChat 中,创建一个新的助手,并进入它的会话设置页:
点击插件列表右侧的 添加 按钮,打开自定义插件添加弹窗:
在 **插件描述文件 Url** 地址 中填入 `http://localhost:3400/manifest-dev.json` ,这是我们本地启动的插件描述清单地址。
此时,你应该可以看到看到插件的标识符一栏已经被自动识别为 `chat-plugin-template`。接下来你需要填写剩下的表单字段(只有标题必填),然后点击 保存 按钮,即可完成自定义插件添加。
完成添加后,在插件列表中就能看到刚刚添加的插件,如果需要修改插件的配置,可以点击最右侧的 设置 按钮进行修改。
### 会话测试插件功能
接来下我们需要测试这个插件的功能是否正常。
点击 返回 按钮回到会话区,然后向助手发送消息:「我应该穿什么? 」此时助手将会尝试向你询问,了解你的性别与当前的心情。
当回答完毕后,助手将会发起插件的调用,根据你的性别、心情,从服务端获取推荐的衣服数据,并推送给你。最后基于这些信息做一轮文本总结。
当完成这些操作后,你已经了解了添加自定义插件,并在 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 默认的插件网关是云端服务,而自定义插件的请求需要发给本地启动的服务,远端调用本地地址,一般调用不通。gateway 字段解决了该问题。通过在 manifest 中指定 gateway,LobeChat 将会向该地址发送插件请求,本地的网关地址将会调度请求到本地的插件服务。发布到线上的插件可以不用指定该字段。
5. `version`:这是插件的版本号,现阶段暂时没有作用;
在实际开发中,你可以根据自己的需求,修改插件的描述清单,声明想要实现的功能。 关于 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 作为开发框架。你可以使用任何你熟悉的开发框架与开发语言,只要能够实现 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]。
模板中的 clothes 接口实现如下:
```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));
};
```
其中 `maniClothes` 和 `womanClothes` 是 mock 数据,在实际场景中,可以替换为数据库查询等。
#### Plugin Gateway
由于 LobeChat 默认的插件网关是云端服务 `/api/plugins`,云端服务通过 manifest 上的 `api.url` 地址发送请求,以解决跨域问题。
针对自定义插件,插件请求需要发送给本地服务, 因此通过在 manifest 中指定网关 ([http://localhost:3400/api/gateway),LobeChat](http://localhost:3400/api/gateway\),LobeChat) 将会直接请求该地址,然后只需要在该地址下创建对应的网关即可。
```ts
import { createLobeChatPluginGateway } from '@lobehub/chat-plugins-gateway';
export const config = {
runtime: 'edge',
};
export default createLobeChatPluginGateway();
```
[`@lobehub/chat-plugins-gateway`](https://github.com/lobehub/chat-plugins-gateway) 包含了 LobeChat 中插件网关的[实现](https://github.com/lobehub/lobe-chat/blob/main/src/pages/api/plugins.api.ts),你可以直接使用该包创建网关,进而让 LobeChat 访问到本地的插件服务。
### 插件 UI 界面
自定义插件的 UI 界面是一个可选项。例如 官方插件 [「🧩 / 🕸 网页内容提取」](https://github.com/lobehub/chat-plugin-web-crawler),没有实现相应的用户界面。
如果你希望在插件消息中展示更加丰富的信息,或者包含一些富交互操作,你可以为插件定制一个用户界面。例如下图则为[「搜索引擎」](https://github.com/lobehub/chat-plugin-search-engine)插件的用户界面。
#### 插件 UI 界面实现
LobeChat 通过 `iframe` 实现插件 ui 的加载,使用 `postMessage` 实现主体与插件的通信。因此, 插件 UI 的实现方式与普通的网页开发一致,你可以使用任何你熟悉的前端框架与开发语言。
在我们提供的模板中使用了 React + Next.js + [antd](https://ant.design/) 作为前端界面框架,你可以在 [`src/pages/index.tsx`](https://github.com/lobehub/chat-plugin-template/blob/main/src/pages/index.tsx) 中找到用户界面的实现。
其中关于插件通信,我们在 [`@lobehub/chat-plugin-sdk`](https://github.com/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();
useEffect(() => {
// 从 LobeChat 获取当前插件的消息
fetchPluginMessage().then((e: ResponseData) => {
setData(e);
});
}, []);
return <>...>;
});
export default Render;
```
## 插件部署与发布
当你完成插件的开发后,你可以使用你习惯的方式进行插件的部署。例如使用 vercel ,或者打包成 docker 发布等等。
如果你希望插件被更多人使用,欢迎将你的插件 [提交上架](https://github.com/lobehub/lobe-chat-plugins) 到插件市场。
[![][submit-plugin-shield]][submit-plugin-url]
### 插件 Shield
[](https://github.com/lobehub/lobe-chat-plugins)
```markdown
[](https://github.com/lobehub/lobe-chat-plugins)
```
## 链接
- **📘 Pluging SDK 文档**: [https://chat-plugin-sdk.lobehub.com](https://chat-plugin-sdk.lobehub.com)
- **🚀 chat-plugin-template**: [https://github.com/lobehub/chat-plugin-template](https://github.com/lobehub/chat-plugin-template)
- **🧩 chat-plugin-sdk**: [https://github.com/lobehub/chat-plugin-sdk](https://github.com/lobehub/chat-plugin-sdk)
- **🚪 chat-plugin-gateway**: [https://github.com/lobehub/chat-plugins-gateway](https://github.com/lobehub/chat-plugins-gateway)
- **🏪 lobe-chat-plugins**: [https://github.com/lobehub/lobe-chat-plugins](https://github.com/lobehub/lobe-chat-plugins)
[fetch-plugin-message-url]: https://github.com/lobehub/chat-plugin-template
[lobe-chat-plugin-template-url]: https://github.com/lobehub/chat-plugin-template
[manifest-docs-url]: https://chat-plugin-sdk.lobehub.com/guides/plugin-manifest
[plugin-error-type-url]: https://github.com/lobehub/chat-plugin-template
[submit-plugin-shield]: https://img.shields.io/badge/🧩/🏪_submit_plugin-%E2%86%92-95f3d9?labelColor=black&style=for-the-badge
[submit-plugin-url]: https://github.com/lobehub/lobe-chat-plugins