使用存储过程构建安全的电子商务聊天代理
I’m happy to translate the article for you, but I’ll need the full text of the post (the content you’d like translated). Could you please paste the article’s body here? Once I have the text, I’ll provide a complete Simplified Chinese translation while preserving the source line, formatting, markdown, and any code blocks.
背景
最近,我尝试为一个特定的电商平台构建一个 GPT‑类聊天代理——不是通用聊天机器人,也不是演示,而是面向真实产品的助理,能够回答诸如:
- “我的订单在哪里?”
- “我可以退款吗?”
- “显示我的最近一次购买。”
为实现这一点,代理必须 访问真实的生产数据——订单、发货、付款。就在这时,我遇到了一个重要的问题。
我遇到的问题
一旦代理需要数据库访问,就会出现一个诱人的想法:
“为什么不直接让 LLM 根据用户的问题生成 SQL 呢?”
听起来很简单,在演示中也能工作,但在真实的电子商务系统中,这很快就会变得危险。
场景
您正在为特定的电子商务平台构建聊天应用程序。聊天代理支持:
- 订单状态查询
- 发货与送达跟踪
- 退款资格检查
- 购买历史摘要
- 与账户相关的问题
这不是通用 GPT。它是一个平台绑定的助理,能够访问敏感的用户数据。
核心问题
聊天代理经常需要访问数据库。一个常见但不安全的方法是:
- 与 LLM 共享数据库模式。
- 要求 LLM 根据用户输入生成 SQL。
- 直接执行该 SQL。
在生产环境中,这种做法会失败。
为什么 LLM‑生成的 SQL 是个坏主意
安全风险
- 提示注入可能操纵查询。
- 过于宽泛的
SELECT *查询会泄露敏感数据。 - 可能导致特权提升。
幻想查询
- 不存在的表或列。
- 错误的连接。
- 错误的业务逻辑。
缺乏治理
- 没有明确的允许查询的合同。
- 难以审计数据访问。
- 模式更改会破坏提示。
核心原则
LLMs 应该决定 要实现的意图,而不是 如何查询数据。
这与传统的后端设计相呼应。
正确的架构:将存储过程作为代理工具
高层流程

关键设计规则
- 数据库逻辑位于 存储过程 中。
- LLM 永不直接看到表名或列。
- 代理仅选择 调用哪个过程。
第一步:定义存储过程(数据库层)
获取最新订单
CREATE PROCEDURE get_latest_order (
IN p_user_id BIGINT
)
BEGIN
SELECT
order_id,
order_status,
total_amount,
created_at
FROM orders
WHERE user_id = p_user_id
ORDER BY created_at DESC
LIMIT 1;
END;
- ✔ 强制执行用户级数据隔离。
- ✔ 不向代理暴露模式。
获取订单的运输状态
CREATE PROCEDURE get_order_shipping_status (
IN p_order_id BIGINT,
IN p_user_id BIGINT
)
BEGIN
SELECT
shipping_provider,
tracking_number,
shipping_status,
estimated_delivery
FROM shipments
WHERE order_id = p_order_id
AND user_id = p_user_id;
END;
- ✔ 在数据库层进行所有权验证。
- ✔ 防止跨用户访问。
第2步:将过程公开为代理工具
LLM 从不直接看到 SQL;它看到的是 工具:
[
{
"name": "get_latest_order",
"description": "Get the most recent order for the authenticated user",
"parameters": {}
},
{
"name": "get_order_shipping_status",
"description": "Get shipping details for a specific order",
"parameters": {
"order_id": "number"
}
}
]
用户身份由系统注入——而不是由 LLM 注入。
第3步:Agent Reasoning Flow
User Message
Where is my last order?
Agent Behavior
- Identify intent: order inquiry。
- No order ID provided → call
get_latest_order。 - Use the returned
order_idto callget_order_shipping_status。
步骤 4:用户响应
Your latest order was placed on March 2.
Status: Shipped
Carrier: Yamato
Tracking Number: 1234‑5678
Estimated Delivery: March 6
高级示例:退款资格
存储过程
CREATE PROCEDURE check_refund_eligibility (
IN p_order_id BIGINT,
IN p_user_id BIGINT
)
BEGIN
SELECT
CASE
WHEN order_status = 'DELIVERED'
AND DATEDIFF(NOW(), delivered_at) <= 7
THEN 'ELIGIBLE'
ELSE 'NOT_ELIGIBLE'
END AS refund_status
FROM orders
WHERE order_id = p_order_id
AND user_id = p_user_id;
END;
业务规则保持 不在提示中。
为什么这种设计有效
默认安全
- 没有任意的 SQL 执行。
- 严格的访问边界。
- 最小的影响范围。
无幻觉
- 大语言模型无法凭空创建表或连接。
- 只能调用允许的操作。
强大的可观测性
每次调用都可以记录,例如:
user_id=123
tool=check_refund_eligibility
order_id=88921
timestamp=2026-01-06T12:34:56Z
存储过程 vs. LLM 生成的 SQL
| 方面 | LLM 生成的 SQL | 存储过程 |
|---|---|---|
| 安全性 | ❌ 有风险 | ✅ 安全 |
| 幻觉 | ❌ 常见 | ✅ 不会出现 |
| 审计 | ❌ 困难 | ✅ 容易 |
| 模式更改 | ❌ 会导致提示失效 | ✅ 隔离处理 |
| 企业级准备 | ❌ 否 | ✅ 是 |
最后思考
聊天代理看起来很新颖,但后端基础仍然适用。
把你的数据库当作私有 API 来对待。
存储过程为你提供:
- 安全性
- 稳定性
- 可观测性
- 企业级控制
这就是构建 真实、可投入生产的电子商务聊天代理 的方式——而不是演示。