DoorDash 如何让购物助手不只依赖大模型:Agent、MCP 工具与持久记忆的协同架构

2026-07-13 28 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

对话式购物助手很容易做出一个演示:把商品列表塞进提示词,再让大模型生成推荐。但进入真实交易链路后,价格是否仍然有效、商品能否配送、用户是否过敏、购物车里已有何物,都不能靠模型猜测。

DoorDash 在介绍 Ask DoorDash 时,强调的正是这种工程边界:LLM 负责理解和表达,专用 AI Agent 负责拆解任务,MCP 工具连接实时后端,智能层则保存消费者的持久记忆。公开的早期结果显示,该系统带来了最高 24% 的结账转化率提升、17% 的购物篮金额增长;使用记忆支持的会话后,意图识别准确度也有所改善。

LLM 是交互入口,不是事实数据库

购物请求往往同时包含偏好、约束和实时状态。例如:

帮我找一家还营业的餐厅,给两个人点一顿不含花生、预算 40 美元以内的晚餐,最好和上周那次差不多。

这句话至少需要处理五类信息:

  • 当前意图:搜索并构建一份晚餐订单。
  • 长期偏好:用户喜欢什么菜系或商家。
  • 强约束:花生过敏、预算上限和用餐人数。
  • 历史上下文:上周点过什么。
  • 实时数据:营业状态、库存、价格、配送范围和费用。

LLM 可以把自然语言转成结构化任务,但不能凭已有参数知识可靠回答实时问题。更稳妥的职责划分是:

  1. LLM 解析意图、补齐缺失信息并组织回复。
  2. Agent 根据任务类型选择搜索、推荐、购物车或订单等流程。
  3. MCP 工具以明确的输入输出契约访问后端能力。
  4. 智能层合并持久记忆、当前会话和实时业务数据。
  5. 确定性服务执行价格计算、库存校验与购物车修改。

这样即使模型生成了一条听起来合理的建议,系统仍会在展示或执行前用后端数据验证它。

专用 Agent 缩小每次决策的范围

单个通用 Agent 如果同时负责检索、推荐、预算计算和下单,提示词会越来越长,工具选择也更容易出错。专用 Agent 可以把问题拆成边界清晰的子任务,例如:

  • 搜索 Agent:理解品类、菜系、地理位置和营业状态。
  • 推荐 Agent:结合偏好、历史行为和候选商品进行排序。
  • 购物车 Agent:处理数量、替代品、预算与冲突检查。
  • 订单 Agent:查询进行中的订单或售后状态。

这类拆分的价值不只在于提示词更短。每个 Agent 可以拥有独立的工具白名单、超时策略、评估集和降级路径。推荐 Agent 可以读取偏好,却不应直接提交订单;购物车 Agent 可以提出修改方案,但高风险操作仍应要求用户确认。

MCP 在这里承担的是工具协议层角色。模型看到的不是数据库连接或内部 RPC,而是带名称、参数和返回结构的业务工具。工具契约越具体,模型越不容易把“搜索商品”和“修改购物车”混为一谈。

持久记忆必须区分偏好与事实

记忆支持的会话能够提升意图准确度,但“记住一切”并不是合格设计。购物助手至少要区分三类状态:

状态 示例 建议生命周期
当前会话 “这次给 4 个人吃” 会话结束后过期
稳定偏好 偏爱素食、常买某品牌 跨会话保存,可由用户修改
敏感约束 食物过敏、饮食禁忌 显式确认,展示来源和更新时间

历史偏好只适合参与排序,不能覆盖本次明确表达。例如用户过去常点牛肉,但当前说“今天吃素”,当前约束必须拥有更高优先级。过敏信息也不能只依赖模型从旧对话中总结;执行前应重新校验,并允许用户查看、纠正或删除记忆。

此外,实时数据与记忆发生冲突时,应以实时后端为准。记忆可以说明“用户常买某商品”,却不能证明该商品今天有库存或价格未变。

可以这样实践:一个可运行的最小编排器

下面是一个假设性示例,用标准库模拟 Agent 路由、MCP 风格工具注册、会话状态和持久偏好。它不是 DoorDash 的内部实现,但可以作为接入真实 LLM、数据库和 MCP Server 前的项目骨架。

将代码保存为 shopping_assistant.py,使用 Python 3.10 及以上版本运行。实际接入时,把 classify_intent 替换为返回结构化 JSON 的模型调用,把两个工具函数替换为后端或 MCP 客户端。

from dataclasses import dataclass, field
from typing import Any, Callable

Tool = Callable[..., dict[str, Any]]


@dataclass
class Memory:
    preferences: dict[str, Any] = field(default_factory=dict)
    sessions: dict[str, list[dict[str, str]]] = field(default_factory=dict)

    def context(self, user_id: str, session_id: str) -> dict[str, Any]:
        return {
            "preferences": self.preferences.get(user_id, {}),
            "recent_turns": self.sessions.get(session_id, [])[-4:],
        }

    def append(self, session_id: str, role: str, content: str) -> None:
        self.sessions.setdefault(session_id, []).append(
            {"role": role, "content": content}
        )


class ToolRegistry:
    def __init__(self) -> None:
        self._tools: dict[str, Tool] = {}

    def register(self, name: str, tool: Tool) -> None:
        self._tools[name] = tool

    def call(self, name: str, **arguments: Any) -> dict[str, Any]:
        if name not in self._tools:
            raise ValueError(f"Tool not allowed: {name}")
        return self._tools[name](**arguments)


def search_catalog(query: str, vegetarian: bool = False) -> dict[str, Any]:
    # Replace this fixture with live catalog, availability and delivery data.
    products = [
        {"id": "meal-1", "name": "Vegetable curry", "price": 14.0,
         "vegetarian": True, "available": True},
        {"id": "meal-2", "name": "Chicken bowl", "price": 16.0,
         "vegetarian": False, "available": True},
    ]
    matches = [
        item for item in products
        if item["available"] and (not vegetarian or item["vegetarian"])
    ]
    return {"query": query, "items": matches}


def price_cart(item_ids: list[str], budget: float) -> dict[str, Any]:
    prices = {"meal-1": 14.0, "meal-2": 16.0}
    total = sum(prices[item_id] for item_id in item_ids)
    return {"item_ids": item_ids, "total": total, "within_budget": total <= budget}


def classify_intent(message: str) -> str:
    # In production, use constrained model output such as an enum or JSON schema.
    return "recommend" if any(word in message.lower() for word in ["find", "meal", "推荐"]) else "unknown"


def handle(message: str, user_id: str, session_id: str,
           memory: Memory, tools: ToolRegistry) -> dict[str, Any]:
    memory.append(session_id, "user", message)
    context = memory.context(user_id, session_id)
    intent = classify_intent(message)

    if intent != "recommend":
        answer = "I need more detail about what you want to shop for."
        memory.append(session_id, "assistant", answer)
        return {"intent": intent, "answer": answer}

    vegetarian = bool(context["preferences"].get("vegetarian", False))
    results = tools.call("catalog.search", query=message, vegetarian=vegetarian)
    candidate_ids = [item["id"] for item in results["items"][:2]]
    cart = tools.call("cart.price", item_ids=candidate_ids, budget=40.0)

    answer = (
        f"Found {len(candidate_ids)} available option(s). "
        f"Live total: ${cart['total']:.2f}; within budget: {cart['within_budget']}."
    )
    memory.append(session_id, "assistant", answer)
    return {"intent": intent, "answer": answer, "cart_preview": cart}


if __name__ == "__main__":
    memory = Memory(preferences={"user-42": {"vegetarian": True}})
    tools = ToolRegistry()
    tools.register("catalog.search", search_catalog)
    tools.register("cart.price", price_cart)

    result = handle(
        "Find a meal for two under $40",
        user_id="user-42",
        session_id="session-1",
        memory=memory,
        tools=tools,
    )
    print(result)

运行命令:

python shopping_assistant.py

这个骨架刻意把“理解”和“执行”分开。生产环境还应在工具层增加身份认证、权限控制、幂等键、超时、重试和审计日志,并在修改购物车或提交订单前加入显式确认。

上线时盯住业务结果,也要盯住失败路径

转化率和购物篮金额能说明助手是否创造了交易价值,但不能单独证明系统可靠。落地时可以同时检查:

  • 意图识别准确率,以及低置信度请求的澄清率。
  • 工具选择正确率、参数有效率和后端调用失败率。
  • 推荐商品展示前的价格、库存与配送资格校验率。
  • 记忆命中后真正改善结果的比例,以及错误记忆的纠正成本。
  • 用户确认前发生写操作的次数,理想值应为零。
  • 延迟、模型成本,以及工具失败时的降级体验。

Ask DoorDash 的架构传递了一个清晰信号:交易型 AI 的核心竞争力并不是让模型说得更像导购,而是把模型限制在它擅长的理解与生成环节,再用 Agent、工具契约、持久记忆和实时后端共同完成可验证的决策。对于准备落地购物助手的团队,这通常比不断扩大提示词更值得投入。


相关推荐