模型 / 数据集
jackmpcollins/magentic avatar
jackmpcollins/magentic

magentic:用 @prompt 装饰器把 LLM 调用写进 Python 函数签名

Seamlessly integrate LLMs as Python functions

2,425 个 Star127 个 ForkPythonMIT

秒懂

它是什么?
这个库把提示词模板、结构化输出和函数调用都收进 Python 的类型注解里,让 LLM 调用看起来像普通函数。适合已经在用 pydantic 的 Python 项目,但它的输出可靠性依赖模型能力,不是免费的。
适合谁用?
如果你的代码库已经用 pydantic 定义数据结构,并且希望 LLM 调用能像普通函数一样被类型检查、被单元测试、被逐层组合,magentic 的装饰器模型正好对上这个需求。如果你需要的是多智能体编排、长期记忆管理或者可视化工作流画布,这个库不提供这些,硬套只会把复杂度堆到你自己身上。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
活跃度在下降。仓库最近一次提交在 6 个月前。
用什么语言写的?
主要是 Python(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。

开源项目深度解析

它解决的是提示词散落在字符串里的问题

大多数 Python 项目调用 LLM 的方式是拼一个字符串,发给 API,再从返回的 JSON 里手动取字段。提示词和解析逻辑分居两处,改一个字段名要同时改两个地方,类型检查器对此一无所知。magentic 的做法是把提示词写成函数体为空、只有装饰器和返回类型注解的函数。README 给的例子是 `@prompt('Add more "dude"ness to: {phrase}')` 配一个 `def dudeify(phrase: str) -> str: ...`,调用 `dudeify("Hello, how are you?")` 时参数被填进模板,返回值直接就是函数声明的类型。目标读者是已经在用 pydantic 的 Python 开发者,因为返回类型可以是任何 pydantic 支持的类型,包括嵌套的 BaseModel。函数体永远不执行,这一点在阅读代码时容易让人停顿,但它是整个设计的支点:类型注解就是契约。

结构化输出靠 pydantic 模型承载,重试是补救层

返回类型为 `Superhero` 这样的 pydantic 模型时,magentic 会把模型的结构信息交给 LLM,再把返回内容解析成实例。README 的例子返回 `Superhero(name='Garden Man', age=30, power='Control over plants', enemies=['Pollution Man', 'Concrete Woman'])`,字段类型和嵌套列表都被还原。这里有一个必须说清楚的边界:LLM 不保证每次都按 schema 输出。magentic 提供 LLM-Assisted Retries,在解析失败时把错误信息回传给模型让它重试。这是补救而不是保证,重试次数、成本和最终失败率都取决于你用的模型。字段越多、嵌套越深、枚举取值越微妙,失败概率越高。如果你的 schema 里有十几个必填字段和多个联合类型,先在小样本上量一下失败率,再决定是否把这条链路放进关键路径。

FunctionCall 与 @prompt_chain 的分工

当提示词里通过 `functions=[...]` 传入普通 Python 函数时,LLM 可以选择调用其中之一,此时被装饰的函数返回一个 `FunctionCall` 对象,而不是最终答案。README 的例子中 `perform_search` 返回 `FunctionCall(<function search_twitter at 0x10c367d00>, 'LLMs', 'latest')`,需要显式调用 `output()` 才真正执行。这个设计把决定权交回给你:可以在执行前记录、校验或者拦截参数。`@prompt_chain` 则自动完成这个循环,它解析 FunctionCall、执行函数、把结果回传给 LLM,直到模型给出最终答案。README 里 `describe_weather("Boston")` 先调用 `get_current_weather` 再返回天气描述。两者的区别是控制权:`FunctionCall` 适合你需要审计或改写参数的场景,`@prompt_chain` 适合你只想要结果、不关心中间步骤的场景。另外,用这三个装饰器造出来的函数可以像普通函数一样作为 functions 传给别的装饰器,这让分层组合成为可能,也让每一层可以单独测试。

安装与 provider 配置

安装命令是 `pip install magentic` 或 `uv add magentic`。默认走 OpenAI,README 说明设置 `OPENAI_API_KEY` 环境变量即可。要换 provider,README 只给了一句指向 configuration 页面的链接,没有在正文里列出 Anthropic 或 Ollama 的具体配置键。如果你打算用 Ollama 跑本地模型,这一点需要提前去官网确认配置项名称和格式,不要凭经验猜。库本身是 MIT 许可,这意味着你可以修改、闭源分发、商用,只需要保留版权声明和许可文本。这里不做法律建议,但如果你的产品对许可证合规有内部流程,MIT 是限制最少的那一档,通常不需要额外审批。

流式与可观测性

`StreamedStr` 和 `AsyncStreamedStr` 用于边生成边消费文本,README 给出的用法是在返回类型注解里使用 `Streamed` 包装。这对需要首字节延迟的交互界面有用,但结构化输出的流式解析比纯文本复杂得多,README 没有展示部分解析失败时会发生什么。可观测性方面,库集成了 OpenTelemetry,并且有 Pydantic Logfire 的原生集成。这里要分清职责:magentic 产生 span,不负责后端存储、采样策略和告警规则。如果你所在的组织没有 OTel collector,这个特性暂时用不上。

它不是编排框架,别当成编排框架用

magentic 的抽象单位是函数,不是智能体、不是图、不是状态机。它没有内置的多智能体通信协议、没有持久化记忆层、没有可视化编排界面。如果你要构建的是多个角色互相辩论、带长期记忆和人工审批节点的系统,用 magentic 意味着这些全部要自己写。另一个容易被忽略的限制是调试体验:函数体为空意味着断点无处可下,排查问题主要靠日志和 trace,而不是单步执行。对于习惯用调试器逐行跟代码的团队,这个工作方式的转变需要适应。还有一点,README 显示 v0.41.0 到 v0.41.1 之间隔了接近五个月,而 v0.40.0 到 v0.41.0 隔了约四个月,版本节奏并不密集,0.x 的主版本号也说明 API 仍有变动空间。

和直接写 SDK 调用相比,差在哪

最直接的替代方案是直接用 openai 官方 SDK 或者 langchain 这类工具。用官方 SDK 时,你手写 messages 列表、手写 JSON schema、手写解析和重试,代码更长但每一层都可见,出问题时排查路径短。langchain 提供的是更宽的抽象层,涵盖 chain、retriever、agent executor 等概念,适合需要把向量检索、工具调用和会话历史串起来的大型应用,代价是抽象层数多、版本升级时破坏性变更频繁。magentic 的位置在两者之间:比裸 SDK 多了类型驱动的结构化输出和自动重试,比 langchain 少了编排和检索能力。判断标准很简单,如果你的 LLM 调用主要是「输入若干参数,输出一个结构化对象」,magentic 的抽象层级刚好;如果你需要的是跨会话的状态管理和多步骤规划,它覆盖不到。

编辑结论

如果你的代码库已经用 pydantic 定义数据结构,并且希望 LLM 调用能像普通函数一样被类型检查、被单元测试、被逐层组合,magentic 的装饰器模型正好对上这个需求。如果你需要的是多智能体编排、长期记忆管理或者可视化工作流画布,这个库不提供这些,硬套只会把复杂度堆到你自己身上。上手前先确认三件事:你选定的模型在结构化输出上的实际表现,因为 LLM-Assisted Retries 只是补救而不是保证;OPENAI_API_KEY 之外你还需要哪些 provider 配置项,README 指向的 configuration 页面是唯一权威来源;以及你打算如何消费 OpenTelemetry 数据,因为库本身只负责产生 span,不负责存储和展示。

官方来源

  1. jackmpcollins/magentic on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
社区笔记

社区笔记