{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "**In this Notebook we will design the full graph using 3 tools: search_tool, RAG tool, and SQL-agent for travel database**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import os\n", "from dotenv import load_dotenv\n", "from pyprojroot import here\n", "load_dotenv()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the environment variables" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "os.environ['GROQ_API_KEY'] = os.getenv(\"GROQ_API_KEY\")\n", "os.environ['TAVILY_API_KEY'] = os.getenv(\"TAVILY_API_KEY\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **1. initialize the Tools**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1.1 RAG tool design**" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "name='lookup_policy' description='Consult the company policies to check whether certain options are permitted.' args_schema= func=\n" ] } ], "source": [ "from langchain_chroma import Chroma\n", "from langchain_huggingface import HuggingFaceEmbeddings\n", "from langchain_core.tools import tool\n", "\n", "EMBEDDING_MODEL = \"all-MiniLM-L6-v2\"\n", "VECTORDB_DIR = \"data/airline_policy_vectordb\"\n", "K = 2\n", "\n", "@tool\n", "def lookup_policy(query: str)->str:\n", " \"\"\"Consult the company policies to check whether certain options are permitted.\"\"\"\n", " vectordb = Chroma(\n", " collection_name=\"rag-chroma\",\n", " persist_directory=str(here(VECTORDB_DIR)),\n", " embedding_function=HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)\n", " )\n", " docs = vectordb.similarity_search(query, k=K)\n", " return \"\\n\\n\".join([doc.page_content for doc in docs])\n", "\n", "print(lookup_policy)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test the RAG tool" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "f:\\end_to_end_AI_Projects\\QueryMind _ AI_Powered_Natural_Language_Interface_for_SQL_&_Vector_Databases\\querymind\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n", "Loading weights: 100%|██████████| 103/103 [00:00<00:00, 2527.99it/s]\n", "Failed to send telemetry event ClientStartEvent: capture() takes 1 positional argument but 3 were given\n", "Failed to send telemetry event ClientCreateCollectionEvent: capture() takes 1 positional argument but 3 were given\n", "Failed to send telemetry event CollectionQueryEvent: capture() takes 1 positional argument but 3 were given\n" ] }, { "data": { "text/plain": [ "'hour cancellation policy that allows passengers to cancel their flights within 24 hours of booking at +1-877-507-7341\\nwithout penalty . This policy applies to all fare types, including non-refundable tickets. If you cancel your Swiss Airlines\\nflight within 24 hours of booking, you\\'ll receive a full refund of your ticket price.\\nHow to Cancel Swiss Airlines Flight within 24 Hours? If you need to cancel your Swiss Airlines flight within 24 hours of\\nbooking, you can do so easily online. Here are the steps to follow:\\nGo to Swiss Airlines\\' website and click on the \"Manage your bookings\" tab. Enter your booking reference number and last\\nname to access your booking. Select the flight you want to cancel and click on \"Cancel flight.\" Confirm your cancellation\\nand you\\'ll receive a full refund of your ticket price. If you booked your Swiss Airlines flight through a travel agent, you\\'ll\\nneed to contact them directly to cancel your flight within 24 hours.\\nImportant Things to Keep in Mind for Swiss Airlines 24 Hour Cancellation Here are some important things to keep in mind\\nwhen cancelling your Swiss Airlines flight within 24 hours:\\nSwiss Airlines\\' 24 hour cancellation policy only applies to flights booked directly through Swiss Airlines. If you booked\\nyour flight through a travel agent or third-party website, you\\'ll need to check their cancellation policy . If you cancel your\\nSwiss Airlines flight after the 24 hour window , you may be subject to cancellation fees or penalties. If you have a non-\\nrefundable ticket and cancel your flight within 24 hours of booking, you\\'ll receive a full refund of your ticket price.\\nHowever , if you cancel your flight after the 24 hour window , you may not be eligible for a refund. Swiss Airlines\\' 24 hour\\ncancellation policy allows passengers to cancel their flights within 24 hours of booking without penalty . If you need to\\ncancel your Swiss Airlines flight within 24 hours, you can do so easily online. Just remember to check the terms and\\nconditions of your ticket to make sure you\\'re eligible for a refund.\\nSwiss Air Cancellation Fees The cancellation fees for Swiss Air flights may vary depending on the type of ticket you have\\npurchased. The airline of fers three dif ferent types of tickets, which are:\\n\\nfor a refund or may only be able to receive a partial refund. If you booked your flight through a third-party website or\\ntravel agent, you may need to contact them directly to cancel your flight. Always check the terms and conditions of your\\nticket to make sure you understand the cancellation policy and any associated fees or penalties. If you\\'re cancelling your\\nflight due to unforeseen circumstances such as a medical emergency or a natural disaster , Swiss Air may of fer you\\nspecial exemptions or accommodations. What is Swiss Airlines 24 Hour Cancellation Policy? Swiss Airlines has a 24'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lookup_policy.invoke(\"can I cancel my ticket?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1.2 Search tool design**" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from langchain_community.tools.tavily_search import TavilySearchResults\n", "\n", "search_tool = TavilySearchResults(max_results=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test the Search Tool" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "search_tool.invoke(\"What's a 'node' in LangGraph?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1.3 SQL agent tool design**" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "from langchain_community.utilities import SQLDatabase\n", "from langchain.chains import create_sql_query_chain\n", "from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool\n", "from langchain_core.prompts import PromptTemplate\n", "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.runnables import RunnablePassthrough\n", "from operator import itemgetter\n", "from langchain_groq import ChatGroq" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**SQL agent chain**" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "sqldb_directory = here(\"data/travel.sqlite\")\n", "\n", "sql_llm = ChatGroq(model=\"openai/gpt-oss-120b\", temperature=0)\n", "# llm = ChatGroq(model=\"llama-3.3-70b-versatile\")\n", "system_role = \"\"\"Given the following user question, corresponding SQL query, and SQL result, answer the user question.\\n\n", " Question: {question}\\n\n", " SQL Query: {query}\\n\n", " SQL Result: {result}\\n\n", " Answer:\n", " \"\"\"\n", "db = SQLDatabase.from_uri(\n", " f\"sqlite:///{sqldb_directory}\")\n", "\n", "execute_query = QuerySQLDataBaseTool(db=db)\n", "write_query = create_sql_query_chain(\n", " sql_llm, db)\n", "answer_prompt = PromptTemplate.from_template(\n", " system_role)\n", "\n", "\n", "answer = answer_prompt | sql_llm | StrOutputParser()\n", "chain = (\n", " RunnablePassthrough.assign(query=write_query).assign(\n", " result=itemgetter(\"query\") | execute_query\n", " )\n", " | answer\n", ")\n", "# Test the chain\n", "# message = \"How many tables do I have in the database? and what are their names?\"\n", "# response = chain.invoke({\"question\": message})\n", "\n", "@tool\n", "def query_sqldb(query):\n", " \"\"\"Query the Swiss Airline SQL Database and access all the company's information. Input should be a search query.\"\"\"\n", " response = chain.invoke({\"question\": query})\n", " return response" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "message = \"How many tables do I have in the database? and what are their names?\"\n", "response = query_sqldb.invoke(message)\n", "print(response)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Wrap up the tools into a list**" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "tools = [search_tool, lookup_policy, query_sqldb]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Load the LLM for the primary agent and bind it with the tools**" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "llm = ChatGroq(model=\"openai/gpt-oss-120b\", temperature=0)\n", "# Tell the LLM which tools it can call\n", "llm_with_tools = llm.bind_tools(tools)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **2. Initialize the Graph State**\n", "\n", "Define our StateGraph's state as a typed dictionary containing an append-only list of messages. These messages form the chat history, which is all the state our chatbot needs." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from typing import Annotated\n", "from typing_extensions import TypedDict\n", "from langgraph.graph import StateGraph, START\n", "from langgraph.graph.message import add_messages\n", "\n", "\n", "class State(TypedDict):\n", " messages: Annotated[list, add_messages]\n", "\n", "\n", "graph_builder = StateGraph(State)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **3. Define the Graph Nodes**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**3.1 First node: chatbot**" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def chatbot(state: State):\n", " return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n", "\n", "\n", "graph_builder.add_node(\"chatbot\", chatbot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we need to create a function that will run the tools when they are needed. To do this, we'll add the tools to a new node.\n", "\n", "In the example below, we'll build a BasicToolNode. This node will check the latest message and, if it contains a request to use a tool, it will run the appropriate tool. This works because many language models (like Anthropic, OpenAI, and Google Gemini) support tool usage." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**3.2 Second node: BasicToolNode that runs the appropriate tool based on the primary agent's output**" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "import json\n", "from langchain_core.messages import ToolMessage\n", "\n", "\n", "class BasicToolNode:\n", " \"\"\"A node that runs the tools requested in the last AIMessage.\"\"\"\n", "\n", " def __init__(self, tools: list) -> None:\n", " self.tools_by_name = {tool.name: tool for tool in tools}\n", "\n", " def __call__(self, inputs: dict):\n", " if messages := inputs.get(\"messages\", []):\n", " message = messages[-1]\n", " else:\n", " raise ValueError(\"No message found in input\")\n", " outputs = []\n", " for tool_call in message.tool_calls:\n", " tool_result = self.tools_by_name[tool_call[\"name\"]].invoke(\n", " tool_call[\"args\"]\n", " )\n", " outputs.append(\n", " ToolMessage(\n", " content=json.dumps(tool_result),\n", " name=tool_call[\"name\"],\n", " tool_call_id=tool_call[\"id\"],\n", " )\n", " )\n", " return {\"messages\": outputs}\n", "\n", "\n", "tool_node = BasicToolNode(tools=[search_tool, lookup_policy, query_sqldb])\n", "graph_builder.add_node(\"tools\", tool_node)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **4. Define the entry point and graph edges**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Aproach 1**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from typing import Literal\n", "\n", "\n", "def route_tools(\n", " state: State,\n", ") -> Literal[\"tools\", \"__end__\"]:\n", " \"\"\"\n", " Use in the conditional_edge to route to the ToolNode if the last message\n", " has tool calls. Otherwise, route to the end.\n", " \"\"\"\n", " if isinstance(state, list):\n", " ai_message = state[-1]\n", " elif messages := state.get(\"messages\", []):\n", " ai_message = messages[-1]\n", " else:\n", " raise ValueError(f\"No messages found in input state to tool_edge: {state}\")\n", " if hasattr(ai_message, \"tool_calls\") and len(ai_message.tool_calls) > 0:\n", " return \"tools\"\n", " return \"__end__\"\n", "\n", "\n", "\n", "graph_builder.add_conditional_edges(\n", " \"chatbot\",\n", " route_tools,\n", " \n", " {\"tools\": \"tools\", \"__end__\": \"__end__\"},\n", ")\n", "# Any time a tool is called, we return to the chatbot to decide the next step\n", "graph_builder.add_edge(\"tools\", \"chatbot\")\n", "graph_builder.add_edge(START, \"chatbot\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Approach 2**" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from langgraph.graph import END, MessagesState\n", "from typing import Literal\n", "\n", "# Define the function that determines whether to continue or not\n", "def should_continue(state: MessagesState) -> Literal[\"tools\", END]:\n", " messages = state['messages']\n", " last_message = messages[-1]\n", " # If the LLM makes a tool call, then we route to the \"tools\" node\n", " if last_message.tool_calls:\n", " return \"tools\"\n", " # Otherwise, we stop (reply to the user)\n", " return END\n", "\n", "graph_builder.add_conditional_edges(\n", " \"chatbot\",\n", " should_continue,\n", " [\"tools\", END],\n", ")\n", "# Any time a tool is called, we return to the chatbot to decide the next step\n", "graph_builder.add_edge(\"tools\", \"chatbot\")\n", "graph_builder.add_edge(START, \"chatbot\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **5. Compile the graph**\n", "\n", "- In this step, we can add a memory to our graph as well." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "from langgraph.checkpoint.memory import MemorySaver\n", "\n", "memory = MemorySaver()\n", "graph = graph_builder.compile(checkpointer=memory)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**5.1 Plot the compiled graph**" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/jpeg": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import Image, display\n", "\n", "try:\n", " display(Image(graph.get_graph().draw_mermaid_png()))\n", "except Exception:\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Save the graph image**" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "save = False\n", "\n", "if save:\n", " from PIL import Image as PILImage\n", " import io\n", " # Assuming graph.get_graph().draw_mermaid_png() returns PNG binary data\n", " try:\n", " # Generate the PNG image from the graph\n", " png_data = graph.get_graph().draw_mermaid_png()\n", " \n", " # Convert the binary data into an image\n", " img = PILImage.open(io.BytesIO(png_data))\n", " \n", " # Save the image locally with 300 DPI\n", " img.save('output_image.png', 'PNG', dpi=(300, 300))\n", " \n", " print(\"Image saved successfully with 300 DPI.\")\n", " except Exception as e:\n", " print(f\"Error: {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **6. Execute the graph**" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "config = {\"configurable\": {\"thread_id\": \"1\"}}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**First query**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Approach 1: Print all the steps the the system goes through it to get the final output" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", "Hi there! My name is Farzad.\n" ] } ], "source": [ "user_input = \"Hi there! My name is Farzad.\"\n", "\n", "# The config is the **second positional argument** to stream() or invoke()!\n", "events = graph.stream(\n", " {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n", ")\n", "for event in events:\n", " event[\"messages\"][-1].pretty_print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Approach 2: Just print the final output" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Hello again, Farzad! How can I help you today?'" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from langchain_core.messages import HumanMessage\n", "user_input = \"Hi there! My name is Farzad.\"\n", "\n", "# Use the Runnable\n", "final_state = graph.invoke(\n", " {\"messages\": [HumanMessage(content=user_input)]},\n", " config=config\n", ")\n", "final_state[\"messages\"][-1].content" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Second query**" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", "Can I cancel my ticket 10 hours before the flight?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", " lookup_policy (call_PnEdkdZICkTDuytncfiYhJo2)\n", " Call ID: call_PnEdkdZICkTDuytncfiYhJo2\n", " Args:\n", " query: ticket cancellation policy\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: lookup_policy\n", "\n", "\"for a refund or may only be able to receive a partial refund. If you booked your flight through a third-party website or\\ntravel agent, you may need to contact them directly to cancel your flight. Always check the terms and conditions of your\\nticket to make sure you understand the cancellation policy and any associated fees or penalties. If you're cancelling your\\nflight due to unforeseen circumstances such as a medical emergency or a natural disaster , Swiss Air may of fer you\\nspecial exemptions or accommodations. What is Swiss Airlines 24 Hour Cancellation Policy? Swiss Airlines has a 24\\n\\nhour cancellation policy that allows passengers to cancel their flights within 24 hours of booking at +1-877-507-7341\\nwithout penalty . This policy applies to all fare types, including non-refundable tickets. If you cancel your Swiss Airlines\\nflight within 24 hours of booking, you'll receive a full refund of your ticket price.\\nHow to Cancel Swiss Airlines Flight within 24 Hours? If you need to cancel your Swiss Airlines flight within 24 hours of\\nbooking, you can do so easily online. Here are the steps to follow:\\nGo to Swiss Airlines' website and click on the \\\"Manage your bookings\\\" tab. Enter your booking reference number and last\\nname to access your booking. Select the flight you want to cancel and click on \\\"Cancel flight.\\\" Confirm your cancellation\\nand you'll receive a full refund of your ticket price. If you booked your Swiss Airlines flight through a travel agent, you'll\\nneed to contact them directly to cancel your flight within 24 hours.\\nImportant Things to Keep in Mind for Swiss Airlines 24 Hour Cancellation Here are some important things to keep in mind\\nwhen cancelling your Swiss Airlines flight within 24 hours:\\nSwiss Airlines' 24 hour cancellation policy only applies to flights booked directly through Swiss Airlines. If you booked\\nyour flight through a travel agent or third-party website, you'll need to check their cancellation policy . If you cancel your\\nSwiss Airlines flight after the 24 hour window , you may be subject to cancellation fees or penalties. If you have a non-\\nrefundable ticket and cancel your flight within 24 hours of booking, you'll receive a full refund of your ticket price.\\nHowever , if you cancel your flight after the 24 hour window , you may not be eligible for a refund. Swiss Airlines' 24 hour\\ncancellation policy allows passengers to cancel their flights within 24 hours of booking without penalty . If you need to\\ncancel your Swiss Airlines flight within 24 hours, you can do so easily online. Just remember to check the terms and\\nconditions of your ticket to make sure you're eligible for a refund.\\nSwiss Air Cancellation Fees The cancellation fees for Swiss Air flights may vary depending on the type of ticket you have\\npurchased. The airline of fers three dif ferent types of tickets, which are:\"\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", "You can cancel your ticket with Swiss Airlines, but the ability to receive a refund or avoid penalties depends on the timing and the type of ticket you purchased. Here are some key points regarding ticket cancellation:\n", "\n", "1. **24-Hour Cancellation Policy**: If you booked your flight directly through Swiss Airlines, you can cancel your flight within 24 hours of booking without penalty and receive a full refund.\n", "\n", "2. **Cancellation 10 Hours Before Flight**: If you are looking to cancel your ticket 10 hours before the flight, you may be subject to cancellation fees or penalties, especially if you have a non-refundable ticket. The specific fees can vary based on the type of ticket you purchased.\n", "\n", "3. **Contacting Third Parties**: If you booked your flight through a third-party website or travel agent, you will need to contact them directly to cancel your flight.\n", "\n", "4. **Special Exemptions**: In cases of unforeseen circumstances (like medical emergencies), Swiss Airlines may offer special exemptions or accommodations.\n", "\n", "It's always best to check the terms and conditions of your specific ticket for detailed information on cancellation policies and any associated fees.\n" ] } ], "source": [ "user_input = \"Can I cancel my ticket 10 hours before the flight?\"\n", "\n", "events = graph.stream(\n", " {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n", ")\n", "for event in events:\n", " event[\"messages\"][-1].pretty_print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Third query**" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", "Right now Harris vs. Trump Presidential Debate is being boradcasted. I want the youtube link to this debate\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", " tavily_search_results_json (call_1jy65jCBXDpiaiDrn9n93HBC)\n", " Call ID: call_1jy65jCBXDpiaiDrn9n93HBC\n", " Args:\n", " query: Harris Trump Presidential Debate YouTube link\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", "[{\"url\": \"https://www.pbs.org/newshour/politics/watch-live-harris-and-trump-debate-pbs-news-simulcast-of-abcs-2024-presidential-debate\", \"content\": \"WATCH: Harris and Trump debate \\u2014 PBS News simulcast of ABC\\u2019s 2024 Presidential Debate Vice President Kamala Harris and former President Donald Trump faced off Tuesday night for their first and possibly only debate before Election Day. The state of the race as they meet in Philadelphia is starkly different than it was just more than two months ago, when Trump debated President Joe Biden in a performance that accelerated calls for Biden to leave the race. WATCH: What to watch in the ABC Harris-Trump debate Watch PBS News\\u2019 special coverage here and the\\u00a0ABC Presidential Debate in the player above. This year\\u2019s presidential race is a genuine contest of ideas between Harris and Trump \\u2014 with clear differences on taxes, abortion, immigration, global alliances, climate change and democracy itself. LIVE FACT CHECK: Trump and Harris meet for presidential debate\"}, {\"url\": \"https://abcnews.go.com/Politics/watch-full-abc-news-presidential-debate/story?id=113470583\", \"content\": \"MORE: READ: Harris-Trump presidential debate transcript Democratic presidential nominee Vice President Kamala Harris shakes hands with former President Donald Trump, during a presidential debate ...\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", "You can watch the Harris vs. Trump Presidential Debate through the following links:\n", "\n", "1. [PBS News Simulcast of the Debate](https://www.pbs.org/newshour/politics/watch-live-harris-and-trump-debate-pbs-news-simulcast-of-abcs-2024-presidential-debate)\n", "2. [ABC News Full Debate Coverage](https://abcnews.go.com/Politics/watch-full-abc-news-presidential-debate/story?id=113470583)\n", "\n", "Feel free to check them out!\n" ] } ], "source": [ "user_input = \"Right now Harris vs. Trump Presidential Debate is being boradcasted. I want the youtube link to this debate\"\n", "\n", "events = graph.stream(\n", " {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n", ")\n", "for event in events:\n", " event[\"messages\"][-1].pretty_print()" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'messages': [HumanMessage(content='Hi there! My name is Farzad.', id='5aa78bed-a259-4d29-91c0-0e00d4113895'),\n", " AIMessage(content='Hello Farzad! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 149, 'total_tokens': 161, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'stop', 'logprobs': None}, id='run-6a8c7f6f-0647-4569-a1ff-58747953ad59-0', usage_metadata={'input_tokens': 149, 'output_tokens': 12, 'total_tokens': 161}),\n", " HumanMessage(content='Hi there! My name is Farzad.', id='45b30b4e-7aca-45f7-945d-48f4f3f738f0'),\n", " AIMessage(content='Hello again, Farzad! How can I help you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 177, 'total_tokens': 191, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'stop', 'logprobs': None}, id='run-632913bf-ab5b-4ddb-8806-aa609e10086c-0', usage_metadata={'input_tokens': 177, 'output_tokens': 14, 'total_tokens': 191}),\n", " HumanMessage(content='Can I cancel my ticket 10 hours before the flight?', id='5a4cd448-96ea-4d6a-b865-ba9aa7661136'),\n", " AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_PnEdkdZICkTDuytncfiYhJo2', 'function': {'arguments': '{\"query\":\"ticket cancellation policy\"}', 'name': 'lookup_policy'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 16, 'prompt_tokens': 210, 'total_tokens': 226, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-dc4bc2d4-19a5-4ee6-b163-a7fc7e533489-0', tool_calls=[{'name': 'lookup_policy', 'args': {'query': 'ticket cancellation policy'}, 'id': 'call_PnEdkdZICkTDuytncfiYhJo2', 'type': 'tool_call'}], usage_metadata={'input_tokens': 210, 'output_tokens': 16, 'total_tokens': 226}),\n", " ToolMessage(content='\"for a refund or may only be able to receive a partial refund. If you booked your flight through a third-party website or\\\\ntravel agent, you may need to contact them directly to cancel your flight. Always check the terms and conditions of your\\\\nticket to make sure you understand the cancellation policy and any associated fees or penalties. If you\\'re cancelling your\\\\nflight due to unforeseen circumstances such as a medical emergency or a natural disaster , Swiss Air may of fer you\\\\nspecial exemptions or accommodations. What is Swiss Airlines 24 Hour Cancellation Policy? Swiss Airlines has a 24\\\\n\\\\nhour cancellation policy that allows passengers to cancel their flights within 24 hours of booking at +1-877-507-7341\\\\nwithout penalty . This policy applies to all fare types, including non-refundable tickets. If you cancel your Swiss Airlines\\\\nflight within 24 hours of booking, you\\'ll receive a full refund of your ticket price.\\\\nHow to Cancel Swiss Airlines Flight within 24 Hours? If you need to cancel your Swiss Airlines flight within 24 hours of\\\\nbooking, you can do so easily online. Here are the steps to follow:\\\\nGo to Swiss Airlines\\' website and click on the \\\\\"Manage your bookings\\\\\" tab. Enter your booking reference number and last\\\\nname to access your booking. Select the flight you want to cancel and click on \\\\\"Cancel flight.\\\\\" Confirm your cancellation\\\\nand you\\'ll receive a full refund of your ticket price. If you booked your Swiss Airlines flight through a travel agent, you\\'ll\\\\nneed to contact them directly to cancel your flight within 24 hours.\\\\nImportant Things to Keep in Mind for Swiss Airlines 24 Hour Cancellation Here are some important things to keep in mind\\\\nwhen cancelling your Swiss Airlines flight within 24 hours:\\\\nSwiss Airlines\\' 24 hour cancellation policy only applies to flights booked directly through Swiss Airlines. If you booked\\\\nyour flight through a travel agent or third-party website, you\\'ll need to check their cancellation policy . If you cancel your\\\\nSwiss Airlines flight after the 24 hour window , you may be subject to cancellation fees or penalties. If you have a non-\\\\nrefundable ticket and cancel your flight within 24 hours of booking, you\\'ll receive a full refund of your ticket price.\\\\nHowever , if you cancel your flight after the 24 hour window , you may not be eligible for a refund. Swiss Airlines\\' 24 hour\\\\ncancellation policy allows passengers to cancel their flights within 24 hours of booking without penalty . If you need to\\\\ncancel your Swiss Airlines flight within 24 hours, you can do so easily online. Just remember to check the terms and\\\\nconditions of your ticket to make sure you\\'re eligible for a refund.\\\\nSwiss Air Cancellation Fees The cancellation fees for Swiss Air flights may vary depending on the type of ticket you have\\\\npurchased. The airline of fers three dif ferent types of tickets, which are:\"', name='lookup_policy', id='306a3eb2-1d47-48cb-baa3-1a721072a1df', tool_call_id='call_PnEdkdZICkTDuytncfiYhJo2'),\n", " AIMessage(content=\"You can cancel your ticket with Swiss Airlines, but the ability to receive a refund or avoid penalties depends on the timing and the type of ticket you purchased. Here are some key points regarding ticket cancellation:\\n\\n1. **24-Hour Cancellation Policy**: If you booked your flight directly through Swiss Airlines, you can cancel your flight within 24 hours of booking without penalty and receive a full refund.\\n\\n2. **Cancellation 10 Hours Before Flight**: If you are looking to cancel your ticket 10 hours before the flight, you may be subject to cancellation fees or penalties, especially if you have a non-refundable ticket. The specific fees can vary based on the type of ticket you purchased.\\n\\n3. **Contacting Third Parties**: If you booked your flight through a third-party website or travel agent, you will need to contact them directly to cancel your flight.\\n\\n4. **Special Exemptions**: In cases of unforeseen circumstances (like medical emergencies), Swiss Airlines may offer special exemptions or accommodations.\\n\\nIt's always best to check the terms and conditions of your specific ticket for detailed information on cancellation policies and any associated fees.\", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 226, 'prompt_tokens': 819, 'total_tokens': 1045, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'stop', 'logprobs': None}, id='run-c83ed911-1952-4ece-b16f-41c9d515b6f3-0', usage_metadata={'input_tokens': 819, 'output_tokens': 226, 'total_tokens': 1045}),\n", " HumanMessage(content='Right now Harris vs. Trump Presidential Debate is being boradcasted. I want the youtube link to this debate', id='4706cd31-61e5-4a67-bb17-c4eb3e17b0e1'),\n", " AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_1jy65jCBXDpiaiDrn9n93HBC', 'function': {'arguments': '{\"query\":\"Harris Trump Presidential Debate YouTube link\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 25, 'prompt_tokens': 1075, 'total_tokens': 1100, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-c25bda9e-c897-4e44-b7c6-94c9f32933e9-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'Harris Trump Presidential Debate YouTube link'}, 'id': 'call_1jy65jCBXDpiaiDrn9n93HBC', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1075, 'output_tokens': 25, 'total_tokens': 1100}),\n", " ToolMessage(content='[{\"url\": \"https://www.pbs.org/newshour/politics/watch-live-harris-and-trump-debate-pbs-news-simulcast-of-abcs-2024-presidential-debate\", \"content\": \"WATCH: Harris and Trump debate \\\\u2014 PBS News simulcast of ABC\\\\u2019s 2024 Presidential Debate Vice President Kamala Harris and former President Donald Trump faced off Tuesday night for their first and possibly only debate before Election Day. The state of the race as they meet in Philadelphia is starkly different than it was just more than two months ago, when Trump debated President Joe Biden in a performance that accelerated calls for Biden to leave the race. WATCH: What to watch in the ABC Harris-Trump debate Watch PBS News\\\\u2019 special coverage here and the\\\\u00a0ABC Presidential Debate in the player above. This year\\\\u2019s presidential race is a genuine contest of ideas between Harris and Trump \\\\u2014 with clear differences on taxes, abortion, immigration, global alliances, climate change and democracy itself. LIVE FACT CHECK: Trump and Harris meet for presidential debate\"}, {\"url\": \"https://abcnews.go.com/Politics/watch-full-abc-news-presidential-debate/story?id=113470583\", \"content\": \"MORE: READ: Harris-Trump presidential debate transcript Democratic presidential nominee Vice President Kamala Harris shakes hands with former President Donald Trump, during a presidential debate ...\"}]', name='tavily_search_results_json', id='45c00f98-cf0e-4e5b-b19a-c3da9ec63434', tool_call_id='call_1jy65jCBXDpiaiDrn9n93HBC'),\n", " AIMessage(content='You can watch the Harris vs. Trump Presidential Debate through the following links:\\n\\n1. [PBS News Simulcast of the Debate](https://www.pbs.org/newshour/politics/watch-live-harris-and-trump-debate-pbs-news-simulcast-of-abcs-2024-presidential-debate)\\n2. [ABC News Full Debate Coverage](https://abcnews.go.com/Politics/watch-full-abc-news-presidential-debate/story?id=113470583)\\n\\nFeel free to check them out!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 106, 'prompt_tokens': 1405, 'total_tokens': 1511, 'prompt_tokens_details': {'cached_tokens': 1024}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_f85bea6784', 'finish_reason': 'stop', 'logprobs': None}, id='run-c011a865-0f6e-47f3-aae6-f139aeba11ca-0', usage_metadata={'input_tokens': 1405, 'output_tokens': 106, 'total_tokens': 1511})]}" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "event" ] } ], "metadata": { "kernelspec": { "display_name": "querymind (3.12.10)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.10" } }, "nbformat": 4, "nbformat_minor": 2 }