{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import utils\n", "\n", "utils.load_env()\n", "os.environ['LANGCHAIN_TRACING_V2'] = \"false\"" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:141: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 0.3.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import ChatOpenAI`.\n", " warn_deprecated(\n", "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:141: LangChainDeprecationWarning: The function `format_tool_to_openai_function` was deprecated in LangChain 0.1.16 and will be removed in 1.0. Use langchain_core.utils.function_calling.convert_to_openai_function() instead.\n", " warn_deprecated(\n" ] } ], "source": [ "from langchain_core.messages import HumanMessage\n", "import operator\n", "import functools\n", "\n", "# for llm model\n", "from langchain_openai import ChatOpenAI\n", "from langchain.agents.format_scratchpad import format_to_openai_function_messages\n", "from tools import find_place_from_text, nearby_search\n", "from typing import Dict, List, Tuple, Annotated, Sequence, TypedDict\n", "from langchain.agents import (\n", " AgentExecutor,\n", ")\n", "from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser\n", "from langchain_community.chat_models import ChatOpenAI\n", "from langchain_community.tools.convert_to_openai import format_tool_to_openai_function\n", "from langchain_core.messages import (\n", " AIMessage, \n", " HumanMessage,\n", " BaseMessage,\n", " ToolMessage\n", ")\n", "from langchain_core.pydantic_v1 import BaseModel, Field\n", "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", "from langgraph.graph import END, StateGraph, START\n", "\n", "## Document vector store for context\n", "from langchain_core.runnables import RunnablePassthrough\n", "from langchain_chroma import Chroma\n", "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", "from langchain_community.document_loaders import CSVLoader\n", "from langchain_openai import OpenAIEmbeddings\n", "import glob\n", "from langchain.tools import Tool\n", "\n", "def format_docs(docs):\n", " return \"\\n\\n\".join(doc.page_content for doc in docs)\n", "\n", "# Specify the pattern\n", "file_pattern = \"document/*.csv\"\n", "file_paths = tuple(glob.glob(file_pattern))\n", "\n", "all_docs = []\n", "\n", "for file_path in file_paths:\n", " loader = CSVLoader(file_path=file_path)\n", " docs = loader.load()\n", " all_docs.extend(docs) # Add the documents to the list\n", "\n", "# Split text into chunks separated.\n", "text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)\n", "splits = text_splitter.split_documents(all_docs)\n", "\n", "# Text Vectorization.\n", "vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())\n", "\n", "# Retrieve and generate using the relevant snippets of the blog.\n", "retriever = vectorstore.as_retriever()\n", "\n", "## tools and LLM\n", "\n", "retriever_tool = Tool(\n", " name=\"Retriever\",\n", " func=retriever.get_relevant_documents,\n", " description=\"Use this tool to retrieve information about population, community and household expenditures.\"\n", ")\n", "\n", "# Bind the tools to the model\n", "tools = [retriever_tool, find_place_from_text, nearby_search] # Include both tools if needed\n", "\n", "llm = ChatOpenAI(model=\"gpt-4o-mini\")\n", "\n", "## Create agents\n", "def create_agent(llm, tools, system_message: str):\n", " \"\"\"Create an agent.\"\"\"\n", " prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\n", " \"system\",\n", " \"You are a helpful AI assistant, collaborating with other assistants.\"\n", " \" Use the provided tools to progress towards answering the question.\"\n", " \" If you are unable to fully answer, that's OK, another assistant with different tools \"\n", " \" will help where you left off. Execute what you can to make progress.\"\n", " \" If you or any of the other assistants have the final answer or deliverable,\"\n", " \" prefix your response with FINAL ANSWER so the team knows to stop.\"\n", " \" You have access to the following tools: {tool_names}.\\n{system_message}\",\n", " ),\n", " MessagesPlaceholder(variable_name=\"messages\"),\n", " ]\n", " )\n", " prompt = prompt.partial(system_message=system_message)\n", " prompt = prompt.partial(tool_names=\", \".join([tool.name for tool in tools]))\n", " llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])\n", " # return prompt | llm.bind_tools(tools)\n", " agent = prompt | llm_with_tools\n", " return agent\n", "\n", "\n", "## Define state\n", "# This defines the object that is passed between each node\n", "# in the graph. We will create different nodes for each agent and tool\n", "class AgentState(TypedDict):\n", " messages: Annotated[Sequence[BaseMessage], operator.add]\n", " sender: str\n", "\n", "\n", "# Helper function to create a node for a given agent\n", "def agent_node(state, agent, name):\n", " result = agent.invoke(state)\n", " # We convert the agent output into a format that is suitable to append to the global state\n", " if isinstance(result, ToolMessage):\n", " pass\n", " else:\n", " result = AIMessage(**result.dict(exclude={\"type\", \"name\"}), name=name)\n", " return {\n", " \"messages\": [result],\n", " # Since we have a strict workflow, we can\n", " # track the sender so we know who to pass to next.\n", " \"sender\": name,\n", " }\n", "\n", "\n", "## Define Agents Node\n", "# Research agent and node\n", "agent_meta = utils.load_agent_meta()\n", "agent_name = [meta['name'] for meta in agent_meta]\n", "\n", "agents={}\n", "agent_nodes={}\n", "\n", "for meta in agent_meta:\n", " name = meta['name']\n", " prompt = meta['prompt']\n", " \n", " agents[name] = create_agent(\n", " llm,\n", " [find_place_from_text, nearby_search],\n", " system_message=prompt,\n", " )\n", " \n", " agent_nodes[name] = functools.partial(agent_node, agent=agents[name], name=name)\n", "\n", "\n", "## Define Tool Node\n", "from langgraph.prebuilt import ToolNode\n", "from typing import Literal\n", "\n", "tool_node = ToolNode(tools)\n", "\n", "def router(state) -> Literal[\"call_tool\", \"__end__\", \"continue\"]:\n", " # This is the router\n", " messages = state[\"messages\"]\n", " last_message = messages[-1]\n", " if last_message.tool_calls:\n", " # The previous agent is invoking a tool\n", " return \"call_tool\"\n", " if \"FINAL ANSWER\" in last_message.content:\n", " # Any agent decided the work is done\n", " return \"__end__\"\n", " return \"continue\"\n", "\n", "\n", "## Workflow Graph\n", "workflow = StateGraph(AgentState)\n", "\n", "# add agent nodes\n", "for name, node in agent_nodes.items():\n", " workflow.add_node(name, node)\n", " \n", "workflow.add_node(\"call_tool\", tool_node)\n", "\n", "\n", "for meta in agent_meta:\n", " workflow.add_conditional_edges(\n", " meta[\"name\"],\n", " router,\n", " {\"continue\": meta['continue'], \"call_tool\": \"call_tool\", \"__end__\": END},\n", " )\n", "\n", "workflow.add_conditional_edges(\n", " \"call_tool\",\n", " # Each agent node updates the 'sender' field\n", " # the tool calling node does not, meaning\n", " # this edge will route back to the original agent\n", " # who invoked the tool\n", " lambda x: x[\"sender\"],\n", " {name: name for name in agent_name},\n", ")\n", "workflow.add_edge(START, \"analyst\")\n", "graph = workflow.compile()" ] }, { "cell_type": "code", "execution_count": 3, "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(xray=True).draw_mermaid_png()))\n", "except Exception:\n", " # This requires some extra dependencies and is optional\n", " pass" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'analyst': {'messages': [AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"location\":\"มาบุญครอง\"}', 'name': 'find_place_from_text'}}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 329, 'total_tokens': 350}, 'model_name': 'gpt-4o-mini', 'system_fingerprint': 'fp_48196bc67a', 'finish_reason': 'function_call', 'logprobs': None}, name='analyst', id='run-e6c09af4-41ab-441b-b471-751510f63096-0')], 'sender': 'analyst'}}\n", "----\n", "{'data collector': {'messages': [AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"input_dict\":{\"keyword\":\"ร้านกาแฟ\",\"location_name\":\"มาบุญครอง\",\"radius\":1000,\"place_type\":\"cafe\"}}', 'name': 'nearby_search'}}, response_metadata={'token_usage': {'completion_tokens': 42, 'prompt_tokens': 326, 'total_tokens': 368}, 'model_name': 'gpt-4o-mini', 'system_fingerprint': 'fp_48196bc67a', 'finish_reason': 'function_call', 'logprobs': None}, name='data collector', id='run-19518aa2-3c77-46bd-a35a-76e87188ade0-0')], 'sender': 'data collector'}}\n", "----\n", "{'reporter': {'messages': [AIMessage(content='ฉันได้ค้นหาร้านกาแฟใกล้มาบุญครองแล้ว นี่คือรายการร้านกาแฟที่น่าสนใจ:\\n\\n1. **ร้านกาแฟ A** \\n - ที่อยู่: ถนนมาบุญครอง\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 08:00 - 20:00\\n\\n2. **ร้านกาแฟ B**\\n - ที่อยู่: ซอยมาบุญครอง\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 09:00 - 21:00\\n\\n3. **ร้านกาแฟ C**\\n - ที่อยู่: มาบุญครอง ชั้น 2\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 07:30 - 19:30\\n\\nหากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับร้านใดหรือรายละเอียดเพิ่มเติม กรุณาแจ้งให้ทราบ!', response_metadata={'token_usage': {'completion_tokens': 203, 'prompt_tokens': 421, 'total_tokens': 624}, 'model_name': 'gpt-4o-mini', 'system_fingerprint': 'fp_507c9469a1', 'finish_reason': 'stop', 'logprobs': None}, name='reporter', id='run-68022425-467e-4b41-930a-fa283d11d60d-0')], 'sender': 'reporter'}}\n", "----\n", "{'data collector': {'messages': [AIMessage(content='FINAL ANSWER: ฉันได้ค้นหาร้านกาแฟใกล้มาบุญครองแล้ว นี่คือรายการร้านกาแฟที่น่าสนใจ:\\n\\n1. **ร้านกาแฟ A** \\n - ที่อยู่: ถนนมาบุญครอง\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 08:00 - 20:00\\n\\n2. **ร้านกาแฟ B**\\n - ที่อยู่: ซอยมาบุญครอง\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 09:00 - 21:00\\n\\n3. **ร้านกาแฟ C**\\n - ที่อยู่: มาบุญครอง ชั้น 2\\n - โทรศัพท์: 02-xxx-xxxx\\n - เวลาเปิด: 07:30 - 19:30\\n\\nหากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับร้านใดหรือรายละเอียดเพิ่มเติม กรุณาแจ้งให้ทราบ!', response_metadata={'token_usage': {'completion_tokens': 207, 'prompt_tokens': 577, 'total_tokens': 784}, 'model_name': 'gpt-4o-mini', 'system_fingerprint': 'fp_48196bc67a', 'finish_reason': 'stop', 'logprobs': None}, name='data collector', id='run-255ad92f-2960-440e-b20a-229da6f87b34-0')], 'sender': 'data collector'}}\n", "----\n" ] } ], "source": [ "graph = workflow.compile()\n", "\n", "events = graph.stream(\n", " {\n", " \"messages\": [\n", " HumanMessage(\n", " content=\"ค้นหาร้านกาแฟใกล้มาบุญครอง\"\n", " )\n", " ],\n", " },\n", " # Maximum number of steps to take in the graph\n", " {\"recursion_limit\": 10},\n", ")\n", "for s in events:\n", " print(s)\n", " print(\"----\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'รายชื่อร้านกาแฟใกล้มาบุญครอง ได้แก่:\\n\\n1. **ร้านกาแฟ A**\\n - ที่อยู่: ถนนพระราม 1\\n - ระยะทาง: 500 เมตรจากมาบุญครอง\\n - ความคิดเห็น: บริการดี บรรยากาศดี\\n\\n2. **ร้านกาแฟ B**\\n - ที่อยู่: สยามสแควร์\\n - ระยะทาง: 800 เมตรจากมาบุญครอง\\n - ความคิดเห็น: กาแฟอร่อย แนะนำเมนูพิเศษ\\n\\n3. **ร้านกาแฟ C**\\n - ที่อยู่: สวนลุมพินี\\n - ระยะทาง: 1.5 กม.จากมาบุญครอง\\n - ความคิดเห็น: มีมุมสงบ เหมาะสำหรับอ่านหนังสือ\\n\\n4. **ร้านกาแฟ D**\\n - ที่อยู่: ถนนสีลม\\n - ระยะทาง: 2 กม.จากมาบุญครอง\\n - ความคิดเห็น: คาเฟ่สไตล์โมเดิร์น มี Wi-Fi ฟรี\\n\\nหากต้องการข้อมูลเพิ่มเติมหรือคำแนะนำเพิ่มเติม สามารถสอบถามได้ค่ะ!'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def submitUserMessage(user_input: str) -> str:\n", " graph = workflow.compile()\n", "\n", " events = graph.stream(\n", " {\n", " \"messages\": [\n", " HumanMessage(\n", " content=user_input\n", " )\n", " ],\n", " },\n", " # Maximum number of steps to take in the graph\n", " {\"recursion_limit\": 15},\n", " )\n", " \n", " events = [e for e in events]\n", " \n", " response = events[-1]['data collector']['messages'][0].content.replace(\"FINAL ANSWER: \", \"\")\n", " \n", " return response\n", "\n", "submitUserMessage(\"ค้นหาร้านกาแฟใกล้มาบุญครอง\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.11.9" } }, "nbformat": 4, "nbformat_minor": 2 }