news 2026/9/16 20:38:13

Higress ai-search 插件深度解析:为 LLM 接入 Google/Bing/Arxiv/Elasticsearch/夸克搜索引擎增强回答能力

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Higress ai-search 插件深度解析:为 LLM 接入 Google/Bing/Arxiv/Elasticsearch/夸克搜索引擎增强回答能力

Higress ai-search 插件深度解析:为 LLM 接入 Google/Bing/Arxiv/Elasticsearch/夸克搜索引擎增强回答能力

【免费下载链接】higress🤖 AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress

Higress 的ai-search插件通过在请求转发到 LLM 之前并行调用多个搜索引擎,把实时搜索结果注入到提示模板中,并可自动在最终回答里追加引用来源。本文基于插件的官方文档 README.md 与源码实现(main.go、engine/types.go 及各引擎实现),完整讲解其运行属性、全部配置字段、搜索重写机制与各类配置示例,帮助你在 Higress 网关上为 DeepSeek 等模型构建带联网检索、论文检索或私有知识库检索能力的 AI 服务。

一、功能定位与运行机制

插件的核心逻辑是:拦截 OpenAI 兼容格式的聊天请求,从messages中取出最后一条 user 消息作为查询词,向配置的搜索引擎发起检索,将结果格式化后填充进提示模板并替换原请求体,再放行到上游 LLM;响应阶段则根据配置决定是否把引用来源(标题+链接列表)插入回答内容中。

关键运行属性:

属性说明
执行阶段默认阶段在转发到 LLM 供应商之前执行,保证能先改写 prompt
执行优先级460优先级数值越大越先执行,需排在请求改写类插件之前

从源码结构看,插件通过 main.go 的init()注册了完整的请求/响应处理链:

  • onHttpRequestHeaders:校验content-type是否为 JSON(非 JSON 直接跳过),移除Accept-EncodingContent-Length头并设置 100MB 的请求体缓冲上限;
  • onHttpRequestBody:提取用户查询、执行搜索(或先执行搜索重写)、替换请求体;
  • onHttpResponseHeaders/onStreamingResponseBody/onHttpResponseBody:仅在开启needReference时介入,负责将引用来源分别插入流式 SSE 响应或非流式响应。

一个值得注意的设计是失败快速降级:当搜索重写调用 LLM 失败、或所有引擎都没有返回结果时,插件会记录日志并直接ResumeHttpRequest放行原请求,即"搜索失败不阻塞对话"。

二、插件配置字段详解

2.1 顶层配置字段

名称数据类型填写要求默认值描述
defaultEnablebool选填true插件功能默认是否开启。设置为 false 时,仅当请求中包含web_search_options字段时才启用插件功能
needReferencebool选填false是否在回答中添加引用来源
referenceFormatstring选填"**References:**\n%s"引用内容格式,必须包含%s占位符,配置不合法会在启动时直接报错
referenceLocationstring选填"head"引用位置:"head"在回答开头,"tail"在回答结尾
defaultLangstring选填-默认搜索语言代码(如 zh-CN/en-US)
promptTemplatestring选填内置模板提示模板,必须包含{search_results}{question}占位符,缺少任一占位符配置校验会失败
searchFromarray of object必填-搜索引擎配置列表,至少配置一个引擎,否则配置解析报错no available search engine found
searchRewriteobject选填-搜索重写配置,用于使用 LLM 服务优化搜索查询

关于promptTemplate,如果不开启needReference,内置模板只要求模型"综合多个网页回答但不给出网页引用来源";如果开启needReference,内置模板会额外要求模型在正文对应位置以[X]编号形式引用(可多引用如[3][5]),并要求区分列举类、创作类、客观问答类问题分别采用不同的回答策略。两种内置模板都包含{cur_date}占位符,由插件在运行时填入北京时间当日日期(格式:2006年1月2日),可用于增强时效性问答的准确性。

2.2 搜索引擎通用配置

searchFrom数组中每个引擎项共享以下字段:

名称数据类型填写要求默认值描述
typestring必填-引擎类型(google/bing/arxiv/elasticsearch/quark)
serviceNamestring必填-后端服务名称(Higress 中的服务来源 FQDN 集群)
servicePortnumber必填-后端服务端口
apiKeystring必填*-搜索引擎 API 密钥(Arxiv 免费接口不需要)
countnumber选填10单次搜索返回结果数量
startnumber选填0搜索结果偏移量(从第 start+1 条结果开始返回)
timeoutMillisecondnumber选填5000API 调用超时时间(毫秒)
optionArgsmap选填-搜索引擎特定参数(key-value 格式,直接拼接到请求 URL 上)

源码中每个引擎都实现了统一的 SearchEngine 接口(NeedExectue/Client/CallArgs/ParseResult),各引擎通过NeedExectue判断是否响应当前搜索上下文(见下文搜索重写),这是多引擎并行检索的扩展点。

三、各搜索引擎的具体实现与特定配置

3.1 Google 搜索

特定配置:

名称数据类型填写要求默认值描述
cxstring必填-Google 自定义搜索引擎 ID,用于指定搜索范围

从 google.go 源码可以看到几个关键实现细节:

  1. 参数校验约束:初始化时强制要求count小于 10 且start + count <= 100,超限直接配置失败。这与 Google Custom Search API 单页最多 10 条、最大偏移 100 条的协议限制一致,因此要取更多结果必须用"多条目 + start 递增"的并发方案(见第五节配置示例);
  2. 请求构造:调用customsearch.googleapis.com/customsearch/v1start参数按 Google 协议传的是start+1defaultLang会转换成lr=lang_XX参数附加到 URL 上;
  3. 结果解析:除snippet摘要外,还会读取pagemap.metatags.0.og:description(网页的 og:description 元数据)并以...\n分隔拼接到正文内容中,为 LLM 提供更丰富的上下文;
  4. 去重:多引擎结果合并时以Link为键去重(见 main.go)。

3.2 Bing 搜索

apiKey通过Ocp-Apim-Subscription-Key请求头传递,调用api.bing.microsoft.com/v7.0/searchdefaultLang映射为mkt参数。

从 bing.go 的解析逻辑看,Bing 引擎不只返回webPages.value网页结果,还会解析:

  • deepLinks:每个网页下的站内子链接,作为独立结果展开;
  • news.value:新闻结果,以description字段作为正文内容。

因此在optionArgs中传入answerCountresponseFilter(如包含 news)等参数可以进一步控制返回类型。

3.3 Arxiv 论文搜索

特定配置:

名称数据类型填写要求默认值描述
arxivCategorystring选填-搜索的论文类别(如 cs.AI, cs.CL 等,Arxiv 官方类别分类法)

Arxiv 是免费开放接口,不需要 API Key。从 arxiv.go 看,其请求与解析特点是:

  1. 查询词会被转换成all:关键词形式,多关键词之间以+AND+连接;如果搜索重写识别出了论文类别(运行时优先级高于静态配置的arxivCategory),还会追加+AND+cat:类别限定;
  2. 最终请求export.arxiv.org/api/query?search_query=...&max_results=...&start=...,返回 Atom XML 格式;
  3. 解析每条论文时提取 title、alternate 链接、摘要(summary)、作者列表与发布时间,并格式化为摘要 + Authors + Publication time的正文喂给 LLM。

3.4 Elasticsearch 私有知识库搜索

特定配置:

名称数据类型填写要求默认值描述
indexstring必填-要搜索的 Elasticsearch 索引名称
contentFieldstring必填-要查询的内容字段名称
semanticTextFieldstring必填-要查询的 embedding 字段名称
linkFieldstring选填-结果链接字段名称,当配置needReference时需要填写(否则初始化报错)
titleFieldstring选填-结果标题字段名称,当配置needReference时需要填写
usernamestring选填-Elasticsearch 用户名
passwordstring选填-Elasticsearch 密码

从 elasticsearch.go 可以看到,插件发送的是一个混合检索(Hybrid Search)请求体:使用rrf(Reciprocal Rank Fusion,倒数排名融合)检索器,同时执行两路检索——

  • 基于contentFieldmatch标准全文匹配(BM25 语义);
  • 基于semanticTextFieldsemantic向量检索;

再由 RRF 融合两路排名得到最终结果。请求 URL 为/{index}/_search?from={start}&size={count},认证走 Basic Auth 头。

版本与 License 前提:

  • RRF 查询要求 Elasticsearch 版本在8.8 及以上
  • 文档向量化依赖 Elasticsearch 内置 Embedding 模型(semantic_text 能力),该功能需要 Elasticsearch 企业版 License 或 30 天 Trial License;如需改用第三方 Embedding 模型,可按 Elasticsearch 官方向量搜索文档自行部署。

另外,main.go 中在初始化 ES 引擎时会把needReference传入,用于在插件启动阶段就校验linkField/titleField是否齐全,避免运行期才发现配置缺失。

3.5 夸克(Quark)搜索

特定配置:

名称数据类型填写要求默认值描述
contentModestring选填"summary"内容模式:"summary"使用摘要(snippet),"full"使用正文(优先 markdownText,为空则用 mainText)

从 quark.go 看,夸克引擎调用阿里云 IQS 的cloud-iqs.aliyuncs.com通用搜索接口,apiKeyX-API-Key头传递;结果按pageItems数组解析,并在客户端侧按count截断(index < count)。contentMode取值非法时配置会直接校验失败,这是五个引擎中少数在启动期做枚举值校验的字段。

一个实现细节:如果searchFrom只配置了 quark 引擎,搜索重写会自动选用中文互联网专用提示词(见 4.2 节),以更好地适配中文互联网内容检索。

四、搜索重写(searchRewrite):用 LLM 优化检索

4.1 功能与适用场景

搜索重写功能先调用一个可配置的 LLM 服务对用户的原始查询进行分析,作用包括:

  1. 判断是否需要搜索——如果用户消息不是提问(如闲聊、翻译要求),LLM 会返回none,插件直接放行原请求,完全不触发搜索逻辑;
  2. 查询改写——把自然语言问题转成更适合搜索引擎的关键词组合;
  3. Arxiv 类别识别——自动判断问题所属论文领域并添加cat:类别限定;
  4. 私有库关键词拆分——把长查询拆成多个精准关键词组合(逗号分隔)。

官方文档强烈建议在使用 Arxiv 或 Elasticsearch 引擎时启用此功能:对 Arxiv 搜索它能准确识别论文领域并优化英文关键词;对私有知识库搜索它能提供更精准的关键词匹配。

4.2 配置字段

名称数据类型填写要求默认值描述
llmServiceNamestring必填-LLM 服务名称(Higress 服务来源)
llmServicePortnumber必填-LLM 服务端口
llmApiKeystring选填-LLM 服务 API 密钥(以 Bearer Token 传递)
llmUrlstring必填-LLM 服务 API 地址(OpenAI 兼容 chat/completions)
llmModelNamestring必填-LLM 模型名称
timeoutMillisecondnumber选填30000API 调用超时时间(毫秒)
maxCountnumber选填3搜索重写生成的最大查询次数

配置解析逻辑在 main.go:四个必填字段任一缺失都会导致插件启动失败;maxCount会被注入到重写提示词的{max_count}占位符中。

4.3 提示词按引擎组合自动选择

插件内置了五份搜索重写提示词(prompts 目录),配置加载时按已启用引擎的组合自动选用:

已配置的引擎组合选用的提示词文件说明
Arxiv + 私有库 + 互联网full.md全场景
Arxiv + 互联网(无私有库)arxiv.md含完整的 Arxiv Category 枚举表
私有库 + 互联网private.md区分 internet:/private: 两类查询
仅互联网(含 google/bing 等)internet.md基础联网查询改写
仅 quarkchinese-internet.md面向中文互联网优化

以 internet.md 为例,重写提示词要求 LLM 按 What → How → Adjust → Final 的思路分析,并按固定格式输出:

internet: 黄金价格走势 internet: The trend of gold prices

每行以internet:/private:/ Arxiv Category(如cs.AI:)为前缀,多行用换行分隔,总条数不超过maxCount;若判断无需搜索则只输出none。arxiv.md 中还内嵌了完整的 Arxiv Category 枚举清单(cs.、math.、quant-ph、stat.* 等),供 LLM 判定论文领域时查表使用。

4.4 重写结果到搜索上下文的映射

main.go 将 LLM 返回的每行解析为SearchContext

  • internet: xxx→ 互联网引擎(google/bing/quark 均响应,其NeedExectueinternet/空上下文均返回 true);
  • private: a,b→ 按逗号拆分为多个关键词,仅 Elasticsearch 引擎响应;
  • 其他前缀(即 Arxiv Category)→ 仅 Arxiv 引擎响应,并携带类别限定。源码中还有一个提升召回率的策略:当识别出 Arxiv 类别时,会同时再追加一个不带类别限定的备份查询,确保不因类别误判而漏检;
  • 重写请求失败或输出中不含任何有效上下文时,均直接放行原始请求(不搜索)。

五、完整配置示例

以下示例全部继承自官方 README,可直接复制到 Higress 控制台或WasmPlugin资源中使用(注意serviceName需先在服务来源中配置好对应域名,如customsearch.googleapis.comapi.bing.microsoft.comcloud-iqs.aliyuncs.comexport.arxiv.org,可参考仓库内同目录的 guide.md 中的分步教程)。

5.1 基础配置(单搜索引擎)

needReference: true searchFrom: - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443 count: 5 optionArgs: fileType: "pdf"

5.2 Arxiv 搜索配置

searchFrom: - type: arxiv serviceName: "arxiv-svc.dns" servicePort: 443 arxivCategory: "cs.AI" count: 10

5.3 夸克搜索配置

searchFrom: - type: quark serviceName: "quark-svc.dns" servicePort: 443 apiKey: "quark api key" contentMode: "full" # 可选值:"summary"(默认)或"full"

5.4 多搜索引擎配置

defaultLang: "en-US" promptTemplate: | # Search Results: {search_results} # Please answer this question: {question} searchFrom: - type: google apiKey: "google-key" cx: "github-search-id" # 专门搜索GitHub内容的搜索引擎ID serviceName: "google-svc.dns" servicePort: 443 - type: google apiKey: "google-key" cx: "news-search-id" # 专门搜索Google News内容的搜索引擎ID serviceName: "google-svc.dns" servicePort: 443 - type: bing apiKey: "bing-key" serviceName: "bing-svc.dns" servicePort: 443 optionArgs: answerCount: "5"

5.5 并发查询(分页取更多结果)

由于搜索引擎对单次查询返回结果数量有限制(如 Google 单次最多 100 条且单页不超过 10 条),可以通过"小 count + start 偏移 + 多条目并发"的方式获取更大结果集。例如要获取 30 条结果,可配置 count=10 并配置三个查询,start 分别为 0、10、20:

searchFrom: - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443 start: 0 count: 10 - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443 start: 10 count: 10 - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443 start: 20 count: 10

注意过高的并发可能会导致被搜索引擎限流,需要根据实际情况调整。

5.6 Elasticsearch 配置(对接私有知识库)

searchFrom: - type: elasticsearch serviceName: "es-svc.static" index: "knowledge_base" contentField: "content" semanticTextField: "semantic_text" # username: "elastic" # password: "password"

5.7 自定义引用格式与位置

needReference: true referenceFormat: "### 数据来源\n%s" searchFrom: - type: bing apiKey: "your-bing-key" serviceName: "search-service.dns" servicePort: 8080
needReference: true referenceLocation: "tail" # 在回答结尾添加引用,而不是开头 searchFrom: - type: bing apiKey: "your-bing-key" serviceName: "search-service.dns" servicePort: 8080

5.8 搜索重写配置

searchFrom: - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443 searchRewrite: llmServiceName: "llm-svc.dns" llmServicePort: 443 llmApiKey: "your-llm-api-key" llmUrl: "https://api.example.com/v1/chat/completions" llmModelName: "gpt-3.5-turbo" timeoutMillisecond: 15000

5.9 按需启用插件(兼容 OpenAI 搜索模型协议)

defaultEnable: false searchFrom: - type: google apiKey: "your-google-api-key" cx: "search-engine-id" serviceName: "google-svc.dns" servicePort: 443

配置defaultEnable: false后,只有当请求体中包含web_search_options字段时插件才激活(即使是空对象"web_search_options": {}也会激活),可以兼容 OpenAI 的搜索模型协议,让同一 LLM 端点根据客户端是否要求联网来动态开关搜索增强。

5.10 动态调整搜索深度(search_context_size)

在请求的web_search_options中携带search_context_size参数,可动态调整搜索查询次数:

{ "web_search_options": { "search_context_size": "medium" } }

search_context_size支持三个级别(见 main.go):

取值效果适用场景
low生成 1 个搜索查询简单问题
medium生成 3 个搜索查询(默认值)常规问题
high生成 5 个搜索查询复杂问题

该设置会覆盖配置中的maxCount值,并在每次请求时基于原始提示词模板重新替换{max_count}占位符,允许客户端按问题复杂度动态调整搜索深度。传入未知值时插件会打警告日志并回退使用配置的maxCount

六、引用来源注入的实现细节

开启needReference后,插件在搜索阶段就为每条结果生成了[序号] 标题形式的引用列表(main.go),并按referenceLocation在响应阶段注入:

非流式响应(onHttpResponseBody):读取choices.0.message.content,若回答以<think>开头(如 DeepSeek-R1 等推理模型),默认会把引用插在</think>之后,即思考过程与正式回答之间;否则按 head/tail 位置拼接后整体替换。

流式 SSE 响应(onStreamingResponseBody):实现更为精细——

  • head 模式:对choices.0.delta.content做 30 字节滑动缓冲,确认首段内容不是<think>后在首个 delta 前拼接引用;若首段是思考内容,则持续缓冲直到检测到完整的</think>标签再插入,并能处理 `

【免费下载链接】higress🤖 AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 20:36:33

SPWM是FOC的地基:STM32电机控制中正弦波驱动的工程本质与性能验证

1. 项目概述&#xff1a;FOC不是玄学&#xff0c;SPWM也不是过渡方案——从电机控制底层讲清“为什么先做SPWM再谈FOC”你手头有一块STM32F407开发板&#xff0c;买了IPM模块和PMSM电机&#xff0c;想跑通FOC但卡在第一步&#xff1a;连最基本的正弦波驱动都调不稳&#xff0c;…

作者头像 李华
网站建设 2026/9/16 20:35:32

Rerun 多 Native Viewer 并发指南:用 gRPC 端口隔离并行可视化窗口

Rerun 多 Native Viewer 并发指南&#xff1a;用 gRPC 端口隔离并行可视化窗口 【免费下载链接】rerun Visualize, query, and stream to train on multimodal robotics data. 项目地址: https://gitcode.com/GitHub_Trending/re/rerun 本指南基于官方 How-To 文档&…

作者头像 李华
网站建设 2026/9/16 20:34:26

N16R8开发避坑指南:PSRAM初始化与量产级PlatformIO配置

1. 这不是“又一个ESP32教程”&#xff0c;而是N16R8这块板子的真实上手现场你搜“ESP32-S3 N16R8”时&#xff0c;大概率会撞进一堆标题党&#xff1a;《5分钟点亮LED》《史上最全环境搭建》《保姆级教程》……结果点进去发现&#xff0c;要么用的是Arduino IDE配旧版驱动&…

作者头像 李华
网站建设 2026/9/16 20:34:14

SpringBoot公益寻人平台开发与智能匹配实践

1. 项目背景与核心价值公益寻人平台是一个基于SpringBoot框架的社会救助系统&#xff0c;旨在通过信息化手段解决失踪人员寻回难题。根据公开数据&#xff0c;我国每年约有数十万起人口走失报案&#xff0c;传统寻人方式效率低下且信息孤岛严重。这个系统的核心价值在于&#x…

作者头像 李华
网站建设 2026/9/16 20:34:02

2026年GEO行业趋势与优质服务商评估指南

1. 2026年GEO行业全景扫描GEO&#xff08;地理空间信息&#xff09;行业正在经历前所未有的技术迭代期。根据最新行业白皮书显示&#xff0c;到2026年全球地理空间分析市场规模预计突破2800亿美元&#xff0c;年复合增长率保持在14.7%的高位。这个曾经以测绘、遥感为主的传统领…

作者头像 李华
网站建设 2026/9/16 20:32:37

KVM图形化安装实战:virt-manager远程管理无头服务器

1. 先把KVM这个概念捋清楚&#xff0c;别一上来就装错东西1.1 搜索"KVM安装"的时候&#xff0c;你到底在找哪一个KVM这个词确实容易串台。我身边不少做机房运维的朋友&#xff0c;一听到"KVM"脑子里蹦出来的是机柜里那台带一排按钮、能切键盘鼠标显示器的切…

作者头像 李华