|
447 | 447 | ")"
|
448 | 448 | ]
|
449 | 449 | },
|
| 450 | + { |
| 451 | + "cell_type": "markdown", |
| 452 | + "id": "c5d9d19d-8ab1-4d9d-b3a0-56ee4e89c528", |
| 453 | + "metadata": {}, |
| 454 | + "source": [ |
| 455 | + "### Custom tools\n", |
| 456 | + "\n", |
| 457 | + ":::info Requires ``langchain-openai>=0.3.29``\n", |
| 458 | + "\n", |
| 459 | + ":::\n", |
| 460 | + "\n", |
| 461 | + "[Custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools) support tools with arbitrary string inputs. They can be particularly useful when you expect your string arguments to be long or complex." |
| 462 | + ] |
| 463 | + }, |
| 464 | + { |
| 465 | + "cell_type": "code", |
| 466 | + "execution_count": 1, |
| 467 | + "id": "a47c809b-852f-46bd-8b9e-d9534c17213d", |
| 468 | + "metadata": {}, |
| 469 | + "outputs": [ |
| 470 | + { |
| 471 | + "name": "stdout", |
| 472 | + "output_type": "stream", |
| 473 | + "text": [ |
| 474 | + "================================\u001b[1m Human Message \u001b[0m=================================\n", |
| 475 | + "\n", |
| 476 | + "Use the tool to calculate 3^3.\n", |
| 477 | + "==================================\u001b[1m Ai Message \u001b[0m==================================\n", |
| 478 | + "\n", |
| 479 | + "[{'id': 'rs_6894ff5747c0819d9b02fc5645b0be9c000169fd9fb68d99', 'summary': [], 'type': 'reasoning'}, {'call_id': 'call_7SYwMSQPbbEqFcKlKOpXeEux', 'input': 'print(3**3)', 'name': 'execute_code', 'type': 'custom_tool_call', 'id': 'ctc_6894ff5b9f54819d8155a63638d34103000169fd9fb68d99', 'status': 'completed'}]\n", |
| 480 | + "Tool Calls:\n", |
| 481 | + " execute_code (call_7SYwMSQPbbEqFcKlKOpXeEux)\n", |
| 482 | + " Call ID: call_7SYwMSQPbbEqFcKlKOpXeEux\n", |
| 483 | + " Args:\n", |
| 484 | + " __arg1: print(3**3)\n", |
| 485 | + "=================================\u001b[1m Tool Message \u001b[0m=================================\n", |
| 486 | + "Name: execute_code\n", |
| 487 | + "\n", |
| 488 | + "[{'type': 'custom_tool_call_output', 'output': '27'}]\n", |
| 489 | + "==================================\u001b[1m Ai Message \u001b[0m==================================\n", |
| 490 | + "\n", |
| 491 | + "[{'type': 'text', 'text': '27', 'annotations': [], 'id': 'msg_6894ff5db3b8819d9159b3a370a25843000169fd9fb68d99'}]\n" |
| 492 | + ] |
| 493 | + } |
| 494 | + ], |
| 495 | + "source": [ |
| 496 | + "from langchain_openai import ChatOpenAI, custom_tool\n", |
| 497 | + "from langgraph.prebuilt import create_react_agent\n", |
| 498 | + "\n", |
| 499 | + "\n", |
| 500 | + "@custom_tool\n", |
| 501 | + "def execute_code(code: str) -> str:\n", |
| 502 | + " \"\"\"Execute python code.\"\"\"\n", |
| 503 | + " return \"27\"\n", |
| 504 | + "\n", |
| 505 | + "\n", |
| 506 | + "llm = ChatOpenAI(model=\"gpt-5\", output_version=\"responses/v1\")\n", |
| 507 | + "\n", |
| 508 | + "agent = create_react_agent(llm, [execute_code])\n", |
| 509 | + "\n", |
| 510 | + "input_message = {\"role\": \"user\", \"content\": \"Use the tool to calculate 3^3.\"}\n", |
| 511 | + "for step in agent.stream(\n", |
| 512 | + " {\"messages\": [input_message]},\n", |
| 513 | + " stream_mode=\"values\",\n", |
| 514 | + "):\n", |
| 515 | + " step[\"messages\"][-1].pretty_print()" |
| 516 | + ] |
| 517 | + }, |
| 518 | + { |
| 519 | + "cell_type": "markdown", |
| 520 | + "id": "5ef93be6-6d4c-4eea-acfd-248774074082", |
| 521 | + "metadata": {}, |
| 522 | + "source": [ |
| 523 | + "<details>\n", |
| 524 | + "<summary>Context-free grammars</summary>\n", |
| 525 | + "\n", |
| 526 | + "OpenAI supports the specification of a [context-free grammar](https://platform.openai.com/docs/guides/function-calling#context-free-grammars) for custom tool inputs in `lark` or `regex` format. See [OpenAI docs](https://platform.openai.com/docs/guides/function-calling#context-free-grammars) for details. The `format` parameter can be passed into `@custom_tool` as shown below:" |
| 527 | + ] |
| 528 | + }, |
| 529 | + { |
| 530 | + "cell_type": "code", |
| 531 | + "execution_count": 3, |
| 532 | + "id": "2ae04586-be33-49c6-8947-7867801d868f", |
| 533 | + "metadata": {}, |
| 534 | + "outputs": [ |
| 535 | + { |
| 536 | + "name": "stdout", |
| 537 | + "output_type": "stream", |
| 538 | + "text": [ |
| 539 | + "================================\u001b[1m Human Message \u001b[0m=================================\n", |
| 540 | + "\n", |
| 541 | + "Use the tool to calculate 3^3.\n", |
| 542 | + "==================================\u001b[1m Ai Message \u001b[0m==================================\n", |
| 543 | + "\n", |
| 544 | + "[{'id': 'rs_689500828a8481a297ff0f98e328689c0681550c89797f43', 'summary': [], 'type': 'reasoning'}, {'call_id': 'call_jzH01RVhu6EFz7yUrOFXX55s', 'input': '3 * 3 * 3', 'name': 'do_math', 'type': 'custom_tool_call', 'id': 'ctc_6895008d57bc81a2b84d0993517a66b90681550c89797f43', 'status': 'completed'}]\n", |
| 545 | + "Tool Calls:\n", |
| 546 | + " do_math (call_jzH01RVhu6EFz7yUrOFXX55s)\n", |
| 547 | + " Call ID: call_jzH01RVhu6EFz7yUrOFXX55s\n", |
| 548 | + " Args:\n", |
| 549 | + " __arg1: 3 * 3 * 3\n", |
| 550 | + "=================================\u001b[1m Tool Message \u001b[0m=================================\n", |
| 551 | + "Name: do_math\n", |
| 552 | + "\n", |
| 553 | + "[{'type': 'custom_tool_call_output', 'output': '27'}]\n", |
| 554 | + "==================================\u001b[1m Ai Message \u001b[0m==================================\n", |
| 555 | + "\n", |
| 556 | + "[{'type': 'text', 'text': '27', 'annotations': [], 'id': 'msg_6895009776b881a2a25f0be8507d08f20681550c89797f43'}]\n" |
| 557 | + ] |
| 558 | + } |
| 559 | + ], |
| 560 | + "source": [ |
| 561 | + "from langchain_openai import ChatOpenAI, custom_tool\n", |
| 562 | + "from langgraph.prebuilt import create_react_agent\n", |
| 563 | + "\n", |
| 564 | + "grammar = \"\"\"\n", |
| 565 | + "start: expr\n", |
| 566 | + "expr: term (SP ADD SP term)* -> add\n", |
| 567 | + "| term\n", |
| 568 | + "term: factor (SP MUL SP factor)* -> mul\n", |
| 569 | + "| factor\n", |
| 570 | + "factor: INT\n", |
| 571 | + "SP: \" \"\n", |
| 572 | + "ADD: \"+\"\n", |
| 573 | + "MUL: \"*\"\n", |
| 574 | + "%import common.INT\n", |
| 575 | + "\"\"\"\n", |
| 576 | + "\n", |
| 577 | + "format_ = {\"type\": \"grammar\", \"syntax\": \"lark\", \"definition\": grammar}\n", |
| 578 | + "\n", |
| 579 | + "\n", |
| 580 | + "# highlight-next-line\n", |
| 581 | + "@custom_tool(format=format_)\n", |
| 582 | + "def do_math(input_string: str) -> str:\n", |
| 583 | + " \"\"\"Do a mathematical operation.\"\"\"\n", |
| 584 | + " return \"27\"\n", |
| 585 | + "\n", |
| 586 | + "\n", |
| 587 | + "llm = ChatOpenAI(model=\"gpt-5\", output_version=\"responses/v1\")\n", |
| 588 | + "\n", |
| 589 | + "agent = create_react_agent(llm, [do_math])\n", |
| 590 | + "\n", |
| 591 | + "input_message = {\"role\": \"user\", \"content\": \"Use the tool to calculate 3^3.\"}\n", |
| 592 | + "for step in agent.stream(\n", |
| 593 | + " {\"messages\": [input_message]},\n", |
| 594 | + " stream_mode=\"values\",\n", |
| 595 | + "):\n", |
| 596 | + " step[\"messages\"][-1].pretty_print()" |
| 597 | + ] |
| 598 | + }, |
| 599 | + { |
| 600 | + "cell_type": "markdown", |
| 601 | + "id": "c63430c9-c7b0-4e92-a491-3f165dddeb8f", |
| 602 | + "metadata": {}, |
| 603 | + "source": [ |
| 604 | + "</details>" |
| 605 | + ] |
| 606 | + }, |
450 | 607 | {
|
451 | 608 | "cell_type": "markdown",
|
452 | 609 | "id": "84833dd0-17e9-4269-82ed-550639d65751",
|
|
0 commit comments