用 Web 开发思维理解 Agent 的三大支柱——Tools + Memory + LLM

图片来源网络,侵权联系删。

文章目录

  • [1. 引言](#1. 引言)
  • [2. 核心概念解析:Tools、Memory、LLM 如何协同工作?](#2. 核心概念解析:Tools、Memory、LLM 如何协同工作?)
    • [2.1 三大组件类比 Web 开发](#2.1 三大组件类比 Web 开发)
    • [2.2 协同工作流程(Mermaid)](#2.2 协同工作流程(Mermaid))
  • [3. 实战项目:构建"智能旅行规划助手"](#3. 实战项目:构建“智能旅行规划助手”)
    • [3.1 功能需求](#3.1 功能需求)
    • [3.2 工具定义(Tools)](#3.2 工具定义(Tools))
  • [4. 工程实现:Node.js 后端 + React 前端](#4. 工程实现:Node.js 后端 + React 前端)
    • [4.1 后端:Express + OpenAI 实现 Agent 编排](#4.1 后端:Express + OpenAI 实现 Agent 编排)
    • [4.2 前端:React 展示行程规划结果](#4.2 前端:React 展示行程规划结果)
  • [5. 关键优化:提升可靠性与用户体验](#5. 关键优化:提升可靠性与用户体验)
    • [5.1 防幻觉:强制数据驱动](#5.1 防幻觉:强制数据驱动)
    • [5.2 内存管理:防止 Token 超限](#5.2 内存管理:防止 Token 超限)
    • [5.3 错误处理](#5.3 错误处理)
  • [6. 总结与延伸:从 Demo 到生产](#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)

Hotel_API Weather_API Agent Backend Frontend User Hotel_API Weather_API Agent Backend Frontend User "帮我规划去杭州的周末行程" POST /plan { query: "...", sessionId: "abc" } 初始化 Memory + 注册 Tools LLM 分析 → 需查天气和酒店 GET /weather?city=杭州&days=2 返回天气数据 POST /search { city: "杭州", dates: [...] } 返回酒店列表 LLM 生成行程建议 返回结构化 JSON 渲染行程卡片 展示"杭州周末游"方案

关键点 :LLM 不直接访问外部世界,而是通过 Tool Call 间接操作,确保安全与可控。


3. 实战项目:构建"智能旅行规划助手"

3.1 功能需求

用户输入自然语言,如:

  • "帮我安排一个杭州的周末短途旅行"
  • "我想带家人去三亚,预算5000元"

系统需:

  1. 自动识别目的地、日期、人数、预算
  2. 调用天气 API 获取未来天气
  3. 调用模拟酒店搜索接口
  4. 生成包含天气、推荐酒店、行程建议的结构化报告

3.2 工具定义(Tools)

ts 复制代码
// src/tools/index.ts
export const TOOLS = [
  {
    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 编排

ts 复制代码
// src/server.ts
import express from 'express';
import { OpenAIApi, Configuration } from 'openai';
import { v4 as uuidv4 } from 'uuid';

const app = express();
app.use(express.json());

// 内存存储(生产环境用 Redis)
const sessions: Record<string, any[]> = {};

// 模拟工具实现
const toolsImpl = {
  get_weather_forecast: async ({ city, days = 2 }) => ({
    city,
    forecast: Array(days).fill().map((_, i) => ({
      date: new Date(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. 构建系统提示词
  const systemPrompt = `
    你是一名专业旅行顾问。请严格按以下步骤执行:
    1. 从用户输入中提取:城市、日期范围、人数、预算
    2. 调用工具获取天气和酒店信息
    3. 生成结构化 JSON 响应,格式如下:
    {
      "destination": "杭州",
      "summary": "简要行程建议",
      "weather": [...],
      "hotels": [...]
    }
  `;

  // 3. 调用 OpenAI(启用 function calling)
  const openai = new OpenAIApi(new Configuration({ apiKey: process.env.OPENAI_API_KEY }));
  const completion = await openai.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'
  });

  const message = completion.data.choices[0].message;

  // 4. 处理工具调用
  if (message.function_call) {
    const { name, arguments: argsStr } = message.function_call;
    const args = JSON.parse(argsStr);
    const result = await toolsImpl[name](args);

    // 添加工具响应到历史
    sessions[sessionId].push(
      { role: 'assistant', content: null, function_call: message.function_call },
      { role: 'function', name, content: JSON.stringify(result) }
    );

    // 二次调用生成最终回答
    const finalCompletion = await openai.createChatCompletion({
      model: 'gpt-4o',
      messages: [
        { role: 'system', content: systemPrompt },
        ...sessions[sessionId]
      ],
      response_format: { type: 'json_object' }
    });

    const finalMessage = finalCompletion.data.choices[0].message;
    sessions[sessionId].push({ role: 'assistant', content: finalMessage.content });
    
    return res.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 展示行程规划结果

tsx 复制代码
// 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 开发者完全可以用现有技术栈构建智能体

工程化实践比模型理论更重要

下一步建议

  1. 替换模拟工具为真实 API(如 OpenWeatherMap、Booking.com API)
  2. 引入向量数据库实现长期记忆(如用户偏好:"不喜欢住高层酒店")
  3. 增加流式响应(SSE / WebSocket)提升交互体验
  4. 集成 LangChain简化工具注册与内存管理

推荐资源

🌟 记住:你不是在"做 AI",而是在"用 AI 扩展你的 Web 工程能力边界"。

相关推荐
哔哔龙7 小时前
LangChain核心组件可用工具
人工智能
全栈独立开发者7 小时前
点餐系统装上了“DeepSeek大脑”:基于 Spring AI + PgVector 的 RAG 落地指南
java·人工智能·spring
dmonstererer8 小时前
【k8s设置污点/容忍】
java·容器·kubernetes
super_lzb8 小时前
mybatis拦截器ParameterHandler详解
java·数据库·spring boot·spring·mybatis
程序之巅8 小时前
VS code 远程python代码debug
android·java·python
2501_941878748 小时前
在班加罗尔工程实践中构建可持续演进的机器学习平台体系与技术实现分享
人工智能·机器学习
我是Superman丶8 小时前
【异常】Spring Ai Alibaba 流式输出卡住无响应的问题
java·后端·spring
墨雨晨曦888 小时前
Nacos
java
guoketg8 小时前
BERT的技术细节和面试问题汇总
人工智能·深度学习·bert
永远在Debug的小殿下8 小时前
SLAM开发环境(虚拟机的安装)
人工智能