Spaces:
Sleeping
Sleeping
Upload 4 files
Browse files- app.py +21 -0
- bot.py +54 -0
- chatbot.ipynb +659 -0
- requirements.txt +7 -0
app.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from bot import chatbot
|
3 |
+
|
4 |
+
st.title("Agent Based Bot")
|
5 |
+
st.write("Ask any question, and I'll try to answer it!")
|
6 |
+
|
7 |
+
mybot = chatbot()
|
8 |
+
workflow = mybot()
|
9 |
+
|
10 |
+
config = {"configurable": {"thread_id": "1"}}
|
11 |
+
question = st.text_input("Enter your question here:")
|
12 |
+
|
13 |
+
if st.button("Get Answer"):
|
14 |
+
if question:
|
15 |
+
response = workflow.invoke({"messages": [question]}, config=config)
|
16 |
+
st.write("**Answer:**", response['messages'][-1].content)
|
17 |
+
else:
|
18 |
+
st.warning("Please enter a question to get an answer.")
|
19 |
+
|
20 |
+
st.markdown("---")
|
21 |
+
st.caption("Powered by Streamlit and LangGraph")
|
bot.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langgraph.graph import StateGraph, MessagesState,START,END
|
2 |
+
from typing import Literal
|
3 |
+
from langchain_core.tools import tool
|
4 |
+
from langgraph.checkpoint.memory import MemorySaver
|
5 |
+
from langgraph.prebuilt import ToolNode
|
6 |
+
from langchain_groq import ChatGroq
|
7 |
+
from langchain_community.tools.tavily_search import TavilySearchResults
|
8 |
+
from dotenv import load_dotenv
|
9 |
+
|
10 |
+
load_dotenv()
|
11 |
+
|
12 |
+
memory = MemorySaver()
|
13 |
+
|
14 |
+
class chatbot:
|
15 |
+
def __init__(self):
|
16 |
+
self.llm = ChatGroq(model_name="Gemma2-9b-It")
|
17 |
+
self.memory = memory
|
18 |
+
self.call_tool()
|
19 |
+
|
20 |
+
def call_tool(self):
|
21 |
+
tool = TavilySearchResults(max_results=2)
|
22 |
+
self.tool_node = ToolNode(tools=[tool])
|
23 |
+
self.llm_with_tool = self.llm.bind_tools([tool])
|
24 |
+
|
25 |
+
def call_model(self, state: MessagesState):
|
26 |
+
config = {"configurable": {"thread_id": "1"}}
|
27 |
+
messages = state['messages']
|
28 |
+
response = self.llm_with_tool.invoke(messages, config=config)
|
29 |
+
return {"messages": [response]}
|
30 |
+
|
31 |
+
def router_function(self, state: MessagesState) -> Literal["tools", END]:
|
32 |
+
messages = state['messages']
|
33 |
+
last_message = messages[-1]
|
34 |
+
if last_message.tool_calls:
|
35 |
+
return "tools"
|
36 |
+
return END
|
37 |
+
|
38 |
+
def __call__(self):
|
39 |
+
workflow = StateGraph(MessagesState)
|
40 |
+
workflow.add_node("agent", self.call_model)
|
41 |
+
workflow.add_node("tools", self.tool_node)
|
42 |
+
workflow.add_edge(START, "agent")
|
43 |
+
workflow.add_conditional_edges("agent", self.router_function, {"tools": "tools", END: END})
|
44 |
+
workflow.add_edge("tools", "agent")
|
45 |
+
|
46 |
+
self.app = workflow.compile(checkpointer=self.memory)
|
47 |
+
return self.app
|
48 |
+
|
49 |
+
if __name__ == "__main__":
|
50 |
+
mybot = chatbot()
|
51 |
+
workflow = mybot()
|
52 |
+
|
53 |
+
response = workflow.invoke({"messages": ["Who is the current prime minister of the USA?"]})
|
54 |
+
print(response['messages'][-1].content)
|
chatbot.ipynb
ADDED
@@ -0,0 +1,659 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 1,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [],
|
8 |
+
"source": [
|
9 |
+
"from langchain_groq import ChatGroq\n",
|
10 |
+
"llm=ChatGroq(model_name=\"Gemma2-9b-It\")"
|
11 |
+
]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"cell_type": "code",
|
15 |
+
"execution_count": 2,
|
16 |
+
"metadata": {},
|
17 |
+
"outputs": [
|
18 |
+
{
|
19 |
+
"data": {
|
20 |
+
"text/plain": [
|
21 |
+
"'Hello! 👋 How can I help you today? 😊\\n'"
|
22 |
+
]
|
23 |
+
},
|
24 |
+
"execution_count": 2,
|
25 |
+
"metadata": {},
|
26 |
+
"output_type": "execute_result"
|
27 |
+
}
|
28 |
+
],
|
29 |
+
"source": [
|
30 |
+
"llm.invoke(\"hi\").content"
|
31 |
+
]
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"cell_type": "code",
|
35 |
+
"execution_count": 3,
|
36 |
+
"metadata": {},
|
37 |
+
"outputs": [],
|
38 |
+
"source": [
|
39 |
+
"from langgraph.graph import StateGraph,MessagesState, START, END\n",
|
40 |
+
"from langgraph.graph.message import add_messages\n",
|
41 |
+
"from typing import Annotated, Literal, TypedDict\n",
|
42 |
+
"from langchain_core.tools import tool\n",
|
43 |
+
"from langchain_core.messages import HumanMessage\n",
|
44 |
+
"from langgraph.checkpoint.memory import MemorySaver\n",
|
45 |
+
"from langgraph.prebuilt import ToolNode"
|
46 |
+
]
|
47 |
+
},
|
48 |
+
{
|
49 |
+
"cell_type": "code",
|
50 |
+
"execution_count": 4,
|
51 |
+
"metadata": {},
|
52 |
+
"outputs": [],
|
53 |
+
"source": [
|
54 |
+
"def call_model(state:MessagesState):\n",
|
55 |
+
" messages = state['messages']\n",
|
56 |
+
" response = llm.invoke(messages)\n",
|
57 |
+
" return {\"messages\": [response]}"
|
58 |
+
]
|
59 |
+
},
|
60 |
+
{
|
61 |
+
"cell_type": "code",
|
62 |
+
"execution_count": 5,
|
63 |
+
"metadata": {},
|
64 |
+
"outputs": [],
|
65 |
+
"source": [
|
66 |
+
"workflow=StateGraph(MessagesState)\n",
|
67 |
+
"workflow.add_node(\"chatbot\",call_model)\n",
|
68 |
+
"workflow.add_edge(START, \"chatbot\")\n",
|
69 |
+
"workflow.add_edge(\"chatbot\",END)\n",
|
70 |
+
"app=workflow.compile()"
|
71 |
+
]
|
72 |
+
},
|
73 |
+
{
|
74 |
+
"cell_type": "code",
|
75 |
+
"execution_count": 6,
|
76 |
+
"metadata": {},
|
77 |
+
"outputs": [
|
78 |
+
{
|
79 |
+
"data": {
|
80 |
+
"image/png": "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",
|
81 |
+
"text/plain": [
|
82 |
+
"<IPython.core.display.Image object>"
|
83 |
+
]
|
84 |
+
},
|
85 |
+
"metadata": {},
|
86 |
+
"output_type": "display_data"
|
87 |
+
}
|
88 |
+
],
|
89 |
+
"source": [
|
90 |
+
"from IPython.display import Image, display\n",
|
91 |
+
"display(Image(app.get_graph().draw_mermaid_png()))"
|
92 |
+
]
|
93 |
+
},
|
94 |
+
{
|
95 |
+
"cell_type": "code",
|
96 |
+
"execution_count": 7,
|
97 |
+
"metadata": {},
|
98 |
+
"outputs": [],
|
99 |
+
"source": [
|
100 |
+
"input={\"messages\":[\"hi, my name is Parthib\"]}"
|
101 |
+
]
|
102 |
+
},
|
103 |
+
{
|
104 |
+
"cell_type": "code",
|
105 |
+
"execution_count": 8,
|
106 |
+
"metadata": {},
|
107 |
+
"outputs": [
|
108 |
+
{
|
109 |
+
"data": {
|
110 |
+
"text/plain": [
|
111 |
+
"{'messages': [HumanMessage(content='hi, my name is Parthib', additional_kwargs={}, response_metadata={}, id='0362fb19-f203-4a00-87f7-4ad6162c1260'),\n",
|
112 |
+
" AIMessage(content=\"Hi Parthib! It's nice to meet you. 👋\\n\\nIs there anything I can help you with today?\\n\", additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 28, 'prompt_tokens': 17, 'total_tokens': 45, 'completion_time': 0.050909091, 'prompt_time': 0.001898827, 'queue_time': 0.232850566, 'total_time': 0.052807918}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'stop', 'logprobs': None}, id='run-752e807b-be6f-4ba5-a277-b4ed014f6300-0', usage_metadata={'input_tokens': 17, 'output_tokens': 28, 'total_tokens': 45})]}"
|
113 |
+
]
|
114 |
+
},
|
115 |
+
"execution_count": 8,
|
116 |
+
"metadata": {},
|
117 |
+
"output_type": "execute_result"
|
118 |
+
}
|
119 |
+
],
|
120 |
+
"source": [
|
121 |
+
"app.invoke(input)"
|
122 |
+
]
|
123 |
+
},
|
124 |
+
{
|
125 |
+
"cell_type": "code",
|
126 |
+
"execution_count": 9,
|
127 |
+
"metadata": {},
|
128 |
+
"outputs": [],
|
129 |
+
"source": [
|
130 |
+
"@tool\n",
|
131 |
+
"def search(query: str):\n",
|
132 |
+
" \"\"\"this is my custom tool.\"\"\"\n",
|
133 |
+
" if \"sf\" in query.lower() or \"san francisco\" in query.lower():\n",
|
134 |
+
" return \"It's 60 degrees and foggy.\"\n",
|
135 |
+
" return \"It's 90 degrees and sunny.\""
|
136 |
+
]
|
137 |
+
},
|
138 |
+
{
|
139 |
+
"cell_type": "code",
|
140 |
+
"execution_count": 10,
|
141 |
+
"metadata": {},
|
142 |
+
"outputs": [
|
143 |
+
{
|
144 |
+
"data": {
|
145 |
+
"text/plain": [
|
146 |
+
"\"It's 60 degrees and foggy.\""
|
147 |
+
]
|
148 |
+
},
|
149 |
+
"execution_count": 10,
|
150 |
+
"metadata": {},
|
151 |
+
"output_type": "execute_result"
|
152 |
+
}
|
153 |
+
],
|
154 |
+
"source": [
|
155 |
+
"search.invoke(\"what is a temprature in sf?\")"
|
156 |
+
]
|
157 |
+
},
|
158 |
+
{
|
159 |
+
"cell_type": "code",
|
160 |
+
"execution_count": 11,
|
161 |
+
"metadata": {},
|
162 |
+
"outputs": [
|
163 |
+
{
|
164 |
+
"data": {
|
165 |
+
"text/plain": [
|
166 |
+
"\"It's 90 degrees and sunny.\""
|
167 |
+
]
|
168 |
+
},
|
169 |
+
"execution_count": 11,
|
170 |
+
"metadata": {},
|
171 |
+
"output_type": "execute_result"
|
172 |
+
}
|
173 |
+
],
|
174 |
+
"source": [
|
175 |
+
"search.invoke(\"Tell me the temperature in India\")"
|
176 |
+
]
|
177 |
+
},
|
178 |
+
{
|
179 |
+
"cell_type": "code",
|
180 |
+
"execution_count": 12,
|
181 |
+
"metadata": {},
|
182 |
+
"outputs": [],
|
183 |
+
"source": [
|
184 |
+
"tools=[search]"
|
185 |
+
]
|
186 |
+
},
|
187 |
+
{
|
188 |
+
"cell_type": "code",
|
189 |
+
"execution_count": 13,
|
190 |
+
"metadata": {},
|
191 |
+
"outputs": [],
|
192 |
+
"source": [
|
193 |
+
"tool_node=ToolNode(tools)"
|
194 |
+
]
|
195 |
+
},
|
196 |
+
{
|
197 |
+
"cell_type": "code",
|
198 |
+
"execution_count": 14,
|
199 |
+
"metadata": {},
|
200 |
+
"outputs": [],
|
201 |
+
"source": [
|
202 |
+
"llm_with_tool = llm.bind_tools(tools)"
|
203 |
+
]
|
204 |
+
},
|
205 |
+
{
|
206 |
+
"cell_type": "code",
|
207 |
+
"execution_count": 15,
|
208 |
+
"metadata": {},
|
209 |
+
"outputs": [],
|
210 |
+
"source": [
|
211 |
+
"\n",
|
212 |
+
"def call_model(state: MessagesState):\n",
|
213 |
+
" messages = state['messages']\n",
|
214 |
+
" response = llm_with_tool.invoke(messages)\n",
|
215 |
+
" return {\"messages\": [response]}"
|
216 |
+
]
|
217 |
+
},
|
218 |
+
{
|
219 |
+
"cell_type": "code",
|
220 |
+
"execution_count": 16,
|
221 |
+
"metadata": {},
|
222 |
+
"outputs": [],
|
223 |
+
"source": [
|
224 |
+
"response=call_model({\"messages\": [\"hi how are you?\"]})"
|
225 |
+
]
|
226 |
+
},
|
227 |
+
{
|
228 |
+
"cell_type": "code",
|
229 |
+
"execution_count": 17,
|
230 |
+
"metadata": {},
|
231 |
+
"outputs": [
|
232 |
+
{
|
233 |
+
"data": {
|
234 |
+
"text/plain": [
|
235 |
+
"{'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_fxmj', 'function': {'arguments': '{\"query\":\"hi how are you\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 81, 'prompt_tokens': 941, 'total_tokens': 1022, 'completion_time': 0.147272727, 'prompt_time': 0.080406297, 'queue_time': 0.237967498, 'total_time': 0.227679024}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-7126749c-2fe7-466e-bb0d-459fbe3f7552-0', tool_calls=[{'name': 'search', 'args': {'query': 'hi how are you'}, 'id': 'call_fxmj', 'type': 'tool_call'}], usage_metadata={'input_tokens': 941, 'output_tokens': 81, 'total_tokens': 1022})]}"
|
236 |
+
]
|
237 |
+
},
|
238 |
+
"execution_count": 17,
|
239 |
+
"metadata": {},
|
240 |
+
"output_type": "execute_result"
|
241 |
+
}
|
242 |
+
],
|
243 |
+
"source": [
|
244 |
+
"response"
|
245 |
+
]
|
246 |
+
},
|
247 |
+
{
|
248 |
+
"cell_type": "code",
|
249 |
+
"execution_count": 18,
|
250 |
+
"metadata": {},
|
251 |
+
"outputs": [],
|
252 |
+
"source": [
|
253 |
+
"def router_function(state: MessagesState) -> Literal[\"tools\", END]:\n",
|
254 |
+
" #print(f\"here is a state from should continue {state}\")\n",
|
255 |
+
" messages = state['messages']\n",
|
256 |
+
" last_message = messages[-1]\n",
|
257 |
+
" #print(f\"here is a last message from should continue {last_message}\")\n",
|
258 |
+
" if last_message.tool_calls:\n",
|
259 |
+
" return \"tools\"\n",
|
260 |
+
" return END"
|
261 |
+
]
|
262 |
+
},
|
263 |
+
{
|
264 |
+
"cell_type": "code",
|
265 |
+
"execution_count": 19,
|
266 |
+
"metadata": {},
|
267 |
+
"outputs": [],
|
268 |
+
"source": [
|
269 |
+
"# Define a new graph\n",
|
270 |
+
"workflow = StateGraph(MessagesState)\n",
|
271 |
+
"\n",
|
272 |
+
"workflow.add_node(\"agent\", call_model)\n",
|
273 |
+
"workflow.add_node(\"tools\", tool_node)\n",
|
274 |
+
"\n",
|
275 |
+
"workflow.add_edge(START, \"agent\")\n",
|
276 |
+
"\n",
|
277 |
+
"workflow.add_conditional_edges(\"agent\",router_function,{\"tools\": \"tools\", END: END})\n",
|
278 |
+
"\n",
|
279 |
+
"app = workflow.compile()"
|
280 |
+
]
|
281 |
+
},
|
282 |
+
{
|
283 |
+
"cell_type": "code",
|
284 |
+
"execution_count": 20,
|
285 |
+
"metadata": {},
|
286 |
+
"outputs": [
|
287 |
+
{
|
288 |
+
"data": {
|
289 |
+
"image/png": "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",
|
290 |
+
"text/plain": [
|
291 |
+
"<IPython.core.display.Image object>"
|
292 |
+
]
|
293 |
+
},
|
294 |
+
"metadata": {},
|
295 |
+
"output_type": "display_data"
|
296 |
+
}
|
297 |
+
],
|
298 |
+
"source": [
|
299 |
+
"from IPython.display import Image, display\n",
|
300 |
+
"display(Image(app.get_graph().draw_mermaid_png()))"
|
301 |
+
]
|
302 |
+
},
|
303 |
+
{
|
304 |
+
"cell_type": "code",
|
305 |
+
"execution_count": 21,
|
306 |
+
"metadata": {},
|
307 |
+
"outputs": [
|
308 |
+
{
|
309 |
+
"data": {
|
310 |
+
"text/plain": [
|
311 |
+
"{'messages': [HumanMessage(content='hi how are you?', additional_kwargs={}, response_metadata={}, id='ee908a18-fbee-4182-8478-0def6aae244c'),\n",
|
312 |
+
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2mrs', 'function': {'arguments': '{\"query\":\"how are you\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 941, 'total_tokens': 1023, 'completion_time': 0.149090909, 'prompt_time': 0.054217907, 'queue_time': 0.232085166, 'total_time': 0.203308816}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-946408e0-d62c-4539-bafc-fdd22a1a9820-0', tool_calls=[{'name': 'search', 'args': {'query': 'how are you'}, 'id': 'call_2mrs', 'type': 'tool_call'}], usage_metadata={'input_tokens': 941, 'output_tokens': 82, 'total_tokens': 1023}),\n",
|
313 |
+
" ToolMessage(content=\"It's 90 degrees and sunny.\", name='search', id='dafff150-754c-420a-b0cd-7d8f4dc54a65', tool_call_id='call_2mrs')]}"
|
314 |
+
]
|
315 |
+
},
|
316 |
+
"execution_count": 21,
|
317 |
+
"metadata": {},
|
318 |
+
"output_type": "execute_result"
|
319 |
+
}
|
320 |
+
],
|
321 |
+
"source": [
|
322 |
+
"app.invoke({\"messages\": [\"hi how are you?\"]})"
|
323 |
+
]
|
324 |
+
},
|
325 |
+
{
|
326 |
+
"cell_type": "code",
|
327 |
+
"execution_count": 22,
|
328 |
+
"metadata": {},
|
329 |
+
"outputs": [
|
330 |
+
{
|
331 |
+
"data": {
|
332 |
+
"text/plain": [
|
333 |
+
"{'messages': [HumanMessage(content='tell me the temperature in sf??', additional_kwargs={}, response_metadata={}, id='b29b6cb9-fb9f-45c9-bbcf-f4e6f57a9648'),\n",
|
334 |
+
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_tkv9', 'function': {'arguments': '{\"query\":\"temperature in san francisco\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 943, 'total_tokens': 1025, 'completion_time': 0.149090909, 'prompt_time': 0.041112254, 'queue_time': 0.232393693, 'total_time': 0.190203163}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-3dd52d5e-dcd5-4c30-bc81-4f741419a2a8-0', tool_calls=[{'name': 'search', 'args': {'query': 'temperature in san francisco'}, 'id': 'call_tkv9', 'type': 'tool_call'}], usage_metadata={'input_tokens': 943, 'output_tokens': 82, 'total_tokens': 1025}),\n",
|
335 |
+
" ToolMessage(content=\"It's 60 degrees and foggy.\", name='search', id='43c2a5a4-6d92-4561-a602-5663782cfb68', tool_call_id='call_tkv9')]}"
|
336 |
+
]
|
337 |
+
},
|
338 |
+
"execution_count": 22,
|
339 |
+
"metadata": {},
|
340 |
+
"output_type": "execute_result"
|
341 |
+
}
|
342 |
+
],
|
343 |
+
"source": [
|
344 |
+
"app.invoke({\"messages\": [\"tell me the temperature in sf??\"]})"
|
345 |
+
]
|
346 |
+
},
|
347 |
+
{
|
348 |
+
"cell_type": "code",
|
349 |
+
"execution_count": 24,
|
350 |
+
"metadata": {},
|
351 |
+
"outputs": [
|
352 |
+
{
|
353 |
+
"name": "stderr",
|
354 |
+
"output_type": "stream",
|
355 |
+
"text": [
|
356 |
+
"Adding an edge to a graph that has already been compiled. This will not be reflected in the compiled graph.\n"
|
357 |
+
]
|
358 |
+
},
|
359 |
+
{
|
360 |
+
"data": {
|
361 |
+
"text/plain": [
|
362 |
+
"<langgraph.graph.state.StateGraph at 0x1873e0e8910>"
|
363 |
+
]
|
364 |
+
},
|
365 |
+
"execution_count": 24,
|
366 |
+
"metadata": {},
|
367 |
+
"output_type": "execute_result"
|
368 |
+
}
|
369 |
+
],
|
370 |
+
"source": [
|
371 |
+
"workflow.add_edge(\"tools\", 'agent')"
|
372 |
+
]
|
373 |
+
},
|
374 |
+
{
|
375 |
+
"cell_type": "code",
|
376 |
+
"execution_count": 26,
|
377 |
+
"metadata": {},
|
378 |
+
"outputs": [],
|
379 |
+
"source": [
|
380 |
+
"\n",
|
381 |
+
"app = workflow.compile()"
|
382 |
+
]
|
383 |
+
},
|
384 |
+
{
|
385 |
+
"cell_type": "code",
|
386 |
+
"execution_count": 28,
|
387 |
+
"metadata": {},
|
388 |
+
"outputs": [
|
389 |
+
{
|
390 |
+
"data": {
|
391 |
+
"image/png": "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",
|
392 |
+
"text/plain": [
|
393 |
+
"<IPython.core.display.Image object>"
|
394 |
+
]
|
395 |
+
},
|
396 |
+
"metadata": {},
|
397 |
+
"output_type": "display_data"
|
398 |
+
}
|
399 |
+
],
|
400 |
+
"source": [
|
401 |
+
"from IPython.display import Image, display\n",
|
402 |
+
"display(Image(app.get_graph().draw_mermaid_png()))"
|
403 |
+
]
|
404 |
+
},
|
405 |
+
{
|
406 |
+
"cell_type": "code",
|
407 |
+
"execution_count": 27,
|
408 |
+
"metadata": {},
|
409 |
+
"outputs": [
|
410 |
+
{
|
411 |
+
"name": "stdout",
|
412 |
+
"output_type": "stream",
|
413 |
+
"text": [
|
414 |
+
"here is output from agent\n",
|
415 |
+
"_______\n",
|
416 |
+
"{'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_bad9', 'function': {'arguments': '{\"query\":\"weather in sf\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 942, 'total_tokens': 1024, 'completion_time': 0.149090909, 'prompt_time': 0.032922777, 'queue_time': 0.23775662999999997, 'total_time': 0.182013686}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-6cb3a8df-3aae-4efe-b0eb-f4a50feeba09-0', tool_calls=[{'name': 'search', 'args': {'query': 'weather in sf'}, 'id': 'call_bad9', 'type': 'tool_call'}], usage_metadata={'input_tokens': 942, 'output_tokens': 82, 'total_tokens': 1024})]}\n",
|
417 |
+
"\n",
|
418 |
+
"\n",
|
419 |
+
"here is output from tools\n",
|
420 |
+
"_______\n",
|
421 |
+
"{'messages': [ToolMessage(content=\"It's 60 degrees and foggy.\", name='search', id='024d6352-1baf-47d2-992f-af1380ecf3a5', tool_call_id='call_bad9')]}\n",
|
422 |
+
"\n",
|
423 |
+
"\n",
|
424 |
+
"here is output from agent\n",
|
425 |
+
"_______\n",
|
426 |
+
"{'messages': [AIMessage(content=\"It's 60 degrees and foggy. \\n\", additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 1020, 'total_tokens': 1034, 'completion_time': 0.025454545, 'prompt_time': 0.035590263, 'queue_time': 0.237606781, 'total_time': 0.061044808}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'stop', 'logprobs': None}, id='run-b569af82-55e4-46ae-8d6e-7d2088a2bdfb-0', usage_metadata={'input_tokens': 1020, 'output_tokens': 14, 'total_tokens': 1034})]}\n",
|
427 |
+
"\n",
|
428 |
+
"\n"
|
429 |
+
]
|
430 |
+
}
|
431 |
+
],
|
432 |
+
"source": [
|
433 |
+
"for output in app.stream({\"messages\": [\"what is the weather in sf\"]}):\n",
|
434 |
+
" for key,value in output.items():\n",
|
435 |
+
" print(f\"here is output from {key}\")\n",
|
436 |
+
" print(\"_______\")\n",
|
437 |
+
" print(value)\n",
|
438 |
+
" print(\"\\n\")"
|
439 |
+
]
|
440 |
+
},
|
441 |
+
{
|
442 |
+
"cell_type": "code",
|
443 |
+
"execution_count": 29,
|
444 |
+
"metadata": {},
|
445 |
+
"outputs": [],
|
446 |
+
"source": [
|
447 |
+
"from langgraph.checkpoint.memory import MemorySaver\n",
|
448 |
+
"\n",
|
449 |
+
"memory = MemorySaver()"
|
450 |
+
]
|
451 |
+
},
|
452 |
+
{
|
453 |
+
"cell_type": "code",
|
454 |
+
"execution_count": 30,
|
455 |
+
"metadata": {},
|
456 |
+
"outputs": [
|
457 |
+
{
|
458 |
+
"data": {
|
459 |
+
"text/plain": [
|
460 |
+
"<langgraph.graph.state.StateGraph at 0x1873e10f4c0>"
|
461 |
+
]
|
462 |
+
},
|
463 |
+
"execution_count": 30,
|
464 |
+
"metadata": {},
|
465 |
+
"output_type": "execute_result"
|
466 |
+
}
|
467 |
+
],
|
468 |
+
"source": [
|
469 |
+
"workflow3 = StateGraph(MessagesState)\n",
|
470 |
+
"\n",
|
471 |
+
"workflow3.add_node(\"agent\", call_model)\n",
|
472 |
+
"workflow3.add_node(\"tools\", tool_node)\n",
|
473 |
+
"\n",
|
474 |
+
"workflow3.add_edge(START, \"agent\")\n",
|
475 |
+
"\n",
|
476 |
+
"workflow3.add_conditional_edges(\"agent\",router_function,{\"tools\": \"tools\", END: END})\n",
|
477 |
+
"\n",
|
478 |
+
"workflow3.add_edge(\"tools\", 'agent')"
|
479 |
+
]
|
480 |
+
},
|
481 |
+
{
|
482 |
+
"cell_type": "code",
|
483 |
+
"execution_count": 31,
|
484 |
+
"metadata": {},
|
485 |
+
"outputs": [],
|
486 |
+
"source": [
|
487 |
+
"app3 = workflow3.compile(checkpointer = memory)"
|
488 |
+
]
|
489 |
+
},
|
490 |
+
{
|
491 |
+
"cell_type": "code",
|
492 |
+
"execution_count": 32,
|
493 |
+
"metadata": {},
|
494 |
+
"outputs": [],
|
495 |
+
"source": [
|
496 |
+
"config = {\"configurable\": {\"thread_id\": \"1\"}}"
|
497 |
+
]
|
498 |
+
},
|
499 |
+
{
|
500 |
+
"cell_type": "code",
|
501 |
+
"execution_count": 33,
|
502 |
+
"metadata": {},
|
503 |
+
"outputs": [],
|
504 |
+
"source": [
|
505 |
+
"events = app3.stream(\n",
|
506 |
+
" {\"messages\": [\"Hi there! My name is parthib.\"]}, config, stream_mode=\"values\"\n",
|
507 |
+
")"
|
508 |
+
]
|
509 |
+
},
|
510 |
+
{
|
511 |
+
"cell_type": "code",
|
512 |
+
"execution_count": 34,
|
513 |
+
"metadata": {},
|
514 |
+
"outputs": [
|
515 |
+
{
|
516 |
+
"name": "stdout",
|
517 |
+
"output_type": "stream",
|
518 |
+
"text": [
|
519 |
+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
520 |
+
"\n",
|
521 |
+
"Hi there! My name is parthib.\n",
|
522 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
523 |
+
"Tool Calls:\n",
|
524 |
+
" search (call_kfx7)\n",
|
525 |
+
" Call ID: call_kfx7\n",
|
526 |
+
" Args:\n",
|
527 |
+
" query: parthib\n",
|
528 |
+
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
529 |
+
"Name: search\n",
|
530 |
+
"\n",
|
531 |
+
"It's 90 degrees and sunny.\n",
|
532 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
533 |
+
"Tool Calls:\n",
|
534 |
+
" search (call_8qkb)\n",
|
535 |
+
" Call ID: call_8qkb\n",
|
536 |
+
" Args:\n",
|
537 |
+
" query: parthib weather\n",
|
538 |
+
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
539 |
+
"Name: search\n",
|
540 |
+
"\n",
|
541 |
+
"It's 90 degrees and sunny.\n",
|
542 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
543 |
+
"\n",
|
544 |
+
"That's good to know!\n"
|
545 |
+
]
|
546 |
+
}
|
547 |
+
],
|
548 |
+
"source": [
|
549 |
+
"for event in events:\n",
|
550 |
+
" event[\"messages\"][-1].pretty_print()"
|
551 |
+
]
|
552 |
+
},
|
553 |
+
{
|
554 |
+
"cell_type": "code",
|
555 |
+
"execution_count": 35,
|
556 |
+
"metadata": {},
|
557 |
+
"outputs": [],
|
558 |
+
"source": [
|
559 |
+
"events = app3.stream(\n",
|
560 |
+
" {\"messages\": [\"Can you please tell me My name?\"]}, config, stream_mode=\"values\"\n",
|
561 |
+
")"
|
562 |
+
]
|
563 |
+
},
|
564 |
+
{
|
565 |
+
"cell_type": "code",
|
566 |
+
"execution_count": 37,
|
567 |
+
"metadata": {},
|
568 |
+
"outputs": [
|
569 |
+
{
|
570 |
+
"name": "stdout",
|
571 |
+
"output_type": "stream",
|
572 |
+
"text": [
|
573 |
+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
574 |
+
"\n",
|
575 |
+
"Can you please tell me My name?\n",
|
576 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
577 |
+
"\n",
|
578 |
+
"parthib\n"
|
579 |
+
]
|
580 |
+
}
|
581 |
+
],
|
582 |
+
"source": [
|
583 |
+
"for event in events:\n",
|
584 |
+
" event[\"messages\"][-1].pretty_print()"
|
585 |
+
]
|
586 |
+
},
|
587 |
+
{
|
588 |
+
"cell_type": "code",
|
589 |
+
"execution_count": 38,
|
590 |
+
"metadata": {},
|
591 |
+
"outputs": [
|
592 |
+
{
|
593 |
+
"data": {
|
594 |
+
"text/plain": [
|
595 |
+
"{'v': 1,\n",
|
596 |
+
" 'ts': '2025-03-13T07:17:52.345242+00:00',\n",
|
597 |
+
" 'id': '1efffdb4-6db2-6579-8008-004795bdac47',\n",
|
598 |
+
" 'channel_values': {'messages': [HumanMessage(content='Hi there! My name is parthib.', additional_kwargs={}, response_metadata={}, id='f1bbde4c-4a84-499e-8983-a97067581103'),\n",
|
599 |
+
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_kfx7', 'function': {'arguments': '{\"query\":\"parthib\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 946, 'total_tokens': 1028, 'completion_time': 0.149090909, 'prompt_time': 0.080832156, 'queue_time': 0.23635677900000002, 'total_time': 0.229923065}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-7dd24c1d-ab2d-4446-b0b3-77c514cb70f9-0', tool_calls=[{'name': 'search', 'args': {'query': 'parthib'}, 'id': 'call_kfx7', 'type': 'tool_call'}], usage_metadata={'input_tokens': 946, 'output_tokens': 82, 'total_tokens': 1028}),\n",
|
600 |
+
" ToolMessage(content=\"It's 90 degrees and sunny.\", name='search', id='30233758-43ce-4a8d-884a-5a0ce92a2964', tool_call_id='call_kfx7'),\n",
|
601 |
+
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_8qkb', 'function': {'arguments': '{\"query\":\"parthib weather\"}', 'name': 'search'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 42, 'prompt_tokens': 1026, 'total_tokens': 1068, 'completion_time': 0.076363636, 'prompt_time': 0.086929684, 'queue_time': 0.23346191, 'total_time': 0.16329332}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-077a29d8-067f-479e-9030-fa2da4bd90ef-0', tool_calls=[{'name': 'search', 'args': {'query': 'parthib weather'}, 'id': 'call_8qkb', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1026, 'output_tokens': 42, 'total_tokens': 1068}),\n",
|
602 |
+
" ToolMessage(content=\"It's 90 degrees and sunny.\", name='search', id='52fcefdd-a21e-40ff-a04a-9f07e0ad487d', tool_call_id='call_8qkb'),\n",
|
603 |
+
" AIMessage(content=\"That's good to know!\", additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 1107, 'total_tokens': 1116, 'completion_time': 0.016363636, 'prompt_time': 0.187245132, 'queue_time': 0.23505791699999998, 'total_time': 0.203608768}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'stop', 'logprobs': None}, id='run-414769b9-fdde-4ecd-adb4-2d76016b0952-0', usage_metadata={'input_tokens': 1107, 'output_tokens': 9, 'total_tokens': 1116}),\n",
|
604 |
+
" HumanMessage(content='Can you please tell me My name?', additional_kwargs={}, response_metadata={}, id='73092115-910c-4cc9-8694-56996976bc74'),\n",
|
605 |
+
" AIMessage(content='parthib', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 1132, 'total_tokens': 1137, 'completion_time': 0.009090909, 'prompt_time': 0.039626394, 'queue_time': 0.237121242, 'total_time': 0.048717303}, 'model_name': 'Gemma2-9b-It', 'system_fingerprint': 'fp_10c08bf97d', 'finish_reason': 'stop', 'logprobs': None}, id='run-2889bd69-a5a6-44f8-bd14-c2b5d1bc6c08-0', usage_metadata={'input_tokens': 1132, 'output_tokens': 5, 'total_tokens': 1137})],\n",
|
606 |
+
" 'agent': 'agent'},\n",
|
607 |
+
" 'channel_versions': {'__start__': '00000000000000000000000000000009.0.3851235431701766',\n",
|
608 |
+
" 'messages': '00000000000000000000000000000010.0.36891079962134077',\n",
|
609 |
+
" 'start:agent': '00000000000000000000000000000010.0.7582001227958053',\n",
|
610 |
+
" 'agent': '00000000000000000000000000000010.0.79576488464161',\n",
|
611 |
+
" 'branch:agent:router_function:tools': '00000000000000000000000000000006.0.5699474757089383',\n",
|
612 |
+
" 'tools': '00000000000000000000000000000007.0.4048586181949164'},\n",
|
613 |
+
" 'versions_seen': {'__input__': {},\n",
|
614 |
+
" '__start__': {'__start__': '00000000000000000000000000000008.0.771603223183003'},\n",
|
615 |
+
" 'agent': {'start:agent': '00000000000000000000000000000009.0.3471992909319417',\n",
|
616 |
+
" 'tools': '00000000000000000000000000000006.0.7804858660862368'},\n",
|
617 |
+
" 'tools': {'branch:agent:router_function:tools': '00000000000000000000000000000005.0.6366621873155655'}},\n",
|
618 |
+
" 'pending_sends': []}"
|
619 |
+
]
|
620 |
+
},
|
621 |
+
"execution_count": 38,
|
622 |
+
"metadata": {},
|
623 |
+
"output_type": "execute_result"
|
624 |
+
}
|
625 |
+
],
|
626 |
+
"source": [
|
627 |
+
"memory.get(config)"
|
628 |
+
]
|
629 |
+
},
|
630 |
+
{
|
631 |
+
"cell_type": "code",
|
632 |
+
"execution_count": null,
|
633 |
+
"metadata": {},
|
634 |
+
"outputs": [],
|
635 |
+
"source": []
|
636 |
+
}
|
637 |
+
],
|
638 |
+
"metadata": {
|
639 |
+
"kernelspec": {
|
640 |
+
"display_name": "Python 3",
|
641 |
+
"language": "python",
|
642 |
+
"name": "python3"
|
643 |
+
},
|
644 |
+
"language_info": {
|
645 |
+
"codemirror_mode": {
|
646 |
+
"name": "ipython",
|
647 |
+
"version": 3
|
648 |
+
},
|
649 |
+
"file_extension": ".py",
|
650 |
+
"mimetype": "text/x-python",
|
651 |
+
"name": "python",
|
652 |
+
"nbconvert_exporter": "python",
|
653 |
+
"pygments_lexer": "ipython3",
|
654 |
+
"version": "3.10.0"
|
655 |
+
}
|
656 |
+
},
|
657 |
+
"nbformat": 4,
|
658 |
+
"nbformat_minor": 2
|
659 |
+
}
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
langgraph
|
3 |
+
langchain_core
|
4 |
+
langchain_community
|
5 |
+
langchain
|
6 |
+
langchain_groq
|
7 |
+
python-dotenv
|