Upload agent.ipynb
Browse files- unit2/langgraph/agent.ipynb +560 -0
unit2/langgraph/agent.ipynb
ADDED
@@ -0,0 +1,560 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"id": "98f5e36a-da49-4ae2-8c74-b910a2f992fc",
|
6 |
+
"metadata": {},
|
7 |
+
"source": [
|
8 |
+
"# Agent\n",
|
9 |
+
"\n",
|
10 |
+
"In this notebook, **we're going to build a simple agent using using LangGraph**.\n",
|
11 |
+
"\n",
|
12 |
+
"This notebook is part of the <a href=\"https://www.hf.co/learn/agents-course\">Hugging Face Agents Course</a>, a free course from beginner to expert, where you learn to build Agents.\n",
|
13 |
+
"\n",
|
14 |
+
"\n",
|
15 |
+
"\n",
|
16 |
+
"As seen in the Unit 1, an agent needs 3 steps as introduced in the ReAct architecture :\n",
|
17 |
+
"[ReAct](https://react-lm.github.io/), a general agent architecture.\n",
|
18 |
+
" \n",
|
19 |
+
"* `act` - let the model call specific tools \n",
|
20 |
+
"* `observe` - pass the tool output back to the model \n",
|
21 |
+
"* `reason` - let the model reason about the tool output to decide what to do next (e.g., call another tool or just respond directly)\n",
|
22 |
+
"\n",
|
23 |
+
"\n",
|
24 |
+
""
|
25 |
+
]
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"cell_type": "code",
|
29 |
+
"execution_count": 1,
|
30 |
+
"id": "63edff5a-724b-474d-9db8-37f0ae936c76",
|
31 |
+
"metadata": {
|
32 |
+
"tags": []
|
33 |
+
},
|
34 |
+
"outputs": [
|
35 |
+
{
|
36 |
+
"name": "stdout",
|
37 |
+
"output_type": "stream",
|
38 |
+
"text": [
|
39 |
+
"Note: you may need to restart the kernel to use updated packages.\n"
|
40 |
+
]
|
41 |
+
}
|
42 |
+
],
|
43 |
+
"source": [
|
44 |
+
"%pip install -q -U langchain_openai langchain_core langgraph"
|
45 |
+
]
|
46 |
+
},
|
47 |
+
{
|
48 |
+
"cell_type": "code",
|
49 |
+
"execution_count": 2,
|
50 |
+
"id": "356a6482",
|
51 |
+
"metadata": {
|
52 |
+
"tags": []
|
53 |
+
},
|
54 |
+
"outputs": [],
|
55 |
+
"source": [
|
56 |
+
"import os\n",
|
57 |
+
"\n",
|
58 |
+
"# Please setp your own key.\n",
|
59 |
+
"os.environ[\"OPENAI_API_KEY\"]=\"sk-xxxxxx\""
|
60 |
+
]
|
61 |
+
},
|
62 |
+
{
|
63 |
+
"cell_type": "code",
|
64 |
+
"execution_count": 65,
|
65 |
+
"id": "71795ff1-d6a7-448d-8b55-88bbd1ed3dbe",
|
66 |
+
"metadata": {
|
67 |
+
"tags": []
|
68 |
+
},
|
69 |
+
"outputs": [],
|
70 |
+
"source": [
|
71 |
+
"import base64\n",
|
72 |
+
"from typing import List\n",
|
73 |
+
"from langchain.schema import HumanMessage\n",
|
74 |
+
"from langchain_openai import ChatOpenAI\n",
|
75 |
+
"\n",
|
76 |
+
"\n",
|
77 |
+
"vision_llm = ChatOpenAI(model=\"gpt-4o\")\n",
|
78 |
+
"\n",
|
79 |
+
"def extract_text(img_path: str) -> str:\n",
|
80 |
+
" \"\"\"\n",
|
81 |
+
" Extract text from an image file using a multimodal model.\n",
|
82 |
+
"\n",
|
83 |
+
" Args:\n",
|
84 |
+
" img_path: A local image file path (strings).\n",
|
85 |
+
"\n",
|
86 |
+
" Returns:\n",
|
87 |
+
" A single string containing the concatenated text extracted from each image.\n",
|
88 |
+
" \"\"\"\n",
|
89 |
+
" all_text = \"\"\n",
|
90 |
+
" try:\n",
|
91 |
+
" \n",
|
92 |
+
" # Read image and encode as base64\n",
|
93 |
+
" with open(img_path, \"rb\") as image_file:\n",
|
94 |
+
" image_bytes = image_file.read()\n",
|
95 |
+
"\n",
|
96 |
+
" image_base64 = base64.b64encode(image_bytes).decode(\"utf-8\")\n",
|
97 |
+
"\n",
|
98 |
+
" # Prepare the prompt including the base64 image data\n",
|
99 |
+
" message = [\n",
|
100 |
+
" HumanMessage(\n",
|
101 |
+
" content=[\n",
|
102 |
+
" {\n",
|
103 |
+
" \"type\": \"text\",\n",
|
104 |
+
" \"text\": (\n",
|
105 |
+
" \"Extract all the text from this image. \"\n",
|
106 |
+
" \"Return only the extracted text, no explanations.\"\n",
|
107 |
+
" ),\n",
|
108 |
+
" },\n",
|
109 |
+
" {\n",
|
110 |
+
" \"type\": \"image_url\",\n",
|
111 |
+
" \"image_url\": {\n",
|
112 |
+
" \"url\": f\"data:image/png;base64,{image_base64}\"\n",
|
113 |
+
" },\n",
|
114 |
+
" },\n",
|
115 |
+
" ]\n",
|
116 |
+
" )\n",
|
117 |
+
" ]\n",
|
118 |
+
"\n",
|
119 |
+
" # Call the vision-capable model\n",
|
120 |
+
" response = vision_llm.invoke(message)\n",
|
121 |
+
"\n",
|
122 |
+
" # Append extracted text\n",
|
123 |
+
" all_text += response.content + \"\\n\\n\"\n",
|
124 |
+
"\n",
|
125 |
+
" return all_text.strip()\n",
|
126 |
+
" except Exception as e:\n",
|
127 |
+
" # You can choose whether to raise or just return an empty string / error message\n",
|
128 |
+
" error_msg = f\"Error extracting text: {str(e)}\"\n",
|
129 |
+
" print(error_msg)\n",
|
130 |
+
" return \"\"\n",
|
131 |
+
"\n",
|
132 |
+
"llm = ChatOpenAI(model=\"gpt-4o\")\n",
|
133 |
+
"\n",
|
134 |
+
"def divide(a: int, b: int) -> float:\n",
|
135 |
+
" \"\"\"Divide a and b.\"\"\"\n",
|
136 |
+
" return a / b\n",
|
137 |
+
"\n",
|
138 |
+
"tools = [\n",
|
139 |
+
" divide,\n",
|
140 |
+
" extract_text\n",
|
141 |
+
"]\n",
|
142 |
+
"llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False)"
|
143 |
+
]
|
144 |
+
},
|
145 |
+
{
|
146 |
+
"cell_type": "markdown",
|
147 |
+
"id": "a2cec014-3023-405c-be79-de8fc7adb346",
|
148 |
+
"metadata": {},
|
149 |
+
"source": [
|
150 |
+
"Let's create our LLM and prompt it with the overall desired agent behavior."
|
151 |
+
]
|
152 |
+
},
|
153 |
+
{
|
154 |
+
"cell_type": "code",
|
155 |
+
"execution_count": 66,
|
156 |
+
"id": "deb674bc-49b2-485a-b0c3-4d7b05a0bfac",
|
157 |
+
"metadata": {
|
158 |
+
"tags": []
|
159 |
+
},
|
160 |
+
"outputs": [],
|
161 |
+
"source": [
|
162 |
+
"from typing import TypedDict, Annotated, List, Any, Optional\n",
|
163 |
+
"from langchain_core.messages import AnyMessage\n",
|
164 |
+
"from langgraph.graph.message import add_messages\n",
|
165 |
+
"class AgentState(TypedDict):\n",
|
166 |
+
" # The input document\n",
|
167 |
+
" input_file: Optional[str] # Contains file path, type (PNG)\n",
|
168 |
+
" messages: Annotated[list[AnyMessage], add_messages]"
|
169 |
+
]
|
170 |
+
},
|
171 |
+
{
|
172 |
+
"cell_type": "code",
|
173 |
+
"execution_count": 76,
|
174 |
+
"id": "d061813f-ebc0-432c-91ec-3b42b15c30b6",
|
175 |
+
"metadata": {
|
176 |
+
"tags": []
|
177 |
+
},
|
178 |
+
"outputs": [],
|
179 |
+
"source": [
|
180 |
+
"from langchain_core.messages import HumanMessage, SystemMessage\n",
|
181 |
+
"from langchain_core.utils.function_calling import convert_to_openai_tool\n",
|
182 |
+
"\n",
|
183 |
+
"\n",
|
184 |
+
"# AgentState\n",
|
185 |
+
"def assistant(state: AgentState):\n",
|
186 |
+
" # System message\n",
|
187 |
+
" textual_description_of_tool=\"\"\"\n",
|
188 |
+
"extract_text(img_path: str) -> str:\n",
|
189 |
+
" Extract text from an image file using a multimodal model.\n",
|
190 |
+
"\n",
|
191 |
+
" Args:\n",
|
192 |
+
" img_path: A local image file path (strings).\n",
|
193 |
+
"\n",
|
194 |
+
" Returns:\n",
|
195 |
+
" A single string containing the concatenated text extracted from each image.\n",
|
196 |
+
"divide(a: int, b: int) -> float:\n",
|
197 |
+
" Divide a and b\n",
|
198 |
+
"\"\"\"\n",
|
199 |
+
" image=state[\"input_file\"]\n",
|
200 |
+
" sys_msg = SystemMessage(content=f\"You are an helpful agent that can analyse some images and run some computatio without provided tools :\\n{textual_description_of_tool} \\n You have access to some otpional images. Currently the loaded images is : {image}\")\n",
|
201 |
+
"\n",
|
202 |
+
"\n",
|
203 |
+
" return {\"messages\": [llm_with_tools.invoke([sys_msg] + state[\"messages\"])],\"input_file\":state[\"input_file\"]}"
|
204 |
+
]
|
205 |
+
},
|
206 |
+
{
|
207 |
+
"cell_type": "markdown",
|
208 |
+
"id": "4eb43343-9a6f-42cb-86e6-4380f928633c",
|
209 |
+
"metadata": {},
|
210 |
+
"source": [
|
211 |
+
"We define a `Tools` node with our list of tools.\n",
|
212 |
+
"\n",
|
213 |
+
"The `Assistant` node is just our model with bound tools.\n",
|
214 |
+
"\n",
|
215 |
+
"We create a graph with `Assistant` and `Tools` nodes.\n",
|
216 |
+
"\n",
|
217 |
+
"We add `tools_condition` edge, which routes to `End` or to `Tools` based on whether the `Assistant` calls a tool.\n",
|
218 |
+
"\n",
|
219 |
+
"Now, we add one new step:\n",
|
220 |
+
"\n",
|
221 |
+
"We connect the `Tools` node *back* to the `Assistant`, forming a loop.\n",
|
222 |
+
"\n",
|
223 |
+
"* After the `assistant` node executes, `tools_condition` checks if the model's output is a tool call.\n",
|
224 |
+
"* If it is a tool call, the flow is directed to the `tools` node.\n",
|
225 |
+
"* The `tools` node connects back to `assistant`.\n",
|
226 |
+
"* This loop continues as long as the model decides to call tools.\n",
|
227 |
+
"* If the model response is not a tool call, the flow is directed to END, terminating the process."
|
228 |
+
]
|
229 |
+
},
|
230 |
+
{
|
231 |
+
"cell_type": "code",
|
232 |
+
"execution_count": 77,
|
233 |
+
"id": "aef13cd4-05a6-4084-a620-2e7b91d9a72f",
|
234 |
+
"metadata": {
|
235 |
+
"tags": []
|
236 |
+
},
|
237 |
+
"outputs": [
|
238 |
+
{
|
239 |
+
"data": {
|
240 |
+
"image/png": "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",
|
241 |
+
"text/plain": [
|
242 |
+
"<IPython.core.display.Image object>"
|
243 |
+
]
|
244 |
+
},
|
245 |
+
"metadata": {},
|
246 |
+
"output_type": "display_data"
|
247 |
+
}
|
248 |
+
],
|
249 |
+
"source": [
|
250 |
+
"from langgraph.graph import START, StateGraph\n",
|
251 |
+
"from langgraph.prebuilt import tools_condition\n",
|
252 |
+
"from langgraph.prebuilt import ToolNode\n",
|
253 |
+
"from IPython.display import Image, display\n",
|
254 |
+
"\n",
|
255 |
+
"# Graph\n",
|
256 |
+
"builder = StateGraph(AgentState)\n",
|
257 |
+
"\n",
|
258 |
+
"# Define nodes: these do the work\n",
|
259 |
+
"builder.add_node(\"assistant\", assistant)\n",
|
260 |
+
"builder.add_node(\"tools\", ToolNode(tools))\n",
|
261 |
+
"\n",
|
262 |
+
"# Define edges: these determine how the control flow moves\n",
|
263 |
+
"builder.add_edge(START, \"assistant\")\n",
|
264 |
+
"builder.add_conditional_edges(\n",
|
265 |
+
" \"assistant\",\n",
|
266 |
+
" # If the latest message (result) from assistant is a tool call -> tools_condition routes to tools\n",
|
267 |
+
" # If the latest message (result) from assistant is a not a tool call -> tools_condition routes to END\n",
|
268 |
+
" tools_condition,\n",
|
269 |
+
")\n",
|
270 |
+
"builder.add_edge(\"tools\", \"assistant\")\n",
|
271 |
+
"react_graph = builder.compile()\n",
|
272 |
+
"\n",
|
273 |
+
"# Show\n",
|
274 |
+
"display(Image(react_graph.get_graph(xray=True).draw_mermaid_png()))"
|
275 |
+
]
|
276 |
+
},
|
277 |
+
{
|
278 |
+
"cell_type": "code",
|
279 |
+
"execution_count": 78,
|
280 |
+
"id": "75602459-d8ca-47b4-9518-3f38343ebfe4",
|
281 |
+
"metadata": {
|
282 |
+
"tags": []
|
283 |
+
},
|
284 |
+
"outputs": [],
|
285 |
+
"source": [
|
286 |
+
"messages = [HumanMessage(content=\"Divide 6790 by 5\")]\n",
|
287 |
+
"\n",
|
288 |
+
"messages = react_graph.invoke({\"messages\": messages,\"input_file\":None})"
|
289 |
+
]
|
290 |
+
},
|
291 |
+
{
|
292 |
+
"cell_type": "code",
|
293 |
+
"execution_count": 79,
|
294 |
+
"id": "b517142d-c40c-48bf-a5b8-c8409427aa79",
|
295 |
+
"metadata": {
|
296 |
+
"tags": []
|
297 |
+
},
|
298 |
+
"outputs": [
|
299 |
+
{
|
300 |
+
"name": "stdout",
|
301 |
+
"output_type": "stream",
|
302 |
+
"text": [
|
303 |
+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
304 |
+
"\n",
|
305 |
+
"Divide 6790 by 5\n",
|
306 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
307 |
+
"Tool Calls:\n",
|
308 |
+
" divide (call_s0G5ewtIQyHUCOv0fClsCpgh)\n",
|
309 |
+
" Call ID: call_s0G5ewtIQyHUCOv0fClsCpgh\n",
|
310 |
+
" Args:\n",
|
311 |
+
" a: 6790\n",
|
312 |
+
" b: 5\n",
|
313 |
+
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
314 |
+
"Name: divide\n",
|
315 |
+
"\n",
|
316 |
+
"1358.0\n",
|
317 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
318 |
+
"\n",
|
319 |
+
"The result of dividing 6790 by 5 is 1358.0.\n"
|
320 |
+
]
|
321 |
+
}
|
322 |
+
],
|
323 |
+
"source": [
|
324 |
+
"for m in messages['messages']:\n",
|
325 |
+
" m.pretty_print()"
|
326 |
+
]
|
327 |
+
},
|
328 |
+
{
|
329 |
+
"cell_type": "markdown",
|
330 |
+
"id": "08386393-c270-43a5-bde2-2b4075238971",
|
331 |
+
"metadata": {},
|
332 |
+
"source": [
|
333 |
+
"## Training program\n",
|
334 |
+
"MR Wayne left a note with his training program for the week. I came up with a recipe for dinner leaft in a note.\n",
|
335 |
+
"\n",
|
336 |
+
"you can find the document [HERE](https://huggingface.co/datasets/agents-course/course-images/blob/main/en/unit2/LangGraph/Batman_training_and_meals.png), so download it and upload it in the local folder.\n",
|
337 |
+
"\n",
|
338 |
+
""
|
339 |
+
]
|
340 |
+
},
|
341 |
+
{
|
342 |
+
"cell_type": "code",
|
343 |
+
"execution_count": 82,
|
344 |
+
"id": "f6e97e84-3b05-4aaf-a38f-1de9b73cd37f",
|
345 |
+
"metadata": {
|
346 |
+
"tags": []
|
347 |
+
},
|
348 |
+
"outputs": [],
|
349 |
+
"source": [
|
350 |
+
"messages = [HumanMessage(content=\"According the note provided by MR wayne in the provided images. What's the list of items I should buy for the dinner menu ?\")]\n",
|
351 |
+
"\n",
|
352 |
+
"messages = react_graph.invoke({\"messages\": messages,\"input_file\":\"Batman_training_and_meals.png\"})"
|
353 |
+
]
|
354 |
+
},
|
355 |
+
{
|
356 |
+
"cell_type": "code",
|
357 |
+
"execution_count": 83,
|
358 |
+
"id": "17686d52-c7ba-407b-a13f-f6c37668e5b0",
|
359 |
+
"metadata": {
|
360 |
+
"tags": []
|
361 |
+
},
|
362 |
+
"outputs": [
|
363 |
+
{
|
364 |
+
"name": "stdout",
|
365 |
+
"output_type": "stream",
|
366 |
+
"text": [
|
367 |
+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
368 |
+
"\n",
|
369 |
+
"According the note provided by MR wayne in the provided images. What's the list of tiems I should buy for the dinner menu ?\n",
|
370 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
371 |
+
"Tool Calls:\n",
|
372 |
+
" extract_text (call_JalVBOR82hwRknFcplnLoTtG)\n",
|
373 |
+
" Call ID: call_JalVBOR82hwRknFcplnLoTtG\n",
|
374 |
+
" Args:\n",
|
375 |
+
" img_path: Batman_training_and_meals.png\n",
|
376 |
+
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
377 |
+
"Name: extract_text\n",
|
378 |
+
"\n",
|
379 |
+
"TRAINING SCHEDULE\n",
|
380 |
+
"For the week of 2/20-2/26\n",
|
381 |
+
"\n",
|
382 |
+
"SUNDAY 2/20\n",
|
383 |
+
"MORNING\n",
|
384 |
+
"30 minute jog\n",
|
385 |
+
"30 minute meditation\n",
|
386 |
+
"\n",
|
387 |
+
"EVENING\n",
|
388 |
+
"clean and jerk lifts—3 reps/8 sets. 262 lbs.\n",
|
389 |
+
"5 sets metabolic conditioning:\n",
|
390 |
+
"10 mile run\n",
|
391 |
+
"12 kettlebell swings\n",
|
392 |
+
"12 pull-ups\n",
|
393 |
+
"30 minutes flexibility\n",
|
394 |
+
"30 minutes sparring\n",
|
395 |
+
"\n",
|
396 |
+
"MONDAY 2/21\n",
|
397 |
+
"MORNING\n",
|
398 |
+
"30 minute jog\n",
|
399 |
+
"30 minutes traditional kata (focus on Japanese forms)\n",
|
400 |
+
"\n",
|
401 |
+
"EVENING\n",
|
402 |
+
"5 sets 20 foot rope climb\n",
|
403 |
+
"30 minutes gymnastics (work on muscle ups in\n",
|
404 |
+
"particular)\n",
|
405 |
+
"high bar jumps—12 reps/8 sets\n",
|
406 |
+
"crunches—50 reps/5 sets\n",
|
407 |
+
"30 minutes heavy bag\n",
|
408 |
+
"30 minutes flexibility\n",
|
409 |
+
"20 minutes target practice\n",
|
410 |
+
"\n",
|
411 |
+
"TUESDAY 2/22\n",
|
412 |
+
"MORNING\n",
|
413 |
+
"30 minute jog\n",
|
414 |
+
"30 minutes yoga\n",
|
415 |
+
"\n",
|
416 |
+
"EVENING\n",
|
417 |
+
"off day\n",
|
418 |
+
"leg heavy dead lift—5 reps/7 sets. 600 lbs.\n",
|
419 |
+
"clean and jerk lift—3 reps/10 sets\n",
|
420 |
+
"30 minutes sparring\n",
|
421 |
+
"\n",
|
422 |
+
"WEDNESDAY 2/23\n",
|
423 |
+
"OFF DAY\n",
|
424 |
+
"\n",
|
425 |
+
"MORNING\n",
|
426 |
+
"20-mile run—last week’s time was 4:50 per mile.\n",
|
427 |
+
"Need to better that time by a half a minute.\n",
|
428 |
+
"\n",
|
429 |
+
"EVENING\n",
|
430 |
+
"skill training only\n",
|
431 |
+
"30 minutes yoga\n",
|
432 |
+
"30 minutes meditation\n",
|
433 |
+
"30 minutes body basics\n",
|
434 |
+
"30 minutes bow basics\n",
|
435 |
+
"30 minutes sword basics\n",
|
436 |
+
"30 minutes observational\n",
|
437 |
+
"exercise\n",
|
438 |
+
"30 minutes kata\n",
|
439 |
+
"30 minutes pressure points\n",
|
440 |
+
"30 minutes modus and pressure points\n",
|
441 |
+
"\n",
|
442 |
+
"THURSDAY 2/24\n",
|
443 |
+
"MORNING\n",
|
444 |
+
"30 minute jog\n",
|
445 |
+
"30 minute meditation\n",
|
446 |
+
"30 minutes traditional kata\n",
|
447 |
+
"(focus on Japanese forms)\n",
|
448 |
+
"\n",
|
449 |
+
"EVENING\n",
|
450 |
+
"squats—10 reps/5 sets. 525 lbs.\n",
|
451 |
+
"30 minutes flexibility\n",
|
452 |
+
"crunches—50 reps/5 sets\n",
|
453 |
+
"20 minutes target practice\n",
|
454 |
+
"30 minutes heavy bag\n",
|
455 |
+
"\n",
|
456 |
+
"FRIDAY 2/25\n",
|
457 |
+
"MORNING\n",
|
458 |
+
"30 minute jog\n",
|
459 |
+
"30 minute meditation\n",
|
460 |
+
"\n",
|
461 |
+
"EVENING\n",
|
462 |
+
"clean and jerk lifts—3 reps/8 sets. 262 lbs.\n",
|
463 |
+
"5 sets metabolic conditioning:\n",
|
464 |
+
"10 mile run\n",
|
465 |
+
"12 kettlebell swings\n",
|
466 |
+
"12 pull-ups\n",
|
467 |
+
"30 minutes flexibility\n",
|
468 |
+
"30 minutes sparring\n",
|
469 |
+
"\n",
|
470 |
+
"SATURDAY 2/26)\n",
|
471 |
+
"MORNING\n",
|
472 |
+
"30 minute jog\n",
|
473 |
+
"30 minutes yoga\n",
|
474 |
+
"\n",
|
475 |
+
"EVENING\n",
|
476 |
+
"crunches—50 reps/5 sets\n",
|
477 |
+
"squats—(5 reps/10 sets. 525 lbs.\n",
|
478 |
+
"push-ups—60 reps/sets\n",
|
479 |
+
"30 minutes monkey bars\n",
|
480 |
+
"30 minute pommel horse\n",
|
481 |
+
"30 minutes heavy bag\n",
|
482 |
+
"2 mile swim\n",
|
483 |
+
"\n",
|
484 |
+
"In an effort to inspire the all- important Dark Knight to take time out of his busy schedule and actually consume a reasonable amount of sustenance, I have taken the liberty of composing a menu for today's scheduled natal to its my hope that these elegantly prepared courses will not share the fate of their predecessors -mated cold and untouched on a computer console.\n",
|
485 |
+
"-A\n",
|
486 |
+
"\n",
|
487 |
+
"W A Y N E M A N O R\n",
|
488 |
+
"\n",
|
489 |
+
"Tuesday's Menu\n",
|
490 |
+
"\n",
|
491 |
+
"Breakfast\n",
|
492 |
+
"six poached eggs laid over artichoke bottoms with a sage pesto sauce\n",
|
493 |
+
"thinly sliced baked ham\n",
|
494 |
+
"mixed organic fresh fruit bowl\n",
|
495 |
+
"freshly squeezed orange juice\n",
|
496 |
+
"organic, grass-fed milk\n",
|
497 |
+
"4 grams branched-chain amino acid\n",
|
498 |
+
"2 grams fish oil\n",
|
499 |
+
"\n",
|
500 |
+
"Lunch\n",
|
501 |
+
"local salmon with a ginger glaze\n",
|
502 |
+
"organic asparagus with lemon garlic dusting\n",
|
503 |
+
"Asian yam soup with diced onions\n",
|
504 |
+
"2 grams fish oil\n",
|
505 |
+
"\n",
|
506 |
+
"Dinner\n",
|
507 |
+
"grass-fed local sirloin steak\n",
|
508 |
+
"bed of organic spinach and piquillo peppers\n",
|
509 |
+
"oven-baked golden herb potato\n",
|
510 |
+
"2 grams fish oil\n",
|
511 |
+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
512 |
+
"\n",
|
513 |
+
"For the dinner menu, you should buy the following items:\n",
|
514 |
+
"\n",
|
515 |
+
"1. Grass-fed local sirloin steak\n",
|
516 |
+
"2. Organic spinach\n",
|
517 |
+
"3. Piquillo peppers\n",
|
518 |
+
"4. Potatoes (for oven-baked golden herb potato)\n",
|
519 |
+
"5. Fish oil (2 grams)\n",
|
520 |
+
"\n",
|
521 |
+
"Ensure the steak is grass-fed and the spinach and peppers are organic for the best quality meal.\n"
|
522 |
+
]
|
523 |
+
}
|
524 |
+
],
|
525 |
+
"source": [
|
526 |
+
"for m in messages['messages']:\n",
|
527 |
+
" m.pretty_print()"
|
528 |
+
]
|
529 |
+
},
|
530 |
+
{
|
531 |
+
"cell_type": "code",
|
532 |
+
"execution_count": null,
|
533 |
+
"id": "b96c8456-4093-4cd6-bc5a-f611967ab709",
|
534 |
+
"metadata": {},
|
535 |
+
"outputs": [],
|
536 |
+
"source": []
|
537 |
+
}
|
538 |
+
],
|
539 |
+
"metadata": {
|
540 |
+
"kernelspec": {
|
541 |
+
"display_name": "Python 3 (ipykernel)",
|
542 |
+
"language": "python",
|
543 |
+
"name": "python3"
|
544 |
+
},
|
545 |
+
"language_info": {
|
546 |
+
"codemirror_mode": {
|
547 |
+
"name": "ipython",
|
548 |
+
"version": 3
|
549 |
+
},
|
550 |
+
"file_extension": ".py",
|
551 |
+
"mimetype": "text/x-python",
|
552 |
+
"name": "python",
|
553 |
+
"nbconvert_exporter": "python",
|
554 |
+
"pygments_lexer": "ipython3",
|
555 |
+
"version": "3.9.5"
|
556 |
+
}
|
557 |
+
},
|
558 |
+
"nbformat": 4,
|
559 |
+
"nbformat_minor": 5
|
560 |
+
}
|