DEV Community

Cover image for Building a Powerful Recommendation System with Palm 2 Model and Streamlit: A Step-by-Step Guide
Tanmay patil
Tanmay patil

Posted on

Building a Powerful Recommendation System with Palm 2 Model and Streamlit: A Step-by-Step Guide

In this article, I’m going to illustrate my experience building a real time recommendation system with the help of Palm2 LLM model , TMDB API and Streamlit.

My goal is to talk about how to design a movie recommendation system using integration of multiple API’s and components.

This blog is written guide for following youtube video 🎥. Like👍 the video and subscribe to the channel . So let’s get started 😊.

What is PaLM 2 Large Language Model API ?

Google's palm 2 model

Large Language Models (LLMs) are a powerful, versatile type of machine learning model that enables computers to comprehend and generate natural language better than ever. They can be used to build all sorts of applications, from chat bots to virtual assistants to translation apps and much more. Plus, you don’t have to be an AI expert or even write code to use them. All it takes are a few sentences or “prompts” to get started designing your own custom LLM app.

The PaLM API is based on Google’s next generation model, PaLM 2, which excels at a variety of capabilities. PaLM 2 has been optimized for ease of use on key developer use cases and the ability to follow instructions with precision and nuance. It has variations that are trained for text and chat generation as well as text embeddings. This guide provides information about each variation to help you decide which is the best fit for your use case.

You can join waitlist to get your API key via MakerSuite and start prototyping quickly .

What is TMDB API ?
The Movie Database (TMDB) is a community built movie and TV database. Every piece of data has been added by the amazing community dating back to 2008.

TMDB API

Steps to get API key for TMDB API :

  1. Create account on TMDB website (https://www.themoviedb.org/) or log in if you already have an account.
  2. Go to profile settings page .
  3. Go to API tab ( https://www.themoviedb.org/settings/api ) . You will find your API key and API read access token . We are going to use API read access token for our project .
  4. You can find more details about how we can use TMDB API and it’s endpoints at https://developer.themoviedb.org/docs 😎.

Little bit about Streamlit 🔥

Streamlit (https://streamlit.io/) is an open-source Python library that makes it easy to create and share beautiful, custom web apps for machine learning and data science. In just a few minutes you can build and deploy powerful data apps

You can find more details about how to use streamlit at official documentation .

You can install it by using pip as following :
$pip install streamlit

Let’s get into coding 🧑‍💻.

let’s install required libraries for project .
$pip install google-generativeai streamlit

Google provides python library called google-generativeai to interact with their generative models.

let’s import required python modules which are necessary .

import os
import dotenv
import google.generativeai as palm
import requests
import time
import urllib.parse
import streamlit as st
Enter fullscreen mode Exit fullscreen mode

Now we are going to add API keys for Palm model and TMDB API into .env file 🔑.

PALM_API_KEY="Your Palm API key here"
TMDB_API_KEY="Your TMDB API access token here"
Enter fullscreen mode Exit fullscreen mode

Now our environment variable is set . Time to import API keys into python code . We can do by following line of code .

dotenv.load_dotenv()
Enter fullscreen mode Exit fullscreen mode

Now we are going to create class by the name of Recommend_movies .

class Recommend_movies:
    def __init__(self) -> None:
        self.model = palm
        self.model.configure(api_key=os.getenv("PALM_API_KEY"))

        self.session = requests.Session()
        self.session.headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {os.getenv('TMDB_API_KEY')}"
        }

        self.defaults = {
            'model': 'models/text-bison-001',
            'temperature': 0.7,
            'candidate_count': 1,
            'top_k': 40,
            'top_p': 0.95,
            'max_output_tokens': 1024,
            'stop_sequences': [],
            'safety_settings': [
                {"category":"HARM_CATEGORY_DEROGATORY","threshold":1},
                {"category":"HARM_CATEGORY_TOXICITY","threshold":1},
                {"category":"HARM_CATEGORY_VIOLENCE","threshold":2},
                {"category":"HARM_CATEGORY_SEXUAL","threshold":2},
                {"category":"HARM_CATEGORY_MEDICAL","threshold":2},
                {"category":"HARM_CATEGORY_DANGEROUS","threshold":2}
            ],
        }

    def urlify_string(self,string):
        url_encoded = urllib.parse.quote(string)
        return url_encoded

    def generate(self,movie_name :str):

        result = []

        prompt = f"""input: Th Dark Knight 
            output: Batman Begins
            The Prestige
            Se7en
            Fight Club
            The Shawshank Redemption
            input: {movie_name}
            output:"""

        response = self.model.generate_text(
            **self.defaults,
            prompt=prompt
        )

        recommendations = response.result.split("\n")
        time.sleep(0.1)
        for i in recommendations:
            movie = self.urlify_string(i)
            url = f"https://api.themoviedb.org/3/search/movie?query={movie}&include_adult=false&language=en-US&page=1"
            res = self.session.get(url).json()
            result.append(res["results"])

        return result
Enter fullscreen mode Exit fullscreen mode

Now we will discuss above code method by method. Let’s start with initializer method.

def __init__(self) -> None:
        self.model = palm
        self.model.configure(api_key=os.getenv("PALM_API_KEY"))

        self.session = requests.Session()
        self.session.headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {os.getenv('TMDB_API_KEY')}"
        }

        self.defaults = {
            'model': 'models/text-bison-001',
            'temperature': 0.7,
            'candidate_count': 1,
            'top_k': 40,
            'top_p': 0.95,
            'max_output_tokens': 1024,
            'stop_sequences': [],
            'safety_settings': [
                {"category":"HARM_CATEGORY_DEROGATORY","threshold":1},
                {"category":"HARM_CATEGORY_TOXICITY","threshold":1},
                {"category":"HARM_CATEGORY_VIOLENCE","threshold":2},
                {"category":"HARM_CATEGORY_SEXUAL","threshold":2},
                {"category":"HARM_CATEGORY_MEDICAL","threshold":2},
                {"category":"HARM_CATEGORY_DANGEROUS","threshold":2}
            ],
        }
Enter fullscreen mode Exit fullscreen mode

First we are going to assign our palm model by following line of code and we are configuring palm api key to model .

self.model = palm
self.model.configure(api_key=os.getenv("PALM_API_KEY"))
Enter fullscreen mode Exit fullscreen mode

Now we going to create session object to call TMDB API and we are going to configure TMDB API key with session object .

self.session = requests.Session()
self.session.headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {os.getenv('TMDB_API_KEY')}"
}
Enter fullscreen mode Exit fullscreen mode

Our Palm model needs some default configurations at the time of generation like which model we are going to use , what will be temperature at the time of text generation .

self.defaults = {
            'model': 'models/text-bison-001',
            'temperature': 0.7,
            'candidate_count': 1,
            'top_k': 40,
            'top_p': 0.95,
            'max_output_tokens': 1024,
            'stop_sequences': [],
            'safety_settings': [
                {"category":"HARM_CATEGORY_DEROGATORY","threshold":1},
                {"category":"HARM_CATEGORY_TOXICITY","threshold":1},
                {"category":"HARM_CATEGORY_VIOLENCE","threshold":2},
                {"category":"HARM_CATEGORY_SEXUAL","threshold":2},
                {"category":"HARM_CATEGORY_MEDICAL","threshold":2},
                {"category":"HARM_CATEGORY_DANGEROUS","threshold":2}
            ],
        }
Enter fullscreen mode Exit fullscreen mode

Next , we need to convert string into it’s url form . By using urlify_string method to convert string into it’s url form 🌐.

def urlify_string(self,string):
        url_encoded = urllib.parse.quote(string)
        return url_encoded
Enter fullscreen mode Exit fullscreen mode

Now we are going to generate results from model . We are going to use output from palm model to fetch movie poster and movie name from TMDB API .

def generate(self,movie_name :str):

        result = []

        prompt = f"""input: Th Dark Knight 
            output: Batman Begins
            The Prestige
            Se7en
            Fight Club
            The Shawshank Redemption
            input: {movie_name}
            output:"""

        response = self.model.generate_text(
            **self.defaults,
            prompt=prompt
        )

        recommendations = response.result.split("\n")
        time.sleep(0.1)
        for i in recommendations:
            movie = self.urlify_string(i)
            url = f"https://api.themoviedb.org/3/search/movie?query={movie}&include_adult=false&language=en-US&page=1"
            res = self.session.get(url).json()
            result.append(res["results"])

        return result
Enter fullscreen mode Exit fullscreen mode

If you take closer look to our prompt . It looks different from normal prompt as you use with ChatGPT .

PaLM Model comes in three flavours as following :

1 . Text Prompt

2 . Data Prompt

3 . Chat Prompt

For our project purpose we are going to use Data prompt .

What exactly is Data prompt 🤔?

Data prompt is some what similar to fine tunning model . Here we need to give palm model some examples for training and then it generates similar output for particular input .

Data Prompt

As you can see in above image example we need to give example input and output to the model . In examples I have given input as The Dark Knight and in output column , there are movies similar to The Dark Knight .

By the way The Dark Knight is my favourite movie 🃏🦇.

Back to the topic , Now we are going to test our prompt .So in input we are going to add Iron man as a movie and then it will generate output movies 🎥.

Now we need to give such input and output in python code 🐍.

prompt = f"""input: Th Dark Knight 
            output: Batman Begins
            The Prestige
            Se7en
            Fight Club
            The Shawshank Redemption
            input: {movie_name}
            output:"""
Enter fullscreen mode Exit fullscreen mode

Here in above python code , we are formatting new string by using f-string in python .We have modified out prompt to give output for particular movie .

response = self.model.generate_text(
            **self.defaults,
            prompt=prompt
        )

recommendations = response.result.split("\n")
Enter fullscreen mode Exit fullscreen mode

Then we are going parse our prompt and default configurations to generate_text method which will generate output . After text generation we going to split output by new line character because movie names in output are on new lines.

for i in recommendations:
            movie = self.urlify_string(i)
            url = f"https://api.themoviedb.org/3/search/movie?query={movie}&include_adult=false&language=en-US&page=1"
            res = self.session.get(url).json()
            result.append(res["results"])

 return result
Enter fullscreen mode Exit fullscreen mode

Then we are going to loop through the recommendation generated by palm model and we are going to make GET request to TMDB API to get information of particular movie . Then we are going to store this into result list and at last we are going to return result .

Now our model text generation code is complete .Now we are going to implement user interface by using streamlit .

First we are going to give title to our web app . It is similar to h1 tag in HTML .Following code will create title by calling st.title(“Title name”) method.

st.title("Recommendation System Using Palm 🎞️")
Enter fullscreen mode Exit fullscreen mode

Now we need text box such that user can able to insert movie name .

text_box = st.text_input("Your movie goes here 🎥")
Enter fullscreen mode Exit fullscreen mode

Now we are going to create object for Recommend_movies class .

r_m = Recommend_movies()
Enter fullscreen mode Exit fullscreen mode

To manage layout in streamlit , we are going to use columns . We will add fetched image in column 1 if index of image is even or else we will add fetched image into column 2.

col1, col2 = st.columns(2)
for i in range(len(result)) :
        if result[i] != []:

            if i % 2 == 0 : 

                col1.image(f"https://image.tmdb.org/t/p/w300_and_h450_bestv2{result[i][0]['poster_path']}")
                col1.write(result[i][0]['title'])
            else :

                col2.image(f"https://image.tmdb.org/t/p/w300_and_h450_bestv2{result[i][0]['poster_path']}")
                col2.write(result[i][0]['title'])
Enter fullscreen mode Exit fullscreen mode

We can add image in column by calling col.image method . We need to pass image path as parameter in col.image .

That’s It now let’s run our application 😊.If you have installed streamlit correctly the you can run cli commands for streamlit as follows :

$streamlit run filename.py

After running python file for project , New browser tab will open at http://localhost:8501/ . You will see web app like this :

Project Interface

You just need to insert movie name in text box and hit enter . You should see output like this :

Project Demo

That’s it ! . Congratulations 😎! You have created recommendation system using PaLM model . Source code is available on Github .

Thanks for reading this article 😊. If you liked content in blog then please like 👍it . Also checkout my youtube channel here .If you have any question then feel free to comment down .

You can connect with me through linkedin and also from portfolio website.

Thank You 😃!

Top comments (0)