@langchain/langgraph 0.2.40 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -154
- package/dist/channels/any_value.cjs +10 -10
- package/dist/channels/any_value.d.ts +1 -1
- package/dist/channels/any_value.js +10 -10
- package/dist/channels/ephemeral_value.cjs +10 -9
- package/dist/channels/ephemeral_value.d.ts +1 -1
- package/dist/channels/ephemeral_value.js +10 -9
- package/dist/channels/last_value.cjs +8 -7
- package/dist/channels/last_value.d.ts +1 -1
- package/dist/channels/last_value.js +8 -7
- package/dist/constants.cjs +33 -6
- package/dist/constants.d.ts +17 -2
- package/dist/constants.js +32 -5
- package/dist/errors.d.ts +3 -3
- package/dist/func/index.cjs +272 -0
- package/dist/func/index.d.ts +310 -0
- package/dist/func/index.js +267 -0
- package/dist/func/types.cjs +15 -0
- package/dist/func/types.d.ts +59 -0
- package/dist/func/types.js +11 -0
- package/dist/graph/graph.cjs +31 -35
- package/dist/graph/graph.d.ts +1 -5
- package/dist/graph/graph.js +1 -5
- package/dist/graph/index.cjs +1 -3
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/index.js +1 -1
- package/dist/graph/message.d.ts +1 -1
- package/dist/graph/state.cjs +17 -17
- package/dist/graph/state.d.ts +2 -1
- package/dist/graph/state.js +2 -2
- package/dist/index.cjs +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/interrupt.cjs +21 -34
- package/dist/interrupt.d.ts +1 -1
- package/dist/interrupt.js +22 -35
- package/dist/prebuilt/agent_executor.cjs +3 -3
- package/dist/prebuilt/agent_executor.d.ts +1 -1
- package/dist/prebuilt/agent_executor.js +1 -1
- package/dist/prebuilt/chat_agent_executor.cjs +3 -3
- package/dist/prebuilt/chat_agent_executor.d.ts +1 -1
- package/dist/prebuilt/chat_agent_executor.js +1 -1
- package/dist/prebuilt/react_agent_executor.cjs +79 -12
- package/dist/prebuilt/react_agent_executor.d.ts +35 -4
- package/dist/prebuilt/react_agent_executor.js +79 -13
- package/dist/prebuilt/tool_node.cjs +1 -2
- package/dist/prebuilt/tool_node.d.ts +1 -1
- package/dist/prebuilt/tool_node.js +1 -2
- package/dist/pregel/algo.cjs +121 -12
- package/dist/pregel/algo.d.ts +8 -6
- package/dist/pregel/algo.js +122 -13
- package/dist/pregel/call.cjs +77 -0
- package/dist/pregel/call.d.ts +15 -0
- package/dist/pregel/call.js +71 -0
- package/dist/pregel/index.cjs +59 -96
- package/dist/pregel/index.d.ts +1 -10
- package/dist/pregel/index.js +61 -98
- package/dist/pregel/io.cjs +6 -1
- package/dist/pregel/io.js +7 -2
- package/dist/pregel/loop.cjs +109 -75
- package/dist/pregel/loop.d.ts +17 -23
- package/dist/pregel/loop.js +110 -75
- package/dist/pregel/messages.d.ts +1 -1
- package/dist/pregel/retry.cjs +22 -50
- package/dist/pregel/retry.d.ts +6 -6
- package/dist/pregel/retry.js +22 -50
- package/dist/pregel/runner.cjs +275 -0
- package/dist/pregel/runner.d.ts +64 -0
- package/dist/pregel/runner.js +271 -0
- package/dist/pregel/stream.cjs +71 -0
- package/dist/pregel/stream.d.ts +17 -0
- package/dist/pregel/stream.js +67 -0
- package/dist/pregel/types.cjs +54 -0
- package/dist/pregel/types.d.ts +78 -6
- package/dist/pregel/types.js +51 -1
- package/dist/pregel/utils/config.cjs +26 -1
- package/dist/pregel/utils/config.d.ts +14 -0
- package/dist/pregel/utils/config.js +22 -0
- package/dist/pregel/write.d.ts +1 -1
- package/dist/utils.cjs +15 -1
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +12 -0
- package/dist/web.cjs +7 -5
- package/dist/web.d.ts +4 -4
- package/dist/web.js +3 -3
- package/package.json +8 -8
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createAgentExecutor = void 0;
|
|
4
4
|
const tool_executor_js_1 = require("./tool_executor.cjs");
|
|
5
5
|
const state_js_1 = require("../graph/state.cjs");
|
|
6
|
-
const
|
|
6
|
+
const constants_js_1 = require("../constants.cjs");
|
|
7
7
|
/** @ignore */
|
|
8
8
|
function createAgentExecutor({ agentRunnable, tools, }) {
|
|
9
9
|
let toolExecutor;
|
|
@@ -54,7 +54,7 @@ function createAgentExecutor({ agentRunnable, tools, }) {
|
|
|
54
54
|
.addNode("action", executeTools)
|
|
55
55
|
// Set the entrypoint as `agent`
|
|
56
56
|
// This means that this node is the first one called
|
|
57
|
-
.addEdge(
|
|
57
|
+
.addEdge(constants_js_1.START, "agent")
|
|
58
58
|
// We now add a conditional edge
|
|
59
59
|
.addConditionalEdges(
|
|
60
60
|
// First, we define the start node. We use `agent`.
|
|
@@ -72,7 +72,7 @@ function createAgentExecutor({ agentRunnable, tools, }) {
|
|
|
72
72
|
// If `tools`, then we call the tool node.
|
|
73
73
|
continue: "action",
|
|
74
74
|
// Otherwise we finish.
|
|
75
|
-
end:
|
|
75
|
+
end: constants_js_1.END,
|
|
76
76
|
})
|
|
77
77
|
// We now add a normal edge from `tools` to `agent`.
|
|
78
78
|
// This means that after `tools` is called, `agent` node is called next.
|
|
@@ -18,5 +18,5 @@ export interface AgentExecutorState {
|
|
|
18
18
|
export declare function createAgentExecutor({ agentRunnable, tools, }: {
|
|
19
19
|
agentRunnable: Runnable;
|
|
20
20
|
tools: Array<Tool> | ToolExecutor;
|
|
21
|
-
}): import("../graph/state.js").CompiledStateGraph<AgentExecutorState, Partial<AgentExecutorState>, "__start__" | "agent" | "action", import("../
|
|
21
|
+
}): import("../graph/state.js").CompiledStateGraph<AgentExecutorState, Partial<AgentExecutorState>, "__start__" | "agent" | "action", import("../web.js").StateDefinition, import("../web.js").StateDefinition, import("../web.js").StateDefinition>;
|
|
22
22
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolExecutor } from "./tool_executor.js";
|
|
2
2
|
import { StateGraph } from "../graph/state.js";
|
|
3
|
-
import { END, START } from "../
|
|
3
|
+
import { END, START } from "../constants.js";
|
|
4
4
|
/** @ignore */
|
|
5
5
|
export function createAgentExecutor({ agentRunnable, tools, }) {
|
|
6
6
|
let toolExecutor;
|
|
@@ -6,7 +6,7 @@ const messages_1 = require("@langchain/core/messages");
|
|
|
6
6
|
const runnables_1 = require("@langchain/core/runnables");
|
|
7
7
|
const tool_executor_js_1 = require("./tool_executor.cjs");
|
|
8
8
|
const state_js_1 = require("../graph/state.cjs");
|
|
9
|
-
const
|
|
9
|
+
const constants_js_1 = require("../constants.cjs");
|
|
10
10
|
/** @deprecated Use {@link createReactAgent} instead with tool calling. */
|
|
11
11
|
function createFunctionCallingExecutor({ model, tools, }) {
|
|
12
12
|
let toolExecutor;
|
|
@@ -99,7 +99,7 @@ function createFunctionCallingExecutor({ model, tools, }) {
|
|
|
99
99
|
.addNode("action", new runnables_1.RunnableLambda({ func: callTool }))
|
|
100
100
|
// Set the entrypoint as `agent`
|
|
101
101
|
// This means that this node is the first one called
|
|
102
|
-
.addEdge(
|
|
102
|
+
.addEdge(constants_js_1.START, "agent")
|
|
103
103
|
// We now add a conditional edge
|
|
104
104
|
.addConditionalEdges(
|
|
105
105
|
// First, we define the start node. We use `agent`.
|
|
@@ -117,7 +117,7 @@ function createFunctionCallingExecutor({ model, tools, }) {
|
|
|
117
117
|
// If `tools`, then we call the tool node.
|
|
118
118
|
continue: "action",
|
|
119
119
|
// Otherwise we finish.
|
|
120
|
-
end:
|
|
120
|
+
end: constants_js_1.END,
|
|
121
121
|
})
|
|
122
122
|
// We now add a normal edge from `tools` to `agent`.
|
|
123
123
|
// This means that after `tools` is called, `agent` node is called next.
|
|
@@ -3,7 +3,7 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
3
3
|
import { RunnableToolLike } from "@langchain/core/runnables";
|
|
4
4
|
import { ToolExecutor } from "./tool_executor.js";
|
|
5
5
|
import { CompiledStateGraph } from "../graph/state.js";
|
|
6
|
-
import { START } from "../
|
|
6
|
+
import { START } from "../constants.js";
|
|
7
7
|
/** @deprecated Use {@link createReactAgent} instead with tool calling. */
|
|
8
8
|
export type FunctionCallingExecutorState = {
|
|
9
9
|
messages: Array<BaseMessage>;
|
|
@@ -3,7 +3,7 @@ import { FunctionMessage } from "@langchain/core/messages";
|
|
|
3
3
|
import { RunnableLambda, } from "@langchain/core/runnables";
|
|
4
4
|
import { ToolExecutor } from "./tool_executor.js";
|
|
5
5
|
import { StateGraph, } from "../graph/state.js";
|
|
6
|
-
import { END, START } from "../
|
|
6
|
+
import { END, START } from "../constants.js";
|
|
7
7
|
/** @deprecated Use {@link createReactAgent} instead with tool calling. */
|
|
8
8
|
export function createFunctionCallingExecutor({ model, tools, }) {
|
|
9
9
|
let toolExecutor;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createReactAgent = void 0;
|
|
3
|
+
exports.createReactAgent = exports.createReactAgentAnnotation = void 0;
|
|
4
4
|
const messages_1 = require("@langchain/core/messages");
|
|
5
5
|
const runnables_1 = require("@langchain/core/runnables");
|
|
6
6
|
const index_js_1 = require("../graph/index.cjs");
|
|
7
|
-
const messages_annotation_js_1 = require("../graph/messages_annotation.cjs");
|
|
8
7
|
const tool_node_js_1 = require("./tool_node.cjs");
|
|
8
|
+
const annotation_js_1 = require("../graph/annotation.cjs");
|
|
9
|
+
const message_js_1 = require("../graph/message.cjs");
|
|
10
|
+
const constants_js_1 = require("../constants.cjs");
|
|
9
11
|
function _convertMessageModifierToStateModifier(messageModifier) {
|
|
10
12
|
// Handle string or SystemMessage
|
|
11
13
|
if (typeof messageModifier === "string" ||
|
|
@@ -65,6 +67,14 @@ function _getModelPreprocessingRunnable(stateModifier, messageModifier) {
|
|
|
65
67
|
}
|
|
66
68
|
return _getStateModifierRunnable(stateModifier);
|
|
67
69
|
}
|
|
70
|
+
const createReactAgentAnnotation = () => annotation_js_1.Annotation.Root({
|
|
71
|
+
messages: (0, annotation_js_1.Annotation)({
|
|
72
|
+
reducer: message_js_1.messagesStateReducer,
|
|
73
|
+
default: () => [],
|
|
74
|
+
}),
|
|
75
|
+
structuredResponse: (annotation_js_1.Annotation),
|
|
76
|
+
});
|
|
77
|
+
exports.createReactAgentAnnotation = createReactAgentAnnotation;
|
|
68
78
|
/**
|
|
69
79
|
* Creates a StateGraph agent that relies on a chat model utilizing tool calling.
|
|
70
80
|
*
|
|
@@ -108,7 +118,7 @@ function _getModelPreprocessingRunnable(stateModifier, messageModifier) {
|
|
|
108
118
|
* ```
|
|
109
119
|
*/
|
|
110
120
|
function createReactAgent(params) {
|
|
111
|
-
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, interruptBefore, interruptAfter, store, } = params;
|
|
121
|
+
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, } = params;
|
|
112
122
|
let toolClasses;
|
|
113
123
|
if (!Array.isArray(tools)) {
|
|
114
124
|
toolClasses = tools.tools;
|
|
@@ -123,32 +133,89 @@ function createReactAgent(params) {
|
|
|
123
133
|
// we're passing store here for validation
|
|
124
134
|
const preprocessor = _getModelPreprocessingRunnable(stateModifier, messageModifier);
|
|
125
135
|
const modelRunnable = preprocessor.pipe(modelWithTools);
|
|
136
|
+
// If any of the tools are configured to return_directly after running,
|
|
137
|
+
// our graph needs to check if these were called
|
|
138
|
+
const shouldReturnDirect = new Set(toolClasses
|
|
139
|
+
.filter((tool) => "returnDirect" in tool && tool.returnDirect)
|
|
140
|
+
.map((tool) => tool.name));
|
|
126
141
|
const shouldContinue = (state) => {
|
|
127
142
|
const { messages } = state;
|
|
128
143
|
const lastMessage = messages[messages.length - 1];
|
|
129
144
|
if ((0, messages_1.isAIMessage)(lastMessage) &&
|
|
130
145
|
(!lastMessage.tool_calls || lastMessage.tool_calls.length === 0)) {
|
|
131
|
-
return
|
|
146
|
+
return responseFormat != null ? "generate_structured_response" : constants_js_1.END;
|
|
132
147
|
}
|
|
133
148
|
else {
|
|
134
149
|
return "continue";
|
|
135
150
|
}
|
|
136
151
|
};
|
|
152
|
+
const generateStructuredResponse = async (state, config) => {
|
|
153
|
+
if (responseFormat == null) {
|
|
154
|
+
throw new Error("Attempted to generate structured output with no passed response schema. Please contact us for help.");
|
|
155
|
+
}
|
|
156
|
+
// Exclude the last message as there's enough information
|
|
157
|
+
// for the LLM to generate the structured response
|
|
158
|
+
const messages = state.messages.slice(0, -1);
|
|
159
|
+
let modelWithStructuredOutput;
|
|
160
|
+
if (typeof responseFormat === "object" &&
|
|
161
|
+
"prompt" in responseFormat &&
|
|
162
|
+
"schema" in responseFormat) {
|
|
163
|
+
const { prompt, schema } = responseFormat;
|
|
164
|
+
modelWithStructuredOutput = llm.withStructuredOutput(schema);
|
|
165
|
+
messages.unshift(new messages_1.SystemMessage({ content: prompt }));
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
modelWithStructuredOutput = llm.withStructuredOutput(responseFormat);
|
|
169
|
+
}
|
|
170
|
+
const response = await modelWithStructuredOutput.invoke(messages, config);
|
|
171
|
+
return { structuredResponse: response };
|
|
172
|
+
};
|
|
137
173
|
const callModel = async (state, config) => {
|
|
138
174
|
// TODO: Auto-promote streaming.
|
|
139
175
|
return { messages: [await modelRunnable.invoke(state, config)] };
|
|
140
176
|
};
|
|
141
|
-
const workflow = new index_js_1.StateGraph(stateSchema ??
|
|
177
|
+
const workflow = new index_js_1.StateGraph(stateSchema ?? (0, exports.createReactAgentAnnotation)())
|
|
142
178
|
.addNode("agent", callModel)
|
|
143
179
|
.addNode("tools", new tool_node_js_1.ToolNode(toolClasses))
|
|
144
|
-
.addEdge(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
180
|
+
.addEdge(constants_js_1.START, "agent");
|
|
181
|
+
if (responseFormat !== undefined) {
|
|
182
|
+
workflow
|
|
183
|
+
.addNode("generate_structured_response", generateStructuredResponse)
|
|
184
|
+
.addEdge("generate_structured_response", constants_js_1.END)
|
|
185
|
+
.addConditionalEdges("agent", shouldContinue, {
|
|
186
|
+
continue: "tools",
|
|
187
|
+
[constants_js_1.END]: constants_js_1.END,
|
|
188
|
+
generate_structured_response: "generate_structured_response",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
workflow.addConditionalEdges("agent", shouldContinue, {
|
|
193
|
+
continue: "tools",
|
|
194
|
+
[constants_js_1.END]: constants_js_1.END,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const routeToolResponses = (state) => {
|
|
198
|
+
// Check the last consecutive tool calls
|
|
199
|
+
for (let i = state.messages.length - 1; i >= 0; i -= 1) {
|
|
200
|
+
const message = state.messages[i];
|
|
201
|
+
if (!(0, messages_1.isToolMessage)(message)) {
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
// Check if this tool is configured to return directly
|
|
205
|
+
if (message.name !== undefined && shouldReturnDirect.has(message.name)) {
|
|
206
|
+
return constants_js_1.END;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return "agent";
|
|
210
|
+
};
|
|
211
|
+
if (shouldReturnDirect.size > 0) {
|
|
212
|
+
workflow.addConditionalEdges("tools", routeToolResponses, ["agent", constants_js_1.END]);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
workflow.addEdge("tools", "agent");
|
|
216
|
+
}
|
|
150
217
|
return workflow.compile({
|
|
151
|
-
checkpointer: checkpointSaver,
|
|
218
|
+
checkpointer: checkpointer ?? checkpointSaver,
|
|
152
219
|
interruptBefore,
|
|
153
220
|
interruptAfter,
|
|
154
221
|
store,
|
|
@@ -3,18 +3,34 @@ import { BaseMessage, BaseMessageLike, SystemMessage } from "@langchain/core/mes
|
|
|
3
3
|
import { Runnable, RunnableToolLike } from "@langchain/core/runnables";
|
|
4
4
|
import { StructuredToolInterface } from "@langchain/core/tools";
|
|
5
5
|
import { All, BaseCheckpointSaver, BaseStore } from "@langchain/langgraph-checkpoint";
|
|
6
|
-
import {
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { CompiledStateGraph, AnnotationRoot } from "../graph/index.js";
|
|
7
8
|
import { MessagesAnnotation } from "../graph/messages_annotation.js";
|
|
8
9
|
import { ToolNode } from "./tool_node.js";
|
|
9
10
|
import { LangGraphRunnableConfig } from "../pregel/runnable_types.js";
|
|
10
|
-
|
|
11
|
+
import { Messages } from "../graph/message.js";
|
|
12
|
+
import { START } from "../constants.js";
|
|
13
|
+
export interface AgentState<StructuredResponseType extends Record<string, any> = Record<string, any>> {
|
|
11
14
|
messages: BaseMessage[];
|
|
15
|
+
structuredResponse: StructuredResponseType;
|
|
12
16
|
}
|
|
13
17
|
export type N = typeof START | "agent" | "tools";
|
|
18
|
+
export type StructuredResponseSchemaAndPrompt<StructuredResponseType> = {
|
|
19
|
+
prompt: string;
|
|
20
|
+
schema: z.ZodType<StructuredResponseType> | Record<string, any>;
|
|
21
|
+
};
|
|
14
22
|
export type StateModifier = SystemMessage | string | ((state: typeof MessagesAnnotation.State, config: LangGraphRunnableConfig) => BaseMessageLike[]) | ((state: typeof MessagesAnnotation.State, config: LangGraphRunnableConfig) => Promise<BaseMessageLike[]>) | Runnable;
|
|
15
23
|
/** @deprecated Use StateModifier instead. */
|
|
16
24
|
export type MessageModifier = SystemMessage | string | ((messages: BaseMessage[]) => BaseMessage[]) | ((messages: BaseMessage[]) => Promise<BaseMessage[]>) | Runnable;
|
|
17
|
-
export
|
|
25
|
+
export declare const createReactAgentAnnotation: <T extends Record<string, any> = Record<string, any>>() => AnnotationRoot<{
|
|
26
|
+
messages: import("../web.js").BinaryOperatorAggregate<BaseMessage[], Messages>;
|
|
27
|
+
structuredResponse: {
|
|
28
|
+
(): import("../web.js").LastValue<T>;
|
|
29
|
+
(annotation: import("../graph/annotation.js").SingleReducer<T, T>): import("../web.js").BinaryOperatorAggregate<T, T>;
|
|
30
|
+
Root: <S extends import("../graph/annotation.js").StateDefinition>(sd: S) => AnnotationRoot<S>;
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
33
|
+
export type CreateReactAgentParams<A extends AnnotationRoot<any> = AnnotationRoot<any>, StructuredResponseType = Record<string, any>> = {
|
|
18
34
|
/** The chat model that can utilize OpenAI-style tool calling. */
|
|
19
35
|
llm: BaseChatModel;
|
|
20
36
|
/** A list of tools or a ToolNode. */
|
|
@@ -76,11 +92,26 @@ export type CreateReactAgentParams<A extends AnnotationRoot<any> = AnnotationRoo
|
|
|
76
92
|
stateSchema?: A;
|
|
77
93
|
/** An optional checkpoint saver to persist the agent's state. */
|
|
78
94
|
checkpointSaver?: BaseCheckpointSaver;
|
|
95
|
+
/** An optional checkpoint saver to persist the agent's state. Alias of "checkpointSaver". */
|
|
96
|
+
checkpointer?: BaseCheckpointSaver;
|
|
79
97
|
/** An optional list of node names to interrupt before running. */
|
|
80
98
|
interruptBefore?: N[] | All;
|
|
81
99
|
/** An optional list of node names to interrupt after running. */
|
|
82
100
|
interruptAfter?: N[] | All;
|
|
83
101
|
store?: BaseStore;
|
|
102
|
+
/**
|
|
103
|
+
* An optional schema for the final agent output.
|
|
104
|
+
*
|
|
105
|
+
* If provided, output will be formatted to match the given schema and returned in the 'structured_response' state key.
|
|
106
|
+
* If not provided, `structured_response` will not be present in the output state.
|
|
107
|
+
*
|
|
108
|
+
* Can be passed in as:
|
|
109
|
+
* - Zod schema
|
|
110
|
+
* - Dictionary object
|
|
111
|
+
* - [prompt, schema], where schema is one of the above.
|
|
112
|
+
* The prompt will be used together with the model that is being used to generate the structured response.
|
|
113
|
+
*/
|
|
114
|
+
responseFormat?: z.ZodType<StructuredResponseType> | StructuredResponseSchemaAndPrompt<StructuredResponseType> | Record<string, any>;
|
|
84
115
|
};
|
|
85
116
|
/**
|
|
86
117
|
* Creates a StateGraph agent that relies on a chat model utilizing tool calling.
|
|
@@ -124,4 +155,4 @@ export type CreateReactAgentParams<A extends AnnotationRoot<any> = AnnotationRoo
|
|
|
124
155
|
* // Returns the messages in the state at each step of execution
|
|
125
156
|
* ```
|
|
126
157
|
*/
|
|
127
|
-
export declare function createReactAgent<A extends AnnotationRoot<any> = AnnotationRoot<any>>(params: CreateReactAgentParams<A>): CompiledStateGraph<(typeof MessagesAnnotation)["State"], (typeof MessagesAnnotation)["Update"],
|
|
158
|
+
export declare function createReactAgent<A extends AnnotationRoot<any> = AnnotationRoot<{}>, StructuredResponseFormat extends Record<string, any> = Record<string, any>>(params: CreateReactAgentParams<A, StructuredResponseFormat>): CompiledStateGraph<(typeof MessagesAnnotation)["State"], (typeof MessagesAnnotation)["Update"], any, typeof MessagesAnnotation.spec & A["spec"], ReturnType<typeof createReactAgentAnnotation<StructuredResponseFormat>>["spec"] & A["spec"]>;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { isAIMessage, isBaseMessage, SystemMessage, } from "@langchain/core/messages";
|
|
1
|
+
import { isAIMessage, isBaseMessage, isToolMessage, SystemMessage, } from "@langchain/core/messages";
|
|
2
2
|
import { Runnable, RunnableLambda, } from "@langchain/core/runnables";
|
|
3
|
-
import {
|
|
4
|
-
import { MessagesAnnotation } from "../graph/messages_annotation.js";
|
|
3
|
+
import { StateGraph, } from "../graph/index.js";
|
|
5
4
|
import { ToolNode } from "./tool_node.js";
|
|
5
|
+
import { Annotation } from "../graph/annotation.js";
|
|
6
|
+
import { messagesStateReducer } from "../graph/message.js";
|
|
7
|
+
import { END, START } from "../constants.js";
|
|
6
8
|
function _convertMessageModifierToStateModifier(messageModifier) {
|
|
7
9
|
// Handle string or SystemMessage
|
|
8
10
|
if (typeof messageModifier === "string" ||
|
|
@@ -62,6 +64,13 @@ function _getModelPreprocessingRunnable(stateModifier, messageModifier) {
|
|
|
62
64
|
}
|
|
63
65
|
return _getStateModifierRunnable(stateModifier);
|
|
64
66
|
}
|
|
67
|
+
export const createReactAgentAnnotation = () => Annotation.Root({
|
|
68
|
+
messages: Annotation({
|
|
69
|
+
reducer: messagesStateReducer,
|
|
70
|
+
default: () => [],
|
|
71
|
+
}),
|
|
72
|
+
structuredResponse: (Annotation),
|
|
73
|
+
});
|
|
65
74
|
/**
|
|
66
75
|
* Creates a StateGraph agent that relies on a chat model utilizing tool calling.
|
|
67
76
|
*
|
|
@@ -105,7 +114,7 @@ function _getModelPreprocessingRunnable(stateModifier, messageModifier) {
|
|
|
105
114
|
* ```
|
|
106
115
|
*/
|
|
107
116
|
export function createReactAgent(params) {
|
|
108
|
-
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, interruptBefore, interruptAfter, store, } = params;
|
|
117
|
+
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, } = params;
|
|
109
118
|
let toolClasses;
|
|
110
119
|
if (!Array.isArray(tools)) {
|
|
111
120
|
toolClasses = tools.tools;
|
|
@@ -120,32 +129,89 @@ export function createReactAgent(params) {
|
|
|
120
129
|
// we're passing store here for validation
|
|
121
130
|
const preprocessor = _getModelPreprocessingRunnable(stateModifier, messageModifier);
|
|
122
131
|
const modelRunnable = preprocessor.pipe(modelWithTools);
|
|
132
|
+
// If any of the tools are configured to return_directly after running,
|
|
133
|
+
// our graph needs to check if these were called
|
|
134
|
+
const shouldReturnDirect = new Set(toolClasses
|
|
135
|
+
.filter((tool) => "returnDirect" in tool && tool.returnDirect)
|
|
136
|
+
.map((tool) => tool.name));
|
|
123
137
|
const shouldContinue = (state) => {
|
|
124
138
|
const { messages } = state;
|
|
125
139
|
const lastMessage = messages[messages.length - 1];
|
|
126
140
|
if (isAIMessage(lastMessage) &&
|
|
127
141
|
(!lastMessage.tool_calls || lastMessage.tool_calls.length === 0)) {
|
|
128
|
-
return END;
|
|
142
|
+
return responseFormat != null ? "generate_structured_response" : END;
|
|
129
143
|
}
|
|
130
144
|
else {
|
|
131
145
|
return "continue";
|
|
132
146
|
}
|
|
133
147
|
};
|
|
148
|
+
const generateStructuredResponse = async (state, config) => {
|
|
149
|
+
if (responseFormat == null) {
|
|
150
|
+
throw new Error("Attempted to generate structured output with no passed response schema. Please contact us for help.");
|
|
151
|
+
}
|
|
152
|
+
// Exclude the last message as there's enough information
|
|
153
|
+
// for the LLM to generate the structured response
|
|
154
|
+
const messages = state.messages.slice(0, -1);
|
|
155
|
+
let modelWithStructuredOutput;
|
|
156
|
+
if (typeof responseFormat === "object" &&
|
|
157
|
+
"prompt" in responseFormat &&
|
|
158
|
+
"schema" in responseFormat) {
|
|
159
|
+
const { prompt, schema } = responseFormat;
|
|
160
|
+
modelWithStructuredOutput = llm.withStructuredOutput(schema);
|
|
161
|
+
messages.unshift(new SystemMessage({ content: prompt }));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
modelWithStructuredOutput = llm.withStructuredOutput(responseFormat);
|
|
165
|
+
}
|
|
166
|
+
const response = await modelWithStructuredOutput.invoke(messages, config);
|
|
167
|
+
return { structuredResponse: response };
|
|
168
|
+
};
|
|
134
169
|
const callModel = async (state, config) => {
|
|
135
170
|
// TODO: Auto-promote streaming.
|
|
136
171
|
return { messages: [await modelRunnable.invoke(state, config)] };
|
|
137
172
|
};
|
|
138
|
-
const workflow = new StateGraph(stateSchema ??
|
|
173
|
+
const workflow = new StateGraph(stateSchema ?? createReactAgentAnnotation())
|
|
139
174
|
.addNode("agent", callModel)
|
|
140
175
|
.addNode("tools", new ToolNode(toolClasses))
|
|
141
|
-
.addEdge(START, "agent")
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
176
|
+
.addEdge(START, "agent");
|
|
177
|
+
if (responseFormat !== undefined) {
|
|
178
|
+
workflow
|
|
179
|
+
.addNode("generate_structured_response", generateStructuredResponse)
|
|
180
|
+
.addEdge("generate_structured_response", END)
|
|
181
|
+
.addConditionalEdges("agent", shouldContinue, {
|
|
182
|
+
continue: "tools",
|
|
183
|
+
[END]: END,
|
|
184
|
+
generate_structured_response: "generate_structured_response",
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
workflow.addConditionalEdges("agent", shouldContinue, {
|
|
189
|
+
continue: "tools",
|
|
190
|
+
[END]: END,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const routeToolResponses = (state) => {
|
|
194
|
+
// Check the last consecutive tool calls
|
|
195
|
+
for (let i = state.messages.length - 1; i >= 0; i -= 1) {
|
|
196
|
+
const message = state.messages[i];
|
|
197
|
+
if (!isToolMessage(message)) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
// Check if this tool is configured to return directly
|
|
201
|
+
if (message.name !== undefined && shouldReturnDirect.has(message.name)) {
|
|
202
|
+
return END;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return "agent";
|
|
206
|
+
};
|
|
207
|
+
if (shouldReturnDirect.size > 0) {
|
|
208
|
+
workflow.addConditionalEdges("tools", routeToolResponses, ["agent", END]);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
workflow.addEdge("tools", "agent");
|
|
212
|
+
}
|
|
147
213
|
return workflow.compile({
|
|
148
|
-
checkpointer: checkpointSaver,
|
|
214
|
+
checkpointer: checkpointer ?? checkpointSaver,
|
|
149
215
|
interruptBefore,
|
|
150
216
|
interruptAfter,
|
|
151
217
|
store,
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.toolsCondition = exports.ToolNode = void 0;
|
|
4
4
|
const messages_1 = require("@langchain/core/messages");
|
|
5
5
|
const utils_js_1 = require("../utils.cjs");
|
|
6
|
-
const graph_js_1 = require("../graph/graph.cjs");
|
|
7
6
|
const errors_js_1 = require("../errors.cjs");
|
|
8
7
|
const constants_js_1 = require("../constants.cjs");
|
|
9
8
|
/**
|
|
@@ -218,7 +217,7 @@ function toolsCondition(state) {
|
|
|
218
217
|
return "tools";
|
|
219
218
|
}
|
|
220
219
|
else {
|
|
221
|
-
return
|
|
220
|
+
return constants_js_1.END;
|
|
222
221
|
}
|
|
223
222
|
}
|
|
224
223
|
exports.toolsCondition = toolsCondition;
|
|
@@ -2,8 +2,8 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
2
2
|
import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
|
|
3
3
|
import { StructuredToolInterface } from "@langchain/core/tools";
|
|
4
4
|
import { RunnableCallable } from "../utils.js";
|
|
5
|
-
import { END } from "../graph/graph.js";
|
|
6
5
|
import { MessagesAnnotation } from "../graph/messages_annotation.js";
|
|
6
|
+
import { END } from "../constants.js";
|
|
7
7
|
export type ToolNodeOptions = {
|
|
8
8
|
name?: string;
|
|
9
9
|
tags?: string[];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ToolMessage, isBaseMessage, } from "@langchain/core/messages";
|
|
2
2
|
import { RunnableCallable } from "../utils.js";
|
|
3
|
-
import { END } from "../graph/graph.js";
|
|
4
3
|
import { isGraphInterrupt } from "../errors.js";
|
|
5
|
-
import { isCommand } from "../constants.js";
|
|
4
|
+
import { END, isCommand } from "../constants.js";
|
|
6
5
|
/**
|
|
7
6
|
* A node that runs the tools requested in the last AIMessage. It can be used
|
|
8
7
|
* either in StateGraph with a "messages" key or in MessageGraph. If multiple
|