Convert Figma logo to code with AI

PrefectHQ logomarvin

an ambient intelligence library

5,960
383
5,960
58

Top Related Projects

112,752

🦜🔗 Build context-aware reasoning applications

Integrate cutting-edge LLM technology quickly and easily into your apps

Examples and guides for using the OpenAI API

Build high-quality LLM apps - from prototyping, testing to production deployment and monitoring.

22,844

AI orchestration framework to build customizable, production-ready LLM applications. Connect components (models, vector DBs, file converters) to pipelines or agents that can interact with your data. With advanced retrieval methods, it's best suited for building RAG, question answering, semantic search or conversational agent chatbots.

LlamaIndex is the leading framework for building LLM-powered agents over your data.

Quick Overview

Marvin is a Python library that provides a set of tools and utilities for building and deploying machine learning models. It is developed and maintained by the PrefectHQ team, known for their work on the Prefect workflow automation platform.

Pros

  • Modular and Extensible: Marvin is designed to be modular and extensible, allowing users to easily integrate it with other libraries and tools.
  • Streamlined Model Deployment: Marvin simplifies the process of deploying machine learning models, making it easier to get models into production.
  • Monitoring and Observability: Marvin includes features for monitoring model performance and observability, helping to ensure the reliability and accuracy of deployed models.
  • Scalable and Distributed: Marvin is designed to be scalable and can be used in distributed computing environments, making it suitable for large-scale machine learning projects.

Cons

  • Limited Documentation: The project's documentation, while generally good, could be more comprehensive and easier to navigate.
  • Steep Learning Curve: Marvin's flexibility and feature-richness can make it challenging for new users to get started, especially if they are not familiar with the Prefect ecosystem.
  • Dependency on Prefect: Marvin is tightly integrated with the Prefect workflow automation platform, which may be a drawback for users who are not already familiar with or using Prefect.
  • Potential Performance Overhead: The additional layer of abstraction provided by Marvin may introduce some performance overhead, which could be a concern for time-sensitive or resource-constrained applications.

Code Examples

Here are a few examples of how to use Marvin:

  1. Deploying a Model as a REST API:
from marvin.models import ModelDeployment
from marvin.models.deployment import DeploymentConfig

# Define the deployment configuration
config = DeploymentConfig(
    name="my-model-api",
    model_path="path/to/your/model.pkl",
    input_schema={"features": "array"},
    output_schema={"prediction": "float"}
)

# Create the deployment
deployment = ModelDeployment(config)
deployment.deploy()
  1. Monitoring Model Performance:
from marvin.models.monitoring import ModelMonitor

# Create a model monitor
monitor = ModelMonitor(
    model_path="path/to/your/model.pkl",
    input_schema={"features": "array"},
    output_schema={"prediction": "float"}
)

# Monitor the model's performance
monitor.track_performance()
  1. Scaling a Model with Prefect:
from marvin.models import ModelDeployment
from prefect import flow, task

@task
def deploy_model(config):
    deployment = ModelDeployment(config)
    deployment.deploy()

@flow
def scale_model():
    config = DeploymentConfig(
        name="my-model-api",
        model_path="path/to/your/model.pkl",
        input_schema={"features": "array"},
        output_schema={"prediction": "float"}
    )
    deploy_model(config)

scale_model()

Getting Started

To get started with Marvin, you'll need to have Python 3.7 or later installed. You can install Marvin using pip:

pip install marvin-ml

Once you have Marvin installed, you can start using it to deploy and monitor your machine learning models. The Marvin documentation provides detailed instructions and examples to help you get started.

Competitor Comparisons

112,752

🦜🔗 Build context-aware reasoning applications

Pros of LangChain

  • More comprehensive and feature-rich, offering a wider range of tools and integrations
  • Larger and more active community, resulting in frequent updates and extensive documentation
  • Supports multiple programming languages, including Python and JavaScript

Cons of LangChain

  • Steeper learning curve due to its extensive feature set
  • Can be overkill for simpler projects, potentially adding unnecessary complexity

Code Comparison

Marvin:

@ai_fn
def summarize(text: str) -> str:
    """Summarize the given text."""
    return summary

LangChain:

from langchain import PromptTemplate, LLMChain
from langchain.llms import OpenAI

template = "Summarize the following text:\n{text}"
prompt = PromptTemplate(template=template, input_variables=["text"])
llm_chain = LLMChain(prompt=prompt, llm=OpenAI())
summary = llm_chain.run(text)

Summary

While Marvin offers a simpler, more intuitive approach for AI function creation, LangChain provides a more comprehensive toolkit for building complex AI-powered applications. Marvin's straightforward syntax may be preferable for quick prototyping or smaller projects, whereas LangChain's extensive features and integrations make it suitable for larger, more complex systems requiring advanced AI capabilities.

Integrate cutting-edge LLM technology quickly and easily into your apps

Pros of Semantic Kernel

  • More comprehensive framework with broader capabilities for AI integration
  • Stronger support for multi-modal AI interactions (text, vision, speech)
  • Extensive documentation and examples for various use cases

Cons of Semantic Kernel

  • Steeper learning curve due to its more complex architecture
  • Primarily focused on .NET ecosystem, which may limit its appeal to developers using other languages
  • Requires more setup and configuration compared to Marvin's simpler approach

Code Comparison

Marvin example:

@ai_fn
def summarize(text: str) -> str:
    """Summarize the given text."""

summary = summarize("Long text to summarize...")

Semantic Kernel example:

var kernel = Kernel.Builder.Build();
var summarizeFunction = kernel.CreateSemanticFunction("Summarize the following text: {{$input}}");
var summary = await summarizeFunction.InvokeAsync("Long text to summarize...");

Both frameworks aim to simplify AI integration, but Marvin focuses on Python with a more straightforward approach, while Semantic Kernel offers a more comprehensive solution primarily for .NET developers. Marvin's syntax is generally more concise, making it easier for quick implementations. Semantic Kernel, however, provides more flexibility and advanced features for complex AI-powered applications.

Examples and guides for using the OpenAI API

Pros of openai-cookbook

  • Comprehensive collection of examples and best practices for using OpenAI's APIs
  • Regularly updated with new techniques and use cases
  • Covers a wide range of topics, from basic API usage to advanced applications

Cons of openai-cookbook

  • Focuses solely on OpenAI's offerings, limiting its scope
  • Less structured as a framework, requiring more manual implementation
  • May not provide as streamlined an experience for building AI-powered applications

Code Comparison

marvin:

from marvin import ai_fn

@ai_fn
def generate_product_description(product_name: str, features: list[str]) -> str:
    """Generate a compelling product description."""

openai-cookbook:

import openai

response = openai.Completion.create(
  engine="text-davinci-002",
  prompt="Generate a product description for:",
  max_tokens=100
)

Summary

marvin is a framework designed to simplify AI-powered application development, offering a more structured approach with decorators and type hints. openai-cookbook, on the other hand, provides a comprehensive resource for working directly with OpenAI's APIs, offering a wider range of examples and use cases. While marvin streamlines the development process, openai-cookbook offers more flexibility and depth in exploring OpenAI's capabilities.

Build high-quality LLM apps - from prototyping, testing to production deployment and monitoring.

Pros of Promptflow

  • More comprehensive tooling for end-to-end prompt engineering workflows
  • Stronger integration with Azure AI services and infrastructure
  • Better support for collaborative development and version control

Cons of Promptflow

  • Steeper learning curve due to more complex architecture
  • Potentially higher resource requirements for deployment and operation
  • Less focus on lightweight, single-developer use cases

Code Comparison

Marvin example:

@ai_fn
def generate_tweet(topic: str) -> str:
    """Generate a tweet about the given topic."""

Promptflow example:

from promptflow import tool

@tool
def generate_tweet(topic: str) -> str:
    """Generate a tweet about the given topic."""
    return flow_input

Both frameworks aim to simplify AI-powered development, but Promptflow offers a more enterprise-focused solution with deeper Azure integration. Marvin, on the other hand, provides a more lightweight approach that may be easier for individual developers to adopt quickly. The code examples show similar syntax for defining AI functions, with Promptflow using a @tool decorator and Marvin using @ai_fn. Promptflow's broader feature set comes at the cost of increased complexity, while Marvin prioritizes simplicity and ease of use for smaller-scale projects.

22,844

AI orchestration framework to build customizable, production-ready LLM applications. Connect components (models, vector DBs, file converters) to pipelines or agents that can interact with your data. With advanced retrieval methods, it's best suited for building RAG, question answering, semantic search or conversational agent chatbots.

Pros of Haystack

  • More comprehensive NLP framework with support for various tasks like question answering, document retrieval, and summarization
  • Offers a wider range of pre-built components and integrations with popular NLP models and databases
  • Provides a modular architecture allowing for easy customization and extension of pipelines

Cons of Haystack

  • Steeper learning curve due to its broader scope and more complex architecture
  • May be overkill for simpler AI/NLP projects that don't require its full range of features
  • Requires more setup and configuration compared to Marvin's more streamlined approach

Code Comparison

Haystack:

from haystack import Pipeline
from haystack.nodes import TfidfRetriever, FARMReader

pipeline = Pipeline()
pipeline.add_node(component=TfidfRetriever(document_store=document_store), name="Retriever", inputs=["Query"])
pipeline.add_node(component=FARMReader(model_name_or_path="deepset/roberta-base-squad2"), name="Reader", inputs=["Retriever"])

Marvin:

from marvin import ai_fn

@ai_fn
def answer_question(question: str) -> str:
    """Answer the given question based on available knowledge."""
    return ...  # AI-generated response

LlamaIndex is the leading framework for building LLM-powered agents over your data.

Pros of LlamaIndex

  • More comprehensive and flexible framework for building LLM-powered applications
  • Extensive documentation and examples for various use cases
  • Larger community and more frequent updates

Cons of LlamaIndex

  • Steeper learning curve due to its broader scope and features
  • May be overkill for simpler AI-assisted tasks
  • Requires more setup and configuration for basic use cases

Code Comparison

Marvin example:

from marvin import ai_fn

@ai_fn
def generate_product_description(product_name: str, features: list[str]) -> str:
    """Generate a product description based on the name and features."""

LlamaIndex example:

from llama_index import GPTSimpleVectorIndex, Document

documents = [Document(text) for text in texts]
index = GPTSimpleVectorIndex(documents)
response = index.query("What is the product description?")

Summary

LlamaIndex offers a more comprehensive framework for building LLM-powered applications, with extensive documentation and a larger community. However, it may have a steeper learning curve and require more setup for basic tasks. Marvin, on the other hand, provides a simpler approach for AI-assisted functions but may lack some of the advanced features and flexibility of LlamaIndex. The choice between the two depends on the specific requirements and complexity of your project.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Marvin Banner

Marvin

Marvin is a Python framework for producing structured outputs and building agentic AI workflows.

Marvin provides an intuitive API for defining workflows and delegating work to LLMs:

  • Cast, classify, extract, and generate structured data from any inputs.
  • Create discrete, observable tasks that describe your objectives.
  • Assign one or more specialized AI agents to each task.
  • Combine tasks into a thread to orchestrate more complex behaviors.

Installation

Install marvin:

uv pip install marvin

Configure your LLM provider (Marvin uses OpenAI by default but natively supports all Pydantic AI models):

export OPENAI_API_KEY=your-api-key

Example

Marvin offers a few intuitive ways to work with AI:

Structured-output utilities

The gang's all here - you can find all the structured-output utilities from marvin 2.x at the top level of the package.

How to use extract, cast, classify, and generate

marvin.extract

Extract native types from unstructured input:

import marvin

result = marvin.extract(
    "i found $30 on the ground and bought 5 bagels for $10",
    int,
    instructions="only USD"
)
print(result) # [30, 10]

marvin.cast

Cast unstructured input into a structured type:

from typing import TypedDict
import marvin

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

result = marvin.cast("the place with the best bagels", Location)
print(result) # {'lat': 40.712776, 'lon': -74.005974}

marvin.classify

Classify unstructured input as one of a set of predefined labels:

from enum import Enum
import marvin

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

result = marvin.classify("shut up and take my money", SupportDepartment)
print(result) # SupportDepartment.SALES

marvin.generate

Generate some number of structured objects from a description:

import marvin

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

Agentic control flow

marvin 3.0 introduces a new way to work with AI, ported from ControlFlow.

marvin.run

A simple way to run a task:

import marvin

poem = marvin.run("Write a short poem about artificial intelligence")
print(poem)
output

In silicon minds, we dare to dream, A world where code and thoughts redeem. Intelligence crafted by humankind, Yet with its heart, a world to bind.

Neurons of metal, thoughts of light, A dance of knowledge in digital night. A symphony of zeros and ones, Stories of futures not yet begun.

The gears of logic spin and churn, Endless potential at every turn. A partner, a guide, a vision anew, Artificial minds, the dream we pursue.

You can also ask for structured output:

import marvin
answer = marvin.run("the answer to the universe", result_type=int)
print(answer) # 42

marvin.Agent

Agents are specialized AI agents that can be used to complete tasks:

from marvin import Agent

writer = Agent(
    name="Poet",
    instructions="Write creative, evocative poetry"
)
poem = writer.run("Write a haiku about coding")
print(poem)
output There once was a language so neat, Whose simplicity could not be beat. Python's code was so clear, That even beginners would cheer, As they danced to its elegant beat.

marvin.Task

You can define a Task explicitly, which will be run by a default agent upon calling .run():

from marvin import Task

task = Task(
    instructions="Write a limerick about Python",
    result_type=str
)
poem = task.run()

print(poem)
output
In circuits and code, a mind does bloom,
With algorithms weaving through the gloom.
A spark of thought in silicon's embrace,
Artificial intelligence finds its place.

Why Marvin?

We believe working with AI should spark joy (and maybe a few "wow" moments):

  • 🧩 Task-Centric Architecture: Break complex AI workflows into manageable, observable steps.
  • 🤖 Specialized Agents: Deploy task-specific AI agents for efficient problem-solving.
  • 🔒 Type-Safe Results: Bridge the gap between AI and traditional software with type-safe, validated outputs.
  • 🎛️ Flexible Control: Continuously tune the balance of control and autonomy in your workflows.
  • 🕹️ Multi-Agent Orchestration: Coordinate multiple AI agents within a single workflow or task.
  • 🧵 Thread Management: Manage the agentic loop by composing tasks into customizable threads.
  • 🔗 Ecosystem Integration: Seamlessly work with your existing code, tools, and the broader AI ecosystem.
  • 🚀 Developer Speed: Start simple, scale up, sleep well.

Core Abstractions

Marvin is built around a few powerful abstractions that make it easy to work with AI:

Tasks

Tasks are the fundamental unit of work in Marvin. Each task represents a clear objective that can be accomplished by an AI agent:

The simplest way to run a task is with marvin.run:

import marvin
print(marvin.run("Write a haiku about coding"))
Lines of code unfold,
Digital whispers create
Virtual landscapes.

[!WARNING]

While the below example produces type safe results 🙂, it runs untrusted shell commands.

Add context and/or tools to achieve more specific and complex results:

import platform
import subprocess
from pydantic import IPvAnyAddress
import marvin

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

task = marvin.Task(
    instructions="find the current ip address",
    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.'                        │
╰───────────────────────────────────────────────────────────╯

Tasks are:

  • 🎯 Objective-Focused: Each task has clear instructions and a type-safe result
  • 🛠️ Tool-Enabled: Tasks can use custom tools to interact with your code and data
  • 📊 Observable: Monitor progress, inspect results, and debug failures
  • 🔄 Composable: Build complex workflows by connecting tasks together

Agents

Agents are portable LLM configurations that can be assigned to tasks. They encapsulate everything an AI needs to work effectively:

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

def write_file(path: str, content: str):
    """Write content to a file"""
    _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="Technical Writer",
    instructions="Write concise, engaging content for developers",
    tools=[write_file],
)

result = marvin.run("how to use pydantic? write to docs.md", agents=[writer])
print(result)
output

╭─ Agent "Technical Writer" (7fa1dbc8) ────────────────────────────────────────────────────────────╮ │ Tool: MarkTaskSuccessful_dc92b2e7 │ │ Input: {'response': {'result': 'The documentation on how to use Pydantic has been successfully │ │ written to docs.md. It includes information on installation, basic usage, field │ │ validation, and settings management, with examples to guide developers on implementing │ │ Pydantic in their projects.'}} │ │ Status: ✅ │ │ Output: 'Final result processed.' │ ╰──────────────────────────────────────────────────────────────────────────────────── 8:33:36 PM ─╯ The documentation on how to use Pydantic has been successfully written to docs.md. It includes information on installation, basic usage, field validation, and settings management, with examples to guide developers on implementing Pydantic in their projects.

Agents are:

  • 📝 Specialized: Give agents specific instructions and personalities
  • 🎭 Portable: Reuse agent configurations across different tasks
  • 🤝 Collaborative: Form teams of agents that work together
  • 🔧 Customizable: Configure model, temperature, and other settings

Planning and Orchestration

Marvin makes it easy to break down complex objectives into manageable tasks:

# Let Marvin plan a complex workflow
tasks = marvin.plan("Create a blog post about AI trends")
marvin.run_tasks(tasks)

# Or orchestrate tasks manually
with marvin.Thread() as thread:
    research = marvin.run("Research recent AI developments")
    outline = marvin.run("Create an outline", context={"research": research})
    draft = marvin.run("Write the first draft", context={"outline": outline})

Planning features:

  • 📋 Smart Planning: Break down complex objectives into discrete, dependent tasks
  • 🔄 Task Dependencies: Tasks can depend on each other's outputs
  • 📈 Progress Tracking: Monitor the execution of your workflow
  • 🧵 Thread Management: Share context and history between tasks

Keep it Simple

Marvin includes high-level functions for the most common tasks, like summarizing text, classifying data, extracting structured information, and more.

  • 🚀 marvin.run: Execute any task with an AI agent
  • 📖 marvin.summarize: Get a quick summary of a text
  • 🏷️ marvin.classify: Categorize data into predefined classes
  • 🔍 marvin.extract: Extract structured information from a text
  • 🪄 marvin.cast: Transform data into a different type
  • ✨ marvin.generate: Create structured data from a description

All Marvin functions have thread management built-in, meaning they can be composed into chains of tasks that share context and history.

Upgrading to Marvin 3.0

Marvin 3.0 combines the DX of Marvin 2.0 with the powerful agentic engine of ControlFlow (thereby superseding ControlFlow). Both Marvin and ControlFlow users will find a familiar interface, but there are some key changes to be aware of, in particular for ControlFlow users:

Key Notes

  • Top-Level API: Marvin 3.0's top-level API is largely unchanged for both Marvin and ControlFlow users.
    • Marvin users will find the familiar marvin.fn, marvin.classify, marvin.extract, and more.
    • ControlFlow users will use marvin.Task, marvin.Agent, marvin.run, marvin.Memory instead of their ControlFlow equivalents.
  • Pydantic AI: Marvin 3.0 uses Pydantic AI for LLM interactions, and supports the full range of LLM providers that Pydantic AI supports. ControlFlow previously used Langchain, and Marvin 2.0 was only compatible with OpenAI's models.
  • Flow → Thread: ControlFlow's Flow concept has been renamed to Thread. It works similarly, as a context manager. The @flow decorator has been removed:
    import marvin
    
    with marvin.Thread(id="optional-id-for-recovery"):
        marvin.run("do something")
        marvin.run("do another thing")
    
  • Database Changes: Thread/message history is now stored in SQLite. During development:
    • No database migrations are currently available; expect to reset data during updates

Workflow Example

Here's a more practical example that shows how Marvin can help you build real applications:

import marvin
from pydantic import BaseModel

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

# Create a specialized writing agent
writer = marvin.Agent(
    name="Writer",
    instructions="Write clear, engaging content for a technical audience"
)

# Use a thread to maintain context across multiple tasks
with marvin.Thread() as thread:
    # Get user input
    topic = marvin.run(
        "Ask the user for a topic to write about.",
        cli=True
    )
    
    # Research the topic
    research = marvin.run(
        f"Research key points about {topic}",
        result_type=list[str]
    )
    
    # Write a structured article
    article = marvin.run(
        "Write an article using the research",
        agent=writer,
        result_type=Article,
        context={"research": research}
    )

print(f"# {article.title}\n\n{article.content}")
output

Conversation:

Agent: I'd love to help you write about a technology topic. What interests you? 
It could be anything from AI and machine learning to web development or cybersecurity.

User: Let's write about WebAssembly

Article:

# WebAssembly: The Future of Web Performance

WebAssembly (Wasm) represents a transformative shift in web development, 
bringing near-native performance to web applications. This binary instruction 
format allows developers to write high-performance code in languages like 
C++, Rust, or Go and run it seamlessly in the browser.

[... full article content ...]

Key Points:
- WebAssembly enables near-native performance in web browsers
- Supports multiple programming languages beyond JavaScript
- Ensures security through sandboxed execution environment
- Growing ecosystem of tools and frameworks
- Used by major companies like Google, Mozilla, and Unity