Hey there Eden here.
And in this video we're going to be implementing the final part of our section.
So we're going to be implementing a version of Adaptive Rack.
And Adaptive Rack is based on this research paper you see right here.
And to be honest, it's a fancy word of simply using a question router to route our question to different
rack flows.
So in this video we're going to be using two rack flows.
So the first one is going to be taking the route to search on the internet and then to continue downstream
on the same logic we have before.
And the second round is going to be to use the retrieval augmentation from our vector store.
So we're first going to take the user's question, and we're going to decide whether the information
is stored in the vector store to answer that question.
And if it's not we're simply going to take the route to web search and answer from there.
And the main thing we're going to do is to implement a question router chain, which will take the question
and decide whether we're going to route it to the web search or to the retrieve node.
We're going to be writing tests to this chain, and we're going to integrate it into our graph by using
the set conditional entry point.
All right.
Let's go to the code.
So let's go and create a new file under chains.
And we want to call this file router.
And this file will hold the implementation of our router chain.
So we'll start from the imports.
And let's import from typing literal.
And if you're not familiar with the literal type like I was a couple of months ago, then it provides
a way to specify that a variable can only take one of predefined set of values.
So this is very useful for validation and type checking.
All right.
We want to import chat prompt template as well because we're going to use structured outputs.
We want to import base model and field from the lecture library.
And also let's import chat OpenAI for our LLM.
Now let's define the class that we want to structure our output.
So we'll call it root query which will inherit from base model.
It will have only one attribute which is called data source and is going to hold only the values of
vector store.
In case we want to search the answer from the vector store, or it's going to hold web search.
If we don't have the answer in the vector store, and we need to perform some external search with Tavileh.
Now when we initialize the field object, if we put here the ellipsis here, then this means that this
field will be required once we instantiate an object of this class.
All right.
And let's also write the description.
And the description is given a user question.
Choose to route it to web search or to vector store.
So we finished with our Pydantic class.
So now it's time to start writing our prompt and to leverage the structured output from LinkedIn.
So we'll create our LLM And we'll create our LLM with structured output with that class.
So basically we are binding now this pedantic class to be called as a function call like we saw earlier
in this course.
And what's going to be interesting here is the system call.
You are an expert at routing a user question to vector store or web search.
The vector store contains documents related to agents, prompt engineering, and adversarial attacks
because that's what we indexed our vector stored with all those articles we ingested in the first video
of this section.
Use the vector store for questions on those topics.
For everything else, use web search.
All right, let's go now and create the prompt itself.
So we'll use chat prompt template from messages.
And we'll first plug in the system message.
And then we're going to plug in the human message which contains the question that we're going to plug
in once we get the user's question.
And lastly, let's go and let's create the chain.
We'll call it question router which will take the route prompt.
We'll pipe it into the router and that's it.
We finished with our chain.
And I hope you're ready because right now we're going to be writing tests to this chain which is super
important for our software hygiene.
And let's go to the file tests.py.
And we want now to import the router question chain.
So let's simply write that string and auto import it.
And let's go up.
And let's just move it after we load the dot env.
So we won't have any issues.
All right.
So now we want to import the um the route query class.
And let's go up.
And we can see we imported it.
And now it's time to write our tests.
So we're simply want to test that we're able to route it to once in the vector store and once to the
web search.
So the first test is going to be dev test raster to vector store, which receives nothing and returns
none.
And here let's put the question to be agent memory.
So it should route to it.
And now we want to invoke the router question chain and will end up with a route query object.
So we'll call it rez which is a route query object.
And it's going to be equal to the question router chain after we invoke it with the question to be agent
memory.
Alrighty.
So let's go now and assert that the data source is going to be equals to vector store, because that's
what we wrote in the prompt.
Remember let's run it.
And we'll wait to get a result.
And we can see this test passed.
Cool.
So now I want to copy this and let's go instead to call it Route to Vector Store.
Let's call it Route to Web Search.
And our question instead of Agent Primary let's write how to make pizza.
And this time this should route us to the web search node.
And let's run it.
And we can see it passed.
And just as a sanity check, let's go and run all of our tests.
And I have to admit, like every developer, seeing all of those green check marks is very satisfying.
So let's wait and and see that everything passes.
By the way, we can make optimizations to all of those tests.
For example, we can run them concurrently because they're not dependent on each other.
But um, we're not going to cover it now, maybe later in this course.
All right.
So all of the tests passed and we are pretty confident with our chain.
All right.
So let's have a look on what we're going to be implementing right now in our graph py file.
Eventually this is how our graph should look like.
We should start from the start node.
Then we should have this conditional branch which would either go to retrieve or either go to web search
depending on our router that we just wrote.
And for this we're going to be introducing something new in graph, which is called a conditional entry
point, which basically is a conditional edge with the first node of the entry point.
So this is basically going to be our routing.
And from them we've already implemented all of the rest of the graph.
All right so let's go back to the graph.py file.
And now we want to import the router and the router query chain from the router.py file.
So this is what happens in line seven.
Cool.
So let's now implement the root question function, which is going to receive the state and return us
a string which is going to be the next node to execute.
And you can see the illustration on the right.
All right.
Let's add a print that we are in the root question.
And let's fish out the question from our graph state.
Now we'll simply run the question router chain with the invoke method.
Plugging in the user's question which we fished out from the state.
And the result we're going to save into a source variable, which is going to be of the type root query.
Because I remind you that the question router chain returns this kind of object because we use the structured
output chain.
All right.
So now we have the result.
Now if the data source is web search we want to route it into the web search node.
So we'll simply return web search.
And if the answer is vector store, then we simply want to route it into the retrieve node to perform
the retrieval.
Augmentation.
All right.
So let's add the conditional entry point.
And for that we want to use the function set conditional entry point.
And now we want to add our route function that we just implemented.
And let's add the path map.
So web search is going to be mapped to web search.
And retrieve is going to be mapped to retrieve.
All right.
So that's it for the implementation.
Let's go.
And let's now run the code.
So I'm going to go to the main file.
And let's run it with what is agent memory.
So our original prompt from the earlier in this section.
So we can see that we are now starting to first route the question.
And now we decide to route it into the vector store and to perform the retrieval, augmentation.
And from then the flow remains, as we know already.
And let's wait for the final answer.
And we indeed get the answer that we want.
We can go to Blanc-smith, and we can check out all of the traces and all of the code that's running
now.
Note that we didn't add any other node here.
We simply added a conditional edge from our entry point.
And let's go to the code.
And let's change the query to how to make pizza.
And let's run it again.
So now we're supposed to root into web search and to start running traveling and to continue from there.
So you can see that we routed into web search.
Indeed.
And yeah, that's pretty much it.
And we got here the answer.
Alrighty.
So we are pretty much done with our advanced drag flow.