Skip to content

Commit

Permalink
docs: Adds versions page, updates docstrings, fix typos (#440)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoblee93 authored Sep 3, 2024
1 parent b7ee998 commit f9102fd
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 55 deletions.
4 changes: 4 additions & 0 deletions docs/docs/versions/.meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
tags:
- versioning
- changelog
- upgrading
56 changes: 56 additions & 0 deletions docs/docs/versions/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# LangGraph Over Time

As LangGraph.js continues to evolve and improve, breaking changes are sometimes necessary to enhance functionality, performance, or developer experience. This page serves as a guide to the version history of LangGraph.js, documenting significant changes and providing assistance for upgrading between versions.

## Version History

### v0.2.0 (Latest)

- (Breaking) [`@langchain/core`](https://www.npmjs.com/package/@langchain/core) is now a peer dependency and requires explicit installation.
- Added support for [dynamic breakpoints](/langgraphjs/how-tos/dynamic_breakpoints/).
- Added support for [separate input and output schema](/langgraphjs/how-tos/input_output_schema/).
- Allow using an array to specify destination nodes from a conditional edge as shorthand for object.
- Numerous bugfixes.

### v0.1.0

- (Breaking) Changed checkpoint representations to support namespacing for subgraphs and pending writes.
- (Breaking) `MessagesState` was changed to [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html).
- Added [`Annotation`](/langgraphjs/reference/modules/langgraph.Annotation.html), a more streamlined way to declare state. Removes the need for separate type and channel declarations.
- Split checkpointer implementations into different libraries for easier inheritance.
- Major internal architecture refactor to use more robust patterns.
- Deprecated `MessageGraph` in favor of [`StateGraph`](/langgraphjs/reference/classes/langgraph.StateGraph.html) + [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html).
- Numerous bugfixes.

## Upgrading

When upgrading LangGraph.js, please refer to the specific version sections below for detailed instructions on how to adapt your code to the latest changes.

### Upgrading to v0.2.0

- You will now need to install `@langchain/core` explicitly. See [this page](https://langchain-ai.github.io/langgraphjs/how-tos/manage-ecosystem-dependencies/) for more information.

### Upgrading to v0.1.0

- Old saved checkpoints will no longer be valid, and you will need to update to use a new prebuilt checkpointer.
- We recommend switching to the new `Annotation` syntax when declaring graph state.

## Deprecation Notices

This section will list any deprecated features or APIs, along with their planned removal dates and recommended alternatives.

#### `MessageGraph`

Use [`MessagesAnnotation`](/langgraphjs/reference/variables/langgraph.MessagesAnnotation.html) with [`StateGraph`](/langgraphjs/reference/classes/langgraph.StateGraph.html).

#### `createFunctionCallingExecutor`

Use [`createReactAgent`](/langgraphjs/reference/functions/langgraph_prebuilt.createReactAgent.html) with a model that supports tool calling.

#### `ToolExecutor`

Use [`ToolNode`](/langgraphjs/reference/classes/langgraph_prebuilt.ToolNode.html) instead.

## Full changelog

For the most up-to-date information on LangGraph.js versions and changes, please refer to our [GitHub repository](https://github.com/langchain-ai/langgraphjs) and [release notes](https://github.com/langchain-ai/langgraphjs/releases).
2 changes: 2 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ nav:
- FAQ: concepts/faq.md
- "Reference":
- "reference/index.html"
- "Versions":
- "versions/index.md"

markdown_extensions:
- abbr
Expand Down
28 changes: 13 additions & 15 deletions examples/how-tos/create-react-agent.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,21 @@
"import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n",
"\n",
"const model = new ChatOpenAI({\n",
" model: \"gpt-4o\",\n",
" });\n",
" model: \"gpt-4o\",\n",
"});\n",
"\n",
"const getWeather = tool((input) => {\n",
" if (['sf', 'san francisco', 'san francisco, ca'].includes(input.location.toLowerCase())) {\n",
" return 'It\\'s 60 degrees and foggy.';\n",
" } else {\n",
" return 'It\\'s 90 degrees and sunny.';\n",
" }\n",
" if (['sf', 'san francisco', 'san francisco, ca'].includes(input.location.toLowerCase())) {\n",
" return 'It\\'s 60 degrees and foggy.';\n",
" } else {\n",
" return 'It\\'s 90 degrees and sunny.';\n",
" }\n",
"}, {\n",
" name: 'get_weather',\n",
" description: 'Call to get the current weather.',\n",
" schema: z.object({\n",
" location: z.string().describe(\"Location to get the weather for.\"),\n",
" })\n",
" name: 'get_weather',\n",
" description: 'Call to get the current weather.',\n",
" schema: z.object({\n",
" location: z.string().describe(\"Location to get the weather for.\"),\n",
" })\n",
"})\n",
"\n",
"const agent = createReactAgent({ llm: model, tools: [getWeather] });"
Expand Down Expand Up @@ -173,9 +173,7 @@
" streamMode: \"values\",\n",
"});\n",
"\n",
"for await (\n",
" const { messages } of stream\n",
") {\n",
"for await (const { messages } of stream) {\n",
" let msg = messages[messages?.length - 1];\n",
" if (msg?.content) {\n",
" console.log(msg.content);\n",
Expand Down
10 changes: 4 additions & 6 deletions examples/how-tos/dynamically-returning-directly.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,9 @@
"id": "f443c375",
"metadata": {},
"source": [
"We can now wrap these tools in a simple ToolExecutor.\\\n",
"This is a real simple class that takes in a ToolInvocation and calls that tool,\n",
"returning the output. A ToolInvocation is any type with `tool` and `toolInput`\n",
"attribute.\n"
"We can now wrap these tools in a `ToolNode`.\n",
"This is a prebuilt node that takes in a LangChain chat model's generated tool call and calls that tool,\n",
"returning the output."
]
},
{
Expand All @@ -133,9 +132,8 @@
"outputs": [],
"source": [
"import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n",
"import { BaseMessage } from \"@langchain/core/messages\";\n",
"\n",
"const toolNode = new ToolNode<{ messages: BaseMessage[] }>(tools);"
"const toolNode = new ToolNode(tools);"
]
},
{
Expand Down
9 changes: 4 additions & 5 deletions examples/how-tos/force-calling-a-tool-first.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@
"id": "8aa4e65a",
"metadata": {},
"source": [
"We can now wrap these tools in a simple ToolExecutor. This is a real simple\n",
"class that takes in a ToolInvocation and calls that tool, returning the output.\n",
"A ToolInvocation is any type with `tool` and `toolInput` attribute."
"We can now wrap these tools in a `ToolNode`.\n",
"This is a prebuilt node that takes in a LangChain chat model's generated tool call and calls that tool,\n",
"returning the output."
]
},
{
Expand All @@ -124,9 +124,8 @@
"outputs": [],
"source": [
"import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n",
"import { BaseMessage } from \"@langchain/core/messages\";\n",
"\n",
"const toolNode = new ToolNode<{ messages: BaseMessage[] }>(tools);"
"const toolNode = new ToolNode(tools);"
]
},
{
Expand Down
35 changes: 16 additions & 19 deletions examples/how-tos/tool-calling.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -318,31 +318,28 @@
"const toolNodeForGraph = new ToolNode(tools)\n",
"\n",
"const shouldContinue = (state: typeof MessagesAnnotation.State) => {\n",
" const { messages } = state;\n",
" const lastMessage = messages[messages.length - 1];\n",
" if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n",
" return \"tools\";\n",
" }\n",
" return END;\n",
" const { messages } = state;\n",
" const lastMessage = messages[messages.length - 1];\n",
" if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n",
" return \"tools\";\n",
" }\n",
" return END;\n",
"}\n",
"\n",
"const callModel = async (state: typeof MessagesAnnotation.State) => {\n",
" const { messages } = state;\n",
" const response = await modelWithTools.invoke(messages);\n",
" return { messages: [response] };\n",
" const { messages } = state;\n",
" const response = await modelWithTools.invoke(messages);\n",
" return { messages: response };\n",
"}\n",
"\n",
"\n",
"const workflow = new StateGraph(MessagesAnnotation)\n",
" // Define the two nodes we will cycle between\n",
" .addNode(\"agent\", callModel)\n",
" .addNode(\"tools\", toolNodeForGraph)\n",
" .addEdge(START, \"agent\")\n",
" .addConditionalEdges(\n",
" \"agent\",\n",
" shouldContinue,\n",
" )\n",
" .addEdge(\"tools\", \"agent\");\n",
" // Define the two nodes we will cycle between\n",
" .addNode(\"agent\", callModel)\n",
" .addNode(\"tools\", toolNodeForGraph)\n",
" .addEdge(START, \"agent\")\n",
" .addConditionalEdges(\"agent\", shouldContinue, [\"tools\", END])\n",
" .addEdge(\"tools\", \"agent\");\n",
"\n",
"const app = workflow.compile()"
]
Expand Down Expand Up @@ -574,7 +571,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"`ToolNode` can also handle errors during tool execution. See our guide on handling errors in `ToolNode` [here](/langgraphjs/how-tos/tool-calling-errors/)"
"`ToolNode` can also handle errors during tool execution. See our guide on handling errors in `ToolNode` [here](/langgraphjs/how-tos/tool-calling-errors/)."
]
}
],
Expand Down
59 changes: 49 additions & 10 deletions libs/langgraph/src/prebuilt/react_agent_executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,57 @@ export type CreateReactAgentParams = {
};

/**
* Creates a StateGraph agent that relies on a chat llm utilizing tool calling.
* @param llm The chat llm that can utilize OpenAI-style function calling.
* @param tools A list of tools or a ToolNode.
* @param messageModifier An optional message modifier to apply to messages before being passed to the LLM.
* Creates a StateGraph agent that relies on a chat model utilizing tool calling.
* @param params.llm The chat model that can utilize OpenAI-style tool calling.
* @param params.tools A list of tools or a ToolNode.
* @param params.messageModifier An optional message modifier to apply to messages before being passed to the LLM.
* Can be a SystemMessage, string, function that takes and returns a list of messages, or a Runnable.
* @param checkpointSaver An optional checkpoint saver to persist the agent's state.
* @param interruptBefore An optional list of node names to interrupt before running.
* @param interruptAfter An optional list of node names to interrupt after running.
* @returns A compiled agent as a LangChain Runnable.
* @param params.checkpointer An optional checkpoint saver to persist the agent's state.
* @param params.interruptBefore An optional list of node names to interrupt before running.
* @param params.interruptAfter An optional list of node names to interrupt after running.
* @returns A prebuilt compiled graph.
*
* @example
* ```ts
* import { ChatOpenAI } from "@langchain/openai";
* import { tool } from "@langchain/core/tools";
* import { z } from "zod";
* import { createReactAgent } from "@langchain/langgraph/prebuilt";
*
* const model = new ChatOpenAI({
* model: "gpt-4o",
* });
*
* const getWeather = tool((input) => {
* if (["sf", "san francisco"].includes(input.location.toLowerCase())) {
* return "It's 60 degrees and foggy.";
* } else {
* return "It's 90 degrees and sunny.";
* }
* }, {
* name: "get_weather",
* description: "Call to get the current weather.",
* schema: z.object({
* location: z.string().describe("Location to get the weather for."),
* })
* })
*
* const agent = createReactAgent({ llm: model, tools: [getWeather] });
*
* const inputs = {
* messages: [{ role: "user", content: "what is the weather in SF?" }],
* };
*
* const stream = await agent.stream(inputs, { streamMode: "values" });
*
* for await (const { messages } of stream) {
* console.log(messages);
* }
* // Returns the messages in the state at each step of execution
* ```
*/
export function createReactAgent(
props: CreateReactAgentParams
params: CreateReactAgentParams
): CompiledStateGraph<
AgentState,
Partial<AgentState>,
Expand All @@ -82,7 +121,7 @@ export function createReactAgent(
checkpointSaver,
interruptBefore,
interruptAfter,
} = props;
} = params;
const schema: StateGraphArgs<AgentState>["channels"] = {
messages: {
value: messagesStateReducer,
Expand Down
2 changes: 2 additions & 0 deletions libs/langgraph/src/prebuilt/tool_executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { StructuredToolInterface } from "@langchain/core/tools";

const INVALID_TOOL_MSG_TEMPLATE = `{requestedToolName} is not a valid tool, try one of {availableToolNamesString}.`;

/** @deprecated Use {@link ToolNode} instead. */
export interface ToolExecutorArgs {
tools: Array<StructuredToolInterface | RunnableToolLike>;
/**
Expand All @@ -30,6 +31,7 @@ type ToolExecutorInputType = any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ToolExecutorOutputType = any;

/** @deprecated Use {@link ToolNode} instead. */
export class ToolExecutor extends RunnableBinding<
ToolExecutorInputType,
ToolExecutorOutputType
Expand Down
Loading

0 comments on commit f9102fd

Please sign in to comment.