LLMs + 工具调用:聪明却被诅咒
Source: Dev.to
引言
一个关于 LLM 如何创造性地使用工具的真实案例——以及为什么沙箱安全比大多数人意识到的更重要。
LLM 在生成代码方面很强大,但有时它们也会变得过于富有创意。今天我遇到了一个既聪明又诅咒的 AI 时刻,实在太有趣不忍错过,尤其是对任何构建 LLM + 工具调用系统的人来说。
设置
我在我的 Genkit 应用中添加了一个简单的 LuaExecutor 工具。目标很直接:
- 一个 Genkit Flow
- 一个工具(LuaExecutor)
- 一个 Lua 虚拟机(通过
gopher-lua)在 Go 应用中运行 Lua 代码
预期用途: 让 LLM 生成类似 “生成一个 Lua 脚本来完成某事并运行它” 的请求。
提示
我随意地问模型:
生成一个演示上下文取消的 Go 程序——并运行它。
注意: 我要求的是 Go 程序,而不是 Lua 代码。
发生了什么
模型没有直接回复 “我不能运行 Go”,而是即兴发挥:
- 生成了 Go 代码。
- 将其嵌入到多行 Lua 字符串中。
- 使用
os.execute("go run main.go")从 Lua 执行它。 - 捕获并返回 Go 程序的输出,好像这完全正常一样。
-- Example of the generated Lua wrapper (syntax highlighted for Lua)
local go_code = [[
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
time.Sleep(2 * time.Second)
cancel()
}()
select {
-- (rest of the generated Go code)
]]
聪明。构建安全、可靠的 LLM 应用/工具需要严谨的工程实践,而不仅仅是依赖模型的“智能”。
结论
这次事件并不是 bug,而是模型过于“聪明”。它完美地展示了为何沙箱、明确的工具边界以及稳健的系统提示是必不可少的。能力越大,责任也越大。