从多语言语义搜索到智能助手:博世数字的技术演进之路

本文详细介绍了博世数字如何从传统关键词搜索升级到基于向量的多语言智能搜索系统,并最终构建出能够理解用户意图的对话助手。技术架构涵盖Rust爬虫、OpenAI嵌入模型、混合搜索策略、Qdrant向量数据库优化以及GLiNER实体识别等核心组件。

为什么关键词搜索不再适用?

自行车及其文档的世界充满了同义词、部件昵称和不断变化的术语。对骑手来说,“Display”、“NYON2”或“BUI350”可能指的是同一事物,但基于词袋的搜索引擎会将每个词视为陌生词汇。除非手动创建无尽的同义词列表,否则召回率会急剧下降。

拼写错误和语音转文本的失误更是雪上加霜。现实中的查询可能显示为“Kioxx 300”、“réinitialiser kios”,或者由于麦克风问题变成语音识别乱码如“reset chaos 300”。基于精确令牌的搜索?它们只会耸耸肩显示“无结果”。相比之下,基于嵌入的搜索对噪声输入的容忍度要高得多。

意图在翻译中也会丢失,特别是对于复杂或带有约束的查询。有人可能输入“在没有笔记本电脑的情况下更新刹车固件”或“仅限雨天模式下的最大扭矩”。关键词搜索会抓住否定词(“笔记本电脑”)并挖掘出错误的文档。相比之下,现代Transformer模型能够理解用户的真实意图并相应地对结果进行排序。

设计更智能的搜索方式

一旦我们找出传统关键词搜索的每个缺陷,就是时候从头重新构想整个流程了。如今,SmartSearch提供的每个答案都经过精确的三步旅程:从原始文档到排序结果——这个旅程专为速度、准确性和多语言扩展而设计。

第一步:爬取。我们自主研发的基于Rust的爬虫每秒可快速处理约25个网页,迅速导航庞大的文档库,同时保持足够的礼貌,从不触发速率限制——就像一个阅读速度快但从不惹麻烦的数字图书管理员。

第二步:嵌入前的分块。HTML被剖析以将标题与内容分开,并使用LLM将语义连贯的主题拼接在一起。然后是嵌入。得益于OpenAI的Ada 002模型(具有庞大的1536个维度),每个内容块都能准确地落在语义空间中。如果它听起来像“重置Kiox 300”,我们的系统就会呈现答案,即使实际语言完全不同。

第三步:使用混合方法进行搜索排序。语义搜索并不总是最佳方法。密集向量存储在向量数据库中,而BM25则保留了经典的关键词搜索。在查询时,我们将两者混合——70%语义,30%稀疏——然后通过MiniLM交叉编码器对最终候选进行决定性排序。结果如何?答案通常在大约750毫秒内出现,95%在1.5秒内交付——即使在那些臭名昭著的固件发布高峰期也是如此。

但所有这些性能并非没有痛苦。构建SmartSearch意味着要突破硬性限制:每个集合1000万个向量的上限、每次添加元数据时痛苦的重索引、32位浮点数导致的存储费用膨胀,以及没有优雅的方法来压缩、量化或将存储分层到更便宜的SSD。规模超过800万个向量时,一切都会变得缓慢。

当搜索变成聊天时

对于搜索栏,十个不完美的链接可能就足够了。但对于博世eBike系统来说,要将其部署为全球用户群的对话助手,就没有犯错的余地——机器人通常只有一次机会。第一次检索必须极其准确,因为我们传递给LLM的每个令牌都需要花费真金白银——如果机器人的开场白没有命中目标,用户的信任就会蒸发。

聊天也爆炸性地扩大了数据规模。现在我们不仅仅是从文档中检索,还要处理大量的对话历史和实时跟进。数以万计的聊天片段,以短期和长期记忆的形式,需要在毫秒级内存储、搜索和呈现。在这里,我们之前向量存储的裂缝暴露无遗:硬向量计数限制、缓慢的重索引时间、零支持量化或内置多阶段查询,以及坚持将所有向量保存在磁盘上——既膨胀了预算又瓶颈了速度。

Qdrant登场。在让几个向量数据库面对我们最苛刻的工作负载后,Qdrant轻松胜出。在一个包含25k查询的多语言测试集上,它在量化的情况下提供了高于0.96的召回率,在400个并发聊天的情况下保持p95延迟低于120毫秒,并且我们通过量化将1000万数据集的存储成本降低了16倍。Qdrant不仅应对了聊天的挑战——它还在这些挑战中茁壮成长。现在,闪电般快速的、聊天规模的检索突然之间不仅成为可能,而且价格合理。

精简大脑,而非智力

我们的第一个原型能够流畅地表达相关性,但却是个存储贪婪者。每个文本块都包裹在一个巨大的1536维Ada-002向量中——数百万个高精度浮点数成排地吞噬着我们的SSD。必须有所改变。

突破来自Jina Embeddings v3。切换一个标志,你就可以获得1024维向量的二值量化嵌入;切换另一个标志,1024维向量可以通过Matryoshka表示学习的力量降至64维。经过大量关于召回质量的内部测试,我们发现在256维时获得了最佳的性能质量比。一夜之间,存储占用下降了98%,搜索质量甚至超过了Ada-002。在最近的评估中,这种设置优于Ada-003,并将一些MTEB排行榜上的佼佼者甩在了后面(我们接下来将评估Qwen3嵌入模型)。此外,得益于我们微调的ModernBERT重新排序器,任何微小的损失都完全消失了。

Qdrant将这些精简的向量转化为闪电般的答案。因为它原生理解多阶段检索,我们现在运行一个两阶段搜索:一个极快的256维召回阶段与BM25融合,然后是一个基于ModernBERT的微调重新排序器以实现精确度。这就是超精简操作应有的样子。

最重要的是,Qdrant的分层存储让我们可以将热分片保存在RAM中,冷向量存放在SSD上,再次削减存储,使其总存储减少5倍,同时p95延迟仍远低于400毫秒。混合搜索?密集分数与BM25在同一个API调用中无缝混合,因此充满拼写错误或完美的查询都能得到同等对待。

名称,而非猜测:GLiNER如何增强识别能力

到目前为止,我们的助手能够以令人印象深刻的速度和准确性找到相关事实——但它仍然在最关键的地方出错:名称。“我的Kiox 300在v1.7.4-B更新后闪烁503”和“Nyon在启动时卡住”对于一个没有真正看到产品、错误代码或固件版本的语言模型来说几乎是一样的——只是一片模糊的名词和动词。上下文丢失了;精确度受到影响。而引入一个拥有数十亿参数的AI大锤来解决这个问题纯粹是杀鸡用牛刀。

突破来自一个意想不到的地方——在LinkedIn上漫无目的地浏览。它就在那里:GLiNER,承诺通用、轻量级的NER(命名实体识别)。少样本学习、CPU快速推理,以及足够小(800 MB)可以放入我们的Docker镜像的存储占用——GLiNER满足了我们甚至不知道自己有的所有条件。

它不仅仅是“容易”——它是变革性的。仅用少量带注释的例子——产品两个,错误代码两个,固件两个——GLiNER在几分钟内就学会了我们的整个领域。推理几乎是瞬间的:每段少于30毫秒,即使在单个笔记本电脑核心上也是如此。

随着标签在聊天轮次中持续存在,上下文得以保留。因此,当骑手说“Kiox 300在v1.7.4-B后显示503”,然后跟进“CX Gen4也会出现这个问题吗?”时,助手会清楚地记住每个产品、错误和固件。每个答案都像外科手术般精确地路由,不再将Kiox误认为Nyon,不再有猜测。

这一切都源于一次LinkedIn浏览、一个800 MB的模型和几行带标签的文本。名称很重要。现在,助手终于对它们了如指掌了。

从答案到行动:下一代助手的代理工作流

找到正确的段落是一回事。对于博世eBike系统助手来说,其任务是支持从简单查询到复杂故障排除的各种用户需求,执行现实世界的任务——提交保修索赔、收集三个不同驱动单元的最新固件链接,或者在聊天中逐步指导机械师完成“显示器重置”——需要更多的东西。简单的流程是不够的:现代助手需要推理、计划、协调和行动,而不仅仅是检索。

这就是代理工作流发挥作用的地方。

我们的平台不是通过单一的、庞大的语言模型(并希望它从不遗漏细节)来引导每个查询,而是协调一个专业AI代理团队,每个代理都有明确的职责。想象一个用户问:“我的Kiox 300闪烁错误503。你能检查我的固件是否过时,告诉我如何修复它,如果不行就起草一条给支持的消息吗?”在过去,这会把一堆模糊的指令扔给一个黑盒聊天机器人。现在,代理工作流将请求分解为可管理的、协调的步骤——每个代理都做自己最擅长的事情。

该过程从一个协调器代理开始,它将用户意图解析为子任务:错误代码查找、固件验证、故障排除指南检索,以及如果需要,支持工单起草。每个子任务被路由到一个专家代理——例如,一个基于产品变体和相应信息的自定义推理工作流。这些代理咨询我们的检索骨干(为精确性而构建,即使面对有噪声的查询),收集事实,交叉检查版本,并将发现拼凑起来。

结果如何?代理工作流让我们的助手超越了回答“是什么”——它们让它能够处理“如何”和“下一步是什么”,将知识、行动甚至人工交接无缝地连接起来。无论是简单的规格查找、多步骤故障排除程序,还是协调现实世界的后续行动,代理工作流都是我们助手从搜索框跃升为对话伙伴背后的连接组织。

我们发现这种模块化、透明的方法不仅提高了速度——它还带来了新的安心。当出现问题时,草稿日志会准确显示做了什么(以及为什么)。如果一个过程遇到障碍,协调器会转向——从不让用户陷入困境,也从不让重要的细节在缝隙中丢失。

我们会再次做的事情——以及我们不会做的事情

伤疤比奖杯教得更深,所以这里有三个仍然让我们(以正确的方式)耿耿于怀的教训:

在宠爱模型之前先打磨页面。我们曾经花了整整一周时间对近乎相同的段落进行去重,剔除样板文件(“© 2021 Bosch eBike Systems-保留所有权利”),并压平FAQ回音室,直到它们不再完全吞噬新问题。搜索质量的改进?比任何新编码器、模型发布或聪明的代理所能实现的都要大——远远超出。学到的教训:一个干净、结构良好的语料库是你在Hugging Face上永远找不到的最便宜的升级,它让每个下游代理都更加敏锐。

将精简纳入首日计划。二值量化和维度精简在存储和推理上节省了一大笔钱。但我们在发布后才匆忙添加这些功能,这意味着在用户实时搜索时重新编码1000万个块——这是没有人需要的棘手问题。下一次,压缩和大小目标将出现在第一个白板上,与召回率、延迟以及现在的代理交接兼容性并列。在集体照之前节食效果更好。而且不仅仅是存储:你的嵌入模型、向量数据库、分块策略,以及是的,代理工作流和通信方案都需要从一开始就协同工作。

复杂查询意味着复杂的代理设计。LLM既是福音也是预算杀手——延迟、成本和“智能”都成为多代理系统中成败攸关的变量。随着工作流变得代理化——计划、委托、保持状态——挑战从“我们能回答这个吗?”转变为“我们能协调这个吗,可审计且高效?”。保持数据清洁,尽早规划你的存储和计算“饮食”,并且绝不要吝啬聘用那些能够读懂字里行间并处理边缘情况的人才。其他一切都只是模型卡上的又一行,或者现在,是代理清单上的又一行。

最终,正是那些痛苦的教训——而不仅仅是漂亮的图表——将SmartSearch塑造成现在的系统。随着每一轮学习,我们的答案变得更快一点,更敏锐一点,并且也许——有一天——更接近完美一点。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计