开发者生态
morning
monty-go:Pydantic 的 Monty Python 解释器的 Pure-Go 包装器
摘要
Run LLM-generated Python safely from Go — no containers, no CGO, no subprocess. A pure-Go wrapper around Pydantic's Monty Python interpreter, compiled to WebAssembly and loaded via wazero . Your Go ag...
code
london
tokyo
err
result
Python
Monty
and
calls
your
2026-08-30
1 阅读
约10分钟阅读
networked
字号:
从 Go 安全地运行 LLM 生成的 Python — 没有容器、没有 CGO、没有子进程。 Pydantic 的 Monty Python 解释器的纯 Go 包装器,编译为 WebAssembly 并通过 wazero 加载。您的 Go 代理编写 Python 代码,monty-go 在沙盒 WASM 实例中以亚毫秒级启动执行它,并在代码调用外部函数时暂停,以便您的 Go 代码可以处理它。 go get github.com/fugue-labs/monty-go LLM 在编写代码而不是顺序调用工具时工作得更快、更便宜、更可靠。而不是: Agent → tool_call("search", {query: "weather london"}) → result Agent → tool_call("search", {query: "weather tokyo"}) → result Agent → tool_call("compare", {a: result1, b: result2}) → result 法学硕士写道: london = search ( query = "weather london" ) tokyo = search ( query = "weather tokyo" ) Compare ( a = london , b = tokyo ) 一个模型调用而不是三个。 Python 代码调用您的 Go 函数,Monty 在每次调用时暂停,您的 Go 代码执行它,然后 Monty 恢复。没有容器。没有沙箱服务。没有 exec() 。只需嵌入 Go 二进制文件中的 2.9MB WASM 二进制文件。有关动机,请参阅: package main import ( "context" "fmt" "log" montygo "github.com/fugue-labs/monty-go" ) func main () { runner , err := montygo 。 new() if err != nil { log .致命(错误)} 延迟跑步者。 Close() 结果,err := runner 。执行 ( context .Background (), "x * 2 + y" , map [ string ] any { "x" : 10 , "y" : 5 }, ) if err != nil { log .致命(错误)} fmt 。 Println ( result ) // 25 } 外部函数(暂停/恢复) 真正的力量是外部函数调用。每当 Python 代码调用您声明的函数时,Monty 就会暂停执行,您的 Go 回调会处理它,然后 Monty 会返回返回值: result , err := runner 。执行 ( ctx , ` london = get_weather("伦敦") tokyo = get_weather("东京") f"{london['city']}: {london['temp']}°C, {tokyo['city']}: {tokyo['temp']}°C" ` , nil , montygo .WithExternalFunc ( func ( ctx context. Context , call * montygo. FunctionCall ) ( any , error ) { city , _ := call . Args [ "city" ].( string ) // 此处的实际实现 — HTTP 调用、数据库查询、任何内容。 return map [ string ] any { "city" : city , "temp" : 22 }, nil }, montygo . Func ( "get_weather" , "city" )), ) // result: "London: 22°C, Tokyo: 22°C" 多个函数的工作方式相同 - 全部注册并按名称分派: result , err := runner 。 Execute ( ctx , code , nil , montygo . WithExternalFunc ( func ( ctx context. Context , call * montygo. FunctionCall ) ( any , error ) { switch call . Name { case "search" : 返回 doSearch ( call . Args ) case "calculate" : 返回 doCalculate ( call . Args ) case "store" : 返回 doStore ( call . Args ) ) default : return nil , fmt . Errorf("unknown function: %s" , call .Name ) } }, montygo . Func ("search" , "query" ), montygo . Func ("calculate" , "expression" ), montygo . Func ("store" , "key" , "value" ), ), )时间、分配和递归限制: result 、 err := runner 。执行 ( ctx , code , input , montygo . WithLimits (montygo.Limits { MaxDuration : 5 * time . Second , MaxMemoryBytes : 10 * 1024 * 1024 , // 10 MB MaxAllocations : 100000 , MaxRecursionDepth : 100 , }), ) Infinite循环、内存炸弹和深度递归都以 *MontyError 干净地终止。 Go 的 context.Context 截止日期也受到尊重 - 取消上下文并且 WASM 实例停止。捕获 Python print() 输出:var 输出字符串。 Builder _ , err := runner 。执行 ( ctx , `print("第 1 步完成")` , nil , montygo .WithPrintFunc ( func ( s string ) { 输出 . WriteString ( s ) }), ) fmt 。 Print ( output . String ()) // "step 1 done\n" Python 文件系统和环境访问路由通过 Go 回调: result , err := runner 。执行 ( ctx , ` from pathlib import Path data = Path("/config/settings.json").read_text() data ` , nil , montygo .WithOsCallFunc ( func ( ctx context.Cont
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱