-: Hey there. Eden here.
And this video was refilmed to match
the latest version of LangGraph
because things have changed
since this video was previously filmed.
And the version I'm going to be using
for this video is 1.0.5.
And the important thing to you to note for this video
is that it's updated according to LangGraph 1.+.
Now let's go to main.py
and let's start assemble all of the pieces together
and let's build our LangGraph graph.
So let's start with the imports.
Let's import Literal from typing.
Let's go and import AIMessage and ToolMessage.
And let's go and import from LangGraph the end node,
the start node.
And we want to import a StateGraph.
And the StateGraph is only going
to hold a list of messages.
So that's why I am also importing MessageState.
And we implemented this from scratch
in the previous section of the reflection agent.
However, we can import it from LangGraph prebuilt.
So eventually the StateGraph is going to have
a state of the MessageState,
which is simply a list of messages.
And let's see, import from our chains PY file,
the reviser chain, we have it right over here
and the first responder chain, which we have it over here.
We also want to import from the tool executor PY file
the execute tool variables,
which is going to be a tool node.
So it's going to be running our tools.
This is going to be running our search tool concurrently.
And let's define Max Iterations equals 2.
So this means we want only two iterations
of revision, draft, revision, draft
and we want to limit this.
In the future, if we want to integrate LLM
as a judge architecture, we can not limit it by the number,
but make an LLM call to decide
whether we want to resume or not.
And we're going to be implementing
these kinds of architecture in the next section
of the course where we're going to build
an agentic correct solution.
So let's start by implementing our graph nodes.
So let's start with the first node,
which is called the draft node.
So this node is going to receive the state,
which I remind you only has a list of messages.
And we simply want to draft the response.
So we want to call the first responder chain
and we are going to give it when we invoke it
in the messages key, the state in the messages place.
So this is going to take all of the messages
that we have in the graph and send it.
And when we start to execute this graph,
the first message is going to be
the human message with our user input.
So when we're going to get a response
from the first responder,
we're going to be getting an answer question.
This is going to be the type of the response.
So it's going to have an answer,
it's going to have the reflection,
so what needs to change, what is missing,
what is superfluous, and the search queries.
So these are going to be the search queries
which we want to run later.
And lastly, once we get this response,
we want to append it into our messages key in our state.
So this line over here is going to take the message
and it's going to append it to the state.
So in the same way,
let's go and let's implement the revised node.
And this is going to revise the answer
based on the tool results, which was the Pydantic critique.
And here, we simply want to take our reviser chain
and we want to invoke it
with all the messages we have so far.
And in the first iteration,
it's going to be the result of the first result.
After we get a response,
we want to append it to the graph state as well.
And before we go and implement our graph,
let's go and remember what we're trying to do here.
So we want to limit the number of iterations we do here.
And the way we want to limit it is with a magic number,
which in our case is 2.
So we want to have only at most two iterations here.
And this is a heuristic.
This is not the best way to do it.
Of course, if you want to make it much more advanced,
we can add an LLM as a judge here.
But for this example, we want to limit it to two.
So in order to count
and to know in which iteration we are,
let's take a look of what's happening here.
So I remind you that we are using function calling
to structure our LLMs output here.
So this kind of response is going
to come from function calling.
And so in order to limit our number of iterations
to two iterations,
because we want to count the number of tool calls
because each tool call is going to be an LLM response
according to our structured output here.
So when we invoke,
the responder is going to be one tool call here.
Executing the tools will not result in tool calls
because it's going to be tool nodes.
So there isn't an LLM making a tool call over here.
And when we're going to run our advisor chain,
we're going to receive a tool call.
So the condition to finish the job
and to endo graph is going to be
if we have more than two tool calls,
this is one, this is two.
And in the second iteration
we're going to have three tool calls.
And here we're going to have four tool calls.
So this number is going to be greater than two.
So this is what we're going to be doing
in the conditional edge here after the reviser chain.
So let's go and implement its logic.
So the conditional edge is going to be called event loop
and it's going to receive the state as an input,
which is going to be a list of messages.
So it's going to return either,
we want to go and execute tools.
So either from here we want to go to execute tools
or we want to go and end.
So this is going to be end here.
And this is the conditional edge.
It goes to the end or it goes to the execute tools here.
So the way we want to do it,
we want to go and count the number of tool calls.
So this is simply iterating over the messages key,
iterating through all the messages.
If it is a tool call, we want to call it.
And here we get the number of the tool visits we have here.
So if this number is going
to be greater than max iterations, which is two,
then we want to finish
'cause it's going to be three or it's going to be four.
And if not, we want to go to execute tools.
So this is going to ensure us
we are running this architecture only twice.
The loop here is running only twice.
And now let's go and implement the graph.
We want to build a StateGraph
which is going to receive the message state,
which is I remind you a list of messages.
We want to add the draft node,
which is going to be this function over here.
We want to add the execute tools nodes,
which is going to be the execute tool node we created here.
And lastly, we want the revised node
to be this revised node we implement of here.
Cool. So we finished with the nodes.
So we have this object right over here,
we have the execute tools nodes,
and we have the reviser node here.
So let's define the first responder here.
The responder, let's define it as the first node,
the draft node.
So let me add an edge from the start of the graph to draft.
So this is going to take the user input
and execute now the reviser agent.
And now we want to go,
after we do that, we get the first response,
we get a critique for it, and we get search results.
So now we want to go
and we want to execute the tools with the tools node.
So let's define an edge from the draft node
into the execute tools node.
And now, after we execute the tools,
we want to go to the reviser node.
So let's create an edge from the execute tool node
to the revised node.
And lastly, after we finish the revised node,
now we want to define the conditional branch.
So let's go and add the conditional edge
from the revised node.
The logic is going to be the event look we have over here.
And the third argument here is going to be a list
that is going to tell LangGraph which nodes can go
and execute after this conditional edge.
So this is going to help when we visualize the graph here
and here, we want to give it execute tools and end,
which those values need to match the values
that we return from here, from the literals.
We can see right over here.
Let's go now and compile the graph
and let's go and print it.
So I'm going to print it with Mermaid.
So here, let me go and copy now the description of our graph
and let's go and visualize it with Mermaid.
So let me go to mermaid.live.
So I'll pasted all of the code here.
So this is the flow execution of our graph here.
And notice here,
this conditional edge from the revised node.
After the revised node, we have the conditional step
either to go and finish
or to go and make another search query
and start revising according to the new query.
So let me go now back to the code here
and let's go and invoke it.
So in order to invoke her graph,
we want to give it a list of messages.
So I'm going to create here a dictionary
and I want to put here the messages field here.
And this is going to be a dictionary.
So the role is going to be user,
I remind you link chain is going to go
and cast this into a human message
because the role here is user,
and the content is going to be right about AI-Powered SOC.
autonomous soc problem domain,
list startups that have raised capital on that.
And after we go and execute it,
we want to go and take last message.
So let me run this in the bag
and let me show you where we take our answer from.
So this is now running
and we can see we got here to this breakpoint
and let's go and check the response.
So if we'll go to res,
we can see all of the messages that we have here
and we're going to review everything in length meet.
But I want to show you the last message
is going to be an AI message.
And this AI message is going to have a tool call.
Let's go and look for the tool calls.
Here we can see we have the tool calls.
It's going to be a tool call where we're going to have
the revised answer.
And the answer here is going to be here in the args here.
See, this is the answer.
So let's go, and according to the structure,
let's go now and let's format the response and print it.
So I want to check if the last message is an AI message.
And if this AI message has a tool call,
I want to take the tool call,
the first one because we're only going to have one,
I want to go to the args and I want to go
and check out the answer key here.
And let's go and print also the rest of the messages.
So let me now go and stop this execution.
Let's go and run it again.
And after we run it,
I will show you in length meet the entire trace.
So let me go now
and let me run everything from the beginning
and I want to show you the printed answer.
And here we can see we got here an answer.
Let me go to the top here.
We can see AI Driven and Autonomous SOC, Problem Domain,
Traditional SOC, face alert overload,
manual triage delays and shortage of skilled analytics,
AI powered SOC apply supervised,
unsupervised machine learning and graph analytics
to reduce false positives by up to 50%
and automate 70% over routine alerts
cutting investigation time by 70 to 90%.
Autonomous SOC extend low risk response, quarantine emails,
isolating endpoints and reconfiguring firewall,
shrinking dwell time and MTTR two under five minutes
in finance and healthcare.
MTTR is Median Time To Response.
And here we can see startups by maturity tier
and the leaders which are Darktrace, Vectra,
the Scale Up, Exabeam, Cybereason
and the Innovators, Deep Instinct, SecBI and Blumira.
All right.
Here we have the list of messages.