|
396 | 396 | "from langchain_community.tools import WikipediaQueryRun\n", |
397 | 397 | "from langchain_community.utilities import WikipediaAPIWrapper\n", |
398 | 398 | "from datetime import datetime\n", |
399 | | - "from langchain.tools import Tool\n", |
| 399 | + "from langchain.tools import tool\n", |
400 | 400 | "\n", |
401 | | - "# Define a tools that searches Wikipedia\n", |
402 | | - "wikipedia_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())\n", |
| 401 | + "# Define a tool that searches Wikipedia\n", |
| 402 | + "_wikipedia_query = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())\n", |
| 403 | + "\n", |
| 404 | + "@tool(\"wikipedia\")\n", |
| 405 | + "def wikipedia_tool(query: str) -> str:\n", |
| 406 | + " \"\"\"Search Wikipedia for the given query and return a summary.\"\"\"\n", |
| 407 | + " try:\n", |
| 408 | + " return _wikipedia_query.invoke(query)\n", |
| 409 | + " except Exception as exc:\n", |
| 410 | + " return f\"Wikipedia lookup failed ({exc}). Answer from your own knowledge instead.\"\n", |
403 | 411 | "\n", |
404 | 412 | "# Define a new tool that returns the current datetime\n", |
405 | | - "datetime_tool = Tool(\n", |
406 | | - " name=\"Datetime\",\n", |
407 | | - " func = lambda x: datetime.now().isoformat(),\n", |
408 | | - " description=\"Returns the current datetime\",\n", |
409 | | - ")" |
| 413 | + "@tool(\"current_datetime\")\n", |
| 414 | + "def datetime_tool() -> str:\n", |
| 415 | + " \"\"\"Returns the current datetime.\"\"\"\n", |
| 416 | + " return datetime.now().isoformat()" |
410 | 417 | ] |
411 | 418 | }, |
412 | 419 | { |
|
428 | 435 | }, |
429 | 436 | "outputs": [], |
430 | 437 | "source": [ |
431 | | - "from langchain.agents import AgentExecutor, create_openai_tools_agent\n", |
| 438 | + "from langchain.agents import create_agent\n", |
432 | 439 | "from langchain_core.messages import BaseMessage, HumanMessage\n", |
433 | 440 | "from langchain_openai import ChatOpenAI\n", |
434 | 441 | "\n", |
435 | | - "def create_agent(llm: ChatOpenAI, system_prompt: str, tools: list):\n", |
| 442 | + "def create_worker_agent(llm: ChatOpenAI, system_prompt: str, tools: list):\n", |
436 | 443 | " # Each worker node will be given a name and some tools.\n", |
437 | | - " prompt = ChatPromptTemplate.from_messages(\n", |
438 | | - " [\n", |
439 | | - " (\n", |
440 | | - " \"system\",\n", |
441 | | - " system_prompt,\n", |
442 | | - " ),\n", |
443 | | - " MessagesPlaceholder(variable_name=\"messages\"),\n", |
444 | | - " MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n", |
445 | | - " ]\n", |
| 444 | + " return create_agent(\n", |
| 445 | + " model=llm,\n", |
| 446 | + " tools=tools,\n", |
| 447 | + " system_prompt=system_prompt,\n", |
446 | 448 | " )\n", |
447 | | - " agent = create_openai_tools_agent(llm, tools, prompt)\n", |
448 | | - " executor = AgentExecutor(agent=agent, tools=tools)\n", |
449 | | - " return executor\n", |
450 | 449 | "\n", |
451 | 450 | "def agent_node(state, agent, name):\n", |
452 | 451 | " result = agent.invoke(state)\n", |
453 | | - " return {\"messages\": [HumanMessage(content=result[\"output\"], name=name)]}" |
| 452 | + " return {\"messages\": [HumanMessage(content=result[\"messages\"][-1].content, name=name)]}" |
454 | 453 | ] |
455 | 454 | }, |
456 | 455 | { |
|
472 | 471 | }, |
473 | 472 | "outputs": [], |
474 | 473 | "source": [ |
475 | | - "from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser\n", |
476 | 474 | "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", |
477 | 475 | "\n", |
478 | 476 | "members = [\"Researcher\", \"CurrentTime\"]\n", |
|
486 | 484 | "# Our team supervisor is an LLM node. It just picks the next agent to process and decides when the work is completed\n", |
487 | 485 | "options = [\"FINISH\"] + members\n", |
488 | 486 | "\n", |
489 | | - "# Using openai function calling can make output parsing easier for us\n", |
| 487 | + "# Using structured output can make routing easier for us\n", |
490 | 488 | "function_def = {\n", |
491 | 489 | " \"name\": \"route\",\n", |
492 | 490 | " \"description\": \"Select the next role.\",\n", |
|
521 | 519 | "llm = ChatOpenAI(model=\"gpt-4o\")\n", |
522 | 520 | "\n", |
523 | 521 | "# Construction of the chain for the supervisor agent\n", |
524 | | - "supervisor_chain = (\n", |
525 | | - " prompt\n", |
526 | | - " | llm.bind_functions(functions=[function_def], function_call=\"route\")\n", |
527 | | - " | JsonOutputFunctionsParser()\n", |
528 | | - ")" |
| 522 | + "supervisor_chain = prompt | llm.with_structured_output(function_def)" |
529 | 523 | ] |
530 | 524 | }, |
531 | 525 | { |
|
561 | 555 | " next: str\n", |
562 | 556 | "\n", |
563 | 557 | "# Add the research agent using the create_agent helper function\n", |
564 | | - "research_agent = create_agent(llm, \"You are a web researcher.\", [wikipedia_tool])\n", |
| 558 | + "research_agent = create_worker_agent(llm, \"You are a web researcher.\", [wikipedia_tool])\n", |
565 | 559 | "research_node = functools.partial(agent_node, agent=research_agent, name=\"Researcher\")\n", |
566 | 560 | "\n", |
567 | 561 | "# Add the time agent using the create_agent helper function\n", |
568 | | - "currenttime_agent = create_agent(llm, \"You can tell the current time at\", [datetime_tool])\n", |
| 562 | + "currenttime_agent = create_worker_agent(llm, \"You can tell the current time.\", [datetime_tool])\n", |
569 | 563 | "currenttime_node = functools.partial(agent_node, agent=currenttime_agent, name = \"CurrentTime\")\n", |
570 | 564 | "\n", |
571 | 565 | "workflow = StateGraph(AgentState)\n", |
|
0 commit comments