
Marvin 是一个用于生成结构化输出和构建 AI 智能体工作流的 Python 框架。
Marvin 提供直观的 API,用于定义工作流并将任务委托给 LLM:
Marvin 可从 PyPI 获取:
uv add marvin
配置 LLM 提供商(Marvin 默认使用 OpenAI,但原生支持所有 Pydantic AI 模型):
export OPENAI_API_KEY=your-api-key
Marvin 提供几种直观的方式与 AI 协作:
所有来自 marvin 2.x 的结构化输出工具都位于包的最顶层。
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)
marvin.Task你可以显式定义一个 Task,在调用 .run() 时由默认智能体执行:
from marvin import Task
task = Task(
instructions="写一首关于 Python 的五行打油诗",
result_type=str
)
poem = task.run()
print(poem)
在电路与代码中,心智绽放, 算法在黑暗中编织。 硅基思维的火花, 人工智能找到了它的位置。
我们相信与 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)
智能体的特点:
- 📝 专业化:为智能体提供具体的指令和个性。
- 🎭 可移植:在不同任务之间重用智能体配置。
- 🤝 协作性:组建团队,共同工作。
- 🔧 可定制:配置模型、温度和其他设置。
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 2.0 的开发者体验和 ControlFlow 的强大智能体引擎(从而取代了 ControlFlow)。Marvin 和 ControlFlow 的用户都会发现熟悉的界面,但有一些关键变化需要注意,尤其是对 ControlFlow 用户:
marvin.fn、marvin.classify、marvin.extract 等。marvin.Task、marvin.Agent、marvin.run、marvin.Memory 来代替它们对应的 ControlFlow 版本。Flow 概念已重命名为 Thread。它的工作方式类似,作为一个上下文管理器。@flow 装饰器已被移除: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}")