写点什么

从 0 到 1:我们如何设计并落地一套基于 AI 平台的内部插件系统

作者:袋鼠云数栈
  • 2025-09-18
    浙江
  • 本文字数:5769 字

    阅读完需:约 19 分钟

从0到1:我们如何设计并落地一套基于AI平台的内部插件系统

本文旨在介绍一个内部 AI 平台插件系统的设计与实现。

该平台的核心目标是通过快速构建特定的 AI 应用,为内部不同部门提供效率提升。在初步阶段,我们实现了对接语雀文档的知识库,并将其植入到 AI 中,使其能够实现文档问答、匹配相似文档内容以及提供文档链接。一个典型的应用场景是构建一个内部技术方案文档知识库 AI 助手 。

我们通过将内部语雀文档知识库对接进来,导入特定目录下的文档。

然后,在 AI bot 界面配置该知识库。

发布 bot 后,用户即可开始进行知识库问答。

为了进一步增强 AI 在不同场景下的能力,我们探索了多种方案,并最终将目光锁定在插件上 。我们研究了市面上流行的平台,如 Coze 和 Dify 的插件设计 。我们发现 Coze 的插件设计非常出色,其插件本质上就是 HTTP 接口 。这意味着,只要拥有一个核心的 HTTP 接口,就可以将其作为一个插件工具进行对接 。该平台支持界面化配置,最终将插件植入到 AI 中,让 AI 能够调用内部插件工具,实现问答能力的增强。

我们的目标是建立一个平台,让用户可以直接通过界面配置一个 HTTP 搜索接口,将其转换为插件工具,无需自定义上传 。在插件编辑界面,我们还提供了调试该插件的方法。构建好插件后,只需在 AI bot 配置界面选择插件,并编写提示词来指定何时调用该插件工具,即可完成集成。

总结来说,我们的设计有以下几个核心特点:

  • 支持界面配置,无需修改代码。

  • 直接对接 HTTP 接口。

  • 实现插件工具快速集成到 AI。

实战案例演示:联网搜索插件

下面以一个联网搜索插件为例,演示如何构建并配置一个能够实现联网搜索功能的插件。

步骤一:配置插件工具

首先,我们需要一个具备联网搜索能力的接口。这里我们使用了 serper.dev 提供的搜索接口。

其对应的 curl 格式如下:

curl --location 'https://google.serper.dev/search' \--header 'X-API-KEY: 4dxxxxxxxxxxxxe5c7269' \--header 'Content-Type: application/json' \--data '{"q":"apple inc","location":"China","gl":"cn","hl":"zh-cn","num":20}'
复制代码

目前平台提供还额外提供了快速对接接口的能力,平台可快速的将 curl 转换为一个插件的工具,如下我们去复制到界面中,首先我们点击导入插件:

将插件名称以及 curl 内容复制进来点击确定:

此时你就获取到了一个搜索插件:

点击进入即可看到该插件的工具列表(你可以理解一个 curl 就是一个插件工具,所以我们初步导入就首先了导入一个工具):

再次点击工具名称,我们进入到具体工具的配置栏目,配置栏目左边就是工具的信息包含对接的 http 接口的请求方式、参数等等,同时还包含有一组参数配置:

我们初步来对参数配置进行调整,其中的 q 字段是关键的搜索问题内容描述,如果我们希望 AI 去自主的去提出问题,那么我们需要将其默认值设置为空,其他如果是带有默认值的默认有值即可,我们也可以对参数描述进行初步的介绍。

此时我们回到工具列表,编辑修改名称为聚合搜索:

至此我们初步的插件工具就配置完成了。

步骤二:测试插件工具

我们重新进入到工具中,点击左上角的“试运行”按钮:

模拟 AI 输入要询问的问题,点击“测试运行” 。如果接口调用成功,右侧会显示响应值。

步骤三:集成 AI 实现插件工具调用

回到工具列表,启用该工具并发布插件。

然后,我们回到 AI bot 的编辑配置界面,添加相应的插件,并在系统提示词中编写调用的场景。


保存并发布后,进入 AI 问答界面,输入一段需要联网搜索的内容。

回车后,AI 会结合联网搜索工具完成对话,并将接口返回的内容组织成最终的回答。

至此我们就初步完成了插件的配置与集成。

实现思路:基于 function call 实现 HTTP 工具调用

Function calling 是大语言模型(LLM)与外部系统或工具交互的核心机制,它允许 AI 模型在推理过程中动态选择并调用预定义的工具方法,从而扩展模型的能力边界(如实时搜索、数据库查询、API 调用等)。其核心思想是将工具方法封装为标准化描述,由 LLM 在对话过程中根据上下文决定是否调用、如何调用,并解析调用结果继续生成回复。

这里首先举一个集成了本地 tools 方法 sum 求和以及求平方根的例子,比如我们有一个 sum 求和工具以及一个求平方根的工具,问题是 1+2 等于多少、指定数字的平方根是多少,此时作为中间层如何和 chat 模型进行交互呢?


在我们的内部 AI 平台中,我们底座 LLM 框架是 langchAIn4j 框架,在 LLM 框架中提供了可扩展的 toolexecutor 接口,我们基于此自己执行了能够完成 http 请求的 toolexecutor 实现。

下面以 serper.dev 的搜索接口为例,说明如何对接 AI 实现工具调用。

第一步:工具描述生成(JSON Schema)

在系统加载插件后会生成如下结构的 ToolSpecification(JSON 格式):

{"name": "searchWeb", "description": "使用 Serper API 搜索网络","parameters": {"type": "OBJECT",    "properties": {"query": {"type": "STRING","description": "搜索关键词"      }, "country": {  "type": "STRING",    "description": "国家代码(如:'cn')", "default": "cn"      },      "language": { "type": "STRING",      "description": "语言代码(如:'zh-CN')",   "default": "zh-CN"     }    },   "required": ["query"]  }}
复制代码

该描述会在对话开始时发送给 LLM,告知其有一个名为 searchWeb 的工具可用于网络搜索。

第二步:用户提问与 LLM 决策

当用户提问“最近有什么关于人工智能的重大新闻?”,LLM 判断需要调用搜索工具,并返回如下 function call 请求 :

{  "name": "searchWeb", "arguments": "{\"query\": \"人工智能 重大新闻 2025\", \"country\": \"cn\", \"language\": \"zh-CN\"}"}
复制代码

第三步:平台执行工具并返回结果

平台接收到上述请求后,通过 ToolExecutor(我们自定义实现的 httpexecutor)执行 searchWeb 方法,向 Serper API 发送请求,获取搜索结果(JSON 格式),并将其返回给 LLM :

{  "role": "tool", "name": "searchWeb","content": "{\"searchResults\": [{\"title\": \"2025年AI技术突破:...\",\"link\": \"https://example.com/news1\"},...]}"}
复制代码

第四步:LLM 生成最终回复

LLM 根据搜索结果生成最终回复:“根据最新搜索,2025 年人工智能领域有以下重大进展:...”

我们内部首先通过自定义 IHttpPlugin 接口统一管理 HTTP 工具插件,再利用 langchAIn4j 的 ToolSpecification 和 ToolExecutor 机制将 HTTP 接口转换为 AI 可识别的工具方法,最终实现自动化的 function call 流程。

那实际上与 AI 交互,如何让 AI 自行多次使用插件工具呢?

在 LangChain4j 中,我们有一个循环来决定是否继续与 AI 工具交互 。如果没有进一步的 function call 请求,AI 的响应内容就会返回给用户界面。

核心插件组件设计实现

为了对接 LangChain4j 的 tools 机制,我们主要实现了两个部分。

第一部分:HttpToolExecutor 的实现

在 langchAIn4j 这个 llm 框架内部给我们提供了一个接口,我们可以基于这个接口来去扩展一个 httpToolExecutor:

public interface ToolExecutor {// ToolExecutionRequest 则是langchAIn4j给我们将function call request封装成了一个类    String execute(ToolExecutionRequest var1,Object var2);}
复制代码

我们设计了一个 HttpToolExecutor 来实现这个接口,在 execute 方法内部我们去做了基于大模型 function calling 的结果中的参数去选择相应的 http 接口然后封装参数去进行请求,最终拿到结果。

第二部分:ToolSpecification 的封装

为了统一管理 HTTP 插件,我们设计了一个 httpplugin 接口:

/** * @description  提供接口后续可自定义扩展httpplugin* @author changlu * @date 2025/8/23 17:19 */public interface IHttpPlugin {    /**       * 初始化必备参数配置       * @param props Properties         * @return void       */    void init(Properties props);    /**        * 获取HttpPlugin实体类      * @param           * @return HttpPlugin       */    HttpPlugin getHttpPlugin();    /**        * 构建plugin name      * @param       * @return String        */        String getPluginName();    /**        * 快速构建可提供注入到AIService中的tools封装        * @return Map<ToolSpecification,ToolExecutor>       */    default Map<ToolSpecification, ToolExecutor> buildHttpTools() {       // 校验特定参数是否传递          doCheckProps();        // 获取自定义HttpPlugin的参数配置               HttpPlugin httpPlugin = this.getHttpPlugin();               if (httpPlugin == null) {                   throw new AIServiceException(String.format(ErrorMsgConstant.PLUGIN_METHOD_NO_IMPL,        this.getClass().getName(),        "getHttpPlugin()"));              }                return HttpPluginFactory.buildHttpPluginTools(httpPlugin);           }    /**       * check是否已填充必填参数,如果没有填写则会直接报错提示         * @param        * @return void       */       void doCheckProps();}
复制代码

同时还设计构成一组插件工具的实体类结构设计:

@Data@Builderpublic class HttpPlugin {    // 基础服务名称    private String baseUrl;    // 公共请求头    private Map<String, String> staticHeaders;    // 包含多个插件方法    List<HttpPluginMethod> pluginMethods;}
复制代码

其中在 IHttpPlugin 中的 buildHttpTools 方法能够将我们的这个 HttpPlugin 转换为 ToolSpecification 以及 ToolExecutor 方便后续对接到 langchAIn4j 的 tools 工具中调用(其中一个 ToolSpecification 就是一个工具的方法参数 json 格式描述的抽象类实现)。

对接方式如下,当我们构建好一个插件后,只需要去转换为一组 ToolSpecification & ToolExecutor,然后按照如下方式集成即可:

业务插件系统模块实现

业务插件系统库表设计

在底层核心功能实现后,我们开始进行应用层的实现 。我们基于核心包中的HttpPlugin、HttpPluginMethod和 HttpToolParameter,设计了三张数据库表来存储插件信息。

  • 方法表:管理插件提供的具体工具方法。

  • 参数表:存储方法参数的详细配置。

  • 插件表:存储插件基本信息,包括名称、基础 URL、描述等。

我们实现了一个工具类,能够将数据库中加载的插件信息转换为我们核心模块的 HttpPlugin 实体类。

因此,我们的实现过程可以理解为:加载数据库插件工具信息 -> 自定义的 HttpPlugin -> Map<ToolSpecification, ToolExecutor>

CURL 解析器实现

对于插件配置界面,提供用户可创建、编辑的方式还不够,我们希望能够有更快的对接方式,让用户将 http 接口快速对接进来,我们还设计了一个基于 curl 的解析器并实现将解析后的内容转换为一个插件工具(和插件业务模块融合对接起来),你可以理解用户只需要如下在浏览器中将接口复制 curl :

对接方式就是我们一开始案例演示中的导入 curl 实现:

针对于该 curl 解析器,我们初步实现了对于 curl 的解析以及转换插件的实现:

CurlParser 为 curl 解析器,用来将 curl 解析为一个实现类 CurlParseResult。CurlParser 的解析接口如下:

public CurlParseResult parse(String curlCommand) {   ...}
复制代码

CurlParseResult 解析结果类实现如下:

@Datapublic class CurlParseResult {   private String url;   private String method = "GET";   private Map<String, String> headers = new HashMap<>(); private String data;private String user;   private List<FormData> formData = new ArrayList<>(); private String cookie;   private String referer;   private String userAgent;   private boolean followRedirects = false;  private boolean insecure = false;    private String proxy;   // 添加查询参数映射 private Map<String, String> queryParams = new HashMap<>(); ...}
复制代码

解析出来之后,我们会将 CurlParseResult 去转换为我们的核心包 HttpPlugin 的核心能力实现提供出去,这块就由 CurlToHttpPluginConverter 转换器来实现,该三个核心实现类我们作为 dt-AI-core 公共包来提供出去。CurlToHttpPluginConverter 转换器的实现接口方法为:

public class CurlToHttpPluginConverter {    public HttpPlugin convert(CurlParseResult curl) {        ...    }}
复制代码

由于这三个核心类具备能够将 curl 转换为一个 HttpPlugin 插件实体类,由于我们是作为 core 包的公共能力提供出去,我们则会将 HttpPlugin 的插件实体类转换为能够进行 db 存储的 pojo 来进行最终存储到 db:

最终完成了解析 -> 导入的功能,至此我们的插件系统初步完成。

总结与未来展望

借助这套核心插件系统模块和业务层的实现,我们能够快速对接 HTTP 接口,并增强 AI 的能力 。这个初步的插件系统是参考了字节的 Coze 插件设计并结合实际场景落地的 。选择 HTTP 接口作为插件工具是因为其广泛性,大多数 web 系统都提供了 HTTP 接口,能够支持用户快速对接。

在整个模块实现过程中,我利用 AI 来完成一些简单、边界的代码编写,而我则专注于顶层的接口方法和抽象类的设计,并对 AI 生成的代码进行审查和校对,最终独立完成了整个插件系统的设计 。目前,当前的插件系统已初步完成业务实现 。未来,我们计划推出插件市场,提供更多内置插件,为更多不同的场景赋能,实现更多内部 AI 文本交互场景的落地。

本文为内部 AI 平台插件系统的技术分享,希望能给你带来一些启发与帮助,如有问题,请指正。基于企业需求,我们推出了一款面向企业级场景的 AI 应用开发平台,聚焦私有化部署与业务场景落地,提供安全可控、灵活扩展的 AI 应用构建能力。平台集成可视化开发、多模型支持、智能工作流编排等核心能力,帮助企业快速构建和交付 AI 应用,实现 AI 与业务流程的深度融合,加速智能化转型。

如有需求可扫描微信二维码咨询官方小助手了解详情~


用户头像

还未添加个人签名 2021-05-06 加入

还未添加个人简介

评论

发布
暂无评论
从0到1:我们如何设计并落地一套基于AI平台的内部插件系统_袋鼠云数栈_InfoQ写作社区