资讯动态

LangChain接入搜索API,让数字分身拥有实时联网能力

发布时间:2026/10/17 7:10:40 来源:尧图企业网站定制
距离上一篇写完LangChain框架搭建数字分身基础骨架已经过去一阵子。那版Demo能回答用户关于目标人物生平、作品、观点的提问效果说不上惊艳但至少“形似”。可真正放到可用状态时我发现一个致命短板它只依赖提前灌进去的静态资料用户一旦问起最近三年发生的行业大事、目标人物最近一次公开露面或者新增的一条言论它就彻底卡壳。所以这篇我集中解决联网搜索这件事核心方案是LangChain框架接上国内主流搜索服务的搜索API让名人数字分身具备实时检索和事实更新的能力。适合正在做AI虚拟人、客服Agent或知识增强问答的朋友参考。1. 数字分身为什么需要联网搜索1.1 静态知识库的信息天花板上一篇里我走的还是最稳妥的RAG路线把人物传记、访谈记录、公开演讲文本全部切成块进向量库然后在问答阶段做相似度检索。这套方案的优点是可控人物说过的原话不会跑偏缺点也明显知识库的时效性完全取决于你最后一次更新索引的时间。举个例子用户问“如果目标人物现在站到某场行业发布会上他会怎么评价当前生成式AI的爆发”这个问题的前半段需要人设知识后半段却依赖对最新行业动态的了解。静态资料里只有两三年前的表述模型只能照搬旧观点给出来的回答就会显得”时代错位”。更别说那些需要具体数字、具体发布日期的实时问题静态向量库基本无能为力。另一个问题出现在逻辑链上。数字分身的本质是“语言风格模拟 立场观点复现”但观点需要锚定事实。如果模型本身对最近几个月发生的事情完全无感它的人设塑造就会像在真空里背稿子听起来漂亮但经不住追问。所以联网搜索不是锦上添花而是让数字分身从“背稿机器人”变成“实时互动体”的关键一步。我决定在这个版本里引入搜索API把外部信息作为临时上下文让模型在保持人物语气的前提下引用最新事实作答。1.2 搜索API带来的核心变化接入搜索API之后整个回答链路从“闭卷考”变成了“开卷考”。模型不再需要从参数里强行回忆某个日期或某个事件而是先根据用户问题生成搜索关键词拿到搜索结果再把这些结果作为背景材料用目标人物的口吻组织成最终回答。这个转变带来的直接收益有三个。第一回答的即时性大幅提升。用户问“最近一个月这个人物有没有公开发声”模型可以直接搜到相关资讯而不是永远拿三年前的旧访谈糊弄。第二回答的引用依据变得可追溯。搜索结果里通常带着标题和链接数字分身可以在回答末尾自然带出“来源参考”这对提升可信度非常有帮助。第三也是我认为最重要的模型可以做出“基于实事的观点推导”。比如搜索到某家科技公司发布了新产品模型结合人设中的审美偏好和价值观可以现场生成一段符合人物风格的评论这种能力是纯静态RAG给不了的。当然这里有个前提搜索API返回的内容质量必须可控。如果搜索出来是一堆低质标题党那模型拿到垃圾输入回答只会更垃圾。所以工具封装时的过滤逻辑非常关键后面我会详细说。1.3 技术选型为什么选国内主流搜索API这个纯属项目真实需求。我做的数字分身主要面向中文场景目标人物也是中文语境下的公众人物所以优先考虑的必然是中文内容覆盖更全的国内搜索服务。对比下来国外搜索API在某些国际资讯上确实更强但处理中文人物动态、国内媒体报道、社交平台讨论时命中率和时效性都差一截。这里我不点名具体服务商避免广告嫌疑。只说选型时的几个判断标准是否提供稳定的网页搜索接口返回结构化JSON而不是让你自己去爬。是否支持按时间范围过滤结果。这个很重要查“最近一周”还是“最近一年”需要显式传参。单日配额是否够用。个人Demo每天几十次调用就够但做成服务就要考虑成本。返回字段里是否包含标题、链接、摘要。摘要字段质量高能省掉后续抓网页正文的麻烦。我最终选的是一家国内搜索服务商提供的开放搜索API支持关键词检索、时间过滤、结果数量控制。它的摘要字段做得比较规整直接拼接给模型用基本不需要额外清洗。整体接入成本比我预想低很多唯一要写点逻辑的是处理限流和超时重试。2. 整体架构设计2.1 从固定问答升级为Agent式检索第一版数字分身的核心流程是用户提问 → 向量库检索 → Prompt拼接 → LLM回答。这是一个固定管线没有分支。这一版我把它升级成了LangChain框架下的Agent模式。Agent模式和固定管线最大的区别在于模型不再只是被动回答问题而是可以主动决策要不要查资料、查什么资料、以及怎么把资料组织进回答。具体到我们这个场景当用户提问“你怎么看最近的新能源政策”模型会判断自己内部知识可能不够新于是调用搜索工具先生成一个搜索词拿到结果后再继续。在LangChain里落地这个逻辑其实只需要做好三件事定义好搜索工具告诉模型这个工具什么时候用设计好人设Prompt明确回答风格和事实处理边界挂上记忆组件让多轮对话里的人设保持一致。数据流转可以简单理解为用户问题进入Agent后模型先生成一段思考决定调用哪个工具、输入什么参数工具返回搜索结果模型阅读结果结合人设知识给出最终回答。这个过程在LangChain中由AgentExecutor自动调度开发者主要精力放在Prompt和工具参数上。2.2 三个核心组件LLM、搜索工具、记忆模块这个架构里三个组件各司其职缺一不可。LLM是数字分身的大脑负责语言风格、逻辑组织和人设判断。我用的还是兼容OpenAI接口的模型具体型号对效果影响不算大关键是温度参数要控制好。温度太低回答会干巴巴像机器人温度太高人设容易崩。我实测下来0.7左右比较稳妥。搜索工具是数字分身的外部记忆。我给LangChain注册了一个自定义Tool内部封装搜索API。工具的描述信息写得越清楚越好因为模型会读这段描述来决定何时调用。比如我写的是“当需要查询最新信息、时事动态、人物近况时使用输入为搜索关键词”模型就能很精准地触发。记忆模块用来保留对话上下文。这里有个容易踩的坑数字分身的人设知识是静态的但对话历史是动态的两者不能混在一个向量库里。我使用ConversationBufferMemory只存最近若干轮对话按需注入Prompt这样既能让回答有连续性又不会干扰人物背景设定。2.3 人设一致性如何不丢联网搜索最难处理的问题就是“搜回来的信息和人设打架”。比如目标人物明明性格含蓄内敛搜到一篇风格激烈的媒体报道模型如果直接“引用”过来整个回答就变味了。我的解法是在Prompt里加了一道“人格过滤器”规则如下搜索材料只是参考事实最终回答必须符合目标人物的语气、用词习惯和价值观。如果搜索内容和人物背景冲突以人物生平设定为优先级。不要机械复制搜索结果中的句子要把信息“翻译”成人物可能的口头表达方式。这个过滤器听起来简单但对Prompt的措辞要求很高。我前后改了五六版才找到比较稳定的写法。核心是让模型理解“你是你资料是资料”而不是让模型觉得“资料里的内容就是你说的全部”。3. 核心实现细节3.1 依赖安装与环境准备这个项目需要的依赖不算多我在Python 3.10环境下测试没有问题。pip install langchain langchain-openai requests beautifulsoup4 python-dotenvlangchain和langchain-openai负责Agent和LLM接入requests用来调搜索APIbeautifulsoup4主要是备用万一搜索结果里的摘要字段不够用我可以自己抓取指定网页正文做补充python-dotenv管理API密钥别把密钥写死在代码里。环境变量我单独放在.env文件里SEARCH_API_KEY你的搜索API密钥 OPENAI_API_KEY你的模型API密钥加载方式很简单from dotenv import load_dotenv load_dotenv()3.2 封装搜索API工具搜索API的原始返回通常是JSON里面包含标题、链接、摘要、发布时间等字段。我封装了一个函数只提取自己需要的字段拼成模型友好的文本格式。import os import requests API_URL https://openapi.example.com/search def search_web(keyword: str, top_k: int 5) - str: 调用搜索API返回整理后的文本。 resp requests.get( API_URL, params{ q: keyword, per_page: top_k, time_range: year, # 一年内内容优先 }, headers{Authorization: fBearer {os.getenv(SEARCH_API_KEY)}}, timeout5, ) resp.raise_for_status() data resp.json() results data.get(results, [])[:top_k] text_parts [] for idx, item in enumerate(results, 1): title item.get(title, ) url item.get(url, ) snippet item.get(snippet, ) or item.get(summary, ) text_parts.append(f[{idx}] {title}\n{url}\n{snippet}) return \n\n.join(text_parts)这里有两个细节值得注意。第一time_range参数。我默认限制在一年内避免搜出一堆古董级内容。如果用户问的是“最近一个月发生了什么”我可以在外层调整这个参数。第二摘要字段的质量直接决定模型输出质量。如果搜索API返回的summary字段包含核心信息就不需要抓取全文如果摘要太短后面需要补一个网页内容读取步骤。我建议优先选摘要字段丰富的服务能省掉很多事。3.3 接入LangChain Agent搜索函数封装好后我用LangChain的Tool把它注册成Agent可以调用的工具。from langchain_core.tools import Tool def search_tool_func(keyword: str) - str: # 转成纯文本查询词去掉多余标点和问号 return search_web(keyword, top_k5) search_tool Tool( nameSearchAPI, description当需要查询最新信息、时事动态、人物近况时使用。输入为搜索关键词尽量简练。, funcsearch_tool_func, )然后初始化一个兼容OpenAI接口的LLM这里以LangChain 0.2.x的API为例。from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_react_agent from langchain_core.prompts import PromptTemplate llm ChatOpenAI(modelgpt-4o-mini, temperature0.7) prompt PromptTemplate.from_template( 你正在扮演目标人物的人格分身。 角色设定 {persona} 对话规则 1. 必须用目标人物的口吻和观点回答问题。 2. 如果问题涉及实时信息先调用SearchAPI获取最新资料。 3. 不能照搬搜索结果要用自己的语言转述。 4. 如果搜索结果与人物背景冲突以人物背景设定为准。 工具列表 {tools} 工具名 {tool_names} 对话历史 {chat_history} 当前问题{input} 思考过程{agent_scratchpad} ) agent create_react_agent(llmllm, tools[search_tool], promptprompt)之后AgentExecutor可以这样创建from langchain.memory import ConversationBufferMemory memory ConversationBufferMemory( memory_keychat_history, return_messagesTrue, ) executor AgentExecutor( agentagent, tools[search_tool], memorymemory, max_iterations4, verboseTrue, )max_iterations4很关键。它限制Agent最多思考并调用工具4次。如果没有这个限制模型可能会反复搜索浪费配额也会让响应时间变得不可接受。3.4 人格Prompt模板的工程化整个项目里最需要反复调的就是Prompt模板。我把它拆成三块人设背景、风格指令、事实处理规则。人设背景一般包含目标人物的身份、职业、性格特征、代表性观点。这部分内容不需要太长但必须有足够信息让模型“入戏”。风格指令要具体到能约束语气比如“喜欢用短句”“常用反问”“语气克制冷静”等。事实处理规则就是我前面提到的人格过滤器。我经常用的模板片段如下persona 目标人物背景 - 身份某虚构科技评论人 - 性格理性、克制、喜欢用具体数字支撑观点 - 语言风格口语化短句常用“我说实话”“但问题在于”这类口头禅 - 核心立场相信技术驱动进步但警惕盲目乐观 事实处理规则 - 回答涉及实时信息时必须调用SearchAPI。 - 搜索材料只能作为事实依据不能改变上述人设。 - 如果材料中观点与上述立场冲突优先按照人物立场作答。 - 不要在回答中出现“根据搜索结果”这类暴露Agent身份的话。 这个模板里最关键的是“不要暴露Agent身份”这一条。最开始我没加这条时模型往往会回答“根据最新搜索资料我认为……”这一下就穿帮了。加了之后模型会把搜索内容消化成人物自己的表达方式效果自然得多。3.5 记忆管理现在说的还是目标人物吗多轮对话里记忆管理比想象中更容易出问题。我最初用的是ConversationBufferWindowMemory只保留最近两轮避免上下文过长。后来发现一个更隐蔽的问题如果用户上一轮问了某机构的具体数据这一轮突然问人物对某个理念的看法模型很容易把上一轮的数据当成人物亲口说的话这就串味了。我的处理办法是把对话历史按“用户说的”和“人物说的”分类存储。LangChain的ConversationBufferMemory会自己组装历史消息但它的return_messagesTrue模式下模型能够区分消息来源整体表现比纯字符串拼接好很多。此外我在每轮对话结束后会用一小段Prompt生成“内部摘要”压缩早期信息只把最新几轮塞进上下文。这样做的目的是保持“人物一致性”数字分身的记忆不是完整录音而是“人物记得什么事”的压缩表示。早期细节消失没关系人设骨架稳定才是关键。4. 实操过程与参数调优4.1 一个完整的对话演示我把整套服务跑起来之后做了一个小测试。用户的问题是“最近AI圈有什么新东西值得关注吗你怎么看”Agent的执行过程大致如下模型看到问题判定需要实时信息于是调用搜索工具输入关键词“AI圈 最新动态 最近一周”。搜索工具返回几条近期资讯包括至少两篇行业分析文章。模型继续思考决定引用其中一篇关于端侧大模型的内容并结合角色“关注技术落地”的人设生成回答。最终输出类似“我看了一圈真正值得关注的不是又出了个大模型而是端侧部署这件事终于有了像样的产品。我说实话纸上谈兵的模型已经太多了能在用户手里跑起来的才是真本事。”加上一句“上周刚有厂商发布了相关方案你可以去看看。”这个回答里既包含实时信息又保持了人物风格。对比没有搜索功能的旧版旧版只会输出“我关注AI发展已经很多年未来的方向是……”这种空话高下立判。4.2 影响效果的关键参数参数调优部分我踩过不少坑。下面列几个影响最明显的参数。温度temperature直接影响语言风格。0.3以下回答太机械像读说明书0.9以上容易天马行空人设飘忽。我最终用0.7既有稳定结构又有一定口语化自由度。max_iterations刚才提过建议设置在3到5之间。太低会导致模型来不及调用工具就直接作答太高会让一次回答耗时十几秒。top_k控制搜索结果条数。我试过1到10最终觉得5最合适。太少信息量不够太多模型会陷入阅读负担反而把核心信息忽略掉。单条结果截断长度。搜索API返回的摘要可能很长如果不截断拼接后可能占掉大量上下文窗口。我通常单条只保留前200到300字一共五条总共也就一千多字足够模型组织答案了。下面是参数建议表参数推荐值说明temperature0.7保持人设稳定与语言自然的平衡max_iterations4防止Agent无限循环调用工具top_k5搜索结果数量过多过少都不好单条摘要截断300字控制上下文长度节省Token时间范围1年默认查最近一年内容可动态调整4.3 效果对比有搜索 vs 无搜索我在同一套人设下分别跑了有搜索和无搜索两种版本对比效果。无搜索版本提问“最近半年国内有什么重要科技政策变化”回答是“我认为科技政策对产业影响深远要持续关注。”明显空而虚给不出任何具体政策名字。有搜索版本同样的问题会先搜索“科技政策 最近半年 重要变化”然后回答里出现具体政策方向、发布时间、相关影响再结合人设给出判断。虽然模型复述的准确性需要抽查但信息密度完全不一样。不过也要说一句搜索不是万能的。如果目标人物本身已经脱离公众视野很多年搜索结果可能几乎没有他的个人动态那就只能靠背景设定来撑。这种情况下搜索的主要价值是补充人物所在行业的大背景而不是检索人物本人。5. 常见问题与排查技巧5.1 搜索结果太旧或质量差搜索API默认返回结果很可能包含几年前的资讯。我一开始没加时间过滤结果用户问“最近”出的新东西模型一本正经引用老新闻非常尴尬。解决办法是优先在API请求层加时间范围参数。如果不能加就在工具函数内部做一个后置过滤根据返回里的时间字段丢弃超出范围的结果。还有一种情况是搜索词太泛导致返回内容全是门户网站首页摘要。我后来让模型在调用工具前把搜索词改写得更精准比如把“新能源怎么看”改成“新能源 行业发展趋势 2025”效果提升非常明显。5.2 Agent循环调用搜索浪费配额有一次我开着verbose跑测试一个问题让模型连续搜索了五六次每次都能看到它反复生成相似关键词明显是在无效循环。原因有两个一是搜索词太长太啰嗦二是模型对自己的答案不满意想通过多次搜索碰运气。处理方式设置max_iterations4不给它无限碰运气机会。在工具描述里写明“输入为关键词不要带标点符号”。在Prompt里加一句“如果搜索两次仍无有效信息就直接基于已有知识回答”。这些手段加上后配额消耗降低了大概三分之一响应时间也稳定了许多。5.3 数字分身突然忘记身份最让我头大的问题是在一次测试里用户问“目标人物与某位名人是朋友吗”模型搜到了相关文章后竟然开始以“我的好朋友……”的口吻说话。这明显是搜索内容污染了人设。问题根源是Prompt里人物背景和搜索结果的边界没有划清。我后来把事实处理规则加重了一级明确写“搜索材料不等于目标人物的真实记忆。只有人物背景设定中的内容才属于人设记忆。搜索结果中的他人口述只能作为第三人称信息使用。”加了这句话之后这种“人格被夺舍”的情况就很少出现了。5.4 多轮对话中记忆串味有一次用户在上一轮问了一个关于A公司的问题数字分身回答时引用了A公司的数据。下一轮用户问“你更喜欢哪个城市”模型居然回答“更喜欢A公司所在城市因为那里有我的合作项目”。这种串味让人非常出戏。排查下来的原因是对话历史里包含了上一轮的所有内容模型分不清哪些是用户提供的哪些是人物结论。我最后用摘要记忆代替了完整历史缓存每轮只留“人物最终说的一句话”用户问的原始问题不做完整保留。这样模型记住的是“人物刚说过什么”而不是“用户上一轮塞了什么资料”。6. 想清楚再动手三条实用建议聊到这儿该说点实在的了。如果你也打算给数字分身接搜索API我个人有三条建议。第一先跑通最小闭环再优化。不要一上来就搞复杂Agent先用一个最简单的LangChain Tool LLM跑通“搜索→回答”确认人设和搜索结果能共存再加记忆、加多轮、加过滤。我第一版花在调试Prompt上的时间远多于写代码就是因为架构太早复杂化。第二搜索API的返回质量永远是核心。宁可选择一个配额少但摘要质量高的接口也不要选一个量大但摘要乱的接口。省下的清洗时间远远大于省下的API费用。实测中摘要字段规整的服务模型回答准确率能提升两成以上。第三所有搜索到的内容都必须经过人设过滤。这一步不是可选项是安全底线。数字分身可以引用事实但不能因为事实就改变人物立场和语气。做好过滤整个项目看起来才像“人”而不是“搜索引擎的套皮”。这篇就写到这里。我后续打算把搜索工具扩展成可并行调用的多工具结构人物知识库再接入图谱能力。有跑通的朋友欢迎留言一起聊聊踩坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑