# Tinkering with Marvin AI

### Introduction

Recently I was introduced to [Marvin AI](https://www.askmarvin.ai/) by my favorite [Python community](https://pybit.es/). I just started to tinker with Marvin, and the results were impressive. I'm planning to use it in one of [my projects that I open-sourced](https://github.com/SambhaviPD/your-recipebuddy) recently.

Thought of sharing a few notes and ideas I made during my learning process.

Of late, I use [FastAPI](https://fastapi.tiangolo.com/) as my backend framework for most of the solutions that I build. Marvin also suggests using the same when it comes to deployment. So let's just go with it.

In this blog, let's build a set of APIs concerning books. The primary reason being I love to read and listen🎧 to books, and the secondary being [I already wrote a blog](https://hellosambhavi.com/my-first-vue-app) with BookReview as a functionality. So let's just build this as a continuation, and in a future post link the two 😀

Let's start to explore how we can use Marvin's components and build some useful APIs.

First of all, a brief introduction about Marvin; it is a collection of building blocks that can be used by developers with the highest level of abstraction. What exactly can it do? Per [their documentation](https://www.askmarvin.ai/src/getting_started/what_is_marvin/):

* *AI Models for structuring text into type-safe schemas*
    
* *AI Classifiers for bulletproof classification and routing*
    
* *AI functions for complex business logic and transformations*
    
* *AI applications for interactive use and persistent state*
    

The goal of building Marvin as quoted on their website is

> Marvin's goal is to bring the best practices of building dependable, observable software to the frontier of generative AI.

It's been quite abstract so far, so let's just dive in and see what exactly can it do.

As always, let's create a folder, a virtual environment and activate it as the first step.

```python
mkdir marvin-ai
cd marvin-ai

py -m venv venv
venv\Scripts\activate
```

We then install FastAPI

```python
pip install "fastapi[all]"
```

Now that we've installed FastAPI, let's go ahead and start writing APIs. It's as easy as importing the package, creating an app and writing a method with a router. Create a file named `main.py` and write the code below

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return { "message" : "Welcome to BookReview APIs"}
```

Time to start the uvicorn server and see the response on the browser 💡

```python
uvicorn main:app --reload
```

Hooray, we see the response like so 👇

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689934332629/d23d233b-6c72-414f-89d8-dddbcf67deae.png align="center")

Now that the foundation is set to start using Marvin, let's go ahead and install Marvin.

```python
pip install marvin
```

Marvin uses OpenAI under the hood, which means we need OpenAI's API key. To procure the same, visit [OpenAI's website](https://openai.com/), Sign up and follow the next steps. You may need to provide your phone number for verification. In the past, it used to take a few days for your request to get approved. These days, I think it's pretty fast.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Proceed with the following steps only after you receive your OpenAI API key</div>
</div>

Create a `.env` file at the same level as `main.py`. This is where we store all our environment variables. Create a variable to store your API key. This is what I created.

```python
MARVIN_OPENAI_API_KEY=<your-api-key-here>
```

Now we are all set to start exploring. As we saw above, there are four components in Marvin, and let's start with the AI function as I found that to be the simplest of all.

### AI Functions

To reiterate, AI functions do not have any source code. It just uses text and description in the form of docstrings to generate outputs. When I came across this method the first time, I was mind-blown 🤩

Let's try a few functions from a book review perspective and check the output.

A simple function that returns a brief review given the name of the book and the author can be written as below.

```python
@ai_fn
def book_review(name_of_book: str, author: str) -> str:
    """
    Given name of a book and author, return a review of the book
    """

@app.get("/book_review")
async def get_book_review(name_of_book: str, author: str):
    review = book_review(name_of_book, author)
    return review
```

I tried a couple of books and captured the output. Check the results 😎

> A Man called Ove by Frederik Backman

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689945757057/abc0ec7a-7345-411d-910b-ed8521280936.png align="center")

> The Secret Garden by Frances Hodgson Burnett

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689945915832/eefe030e-86bf-4641-b86b-3a5ed0d80038.png align="center")

> I know why the caged bird sings by Maya Angelou

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689946067156/275e77fa-d2b2-45ff-b31f-648a8452f7fe.png align="center")

Let's write another function that returns the genre given the name of the book and the author

```python
@ai_fn
def book_genre(name_of_book: str, author: str) -> str:
    """
    Given name of a book and author, return multiple genres of the book
    """

@app.get("/book_genre")
async def get_book_genre(name_of_book: str, author: str):
    genres = book_genre(name_of_book, author)
    return genres
```

Now let's try a couple of books

> Founding Sales - The Startup Sales Handbook by Peter Kazanjy

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689946964582/1c603c05-b25d-4340-b3b6-9274d05771e4.png align="center")

> The Color of Law: A Forgotten History of How Our Government Segregated America by Richard Rothstein

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689946864035/692fa1e9-de24-4283-a980-44f0d2f8cc22.png align="center")

> 99 Bottles of OOp by Sandi Metz, Katrina Owen

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689946801511/378d7210-ef9f-47e9-b2f1-fddd539e32f7.png align="center")

Pretty impressive, isn't it? Most of the trick lies in the correct set of prompts that we give. Prompt engineering is a subject in itself.

### AI Classifiers

These let us build multi-label classifiers with no code and no training data. We just define multiple categories for a scenario as `Enums` in a class.

Per Marvin's documentation,

> Given user input, each classifier uses a clever logit bias trick to force an LLM to deductively choose the best option

Let's define a class of different types of sentiments as a Classifier. When we invoke the class by passing a book review, it returns the sentiment.

Here is the code

```python
@ai_classifier
class BookReviewSentiment(Enum):
    """
    Classifies incoming book reviews
    """
    POSITIVE = "Positive"
    NEGATIVE = "Negative"
    NEUTRAL = "Neutral"
    ENTHUSIASTIC = "Enthusiastic"
    CRITICAL = "Critical"
    INDIFFERENT = "Indifferent"
    APPRECITATIVE = "Appreciative"
    DISAPPROVING = "Disapproving"


@app.get("/book_review_classifier")
async def get_book_review_classifier(review: str):
    sentiment = BookReviewSentiment(review)
    return sentiment
```

Let's test it with a few reviews and see what it returns

> A Man Called Ove is a tedious and clichéd portrayal of a grumpy old man, filled with predictable and overused tropes. The story fails to deliver any real depth or originality, leaving readers disappointed by its lackluster plot and one-dimensional characters

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689956224935/36db6ae8-bf1b-4c7a-9bf7-0c7ed8b424fb.png align="center")

> The Five-Star Weekend is an enthralling and exhilarating thriller that keeps readers on the edge of their seats from start to finish. With its fast-paced plot, complex characters, and unexpected twists, this book is an absolute must-read for fans of the genre.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689956332585/47f96cd3-6f59-4819-9047-b9a53b6fcfa2.png align="center")

> What the Neighbors Saw is a mystery novel set in a suburban neighborhood, exploring the secrets of its residents. While the plot held potential for intrigue, the execution lacked the depth needed to fully engage readers, resulting in a somewhat forgettable reading experience.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689956555793/3508add0-afbc-47fb-b73e-98737029e5e3.png align="center")

These are the two components that I explored recently. There is a lot more that Marvin AI offers. I just scratched the surface. Hope I kindled your curiosity to explore further and try using it in your work.

### Final Steps

Let's quickly deploy this application so that you can see it working. I chose [Render](https://render.com/) as my cloud provider to deploy these services. It's extremely simple to deploy a FastAPI web service in Render.

I followed [their documentation](https://render.com/docs/deploy-fastapi) and boom, here is [my application deployed](https://marvin-ai.onrender.com/docs) 🤩🤩

Two points that need to be noted while deployment are:

1. By default, Render uses the patch version of Python 3.7. Marvin requires a minimum of 3.9. For this to be reflected, on your render dashboard, go to settings -&gt; Environment -&gt; Add a variable PYTHON\_VERSION and give the value as 3.10.7. Only by doing this can Marvin be installed. Of course, you can install any version &gt;= 3.9
    
2. In settings, goto Environment menu again, either add a secrets file and add your `.env` file that has the variable MARVIN\_OPENAI\_API\_KEY and your OpenAI's API key as value. Or, you can add an environment variable directly for Marvin's key.
    

Quick screenshot from my Render dashboard

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690179223124/25189415-c44c-4ab5-b56a-0f90de88eb69.png align="center")

Here is my [code repo on github](https://github.com/SambhaviPD/marvin-ai)

### Conclusion

This is my first time with Marvin AI, and the results were good. Concerning speed, I'm yet to test. Feel free to play around with my app that is deployed on Render.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Please be wary to use the APIs though as Open AI has limits on number of requests per minute 😁</div>
</div>

### References

[https://www.askmarvin.ai/src/docs/](https://www.askmarvin.ai/src/docs/)

[https://render.com/docs/deploy-fastapi](https://render.com/docs/deploy-fastapi)

[https://render.com/docs/python-version](https://render.com/docs/python-version)
