图片来源网络,侵权联系删。
文章目录
- 1. 引言
- 2. 核心概念解析:Tools、Memory、LLM 如何协同工作?
- 2.1 三大组件类比 Web 开发
- 2.2 协同工作流程(Mermaid)
- 3. 实战项目:构建“智能旅行规划助手”
- 3.1 功能需求
- 3.2 工具定义(Tools)
- 4. 工程实现:Node.js 后端 + React 前端
- 4.1 后端:Express + OpenAI 实现 Agent 编排
- 4.2 前端:React 展示行程规划结果
- 5. 关键优化:提升可靠性与用户体验
- 5.1 防幻觉:强制数据驱动
- 5.2 内存管理:防止 Token 超限
- 5.3 错误处理
- 6. 总结与延伸:从 Demo 到生产
- 下一步建议
- 推荐资源
1. 引言
如果你是一名 Web 开发者,你一定熟悉这样的场景:
用户在前端填写表单 → 后端调用数据库查询用户信息 → 调用支付网关 → 发送邮件通知 → 返回成功页面
这个流程中包含了三个关键要素:
- 工具(Tools):数据库、支付接口、邮件服务
- 状态(Memory):用户会话、订单 ID、临时数据
- 逻辑(Logic):业务规则、判断分支、错误处理
而AI Agent 正是这一模式的智能化延伸:
- LLM扮演“动态业务逻辑引擎”
- Tools提供外部能力(API、函数、数据库)
- Memory维护上下文与历史状态
💡 本文将通过一个旅行规划助手实战项目,手把手带你用Node.js + React实现一个具备 Tools 调用、Memory 管理、流式响应的完整 Agent 系统,所有代码均可直接运行。
2. 核心概念解析:Tools、Memory、LLM 如何协同工作?
2.1 三大组件类比 Web 开发
| Agent 组件 | Web 开发类比 | 作用 |
|---|---|---|
| LLM | 业务逻辑层(Service Layer) | 动态决策:该调用哪个工具?如何组合结果? |
| Tools | 微服务 / API 客户端 | 封装外部能力:查天气、订酒店、搜航班 |
| Memory | Session / Vuex / Redis | 存储对话历史、用户偏好、中间状态 |
2.2 协同工作流程(Mermaid)
✅关键点:LLM 不直接访问外部世界,而是通过Tool Call间接操作,确保安全与可控。
3. 实战项目:构建“智能旅行规划助手”
3.1 功能需求
用户输入自然语言,如:
- “帮我安排一个杭州的周末短途旅行”
- “我想带家人去三亚,预算5000元”
系统需:
- 自动识别目的地、日期、人数、预算
- 调用天气 API 获取未来天气
- 调用模拟酒店搜索接口
- 生成包含天气、推荐酒店、行程建议的结构化报告
3.2 工具定义(Tools)
// src/tools/index.tsexportconstTOOLS=[{name:"get_weather_forecast",description:"获取某城市未来N天的天气预报",parameters:{type:"object",properties:{city:{type:"string",description:"城市名,如 杭州"},days:{type:"integer",minimum:1,maximum:7,default:2}},required:["city"]}},{name:"search_hotels",description:"根据城市和日期搜索可用酒店",parameters:{type:"object",properties:{city:{type:"string"},checkIn:{type:"string",format:"date"},checkOut:{type:"string",format:"date"},guests:{type:"integer",default:2}},required:["city","checkIn","checkOut"]}}];🔍 这相当于 Web 后端的OpenAPI 文档,LLM 会据此决定调用哪个“微服务”。
4. 工程实现:Node.js 后端 + React 前端
4.1 后端:Express + OpenAI 实现 Agent 编排
// src/server.tsimportexpressfrom'express';import{OpenAIApi,Configuration}from'openai';import{v4asuuidv4}from'uuid';constapp=express();app.use(express.json());// 内存存储(生产环境用 Redis)constsessions:Record<string,any[]>={};// 模拟工具实现consttoolsImpl={get_weather_forecast:async({city,days=2})=>({city,forecast:Array(days).fill().map((_,i)=>({date:newDate(Date.now()+i*86400000).toISOString().split('T')[0],condition:Math.random()>0.5?'sunny':'cloudy',temp:20+Math.floor(Math.random()*15)}))}),search_hotels:async({city,checkIn,checkOut,guests=2})=>({hotels:[{name:`${city}中心精品酒店`,price:400,rating:4.5},{name:`${city}湖景度假村`,price:600,rating:4.8}]})};app.post('/api/plan',async(req,res)=>{const{query,sessionId=uuidv4()}=req.body;// 1. 加载或初始化会话历史if(!sessions[sessionId])sessions[sessionId]=[];sessions[sessionId].push({role:'user',content:query});// 2. 构建系统提示词constsystemPrompt=`你是一名专业旅行顾问。请严格按以下步骤执行: 1. 从用户输入中提取:城市、日期范围、人数、预算 2. 调用工具获取天气和酒店信息 3. 生成结构化 JSON 响应,格式如下: { "destination": "杭州", "summary": "简要行程建议", "weather": [...], "hotels": [...] }`;// 3. 调用 OpenAI(启用 function calling)constopenai=newOpenAIApi(newConfiguration({apiKey:process.env.OPENAI_API_KEY}));constcompletion=awaitopenai.createChatCompletion({model:'gpt-4o',messages:[{role:'system',content:systemPrompt},...sessions[sessionId]],functions:TOOLS.map(tool=>({name:tool.name,description:tool.description,parameters:tool.parameters})),function_call:'auto'});constmessage=completion.data.choices[0].message;// 4. 处理工具调用if(message.function_call){const{name,arguments:argsStr}=message.function_call;constargs=JSON.parse(argsStr);constresult=awaittoolsImpl[name](args);// 添加工具响应到历史sessions[sessionId].push({role:'assistant',content:null,function_call:message.function_call},{role:'function',name,content:JSON.stringify(result)});// 二次调用生成最终回答constfinalCompletion=awaitopenai.createChatCompletion({model:'gpt-4o',messages:[{role:'system',content:systemPrompt},...sessions[sessionId]],response_format:{type:'json_object'}});constfinalMessage=finalCompletion.data.choices[0].message;sessions[sessionId].push({role:'assistant',content:finalMessage.content});returnres.json(JSON.parse(finalMessage.content!));}// 无工具调用,直接返回sessions[sessionId].push({role:'assistant',content:message.content});res.json({error:'无法解析请求'});});app.listen(3001,()=>console.log('Agent server running on http://localhost:3001'));4.2 前端:React 展示行程规划结果
// src/App.tsx import React, { useState } from 'react'; import axios from 'axios'; function App() { const [query, setQuery] = useState(''); const [result, setResult] = useState<any>(null); const [sessionId] = useState(localStorage.getItem('session') || Date.now().toString()); React.useEffect(() => { localStorage.setItem('session', sessionId); }, [sessionId]); const handleSubmit = async () => { const res = await axios.post('http://localhost:3001/api/plan', { query, sessionId }); setResult(res.data); }; return ( <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}> <h1>✈️ 智能旅行规划助手</h1> <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="例如:帮我安排杭州周末游" style={{ width: '70%', padding: '8px' }} /> <button onClick={handleSubmit} style={{ padding: '8px 16px' }}>规划行程</button> {result && ( <div style={{ marginTop: '20px' }}> <h2>目的地:{result.destination}</h2> <p><strong>建议:</strong>{result.summary}</p> <h3>🌤️ 天气预报</h3> <ul> {result.weather?.map((w: any) => ( <li key={w.date}>{w.date}: {w.condition}, {w.temp}°C</li> ))} </ul> <h3>🏨 推荐酒店</h3> <ul> {result.hotels?.map((h: any) => ( <li key={h.name}>{h.name} - ¥{h.price}/晚 ({h.rating}⭐)</li> ))} </ul> </div> )} </div> ); } export default App;5. 关键优化:提升可靠性与用户体验
5.1 防幻觉:强制数据驱动
在系统提示词中明确:
“你必须仅基于工具返回的数据生成回答。禁止编造酒店名称、天气或价格。”
5.2 内存管理:防止 Token 超限
- 限制对话历史最多保留 6 轮
- 自动摘要旧对话(如:“此前用户计划去杭州…”)
5.3 错误处理
- 工具调用失败时返回友好提示
- 前端显示加载状态和错误信息
6. 总结与延伸:从 Demo 到生产
通过本次实战,我们验证了:
✅Tools + Memory + LLM = 可控、可靠、可扩展的 Agent 架构
✅Web 开发者完全可以用现有技术栈构建智能体
✅工程化实践比模型理论更重要
下一步建议
- 替换模拟工具为真实 API(如 OpenWeatherMap、Booking.com API)
- 引入向量数据库实现长期记忆(如用户偏好:“不喜欢住高层酒店”)
- 增加流式响应(SSE / WebSocket)提升交互体验
- 集成 LangChain简化工具注册与内存管理
推荐资源
- 📦 LangChain.js —— 官方 JavaScript SDK
- 🧪 Vercel AI SDK —— 构建流式 AI 应用
- 📊 LangSmith —— 调试与监控 Agent
🌟记住:你不是在“做 AI”,而是在“用 AI 扩展你的 Web 工程能力边界”。