Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Whenever you are calling the graph,argument should be a dictionary and dictinary as per the graphstate class args.
- #graph return the graph state only.
- from langgraph.prebuilt import ToolNode
- from langgraph.prebuilt import tools_condition
- tools=[add]
- graph=StateGraph(State)
- graph.add_node(llm_tool,"llm_tool")
- graph.add_node("tools",ToolNode(tools)) #It wraps the tools and make it langgraph compatible
- graph.add_edge(START,"llm_tool")
- graph.add_conditional_edges(
- "llm_tool",
- tools_condition
- )
- graph.add_edge("tools",END)
- graph=graph.compile()
- graph.invoke({"messages":"what is 2+4?"})
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #ChatPromptTemplate ways:-
- reflection_prompt=ChatPromptTemplate.from_messages(
- [
- (
- "system",
- "You are a viral twitter influencer grading a tweet. Generate critique and recommendations for the user's tweet."
- "Always provide detailed recommendations, including requests for length, virality, style, etc.",
- ),
- MessagesPlaceholder(variable_name="messages") ,
- ]
- )
- chain = prompt | llm
- result = chain.invoke({"messages": [HumanMessage(content="What's the capital of Germany?")]})
- prompt = ChatPromptTemplate.from_messages([
- ("system", "You are a helpful assistant."),
- ("human", "What is the capital of {country}?")
- ])
- response = chain.invoke({"country": "France"})
- # ----OR
- filled_prompt = prompt.format_messages(country="France")
- response = llm(filled_prompt)
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #StateGraph
- class State(TypedDict):
- messages:Annotated[list,add_messages] #messages would be a key for state,It's value should be a list
- #add_messages tell that whenever a node outputs,append into the list,also called reducer, rather than replacing.
- #Lot of nodes will update the message by returnning the messages then always return in form of a list
- #eg. return {"messages": [AIMessage(content="2 + 2 is 4")]}
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #one way to invoke llm means we can give SystemMessage also while invoking and can avoid making prompt
- content = llm.invoke([ #LLM can be invoked with chat history also and .content is neede to extract output
- SystemMessage(content="Write a report section following the provided name and description. Include no preamble. Use markdown formatting."),
- HumanMessage(content=f"Here is the section name: {section.name} and description: {section.description}")
- ])
- # Method-2 for invoking LLM
- msg = llm.invoke( f"Write a joke about {state['topic']} but take into account the feedback: {state['feedback']}")
- #Calling the LLM without SystemMessage
- tool_call=llm_with_tools.invoke([HumanMessage(content=f"What is 2 plus 2",name="Krish")])
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #Invoking a graph-Method1
- graph.invoke({'messages':"Hello, What is agentic ai?"})
- #Invoking a graph-Method2
- messages = graph.invoke({
- "messages": [{"role": "user", "content": "What is agentic ai and 2 plus 2"}]
- })
- #Invoking a graph-Method 3
- messages=graph.invoke({"messages":HumanMessage(content="Provide me the top 10 recent AI news for MArch 3rd 2025,add 5 plus 5 and then multiply by 10")})
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #For printing messages
- from pprint import pprint
- messages=[AIMessage(content=f"Please tell me how can I help",name="LLMModel")]
- messages.append(HumanMessage(content=f"I want to learn coding",name="Krish"))
- messages.append(AIMessage(content=f"Which programming language you want to learn",name="LLMModel"))
- messages.append(HumanMessage(content=f"I want to learn python programming language",name="Krish"))
- for message in messages:
- message.pretty_print()
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #Tool to node method 1
- from langgraph.graph import ToolNode
- tool = StructuredTool.from_function( #Add is just a function takes two arguments and return their sum.
- func=add,
- name="add_numbers", # 👈 THIS is the tool's name
- description="Add two integers"
- )
- execute_tools = ToolNode(tools=[tool])
- #Here we are manually wrapping the function and giving args like func,name and description where name is used for internal tool calls.
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #Tool to node, method 2 here -Langgraph internally wraps the function and give name and description to the node
- from langgraph.prebuilt import ToolNode
- def add(a:int,b:int)-> int:
- """ Add a and b
- Args:
- a (int): first int
- b (int): second int
- Returns:
- int
- """
- return a+b
- tools=[add]
- builder=StateGraph(State)
- #Make it a node
- builder.add_node("tools",ToolNode(tools))
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #Conditional_edge for tools_condition
- from langgraph.prebuilt import tools_condition #You can directly connect from START to multiple nodes without conditional edge also,It will go to all the nodes parallely.
- builder = StateGraph(State)
- builder.add_node("tool_calling_llm", tool_calling_llm)
- builder.add_node("tools", ToolNode(tools))
- builder.add_conditional_edges(
- "llm_tool",
- # If the latest message (result) from assistant is a tool call -> tools_condition won't do anything,it will get routedt to tool call.
- # If the latest message (result) from assistant is a not a tool call -> tools_condition routes to END
- #the above conditions are defined internally with tools_condition
- tools_condition
- )
- builder.add_edge("tools","tool_calling_llm") #Bind it back to llm node
- e
- # Method-2 for conditional edge
- # if condition1: #this should be a way to return to graph
- # return {"next":"grade_answer"}
- # else:
- # return {"next":"generate"}
- graph.add_conditional_edges(
- "hallucination",
- lambda state: state["next"],
- {
- "grade_answer": "grade_answer",
- "generate": "generate"
- }
- )
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- from langchain_community.tools import ArxivQueryRun,WikipediaQueryRun
- from langchain_community.utilities import WikipediaAPIWrapper,ArxivAPIWrapper
- from langchain_community.tools.tavily_search import TavilySearchResults
- api_wrapper_arxiv=ArxivAPIWrapper(top_k_results=2,doc_content_chars_max=500)
- arxiv=ArxivQueryRun(api_wrapper=api_wrapper_arxiv)
- tavily = TavilySearchResults()
- tools=[arxiv,tavily,] #you can put here custom python simple functions also as a tool
- llm_with_tools = llm.bind_tools(tools)
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- from langgraph.checkpoint.memory import MemorySaver
- memory=MemorySaver()
- graph_memory = builder.compile(checkpointer=memory)
- ## Specify the thread
- config={"configurable":{"thread_id":"1"}}
- # Specify an input
- messages = [HumanMessage(content="Add 12 and 13.")]
- messages=graph_memory.invoke({"messages":messages},config=config)
- for m in messages['messages']:
- m.pretty_print()
- messages = [HumanMessage(content="add that number to 25")] #Keeping the same config will remeber the previous conversation
- messages=graph_memory.invoke({"messages":messages},config=config)
- for m in messages['messages']:
- m.pretty_print()
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #Memory saver with human in the loop
- memory=MemorySaver()
- graph=builder.compile(interrupt_before=["assistant"],checkpointer=memory)
- thread={"configurable":{"thread_id":"123"}}
- initial_input={"messages":HumanMessage(content="Multiply 2 and 3")}
- # for seeing the full flow
- for event in graph.stream(initial_input,thread,stream_mode="values"):
- event['messages'][-1].pretty_print()
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- # Schema for structured output to use in evaluation
- class Feedback(BaseModel):
- grade: Literal["funny", "not funny"] = Field(
- description="Decide if the joke is funny or not.", #Description helps langgraph to show to the llm while deciding the grade.
- )
- feedback: str = Field(
- description="If the joke is not funny, provide feedback on how to improve it.",
- )
- # Augment the LLM with schema for structured output
- evaluator = llm.with_structured_output(Feedback)
- #You can make the chain of evaluator with prompt also and call using .invoke method
- #
- # -Use tools list when you are binding the tools with llm but in graph,use ToolNode(tools) where tools are the list of the tools.
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- tools=[add,multiply,divide]
- llm=llm.bind_tools(tools)
- def llm_with_tools(state:State):
- return {'messages':[llm.invoke(state['messages'])]}
- graph=StateGraph(State)
- graph.add_node('llm_with_tools',llm_with_tools)
- graph.add_node('tools',ToolNode(tools))
- graph.add_edge(START,'llm_with_tools')
- graph.add_edge('llm_with_tools','tools')
- graph.add_conditional_edges('llm_with_tools',tools_condition)
- graph=graph.compile()
- #When we are binding the tools with LLM,this will help LLM to decide wherther to call a tool or not or which tool.It does the tool selection,not it's exectuion.
- #but ToolNode(tools) which we have created as a node, does the tool execution.
- #One more thing to notice that,you make only one edge with tools but it's two way because the tools returns the response.
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #this code is for a chatbot where the LLM gets the previous messsages everytime.
- from langgraph.graph import StateGraph
- from typing import Annotated
- from typing_extensions import TypedDict
- from langgraph.graph.message import add_messages
- class State(TypedDict):
- messages: Annotated[list, add_messages]
- # Build graph
- graph = StateGraph(State)
- def chatbot(state: State):
- return {"messages": [llm.invoke(state["messages"])]}
- graph.add_node("chatbot", chatbot)
- graph.set_entry_point("chatbot")
- graph.set_finish_point("chatbot")
- app = graph.compile()
- # Run infinitely
- while True:
- user_input = input("You: ")
- if user_input.lower() == "exit":
- break
- state = app.invoke({"messages": [{"role": "user", "content": user_input}]})
- print("AI:", state["messages"][-1].content)
Advertisement
Add Comment
Please, Sign In to add comment