In this section, we'll be adding some slight
improvements to our Travel Companion application.
The Gemini API provides more features that
we can take advantage of to make our application
more efficient and our code cleaner and we'll
be making use of some of these features to
make our already good application even better.
In this video, we'll be refactoring our Gemini
API requests to produce structured outputs.
So far, we have been instructing the models
about how we want our JSON output directly
in our prompt.
We have also been clearing up and passing
the JSON string return.
This strategy is referred to as JSON passing.
And while JSON passing is good, we can already
see it working in our application without
issues.
Structured outputs help define and produce
an already structured JSON output that we
can use directly in our code.
No prompt instructions and parsing logic needed.
Sounds awesome, right?
Let's do that right away.
First, to retain our previous code for reference
purposes,
let us create a new branch for all the enhancements
we'll be adding to this app.
So I'm going to pull up the command line,
kill the server for the front end,
do the same for the back end.
And I'm just going to go back here.
Let's clear this.
And I will say git checkout-b enhancements.
This is going to be our enhancement branch.
So hit Enter.
And as you can see, we have switched to the
enhancements
branch.
That's good.
You can see the back into my back end.
And when I go back to my front end,
I see that we're still in the enhancement
branch.
So if I run git branch, yeah, we are on the
enhancement branch.
So let's just clear this.
And I'm just going to run my front-end once
again,
so that that can keep running in the background.
Good.
Now to begin, we need to define a schema for
our destination
data that needs to be returned.
We'll be doing that using Pydantic.
So let us go ahead and get started.
I'm going to close out of this command line.
Then we're going to be defining two schemas,
one schema for our destination and one schema
for a list of our destinations, that is the
actual schema we're going to be giving to
our model to return.
So just below the models we already have,
we're going to define a new class and call
it destination.
it base model and this will be our schema
for the destination we want to return.
This is going to have the same structure as
we had in our prompt.
The same structure that we told Gemini to
return.
We have name which will be a string.
We have description which is going to be a
string also.
We also have best underscore time, which is
also a string that tells us the best time
the user can visit.
We have attractions.
Attractions will be a list of strings.
And we have our budget level, which is a string.
So this is our destination data structure.
This is what we told our prompts to return
if we scroll down to look at our prompt, not
this one, the endpoints that are returning
the destinations, and we go to the prompt,
we see we have name, description, best time,
attractions, and budget level.
So that's the same thing that we are defining
in our data model.
Let's go up.
Now we actually need our Gemini model to return
a list of these destination objects.
So I'm going to create another class, call
it DestinationList, we'll also give it BaseModel.
And it will contain a destination's key.
And this will be a list of the type Destination.
So we have these two defined and that is all
we need.
The next thing we need to do is to go to our
prompt.
Let's go to the one for SuggestByLocation.
And we're going to get rid of all these data
instructions.
So I'm just going to get a new clean up prompt
and I'm going to paste it here.
Boom.
So this prompt is basically the same as the
last one but without all the data instructions.
It just says, make sure each destination has
exactly three attractions in the attractions
array which the previous one also says and
ensure that budget level is one of budget
moderator luxury, which we also know it was
specified in the previous prompt.
But now we don't have any of those data stuff
anymore.
So that is cleaner.
Now the next thing we need to do is to instruct
our Gemini API request to produce structured
outputs.
We need to tell it about our models so that
it can then use the models that we have given
it to create structured outputs.
And we can achieve this by adding a generation
config.
So we're just going to add a config parameter
to this.
And inside this generation config, we're going
to tell it about our structured data models.
First, we're going to tell it what we want
back as our response MIME type.
response MIME type.
I will tell it application JSON so that it
returns it
as a JSON object.
And we then tell it about our schemas.
So say response
underscore JSON underscore schema.
So this is where we give it our data model.
And
And what we want is the destination list model,
which already contains the destination model.
And we need to call .model.jsonSchema.
Very important so that it can return the JSON
schema to the request.
So .model.jsonSchema.
So that's how we tell our request that we
want it to use our schemas to produce structured
outputs.
Now that we have this logic in place, now
that we are telling it to produce structured
outputs, we don't need all the text parsing
stuff anymore.
So let us get rid of that.
So from this line, down to this line, we can
say, bye bye, say bye bye.
And now all we need to do is get our destinations
from the new response and return it to this
request.
So I'm just going to say result equals destination
list, then we'll call it the .model,
underscore
validate, underscore JSON function, and simply
give it our response text, which I'm going
to say response.text.
So we get our results.
We validate it.
And here, we can just simply
say result, which is our actual result object
that comes back and called the destinations.
That is this destination key here, the destinations.
That's where we get our destinations.
And
we simply return it back to our user.
Simple and clean.
And more programmatic, more native to programming.
Now that we're all done, let us run our server
and test this
out to make sure that everything
is working as expected.
Let's go back to our back end and say Python
main.py.
Nothing is really going to change in the front
end, but
that is the success story, the fact that we're
now using
structured outputs to produce these responses.
So back in our browser, first let us refresh
our application.
It's good.
And let us search for Tokyo this time.
Let's say Tokyo.
And it gets suggestions.
Everything should work just fine.
We should get no errors.
Simply perfect.
So our structured outputs are working perfectly.
Now they are working for the text search endpoint.
Let us head back to VSCode and implement structured
outputs
also for the image search endpoint.
Back in VSCode, first, I'm going to kill the
server.
And let us head to our other endpoint,
which is search by image.
Now, we already have our data models for the
destination,
so we don't need to touch those.
The first thing we need to do is to clean
up this prompt
of all instructions.
So I'm just going to clean that up.
Good.
It was formatted.
And now here we have the same prompt
that says analyze this landmark or travel
image
and suggest five similar travel destinations
with comparable features, architecture, atmosphere.
We have our preferences text.
what we want back as data, and no data return
instruction, no data structure instruction.
So we have that in place, next, let us get
our configuration in.
I'm just going to copy that from here, copy
that, go down, and give it to this request
also, that's fine.
And also, we get rid of all the parsing logic,
get our result, destination list.model.validate.json,
parse it our response text, which is response.text,
directly from the request response, and here
we can say result.destinations.
Perfect.
Now, let's try this out.
First, let us rerun
the server.
Server is running fine.
Now, I'll see you in the browser.
Now, in the browser, let us refresh once again.
And now, let us switch to the image search.
Let's pick our London Eye image once again.
And let us find similar destinations.
Everything should work fine if our structured
output is in effect.
We should see no errors.
Boom.
Simply awesome.
The Singapore Flyer, the Airgola in Las Vegas
and the High of the Sahara in Mauritania.
Perfect.
So, we have implemented structured output
for our search endpoints.
an assignment for you to implement structured
Now I'll be leaving the weather endpoint as
outputs into.
That should be fun.