-
Notifications
You must be signed in to change notification settings - Fork 132
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add how-to guide on structured output prebuilt react agent (#794)
- Loading branch information
Showing
2 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# How to return structured output from the prebuilt ReAct agent\n", | ||
"\n", | ||
"\n", | ||
"!!! info \"Prerequisites\"\n", | ||
"\n", | ||
" - [Agent Architectures](../../concepts/agentic_concepts/)\n", | ||
" - [Chat Models](https://python.langchain.com/docs/concepts/chat_models/)\n", | ||
" - [Tools](https://python.langchain.com/docs/concepts/tools/)\n", | ||
" - [Structured Output](https://python.langchain.com/docs/concepts/structured_outputs/)\n", | ||
"\n", | ||
"\n", | ||
"To return structured output from the prebuilt ReAct agent you can provide a response_format parameter with the desired output schema to [`createReactAgent`](https://langchain-ai.github.io/langgraphjs/reference/functions/prebuilt.createReactAgent.html):" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import { z } from \"zod\";\n", | ||
"import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n", | ||
"\n", | ||
"const responseFormat = z.object({\n", | ||
" // Respond to the user in this format\n", | ||
" mySpecialOutput: z.string(),\n", | ||
"})\n", | ||
"\n", | ||
"const graph = createReactAgent({\n", | ||
" llm: llm,\n", | ||
" tools: tools,\n", | ||
" // specify the schema for the structured output using `responseFormat` parameter\n", | ||
" responseFormat: responseFormat\n", | ||
"})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The agent will return the output in the format specified by the `responseFormat` schema by making an additional LLM call at the end of the conversation, once there are no more tool calls to be made. You can read [this guide](./respond-in-format) to learn about an alternate way - treating the structured output as another tool = to achieve structured output from the agent.\n", | ||
"\n", | ||
"## Setup\n", | ||
"\n", | ||
"First, we need to install the required packages.\n", | ||
"\n", | ||
"```bash\n", | ||
"yarn add @langchain/langgraph @langchain/openai @langchain/core zod\n", | ||
"```\n", | ||
"\n", | ||
"This guide will use OpenAI's GPT-4o model. We will optionally set our API key\n", | ||
"for [LangSmith tracing](https://smith.langchain.com/), which will give us\n", | ||
"best-in-class observability." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"// process.env.OPENAI_API_KEY = \"sk_...\";\n", | ||
"\n", | ||
"// Optional, add tracing in LangSmith\n", | ||
"// process.env.LANGSMITH_API_KEY = \"ls__...\"\n", | ||
"process.env.LANGSMITH_TRACING = \"true\";\n", | ||
"process.env.LANGSMITH_PROJECT = \"ReAct Agent with system prompt: LangGraphJS\";" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Code" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import { ChatOpenAI } from \"@langchain/openai\";\n", | ||
"import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n", | ||
"import { tool } from \"@langchain/core/tools\";\n", | ||
"import { z } from \"zod\";\n", | ||
"\n", | ||
"const weatherTool = tool(\n", | ||
" async (input): Promise<string> => {\n", | ||
" if (input.city === \"nyc\") {\n", | ||
" return \"It might be cloudy in nyc\";\n", | ||
" } else if (input.city === \"sf\") {\n", | ||
" return \"It's always sunny in sf\";\n", | ||
" } else {\n", | ||
" throw new Error(\"Unknown city\");\n", | ||
" }\n", | ||
" },\n", | ||
" {\n", | ||
" name: \"get_weather\",\n", | ||
" description: \"Use this to get weather information.\",\n", | ||
" schema: z.object({\n", | ||
" city: z.enum([\"nyc\", \"sf\"]).describe(\"The city to get weather for\"),\n", | ||
" }),\n", | ||
" }\n", | ||
");\n", | ||
"\n", | ||
"const WeatherResponseSchema = z.object({\n", | ||
" conditions: z.string().describe(\"Weather conditions\"),\n", | ||
"});\n", | ||
"\n", | ||
"const tools = [weatherTool];\n", | ||
"\n", | ||
"const agent = createReactAgent({\n", | ||
" llm: new ChatOpenAI({ model: \"gpt-4o\", temperature: 0 }),\n", | ||
" tools: tools,\n", | ||
" responseFormat: WeatherResponseSchema,\n", | ||
"}); " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Usage\n", | ||
"\n", | ||
"Let's now test our agent:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"const response = await agent.invoke({\n", | ||
" messages: [\n", | ||
" {\n", | ||
" role: \"user\",\n", | ||
" content: \"What's the weather in NYC?\",\n", | ||
" },\n", | ||
" ],\n", | ||
"})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"You can see that the agent output contains a `structuredResponse` key with the structured output conforming to the specified `WeatherResponse` schema, in addition to the message history under `messages` key" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"{ conditions: 'cloudy' }\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"response.structuredResponse" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Customizing system prompt\n", | ||
"\n", | ||
"You might need to further customize the second LLM call for the structured output generation and provide a system prompt. To do so, you can pass an object with the keys `prompt`, `schema` to the `responseFormat` parameter:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"const agent = createReactAgent({\n", | ||
" llm: new ChatOpenAI({ model: \"gpt-4o\", temperature: 0 }),\n", | ||
" tools: tools,\n", | ||
" responseFormat: {\n", | ||
" prompt: \"Always return capitalized weather conditions\",\n", | ||
" schema: WeatherResponseSchema,\n", | ||
" }\n", | ||
"}); \n", | ||
"\n", | ||
"const response = await agent.invoke({\n", | ||
" messages: [\n", | ||
" {\n", | ||
" role: \"user\",\n", | ||
" content: \"What's the weather in NYC?\",\n", | ||
" },\n", | ||
" ],\n", | ||
"})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"You can verify that the structured response now contains a capitalized value:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"{ conditions: 'Cloudy' }\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"response.structuredResponse" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "TypeScript", | ||
"language": "typescript", | ||
"name": "tslab" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"mode": "typescript", | ||
"name": "javascript", | ||
"typescript": true | ||
}, | ||
"file_extension": ".ts", | ||
"mimetype": "text/typescript", | ||
"name": "typescript", | ||
"version": "3.7.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |