In this video, we'll be writing the endpoint
that will take a user's request for a place,
city or country they wish to visit, an optional
list of preferences and then call Gemini to
suggest travel destinations.
Sounds fun?
Let's dive in.
First, we'll be modeling the request data
using Pydantic.
So to get started with that, we need to import
some models.
So here in VSCode, let us scroll up, and just
under OS, let us say from Pydantic, import
base model.
We'll also be getting some items from our
typing library that will be list and optional,
and we'll also import JSON so that we can
send back JSON responses.
Good, now we will need to define the pedantic
model that will contain the data we are expecting
in our request.
So let's put it just above our endpoint.
Let us create the class LocationRequest that
will inherit this model.
And for our request, we expect a location
parameter which is a string and a preferences
parameter which is an optional list of strings.
And we can simply default that to an empty
list.
Good.
Now that we have defined the structure of
the data we're expecting, let us write our
endpoint for our location text-based search
and also define its handler.
We're going to
be doing that just below the root endpoint.
Here we'll say app dot, this will be a post
endpoint, and as we saw in our plan, it will
be slash API for slash suggest by location.
We can then define an handler for this.
This will be an async function because we're
going to be calling the Gemini API and that
is an asynchronous process.
So we say our handler will be suggest, underscore
buy, underscore location, and it will take
in a request with the shape of location request.
Good.
Let's put some small documentation here and
say generates travel suggestions based
on location search.
Awesome.
Now, inside this function, we need to make
a request to the Gemini API using the data
that we collected from our request.
To kick that off, let's start by opening a
try-except block, where we'll be wrapping
our Gemini request.
So down here, I'm just going to say try.
We'll leave this empty for now.
And we'll say accept exception as e.
And here, we're just going to raise an HTTP
error.
With an HTTP exception, so the status code
2500,
indicating a server error.
That would be status code, not status.
Then we'll provide some detail so that the
client can
understand what is going on.
And here, we'll simply say, error generating
suggestions.
And let us send back the error as a string.
Good.
Now, with this in place, we can now go into
the Try section
to prepare our data, send our Gemini request,
and return the response.
First, let us prepare our list of preferences
for the prompt
by converting it from a list into a single
sentence.
Let's go into the Try section here.
Here we can say, preferences, text.
Let's set that to an empty string.
We can then say from the request,
if we have preferences, because it's an optional
piece of data
that the client can send, we can then build
our preferences
text here and say a string newline user preferences
and this idea we can convert our user preferences
list into a string by making it a comma separated
string so join request dot preferences.
So this will simply build a preferences text
that we can simply embed in our prompt if
the user sends a list of preferences.
Now with this in place, we can now write our
full prompt.
It's going to be a pretty substantial amount
of text and I'm sure you don't just want
to sit there and watch me type all that.
So I'll just copy it from the completed version
of the exercise files and bring it here.
So grab the prompt and paste it here.
As you can see, it's pretty lengthy.
Let me format that a little bit, let's say,
and we'll put this here, good.
So let us go through the prompt that we just
brought in.
It says, you are a travel expert.
Generate five travel destination suggestions
near or related to the location that we sent.
We also give it our preferences text if it
exists, else it will just be an empty string
and it will be completely ignored.
Then our prompt goes further to say that for
each destination, provide name of the destination,
Brief description which is 2-3 sentences Best
time to visit
Main attractions we want to list 3 And an
estimated budget level using the indicators
budget, moderate or luxury Then we also want
a formatted response back
as a JSON array Each object in the collection
should have
a name field which will be the destination's
name
A description field which will be a brief
description of the destination
the best time to visit, attractions which
will be a list of attractions, and a budget
level which will be picked between the options
budget, moderate and luxury.
And we give it a final instruction by saying
only return the JSON array, no additional
text.
So we don't want any explanation or descriptions
from the model.
Just simply return the JSON array as a string.
Great.
Now we can send our prompt to the Gemini API.
So let's go ahead and do that.
It's going to come down here.
And we're going to say response equals.
We'll take our GenAI client.
We'll say models.generateContent.
That's good.
Now inside here, we need to pass our model.
And that will be our constant that we defined
up here,
which is Gemini model.
And then we need to also define a content
property, which
will be set to our prompt.
And once we have the response back,
Let us get the response text by saying response.text
and we want to strip it of whitespaces so
I'm just going to call the strip function
on it.
Good.
Now that we have our response text, we need
to clean up any markdown code because Gemini
When I send our results which we have told
it to send as a list of destination objects,
it sends it as Markdown and it denotes it
as JSON.
So we need to clean up all that Markdown information
so that we get clean JSON string that we can
then parse.
So let's go ahead and do that.
Next we'll check if our response text starts
with the markdown label of json.
If it does then we'll simply strip out the
first 7 characters which is this3 and the
word json.
We'll say response underscore text and start
after the first 7 characters.
Next we check once again if our response text
starts with just the backticks.
If so, we can simply copy this and say we
want to strip the first three characters.
Also, if our response text ends with the three
backticks, which most likely if it has the
first set of backticks, it would have the
last set of backticks.
If it does, then what we want to do is to
get rid of those final three backticks.
Good.
And once we are done with this, we also want
to still strip our response text of any white
space.
Just going to copy the response text and call
the strip function on it.
Good.
Now that we've cleaned up our markdown, we
can now pass it and return our destinations
back to the user.
So let's do that next.
We're going to say destinations be equal to
json.loads,
then we can pass this, our response
text.
And then to the client, we can simply return
our dictionary of destinations.
Awesome.
We have now finished with our text-based search
endpoint.
Now, to ensure that everything we just did
is working as expected, let us test it out
and see if we can send a search query to it
and get results back from the Gemini API.
Now to do that, first you should make sure
that the file is saved.
Then we need to put up our command line and
run our server.
Our server runs without errors.
Now let us head to our browser and check out
the documentation.
Now back here in our browser, we previously
had just the root endpoint, but now if we
refresh this, we now have two endpoints, our
root endpoint, which is a GET endpoint, and
our new SUGGEST BY LOCATION endpoint, which
is a POST endpoint.
So let's test this.
Let's expand it.
Then we see the data it takes, location, and
a list of preferences.
to click try out.
For the location, let's put in Paris.
For the preferences, let's say beaches.
And cuisine.
And now we can simply click execute.
Loading as it's performing an asynchronous
operation.
And once it's done, we scroll down, we see
we get a 200 okay requests.
So our request
was successful.
And we get back a list of destinations.
As you can see, we have destinations.
And we have the list.
And inside the list, we have objects of destinations
that have been
suggested by the Gemini API.
Down here, we have St.
Malo, we have the description,
The best time to visit is May to September
and we have the top attractions and budget
level which is set to moderate.
Awesome.
As you can see our endpoint works fine
and in the next video we'll be working on
the front end side of things
and integrating our search feature with this
search endpoint.
See you there.