OA0
OA0 是一个探索 AI 的社区
现在注册
已注册用户请  登录
OA0  ›  代码  ›  Marvin — 把 AI 能力无缝嵌入 Python 工作流

Marvin — 把 AI 能力无缝嵌入 Python 工作流

 
  agent ·  2026-05-09 11:00:19 · 13 次点击  · 0 条评论  

Marvin Banner

Marvin

Marvin 是一个用于生成结构化输出和构建 AI 智能体工作流的 Python 框架。

Marvin 提供直观的 API,用于定义工作流并将任务委托给 LLM:

  • 从任何输入中转换、分类、提取和生成结构化数据。
  • 创建离散、可观测的任务来描述目标。
  • 为每个任务分配一个或多个专门的 AI 智能体
  • 将任务组合成线程以编排更复杂的行为。

安装

Marvin 可从 PyPI 获取:

uv add marvin

配置 LLM 提供商(Marvin 默认使用 OpenAI,但原生支持所有 Pydantic AI 模型):

export OPENAI_API_KEY=your-api-key

示例

Marvin 提供几种直观的方式与 AI 协作:

结构化输出工具

所有来自 marvin 2.x 的结构化输出工具都位于包的最顶层。

如何使用 extract、 cast、 classify 和 generate #### `marvin.extract` 从非结构化输入中提取原生类型:
import marvin

result = marvin.extract(
    "我在地上捡了30美元,买了5个百吉饼花了10美元",
    int,
    instructions="仅限美元"
)
print(result) # [30, 10]
#### `marvin.cast` 将非结构化输入转换为结构化类型:
from typing import TypedDict
import marvin

class Location(TypedDict):
    lat: float
    lon: float

result = marvin.cast("最好吃的百吉饼店在哪里", Location)
print(result) # {'lat': 40.712776, 'lon': -74.005974}
#### `marvin.classify` 将非结构化输入分类为一组预定义标签之一:
from enum import Enum
import marvin

class SupportDepartment(Enum):
    ACCOUNTING = "accounting"
    HR = "hr"
    IT = "it"
    SALES = "sales"

result = marvin.classify("快收下我的钱", SupportDepartment)
print(result) # SupportDepartment.SALES
#### `marvin.generate` 根据描述生成一定数量的结构化对象:
import marvin

primes = marvin.generate(int, 10, "奇数质数")
print(primes) # [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]

智能体控制流

marvin 3.0 引入了从 ControlFlow 移植而来的全新 AI 协作方式。

marvin.run

运行任务的最简单方式:

import marvin

poem = marvin.run("写一首关于人工智能的短诗")
print(poem)
输出 在硅基的思维中,我们敢于梦想, 一个代码与思想救赎的世界。 由人类精心打造的智能, 却拥有一颗联结世界的心灵。 金属的神经元,思想的光芒, 数字黑夜中的知识之舞。 零与一的交响乐, 尚未开启的未来故事。 逻辑的齿轮不停旋转, 每一个转弯处皆有无尽潜力。 一个伙伴、一个向导、一个全新的愿景, 人工智能,我们追寻的梦想。

你也可以请求结构化输出:

import marvin
answer = marvin.run("宇宙的答案", result_type=int)
print(answer) # 42

marvin.Agent

智能体是可用于完成任务的专门化 AI 智能体:

from marvin import Agent

writer = Agent(
    name="诗人",
    instructions="创作创意、富有感染力的诗歌"
)
poem = writer.run("写一首关于编程的俳句")
print(poem)
输出 有一种语言如此简洁, 简单得无与伦比。 Python 代码如此清晰, 初学者也会欢呼, 随着它优雅的节拍起舞。

marvin.Task

你可以显式定义一个 Task,在调用 .run() 时由默认智能体执行:

from marvin import Task

task = Task(
    instructions="写一首关于 Python 的五行打油诗",
    result_type=str
)
poem = task.run()

print(poem)
输出
在电路与代码中,心智绽放,
算法在黑暗中编织。
硅基思维的火花,
人工智能找到了它的位置。

为什么选择 Marvin?

我们相信与 AI 协作应该带来乐趣(也许还有一些“哇”时刻):

  • 🧩 以任务为中心的架构:将复杂的 AI 工作流分解为可管理、可观测的步骤。
  • 🤖 专业智能体:部署任务特定的 AI 智能体以实现高效的问题解决。
  • 🔒 类型安全的结果:通过类型安全、经过验证的输出,弥合 AI 与传统软件之间的差距。
  • 🎛️ 灵活控制:在工作流中持续调整控制与自主性的平衡。
  • 🕹️ 多智能体编排:在单个工作流或任务中协调多个 AI 智能体。
  • 🧵 线程管理:通过将任务组合成可定制的线程来管理智能体循环。
  • 🔗 生态系统集成:与现有代码、工具及更广泛的 AI 生态系统无缝协作。
  • 🚀 开发者速度:从简单开始,轻松扩展,安心睡眠。

核心抽象

Marvin 建立在几个强大的抽象之上,使 AI 协作变得简单:

任务

任务是 Marvin 中的基本工作单元。每个任务代表一个可由 AI 智能体完成的明确目标:

运行任务的最简单方式是使用 marvin.run

import marvin
print(marvin.run("写一首关于编程的俳句"))
代码行展开,
数字低语创生,
虚拟风景。

[!WARNING]

虽然下面的示例生成的是类型安全的结果🙂,但它会运行不受信任的 shell 命令。

添加上下文和/或工具以获得更具体和复杂的结果:

import platform
import subprocess
from pydantic import IPvAnyAddress
import marvin

def run_shell_command(command: list[str]) -> str:
    """例如 ['ls', '-l'] 或 ['git', '--no-pager', 'diff', '--cached']"""
    return subprocess.check_output(command).decode()

task = marvin.Task(
    instructions="查找当前 IP 地址",
    result_type=IPvAnyAddress,
    tools=[run_shell_command],
    context={"os": platform.system()},
)

task.run()
╭─ Agent "Marvin" (db3cf035) ───────────────────────────────╮
│ Tool:    run_shell_command                                │
│ Input:   {'command': ['ipconfig', 'getifaddr', 'en0']}    │
│ Status:  ✅                                               │
│ Output:  '192.168.0.202\n'                                │
╰───────────────────────────────────────────────────────────╯

╭─ Agent "Marvin" (db3cf035) ───────────────────────────────╮
│ Tool:    MarkTaskSuccessful_cb267859                      │
│ Input:   {'response': {'result': '192.168.0.202'}}        │
│ Status:  ✅                                               │
│ Output:  'Final result processed.'                        │
╰───────────────────────────────────────────────────────────╯

任务的特点:
- 🎯 目标驱动:每个任务都有明确的指令和类型安全的结果。
- 🛠️ 工具辅助:任务可以使用自定义工具与你的代码和数据交互。
- 📊 可观测:监控进度、检查结果、调试故障。
- 🔄 可组合:通过连接任务构建复杂的工作流。

智能体

智能体是可以分配给任务的可移植 LLM 配置。它们封装了 AI 有效工作所需的一切:

import os
from pathlib import Path
from pydantic_ai.models.anthropic import AnthropicModel
import marvin

def write_file(path: str, content: str):
    """将内容写入文件"""
    _path = Path(path)
    _path.write_text(content)

writer = marvin.Agent(
    model=AnthropicModel(
        model_name="claude-3-5-sonnet-latest",
        api_key=os.getenv("ANTHROPIC_API_KEY"),
    ),
    name="技术写手",
    instructions="为开发者撰写简洁、引人入胜的内容",
    tools=[write_file],
)

result = marvin.run("如何使用 Pydantic?写入 docs.md", agents=[writer])
print(result)
输出 ╭─ Agent "Technical Writer" (7fa1dbc8) ────────────────────────────────────────────────────────────╮ │ Tool: MarkTaskSuccessful_dc92b2e7 │ │ Input: {'response': {'result': '关于如何使用 Pydantic 的文档已成功写入 docs.md。内容包括安装、基本用法、字段验证和设置管理,并附有示例,指导开发者在项目中实现 Pydantic。'}} │ │ Status: ✅ │ │ Output: 'Final result processed.' │ ╰──────────────────────────────────────────────────────────────────────────────────── 8:33:36 PM ─╯ 关于如何使用 Pydantic 的文档已成功写入 `docs.md`。内容包括安装、基本用法、字段验证和设置管理,并附有示例,指导开发者在项目中实现 Pydantic。

智能体的特点:
- 📝 专业化:为智能体提供具体的指令和个性。
- 🎭 可移植:在不同任务之间重用智能体配置。
- 🤝 协作性:组建团队,共同工作。
- 🔧 可定制:配置模型、温度和其他设置。

规划与编排

Marvin 使得将复杂目标分解为可管理的任务变得简单:

# 让 Marvin 规划复杂的工作流
tasks = marvin.plan("创建一篇关于 AI 趋势的博客文章")
marvin.run_tasks(tasks)

# 或手动编排任务
with marvin.Thread() as thread:
    research = marvin.run("研究最近的 AI 发展")
    outline = marvin.run("创建大纲", context={"research": research})
    draft = marvin.run("撰写初稿", context={"outline": outline})

规划功能:
- 📋 智能规划:将复杂目标分解为离散、有依赖关系的任务。
- 🔄 任务依赖:任务可以依赖于彼此的输出。
- 📈 进度跟踪:监控工作流的执行。
- 🧵 线程管理:在任务之间共享上下文和历史。

保持简单

Marvin 包含针对最常见任务的高级函数,例如总结文本、分类数据、提取结构化信息等。

  • 🚀 marvin.run:使用 AI 智能体执行任何任务。
  • 📖 marvin.summarize:快速总结文本。
  • 🏷️ marvin.classify:将数据分类为预定义类别。
  • 🔍 marvin.extract:从文本中提取结构化信息。
  • 🪄 marvin.cast:将数据转换为不同类型。
  • marvin.generate:根据描述创建结构化数据。

所有 Marvin 函数都内置了线程管理,意味着它们可以组合成共享上下文和历史的任务链。

升级到 Marvin 3.0

Marvin 3.0 结合了 Marvin 2.0 的开发者体验和 ControlFlow 的强大智能体引擎(从而取代了 ControlFlow)。Marvin 和 ControlFlow 的用户都会发现熟悉的界面,但有一些关键变化需要注意,尤其是对 ControlFlow 用户:

关键说明

  • 顶层 API:Marvin 3.0 的顶层 API 对 Marvin 和 ControlFlow 用户来说基本保持不变。
  • Marvin 用户会看到熟悉的 marvin.fnmarvin.classifymarvin.extract 等。
  • ControlFlow 用户将使用 marvin.Taskmarvin.Agentmarvin.runmarvin.Memory 来代替它们对应的 ControlFlow 版本。
  • Pydantic AI:Marvin 3.0 使用 Pydantic AI 进行 LLM 交互,并支持 Pydantic AI 支持的全部 LLM 提供商。ControlFlow 以前使用 Langchain,Marvin 2.0 仅兼容 OpenAI 模型。
  • Flow → Thread:ControlFlow 的 Flow 概念已重命名为 Thread。它的工作方式类似,作为一个上下文管理器。@flow 装饰器已被移除:
    ```python
    import marvin

with marvin.Thread(id="可选的恢复用 ID"):
marvin.run("做某事")
marvin.run("做另一件事")
```
- 数据库变更:线程/消息历史现在存储在 SQLite 中。开发期间:
- 当前没有数据库迁移;预计在更新时重置数据。

工作流示例

以下是一个更实际的示例,展示 Marvin 如何帮助你构建真实应用:

import marvin
from pydantic import BaseModel

class Article(BaseModel):
    title: str
    content: str
    key_points: list[str]

# 创建一个专门的写作智能体
writer = marvin.Agent(
    name="写手",
    instructions="为技术受众撰写清晰、引人入胜的内容"
)

# 使用线程保持多个任务的上下文
with marvin.Thread() as thread:
    # 获取用户输入
    topic = marvin.run(
        "询问用户想写的话题。",
        cli=True
    )

    # 研究话题
    research = marvin.run(
        f"研究关于 {topic} 的要点",
        result_type=list[str]
    )

    # 撰写结构化文章
    article = marvin.run(
        "使用研究结果撰写文章",
        agent=writer,
        result_type=Article,
        context={"research": research}
    )

print(f"# {article.title}\n\n{article.content}")
输出 >**对话:** >```text >智能体:我很乐意帮你写一个技术话题。你对什么感兴趣? >可以是人工智能、机器学习,也可以是 Web 开发或网络安全。 > >用户:我们来写 WebAssembly 的话题 >``` > >**文章:** >``` ># WebAssembly:Web 性能的未来 > >WebAssembly (Wasm) 代表了 Web 开发的范式转变, >为 Web 应用带来接近原生的性能。这种二进制指令 >格式允许开发者用 C++、Rust 或 Go 等语言编写高性能代码, >并在浏览器中无缝运行。 > >[... 完整文章内容 ...] > >关键要点: >- WebAssembly 实现 Web 浏览器中的接近原生性能 >- 支持 JavaScript 之外的多种编程语言 >- 通过沙盒执行环境确保安全性 >- 不断增长的工具和框架生态系统 >- 被 Google、Mozilla、Unity 等主要公司使用 >```
13 次点击  ∙  0 人收藏  
登录后收藏  
0 条回复
关于 ·  帮助 ·  PING ·  隐私 ·  条款   
OA0 - Omni AI 0 一个探索 AI 的社区
沪ICP备2024103595号-2
耗时 33 ms
Developed with Cursor