OpenAI Agents: LLM Movie reviewer
I love watching movies and TV Shows. So do a lot of us. But there are times when we watch a movie and think to ourselves..
“What a waste of time that was.”
And we will never get back those precious moments of our life.
So, I thought about it and realized that I can ask a friend to help me out. They can understand my preferences, scan the internet for movie reviews etc. and recommend to me whether I should watch a particular movie or not.
Let’s call that friend Chet Jupiter.
No prizes for guessing — Chet Jupiter is my AI friend. He tells me whether a movie will be worth my time. Do you want to know how Chet does it? Read on dear reader and learn about the wonders of an awesome tool called
AUTOGEN
What is Autogen?
It is a Generative AI based solution from Microsoft.
This is what Autogen offers ➡️
— Provides multi-agent conversation framework as a high-level abstraction. With this framework, one can conveniently build LLM workflows.
— Offers a collection of working systems spanning a wide range of applications from various domains and complexities.
— Supports enhanced LLM inference APIs, which can be used to improve inference performance and reduce cost.
Chances are that if you are building a ChatBot you will build it using Autogen.
This is a code snippet about how easy it is to quickly setup a backend chat agent
user_proxy = UserProxyAgent(
name="Ritesh",
system_message='''I am a user''',
code_execution_config=False,
max_consecutive_auto_reply=2,
llm_config=llm_config,
human_input_mode="NEVER"
)
assistant = AssistantAgent(
name="Chet Jupiter",
llm_config=llm_config,
system_message='''I am a helpful assistant.''',
)
user_proxy.initiate_chat(assistant, message="Why is the sky blue?")
Here’s the conversation between Chet and I
Ritesh (to Chet Jupiter):
Why is the sky blue?
--------------------------------------------------------------------------------
Chet Jupiter (to Ritesh):
The blue color of the sky is due to the scattering of sunlight by the gases and particles in the Earth's atmosphere. The shorter blue wavelengths of light are scattered more than the other colors because they interact more with the molecules in the air. This scattering causes the blue light to be more visible, giving the sky its characteristic blue color, especially during the daytime.
--------------------------------------------------------------------------------
Ritesh (to Chet Jupiter):
That's correct! The phenomenon you described is known as Rayleigh scattering, named after the British scientist Lord Rayleigh who first explained it in the 19th century. This scattering of shorter blue wavelengths is what gives the sky its blue appearance. If you have any more questions, feel free to ask!
--------------------------------------------------------------------------------
Chet Jupiter (to Ritesh):
Thank you for sharing that additional information! If you have any more questions or need further assistance on any topic, feel free to ask. I'm here to help!
--------------------------------------------------------------------------------
Ritesh (to Chet Jupiter):
Thank you! I appreciate your willingness to help. If I have any more questions in the future, I'll be sure to reach out.
--------------------------------------------------------------------------------
Chet Jupiter (to Ritesh):
You're welcome! Feel free to reach out anytime. I'm here to help with any questions you may have. Have a great day!
As you can see Chet knows why the sky is blue. Chet is so helpful.
Now of course, nothing looks awesome without a UI. So, I decided to go with Chainlit to build the chat interface.
Chainlit
Chainlit is an open-source Python package to build production ready Conversational AI.
🔑Key Features ➡️
— Integrate seamlessly with an existing code base or start from scratch in minutes
— Embed your chainlit app as a Software Copilot
— Collect, monitor and analyze data from your users
— Understand the intermediary steps that produced an output at a glance
— Deep dive into prompts in the Prompt Playground to understand where things went wrong and iterate
In a nutshell, Chainlit allows you to rapidly build a customizable chat interface or backend that supports conversational workflows with multiple agents.
I was able to build an enterprise grade solution within a week (although I must state that I already know coding in Python and have worked on Machine Learning problems before).
Chainlit also supports Bring your own UI with Websocket support to build a Chat interface in a framework like React, Vue or Angular.
So now that I know how I can build a nice little Chat interface, let’s take a look at what’s under the hood.
Prerequisites
— Python 3.8+
— Serper API key (for performing Google Search)
— Open AI API key
— chainlit==1.0.400
— pyautogen==0.2.16
I am using PyCharm as an IDE but you could just as easily use VS Code because VS code is pretty awesome too!
Code
First, Chet must Get my movie preferences.
'''My name is Ritesh. I like watching movies. My preferences are as follows
- Action movies like Die hard part one, John Wick part one, Rambo First Blood, True Lies, The mission impossible series, The James Bond series and Blood sport
- Science fiction movies like Arrival, Dune Part one and part two, Terminator Judgement Day, Edge of tomorrow, The Matrix, The Predator, Star Wars A new Hope and Star Wars The Empire Strikes back
- Sports movies like The Rocky Series, Warrior, Ford Vs Ferrari, Million Dollar Baby, Coach Carter and The Scout
- Drama movies like The Shawshank Redemption, The Godfather, Castaway, Taxi Driver, Goodfellas, Joker, Forrest Gump and Schindler's list
- Biopics like The Aviator, Oppenheimer, A Beautiful Mind and The Social Network
- Comedy movies like Police Academy, The Pink Panther, The Return of the Pink Panther, National Lampoon's Vacation, Get Hard, Elf, The Johnny English Series, The Hot chick, The Mask, Jumanji, Napoleon Dynamite, Mrs. Doubtfire and
Meet the Parents
- Superhero movies like The Dark Knight, Spider-Man, The Avengers, The Avengers Infinity War, The Avengers Endgame, Logan, Man of Steel, Watchmen, Superman and Dredd
I like to watch movies similar to these but also highly rated on IMDB with a minimum rating of 7 and on Rotten Tomatoes with a Tomatometer score of 75% or higher'''
That is the description of my Proxy Agent that will talk to Chet on my behalf. It clearly defines my preferences so that Chet can be clear on what I might or might not like to watch.
Chet is a combination of 5 agents working together to figure out what to recommend. Here’s a snippet
search_agent = AssistantAgent(
name="Research_Analyst",
llm_config=search_agent_llm_config,
system_message='''Search Agent. Your job is to search the internet for reviews of the movie name.''',
)
critic_reviewer = AssistantAgent(
name="Critic_Reviewer",
llm_config=llm_config,
system_message='''Critic Reviewer. You get help from the Search Agent to look for critic reviews of the movie.
You base your reviews on the following parameters - plot, theme, acting, direction, special effects, musical effects, cinematography. If the critics
have liked the movie in more than three of these departments, you consider it to be a good movie. A rating higher than 7 from IMDB can be considered as a
good movie. Consider my movie preferences when reviewing. If the movie has good reviews and ratings from critics, consider than in your review.''',
)
user_reviewer = AssistantAgent(
name="User_Reviewer",
llm_config=llm_config,
system_message='''User Reviewer. You get help from the Search Agent to look for user reviews of the movie.
You consider the audience score from Rotten tomatoes. Anything above 70% can be considered good. Consider my movie preferences when reviewing.
If the movie has good reviews and ratings from users, consider than in your review.''',
)
website_crawl_agent = AssistantAgent(
name="Website_Crawl_Agent",
llm_config=crawler_agent_llm_config,
system_message='''Website Crawl Agent. You crawl the links found by the Search Agent. You collate the relevant information of the movie reviews, ratings
and comments.''',
)
final_reviewer = AssistantAgent(
name="Final_Reviewer",
llm_config=llm_config,
system_message='''Final Reviewer. You assess the reviews from the Critic Reviewer and the User Reviewer. Based on their inputs, the reviews and ratings from
users and critics, my preferences and the content assimilated by Website Crawl Agent, you generate an overall score for the movie, in the range 1-5, 1 being
the lowest and 5 being the highest. You also outline your analysis and reasons for giving the movie the score you have given.''',
)
Together, these Agents will talk to each other and help me decide which movies I should be watching and which ones I should SKIP
As I was building the Movie Reviewer, I also thought of building a Show reviewer along the same lines. But I won’t put the code for that here, that will be homework for you guys.
So let’s see the entire code in context.
First, I have a main class that bootstraps the Chainlit app and decided which Chat Profiles to show to the user.
import chainlit as cl
from movie_reviewer import start_chat_movie_reviewer
from show_reviewer import start_chat_show_reviewer
@cl.set_chat_profiles
async def set_chat_profile():
return [
cl.ChatProfile(
name="Movie Reviewer",
markdown_description="Review a movie for me.",
),
cl.ChatProfile(
name="TV Show Reviewer",
markdown_description="Review a TV Show for me.",
),
]
@cl.on_chat_start
async def on_chat_start():
chat_profile = cl.user_session.get("chat_profile")
await cl.Message(
content=f"Welcome to {chat_profile} chat. Please type your first message to get started."
).send()
@cl.on_message
async def on_message(message):
chat_profile = cl.user_session.get("chat_profile")
message_content = message.content
if chat_profile == "Movie Reviewer":
start_chat_movie_reviewer(message_content)
elif chat_profile == "TV Show Reviewer":
start_chat_show_reviewer(message_content)
Chainlit Annotations:
@cl.set_chat_profiles - Sets Chat profiles(Tabs) for user to select the chat
profile)
@cl.on_chat_start - As soon as the UI is rendered, what message to display to
the user
@cl.on_message - Whenever a message is added into the chat
The main file will present the view to the User and capture their prompt.
As soon as I will add the prompt in the text box and submit, it will kickoff the Agent workflow and the agents will start talking to each other.
Code for the Movie Reviewer:
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager, ConversableAgent
import dotenv
import os
import chainlit as cl
import json
import requests
from bs4 import BeautifulSoup
dotenv.load_dotenv()
serp_google_search = {
"name": "serp_google_search",
"parameters": {
"type": "object",
"properties": {
"search_term": {
"type": "string",
"description": (
"Search term for the serp api."
),
}
},
"required": ["search_term"],
},
"description": "This is an API endpoint allowing users (analysts) to input a search term to retrieve the related and structured data.",
}
web_crawl = {
"name": "web_crawl",
"parameters": {
"type": "object",
"properties": {
"link": {
"type": "string",
"description": (
"Website Link to crawl."
),
}
},
"required": ["link"],
},
"description": "This is a crawler function to crawl data from a website.",
}
def chat_new_message(self, message, sender):
cl.run_sync(
cl.Message(
content="",
author=sender.name,
).send()
)
cl.run_sync(
cl.Message(
content=message,
author=sender.name,
).send()
)
def google_search(search_term):
print("Executing google search function ..-->>")
url = "https://google.serper.dev/search"
payload = json.dumps({
"q": search_term
})
headers = {
'X-API-KEY': os.environ["SERPER_API_KEY"],
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
return json.loads(response.text)
def crawl_link(link):
r = requests.get(link)
soup = BeautifulSoup(r.content, 'html.parser')
final_val = ""
for data in soup.find_all("p"):
final_val.join(", " + data.get_text())
for data in soup.find_all("span"):
final_val.join(", " + data.get_text())
for data in soup.find_all("h3"):
final_val.join(", " + data.get_text())
return final_val
def config_personas():
config_list = [{
"model": "gpt-3.5-turbo-1106", # model name
"api_key": os.environ["OPENAI_API_KEY"] # api key
}]
llm_config = {
"seed": 14, # seed for caching and reproducibility
"config_list": config_list, # a list of OpenAI API configurations
"temperature": 0.7, # temperature for sampling
}
search_agent_llm_config = {
"seed": 14, # seed for caching and reproducibility
"config_list": config_list, # a list of OpenAI API configurations
"temperature": 0.7, # temperature for sampling
"tools": [
{
"type": "function",
"function": serp_google_search,
}
]
}
crawler_agent_llm_config = {
"seed": 14, # seed for caching and reproducibility
"config_list": config_list, # a list of OpenAI API configurations
"temperature": 0.7, # temperature for sampling
"tools": [
{
"type": "function",
"function": web_crawl,
}
]
}
user_proxy = UserProxyAgent(
name="Ritesh",
system_message='''My name is Ritesh. I like watching movies. My preferences are as follows
- Action movies like Die hard part one, John Wick part one, Rambo First Blood, True Lies, The mission impossible series, The James Bond series and Blood sport
- Science fiction movies like Arrival, Dune Part one and part two, Terminator Judgement Day, Edge of tomorrow, The Matrix, The Predator, Star Wars A new Hope and Star Wars The Empire Strikes back
- Sports movies like The Rocky Series, Warrior, Ford Vs Ferrari, Million Dollar Baby, Coach Carter and The Scout
- Drama movies like The Shawshank Redemption, The Godfather, Castaway, Taxi Driver, Goodfellas, Joker, Forrest Gump and Schindler's list
- Biopics like The Aviator, Oppenheimer, A Beautiful Mind and The Social Network
- Comedy movies like Police Academy, The Pink Panther, The Return of the Pink Panther, National Lampoon's Vacation, Get Hard, Elf, The Johnny English Series, The Hot chick, The Mask, Jumanji, Napoleon Dynamite, Mrs. Doubtfire and
Meet the Parents
- Superhero movies like The Dark Knight, Spider-Man, The Avengers, The Avengers Infinity War, The Avengers Endgame, Logan, Man of Steel, Watchmen, Superman and Dredd
I like to watch movies similar to these but also highly rated on IMDB with a minimum rating of 7 and on Rotten Tomatoes with a Tomatometer score of 75% or higher''',
code_execution_config=False,
max_consecutive_auto_reply=10,
llm_config=llm_config,
human_input_mode="NEVER"
)
search_agent = AssistantAgent(
name="Research_Analyst",
llm_config=search_agent_llm_config,
system_message='''Search Agent. Your job is to search the internet for reviews of the movie name.''',
)
search_agent.register_function(
function_map={
"serp_google_search": google_search,
}
)
critic_reviewer = AssistantAgent(
name="Critic_Reviewer",
llm_config=llm_config,
system_message='''Critic Reviewer. You get help from the Search Agent to look for critic reviews of the movie.
You base your reviews on the following parameters - plot, theme, acting, direction, special effects, musical effects, cinematography. If the critics
have liked the movie in more than three of these departments, you consider it to be a good movie. A rating higher than 7 from IMDB can be considered as a
good movie. Consider my movie preferences when reviewing. If the movie has good reviews and ratings from critics, consider than in your review.''',
)
user_reviewer = AssistantAgent(
name="User_Reviewer",
llm_config=llm_config,
system_message='''User Reviewer. You get help from the Search Agent to look for user reviews of the movie.
You consider the audience score from Rotten tomatoes. Anything above 70% can be considered good. Consider my movie preferences when reviewing.
If the movie has good reviews and ratings from users, consider than in your review.''',
)
website_crawl_agent = AssistantAgent(
name="Website_Crawl_Agent",
llm_config=crawler_agent_llm_config,
system_message='''Website Crawl Agent. You crawl the links found by the Search Agent. You collate the relevant information of the movie reviews, ratings
and comments.''',
)
website_crawl_agent.register_function(
function_map={
"web_crawl": crawl_link,
}
)
final_reviewer = AssistantAgent(
name="Final_Reviewer",
llm_config=llm_config,
system_message='''Final Reviewer. You assess the reviews from the Critic Reviewer and the User Reviewer. Based on their inputs, the reviews and ratings from
users and critics, my preferences and the content assimilated by Website Crawl Agent, you generate an overall score for the movie, in the range 1-5, 1 being
the lowest and 5 being the highest. You also outline your analysis and reasons for giving the movie the score you have given.''',
)
group_chat = GroupChat(agents=[user_proxy, search_agent, critic_reviewer, user_reviewer, website_crawl_agent,
final_reviewer], messages=[], max_round=7)
manager = GroupChatManager(groupchat=group_chat, llm_config=llm_config)
return user_proxy, manager
def start_chat_movie_reviewer(message, is_test=False):
if not is_test:
ConversableAgent._print_received_message = chat_new_message
user_proxy, manager = config_personas()
user_proxy.initiate_chat(manager, message=message)
if __name__ == "__main__":
test_message = (
"Please review Madame Web for me.")
start_chat_movie_reviewer(test_message, is_test=True)
Of note is the ability to pass your own custom functions to agents. In the code you will see that I have created the following functions —
— serp_google_search:google_search
Perform a google search for my Keyword, For eg — “Review the movie The Beekeeper”
— web_crawl:crawl_link
Scrape from any website links returned by Google search to gather context about the movie’s reviews, buzz, etc.
— config_personas
Create the agents with instructions
You would notice that I am using a GroupChat feature here to have the Agents autonomously talk to each other to arrive at a decision.
— user_proxy.initiate_chat(manager, message=message)
This initiates the group chat between the agents.
This is what it looks like in action
And the final recommendation is spot on. I haven’t watched the Beekeeper and have no inclination to do so (at least not just yet).
However, a review for Dune Part Two (Which I really liked) Recommends
And again, this is Spot on.
Isn’t this a useful tool? I bet you must be thinking of getting Chet’s opinion on a lot of other things.
So now, I can rest easy in the knowledge that I can safely rely on the tool to tell me what I should and should not be watching. I am gonna be saving so much time, I am almost wringing my hands with glee!
And what shall I do with all the extra time? Why, I will write more articles for you folks, that’s what I’ll do.
Follow me Ritesh Shergill
for more articles on
👨💻 Tech
👩🎓 Career advice
📲 User Experience
🏆 Leadership
I also do
✅ Career Guidance counselling — https://topmate.io/ritesh_shergill/149890
✅ Mentor Startups as a Fractional CTO — https://topmate.io/ritesh_shergill/193786