别再用正则过滤代码了!带你彻底搞懂 AST 沙箱的必要性
“Goals tell you where you want to go. Systems determine what you actually do every day.” — Terry J. Govier
别再用正则过滤代码了!带你彻底搞懂 AST 沙箱的必要性
从“野蛮生长”的 Python REPL 到工业级的 AST 沙箱:构建金融级 Agent 的安全底座。
「如果你在处理涉及金额的金融系统,当 LLM Agent 吐出一个包含货币符号、百分号且嵌套了多重括号的计算结果时,你敢直接把这个结果写入数据库吗?」
在这篇文章中,我将带你拆解从“入门级”的 Python REPL 调用到“工业级”的 AST 沙箱架构的演进路径,教你如何构建一个不仅能跑通、而且真正具备金融级安全性的代码执行环境。
在构建 AI Agent 时,尤其是处理金融数据时,你会发现 LLM 在处理算术逻辑时表现出一种极度不稳定的“智力断层”。虽然最前沿的模型在很多任务上表现惊人,但一旦涉及到复杂的括号嵌套、财务会计符号(例如用括号表示负数损失)或混合单位的计算,它们依然极易产生幻觉。
很多初级工程师在面对这个问题时的直觉是:“既然模型算不准,那就给它个 Python 解释器(REPL)不就行了?”
这在 Demo 视频里看起来是完美的解决方案,但在生产环境中,这种做法简直是灾难的代名词。原因有两个:
- 安全漏洞的温床:直接暴露 Python 执行工具给 LLM,等于给黑客开了一扇大门。Prompt Injection 并不是玩笑,一个恶意用户只需构造包含
__import__('os').system(...)的输入,就能在毫秒内让你的 Agent 变成攻击工具。 - 极高的执行脆性:金融数据往往不是标准格式。当你面对类似
"( $100 - $80 ) / 20%"这种带有货币符号和百分号的字符串时,原生 Python 的eval()函数会因为无法解析$和%字符而直接崩溃。
真正的工业级解法:AST 沙箱执行
在 AI-FDE-Playbook 中,我实现了一套专门为金融问答优化的硬核 AST(抽象语法树)沙箱。它的核心逻辑不是试图去“修复”坏字符串,而是从语法解析层面重新定义规则:
- 预处理清洗 (Pre-processing Sanitization):在进入任何解析逻辑之前,系统会自动剥离
$符号,并将%统一转化为/100。这把不规则的“人类表达”强行对齐到标准的数学表达式上。 - AST 节点白名单 (AST Node Whitelisting):我们利用
ast.parse将表达式解析为树结构。随后,程序会遍历这棵树,仅允许执行极少数安全的二进制操作(例如ast.Add,ast.Sub)。任何试图调用外部函数、访问对象属性或进行循环的操作,在解析阶段就会被彻底拦截。
# 核心逻辑片段:src/solver/tools.py
def safe_eval_expression(expr: str) -> float:
# 1. 强制清洗脏数据
expr = expr.replace("$", "").replace("%", "/100")
# 2. 解析为 AST(抽象语法树)
node = ast.parse(expr, mode='eval').body
# 3. 仅允许白名单内的节点进行递归评估
return _eval_node(node)
错误即价值的弹性设计 (Error-as-Value Resilience)
更高级的架构设计还包含一个关键细节:永远不要让工具的异常崩溃你的主 Agent 循环。
当用户输入的内容完全不符合语法时,我们不应该让程序抛出 Exception,而是捕获它,并将其转化为一个“软提示”反馈给模型。例如:
error: invalid syntax. Hint: Use '*' for multiplication, not 'x'.
通过这种方式,LLM 可以感知到自己的逻辑错误,并在下一次迭代中根据这个提示进行自我修正。这就是高级 AI 工程师构建稳健架构的底层逻辑。在生产环境中,用正则去过滤代码逻辑,就像用筛子去过滤核武器——漏洞就在你意想不到的缝隙里。
如果你想深入了解完整的开源实现,可以参考 AI-FDE-Playbook 的工程实践。