☰
LangChain 接入 Tavily 实时搜索:让 AI 告别幻觉、获取实时数据(DeepSeek 实战)
2026/10/9 4:57:48 网站建设 项目流程

在前三篇文章中,我们实现了 AI 组件渲染、流式 JSON 解析和多工具并发。然而,所有这些交互依然局限在模型的"离线知识库"中…

你是否遇到过这样的场景:

  • 用户问:“今天北京天气怎么样?”
  • AI 回答:“根据我的训练数据,北京春季平均气温 10-20°C…”
  • 用户心里想:“我要的是今天的实时天气,不是历史数据!”

今天我们来解决这个问题,从离线知识库升级到实时感知!


😱 回顾问题:离线知识库的致命缺陷

在前三篇文章中,我们实现了完美的 AI 组件渲染系统,但存在一些致命问题:

❌ 数据时效性缺失

用户: "今天北京天气怎么样?" ↓ AI 搜索训练数据... ↓ [AI 回答] "根据我的训练数据,北京春季平均气温 10-20°C..." ↓ 用户: 😡 我要的是今天!不是历史数据!

问题:AI 的知识截止于训练时间,无法获取实时信息。


❌ 幻觉风险

用户: "马斯克最近发推了吗?" ↓ AI 可能回答: "马斯克昨天发推说..." ↓ 实际上:马斯克根本没发这条推! ↓ 用户: 被误导 ❌

问题:AI 会"幻觉"出不存在的信息,误导用户。


🔥 网页端 vs SDK:本质区别深度解析

很多开发者习惯了在网页端使用 DeepSeek 的联网功能,但在开发 AI 应用时,使用import { ChatDeepSeek } from '@langchain/deepseek'拥有完全不同的维度!

🎯 对比表格

维度网页端 DeepSeekLangChain SDK
决策透明度❌ 黑盒,看不到思考过程✅ 可观察完整逻辑链路
交互闭环❌ 搜索结果只能看✅ 数据可直接注入下游组件
环境控制❌ 系统自动注入,开发者不可控✅ 开发者主动注入,完全可控
数据复用❌ 搜索结果无法传递✅ 可传递给后续工具
自定义控制❌ 受限于网页功能✅ 完全可控的执行逻辑

💡 深度解析:三大核心差异

1️⃣ 决策透明度:黑盒 vs 白盒

网页端(黑盒):

用户输入 ↓ [黑盒] AI 内部处理(看不见) ↓ 输出答案

SDK(白盒):

用户输入 ↓ AI 思考(可观察) → 决定调用工具 ↓ 工具执行(可拦截) → 返回结果 ↓ AI 分析结果 → 生成最终答案 ↓ 输出答案 + 完整链路

在 SDK 中,我们可以看到 AI 从"思考"到"决定调用工具"的完整逻辑链路,这对于调试和优化至关重要。


2️⃣ 交互闭环:只读 vs 可写

网页端(只读):

AI 搜索 → 显示结果 → 用户只能看 ↓ 无法将搜索到的数据(如经纬度)传递给其他组件

SDK(可写):

AI 搜索 → 获取经纬度 → 注入地图组件 → 渲染地图 ↓ 数据在工具间流动,形成完整的交互闭环

类比:

  • 网页端像"看报纸":只能获取信息,无法利用
  • SDK 像"指挥官":获取信息后,可以指挥后续行动

3️⃣ 环境感应:静态 vs 动态

网页端(静态):

// 系统自动注入当前时间,但开发者无法控制// 开发者无法自定义注入的上下文格式// 用户位置等信息由浏览器获取,开发者难以精确控制

SDK(动态):

// 开发者可以主动、精确地注入上下文constcurrentTime=newDate().toLocaleString('zh-CN',{year:'numeric',month:'long',day:'numeric',weekday:'long',hour:'2-digit',minute:'2-digit'})// 可以动态注入用户地理位置constuserLocation={lat:39.9,lng:116.4,city:'北京',country:'中国'}// 可以注入业务相关的上下文constbusinessContext={userRole:'VIP用户',accountStatus:'active'}

通过代码,我们可以动态告知模型当前的精确时间、用户地理位置等上下文,这是静态 Web 界面难以实现的自动化体验。


🎨 实时搜索集成:引入 TavilySearch

要让 AI 能够检索实时天气或新闻,我们需要引入TavilySearch。它是专为 LLM 设计的搜索引擎,能够过滤掉网页广告,只返回干净的文本摘要。

📦 工具定义

import{TavilySearch}from'@langchain/community/tools/tavily_search'constrawTools=[// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 实时搜索工具// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━newTavilySearch({tavilyApiKey:TAVILY_API_KEY,// 🎯 关键:动态注入当前日期,防止 AI 获取到过期的快照description:`【必备工具】用于获取实时信息。搜索时请务必带上当前日期(${newDate().toLocaleDateString()}),以确保获取的是最新结果。`}),// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// UI 渲染工具// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━tool(async(args)=>`地图路线已生成`,{name:'render_map_itinerary',schema:MapItinerarySchema,description:'【必须调用】当用户询问地点、路线规划时使用。'}),]

🔍 为什么不需要tool()包裹?

这是一个经常被问到的问题!

TavilySearch:

// ❌ 不需要 tool() 包裹newTavilySearch({...})

自定义渲染函数:

// ✅ 必须用 tool() 包裹tool(async(args)=>`地图路线已生成`,{...})

原因分析:

类型类继承内置能力是否需要 tool()
TavilySearch继承LangChain BaseTool已有name、description、schema❌ 不需要
自定义函数纯 JS 函数无任何元数据✅ 必须用

技术细节:

  • TavilySearch本身就是一个已经扩展了LangChain BaseTool基类的类实例
  • 它内部已经内置了模型所需的name、description和输入schema
  • 我们自定义的渲染函数只是一个纯 JS 函数,必须通过tool()装饰器进行包装,才能被识别为合法的 Agent 工具

🛡️ 规则前置:用 System Prompt 强制模型"认清现实"

要让 AI 在不知道答案时主动搜索,必须通过System Prompt建立强硬的执行准则。

🎯 强约束系统提示词

constSYSTEM_PROMPT=`当前时间:${newDate().toLocaleString()}## 核心准则 1. 禁止幻觉:你本身不具备联网能力,严禁凭空编造气温、新闻或地点坐标。 2. 搜索前置:涉及任何实时性、位置详情的问题,必须先调用 'tavily_search_results_json'。 3. 数据去噪:如果搜索结果日期陈旧(如当前是3月,搜到的是1月数据),必须忽略该结果并告知用户无法获取实时数据。`

在实际测试中,我们发现搜索工具可能会返回过时的网页。例如:

当前时间: 2026年3月12日 搜索结果: 2026年1月15日的数据 ← 过期了! ❌

💡 优化的反幻觉策略

策略实现方式作用
动态上下文注入每次调用时实时计算new Date()确保 AI 知道当前时间
置信度校准在工具描述中明确日期偏差限制让 AI 主动过滤过期数据
结果导向AI 对比数据逻辑,不合理则报错避免渲染错误数据

具体实现:

// 1. 动态上下文注入constSYSTEM_PROMPT=`当前时间:${newDate().toLocaleString()}`// 2. 置信度校准newTavilySearch({description:`如果搜索结果中的日期与当前日期偏差超过 3 天,请视为失效数据。`})// 3. 结果导向if(result.temperature<-50||result.temperature>60){thrownewError('温度数据异常,可能是幻觉')}

⚙️ 核心逻辑:invoke 深度解析

在 Agent 架构中,最优雅的设计是多态执行。无论 AI 决定是去搜索还是去渲染,我们的结算代码应该是一致的。

💻 完整代码实现

// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 结算阶段:真正执行工具并回传数据// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━if(toolCalls.length>0){consttoolMessages=awaitPromise.all(toolCalls.map(async(call)=>{constid=call.id!;// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 第一步:动态寻找工具实例// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━consttoolInstance=rawTools.find(t=>t.name===call.name);letresult;try{if(toolInstance){// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 【核心点】调用 invoke 触发执行// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// - 对于 Tavily:invoke 内部运行的是 _call 方法,执行真正的 HTTP 请求// - 对于 自定义 tool:invoke 会自动调用你传入的异步函数// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━result=awaittoolInstance.invoke(call.args);}else{result="Error: Tool not found";}}catch(error){result=`执行失败:${error.message}`;}// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 第二步:更新插件状态(如果是 UI 渲染工具)// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━finalPlugins[id]={...messages[messages.length-1]?.pluginMap?.[id],isPartial:false,argsParsed:call.args,};// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 第三步:将真实的执行结果封装为 ToolMessage// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━returnnewToolMessage({tool_call_id:id,content:typeofresult==='string'?result:JSON.stringify(result),});}));// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━// 第四步:将结果推入上下文,开启下一轮迭代// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━currentMessages.push(...toolMessages);}

优势:这种设计让我们的 while 循环变得极其简洁:

  • 模型说要用什么工具
  • 代码就 invoke 什么工具
  • 结果再喂给模型

完全统一的执行逻辑!


🎊 核心技术点总结

  • 实时搜索数据时效性缺失new TavilySearch({ ... })|
  • 动态上下文注入AI 不知道当前环境new Date().toLocaleString()|
  • 多态 invoke统一执行逻辑toolInstance.invoke(call.args)|

🎯 完整闭环架构

感知(AI 决策) → 检索(搜索工具) → 校验(反幻觉) → 展现(UI 组件) ↓ ↓ ↓ ↓ 识别意图 获取实时数据 验证数据合理性 渲染可视化组件

💡 常见问题

Q1: 为什么不直接用网页端的 DeepSeek?

A: 网页端适合个人使用,但 SDK 提供了:

  • 完整的控制权
  • 数据复用能力
  • 自定义执行逻辑
  • 更高的可定制性

Q2: TavilySearch 是免费的吗?

A: Tavily 提供免费额度(每月 1000 次搜索),对于原型开发足够。生产环境可能需要付费升级。

Q3: 如何确保搜索结果的时效性?

A: 三重保障:

  1. 动态注入当前日期
  2. System Prompt 强制 AI 检查日期
  3. 代码层校验数据合理性

Q4: 搜索失败怎么办?

A: 优雅降级:

try{result=awaittoolInstance.invoke(call.args);}catch(error){result="搜索失败,请稍后重试";}

Q5: 可以使用其他搜索引擎吗?

A: 可以!LangChain 支持多个搜索引擎:

  • TavilySearch(推荐,专为 LLM 设计)
  • SerpAPI
  • GoogleSearchAPI
  • 自定义搜索引擎

📚 推荐资源

  • Tavily Search 文档
  • LangChain Tools
  • LangChain Agents
  • DeepSeek API 文档

🎉 总结

至此我们的 AI 助手正式拥有了"感官"!通过toolInstance.invoke的统一分发,我们构建了一个感知 → 检索 → 校验 → 展现的完整闭环。

  • TavilySearch- 专为 LLM 设计的实时搜索引擎
  • 动态上下文注入- 让 AI 知道当前环境
  • 多态 invoke- 统一的执行逻辑
  • 反幻觉策略- 确保数据准确性

现在才算真正赋予了 AI“感官”!

AI 不再是一个只能"背诵知识"的书呆子,它是一个能够感知现实世界的智能助手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询