当前越来越多的模型拥有显著增长的上下文长度,DeepSeek R1的上下文长度限制为128K。使用这种长上下文模型作为底层LLM,应用产品可发挥的余地自然大了很多,很多用户场景下可能都涉及不到上下文长度超限的处理。
其次,在需要联网搜索时,正如我们在检索时一样,我们可能更关心除掉广告之外的第一页的内容。AI联网产品也是类似,虽然召回内容可能成千上万,但是高质量的内容通常都在前TopN返回之内。因此没有必要使用太多搜索引擎检索召回的内容。
用户提问的相关内容可能只存在于检索召回的文档的部分片段之中,如果为此将全部内容都置于上下文中,既不经济也有可能会干扰大模型的运行。
在研发RAG智能知识库时,我在解析知识文档时,是将文档按照句读划分为不超过500字的知识片段,每个片段进行向量化。因此在问答阶段,用户提问的召回是以该知识片段为维度的。
联网搜索产品也是类似,在搜索引擎API返回检索内容时,通常会包括文档的内容摘要,不同的产品实现上或许有差异,有的可能还会再通过大模型自行概况一遍网页生成更详细更精细化的摘要内容。
总之在此阶段,通过将检索召回的网页文档通过概括总结,压缩生成摘要来减少整体内容的大小。
除了从外部互联网召回文档可能产生较大的上下文内容之外,用户多轮对话产生的内容也会被加入到每轮的对话上下文中,也是可能造成上下文超限的另一个重要原因。
基于相关性的历史压缩策略旨在智能地筛选并保留那些对理解当前问题最有价值的历史片段,并非所有的前述对话都对当前的问题直接相关。
这种策略地实现也会依赖语义相似度模型,比如现将用户历史对话的问题传递给大模型筛选出与当前问题相关的问题,再组合相关的历史对话内容作为前述对话的上下文。
在与用户多轮对话的过程中,涉及处理的联网搜索召回内容越多,回答的内容也可能越长,相应地,后续对话涉及的上下文内容也会越长。
该策略旨在将摘要技术同时运用在对历史对话的回答上,将冗长的历史对话浓缩成几句关键信息,保留核心要点去除不必要的细节。这种方法能在保持对话连贯性的同时,极大地减少需要处理的文本长度。
一些先进的AI联网搜索产品还具备动态调整上下文窗口的能力。这意味着系统可以根据当前查询的复杂性以及检索到的外部信息的多少,灵活地决定输入给大模型的上下文长度和具体内容。
比如,当前查询非常简单,且搜索召回内容也很简洁,系统可能会选择包含更多的历史对话信息。相反,如果当前查询很复杂,需要引入大量外部信息,系统可能会选择缩减历史对话的长度,优先保留最新的用户提问和回答内容。
我在研发RAG智能知识库时,实现了类似的简化功能,系统默认以FIFO的方式淘汰历史对话,默认保留最多10轮,用户可以在运行时再自行配置。
接下来我们使用Coze搭建一个AI联网搜索产品的demo,来直观地观察一下它的运作过程,验证一下一个AI联网搜索产品的实现方式,真正的用户级产品可能更加复杂,但以管窥豹,可以从中验证我们上述提到的策略和技术。
使用Coze创建一个工作流如下:
流程节点较多,我分开截图:
上面的Coze我无法直接分享出外部可编辑的版本出来,我制作了一个公开可访问的测试Agent,感兴趣的可以访问:https://www.coze.cn/store/agent/7484186385763926028?bot_id=true (链接已放在原文链接)。
我挑几个重点的节点,将具体配置列出来,方便部分感兴趣的读者进行复现。
1)生成搜索query
跟节点根据用户输入判断是否需要进行互联网检索,需要的话生成对应的检索query。
系统prompt如下:
用户输入:{{input}} 请根据上面的用户输入问题,判断是否需要进行联网搜索,涉及时效性相关的问题需要进行联网搜索。 需要联网搜索的问题生成对应的检索query,确保这些query能够涵盖相关的基本背景信息、事实依据或其他影响判断的关键信息。
2)搜索材料
该节点是名为“头条搜索”的搜索引擎插件,在添加节点时从插件商店选中该插件。
将上一节点返回的query参数作为入参传递。
该节点为批处理模式,该模式下节点会多次运行,在每次运行中,批处理列表会按照顺序将列表中的一项赋值给批处理变量,直到达到批处理的上限或列表的最大长度。
输入参数里可以通过指定count来确定召回条数。
3)处理输出结果
添加一个代码处理节点,处理一下搜索引擎输出的结果。
代码部分输入:
asyncdefmain(args:Args)->Output:params=args.paramsoutputList=params['outputList']markdown_str=""message_count=0foriteminoutputList:data=item.get('data',{})doc_results=data.get('doc_results',[])fordocindoc_results:sitename=doc.get('sitename','')summary=doc.get('summary','')title=doc.get('title','')url=doc.get('url','')#拼接markdown格式markdown_str+=f"#####{title}\n\n"markdown_str+=f"**网站**:{sitename}\n\n"markdown_str+=f"**摘要**:{summary}\n\n"markdown_str+=f"[点击这里查看详情]({url})\n\n\n"message_count=message_count+1ret:Output={"markdown_str":markdown_str,"message_count":message_count,}returnret这部分代码从搜索引擎返回的网页文档中,解析出网站的摘要,此处使用的是搜索引擎API自带的摘要,没有再使用网页爬取插件+LLM来整理摘要。
4)生成初步总结
工作流搭建完成,我们开启debug模式运行一下,看一下各节点的处理过程。
输入问题:“字节跳动和腾讯哪个成立时间早?”,运行后点开运行日志:
在搜索引擎节点,我们可以看到:
大模型首先根据用户的提问,生成了两个待查询的query:“字节跳动成立时间”以及“腾讯成立时间”,然后搜索引擎两次调用了查询,每次查询返回了10个文档(我工作流没有设置count,默认返回最优召回的10条)。
返回内容中包括了summary字段,该字段即对应网页的摘要部分。我们还可以在该阶段添加网页爬取节点,将搜索引擎返回的网页链接url字段输入给爬取插件,再将爬取的内容交由大模型进行摘要总结。这里为了减少实验的复杂性,我们采取信任搜索引擎返回的摘要,原理上是一致的。
搜索展示过程,可以看到经过处理,搜索内容的摘要被整合成与大模型交互的上下文信息:
搜索引擎访问了20个网页,结果的摘要内容token数大约为3828,而模型的上下文长度限制为12.8万左右。
这里只着重展示了一下,联网搜索的内容如何通过摘要技术控制了上下文长度,再结合上面提到的其他策略,可以在保证正确性的前提下将上下文压缩得更小。
本文通过我个人在AI应用研发领域的经验和对AI Agent的了解,解析了一下AI联网产品在检索外部互联网上巨大的信息内容后,是如何突破大模型对话的上下文限制的若干种办法。
并通过Coze搭建了工作流,按照上述策略实现了一个AI联网产品的Demo。
当然,工程上的用户级产品需要考虑更多复杂的情形,相应地实现手段可能更加丰富。如果你有什么想法或疑问,欢迎留言讨论~
| 欢迎光临 链载Ai (https://www.lianzai.com/) | Powered by Discuz! X3.5 |