@langchain/langgraph 0.0.18 → 0.0.19
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/dist/checkpoint/base.d.ts +1 -1
- package/dist/graph/graph.cjs +5 -30
- package/dist/graph/graph.d.ts +0 -2
- package/dist/graph/graph.js +5 -30
- package/dist/graph/state.cjs +1 -20
- package/dist/graph/state.js +1 -20
- package/dist/prebuilt/react_agent_executor.cjs +8 -7
- package/dist/prebuilt/react_agent_executor.d.ts +11 -3
- package/dist/prebuilt/react_agent_executor.js +8 -7
- package/dist/pregel/index.cjs +1 -1
- package/dist/pregel/index.js +1 -1
- package/dist/pregel/io.cjs +1 -1
- package/dist/pregel/io.d.ts +1 -1
- package/dist/pregel/io.js +1 -1
- package/dist/tests/checkpoints.test.js +4 -3
- package/dist/tests/prebuilt.int.test.js +2 -2
- package/dist/tests/prebuilt.test.js +42 -5
- package/dist/tests/pregel.test.js +39 -67
- package/package.json +2 -1
|
@@ -13,7 +13,7 @@ export interface CheckpointMetadata {
|
|
|
13
13
|
* -1 for the first "input" checkpoint.
|
|
14
14
|
* 0 for the first "loop" checkpoint.
|
|
15
15
|
* ... for the nth checkpoint afterwards. */
|
|
16
|
-
writes
|
|
16
|
+
writes: Record<string, unknown> | null;
|
|
17
17
|
}
|
|
18
18
|
export interface Checkpoint<N extends string = string, C extends string = string> {
|
|
19
19
|
/**
|
package/dist/graph/graph.cjs
CHANGED
|
@@ -25,12 +25,6 @@ class Branch {
|
|
|
25
25
|
writable: true,
|
|
26
26
|
value: void 0
|
|
27
27
|
});
|
|
28
|
-
Object.defineProperty(this, "then", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: void 0
|
|
33
|
-
});
|
|
34
28
|
this.condition = options.path;
|
|
35
29
|
this.ends = Array.isArray(options.pathMap)
|
|
36
30
|
? options.pathMap.reduce((acc, n) => {
|
|
@@ -38,7 +32,6 @@ class Branch {
|
|
|
38
32
|
return acc;
|
|
39
33
|
}, {})
|
|
40
34
|
: options.pathMap;
|
|
41
|
-
this.then = options.then;
|
|
42
35
|
}
|
|
43
36
|
compile(writer, reader) {
|
|
44
37
|
return write_js_1.ChannelWrite.registerWriter(new utils_js_1.RunnableCallable({
|
|
@@ -57,6 +50,9 @@ class Branch {
|
|
|
57
50
|
else {
|
|
58
51
|
destinations = result;
|
|
59
52
|
}
|
|
53
|
+
if (destinations.some((dest) => !dest)) {
|
|
54
|
+
throw new Error("Branch condition returned unknown or null destination");
|
|
55
|
+
}
|
|
60
56
|
return writer(destinations);
|
|
61
57
|
}
|
|
62
58
|
}
|
|
@@ -207,26 +203,8 @@ class Graph {
|
|
|
207
203
|
validate(interrupt) {
|
|
208
204
|
// assemble sources
|
|
209
205
|
const allSources = new Set([...this.allEdges].map(([src, _]) => src));
|
|
210
|
-
for (const [start
|
|
206
|
+
for (const [start] of Object.entries(this.branches)) {
|
|
211
207
|
allSources.add(start);
|
|
212
|
-
for (const branch of Object.values(branches)) {
|
|
213
|
-
if (branch.then) {
|
|
214
|
-
if (branch.ends) {
|
|
215
|
-
for (const end of Object.values(branch.ends)) {
|
|
216
|
-
if (end !== exports.END) {
|
|
217
|
-
allSources.add(end);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
for (const node of Object.keys(this.nodes)) {
|
|
223
|
-
if (node !== start) {
|
|
224
|
-
allSources.add(node);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
208
|
}
|
|
231
209
|
// validate sources
|
|
232
210
|
for (const node of Object.keys(this.nodes)) {
|
|
@@ -243,9 +221,6 @@ class Graph {
|
|
|
243
221
|
const allTargets = new Set([...this.allEdges].map(([_, target]) => target));
|
|
244
222
|
for (const [start, branches] of Object.entries(this.branches)) {
|
|
245
223
|
for (const branch of Object.values(branches)) {
|
|
246
|
-
if (branch.then) {
|
|
247
|
-
allTargets.add(branch.then);
|
|
248
|
-
}
|
|
249
224
|
if (branch.ends) {
|
|
250
225
|
for (const end of Object.values(branch.ends)) {
|
|
251
226
|
allTargets.add(end);
|
|
@@ -254,7 +229,7 @@ class Graph {
|
|
|
254
229
|
else {
|
|
255
230
|
allTargets.add(exports.END);
|
|
256
231
|
for (const node of Object.keys(this.nodes)) {
|
|
257
|
-
if (node !== start
|
|
232
|
+
if (node !== start) {
|
|
258
233
|
allTargets.add(node);
|
|
259
234
|
}
|
|
260
235
|
}
|
package/dist/graph/graph.d.ts
CHANGED
|
@@ -11,12 +11,10 @@ export interface BranchOptions<IO, N extends string> {
|
|
|
11
11
|
source: N;
|
|
12
12
|
path: Branch<IO, N>["condition"];
|
|
13
13
|
pathMap?: Record<string, N | typeof END> | N[];
|
|
14
|
-
then?: N | typeof END;
|
|
15
14
|
}
|
|
16
15
|
export declare class Branch<IO, N extends string> {
|
|
17
16
|
condition: (input: IO, config?: RunnableConfig) => string | string[] | Promise<string> | Promise<string[]>;
|
|
18
17
|
ends?: Record<string, N | typeof END>;
|
|
19
|
-
then?: BranchOptions<IO, N>["then"];
|
|
20
18
|
constructor(options: Omit<BranchOptions<IO, N>, "source">);
|
|
21
19
|
compile(writer: (dests: string[]) => Runnable | undefined, reader?: (config: RunnableConfig) => IO): RunnableCallable<unknown, unknown>;
|
|
22
20
|
_route(input: IO, config: RunnableConfig, writer: (dests: string[]) => Runnable | undefined, reader?: (config: RunnableConfig) => IO): Promise<Runnable | undefined>;
|
package/dist/graph/graph.js
CHANGED
|
@@ -22,12 +22,6 @@ export class Branch {
|
|
|
22
22
|
writable: true,
|
|
23
23
|
value: void 0
|
|
24
24
|
});
|
|
25
|
-
Object.defineProperty(this, "then", {
|
|
26
|
-
enumerable: true,
|
|
27
|
-
configurable: true,
|
|
28
|
-
writable: true,
|
|
29
|
-
value: void 0
|
|
30
|
-
});
|
|
31
25
|
this.condition = options.path;
|
|
32
26
|
this.ends = Array.isArray(options.pathMap)
|
|
33
27
|
? options.pathMap.reduce((acc, n) => {
|
|
@@ -35,7 +29,6 @@ export class Branch {
|
|
|
35
29
|
return acc;
|
|
36
30
|
}, {})
|
|
37
31
|
: options.pathMap;
|
|
38
|
-
this.then = options.then;
|
|
39
32
|
}
|
|
40
33
|
compile(writer, reader) {
|
|
41
34
|
return ChannelWrite.registerWriter(new RunnableCallable({
|
|
@@ -54,6 +47,9 @@ export class Branch {
|
|
|
54
47
|
else {
|
|
55
48
|
destinations = result;
|
|
56
49
|
}
|
|
50
|
+
if (destinations.some((dest) => !dest)) {
|
|
51
|
+
throw new Error("Branch condition returned unknown or null destination");
|
|
52
|
+
}
|
|
57
53
|
return writer(destinations);
|
|
58
54
|
}
|
|
59
55
|
}
|
|
@@ -203,26 +199,8 @@ export class Graph {
|
|
|
203
199
|
validate(interrupt) {
|
|
204
200
|
// assemble sources
|
|
205
201
|
const allSources = new Set([...this.allEdges].map(([src, _]) => src));
|
|
206
|
-
for (const [start
|
|
202
|
+
for (const [start] of Object.entries(this.branches)) {
|
|
207
203
|
allSources.add(start);
|
|
208
|
-
for (const branch of Object.values(branches)) {
|
|
209
|
-
if (branch.then) {
|
|
210
|
-
if (branch.ends) {
|
|
211
|
-
for (const end of Object.values(branch.ends)) {
|
|
212
|
-
if (end !== END) {
|
|
213
|
-
allSources.add(end);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
for (const node of Object.keys(this.nodes)) {
|
|
219
|
-
if (node !== start) {
|
|
220
|
-
allSources.add(node);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
204
|
}
|
|
227
205
|
// validate sources
|
|
228
206
|
for (const node of Object.keys(this.nodes)) {
|
|
@@ -239,9 +217,6 @@ export class Graph {
|
|
|
239
217
|
const allTargets = new Set([...this.allEdges].map(([_, target]) => target));
|
|
240
218
|
for (const [start, branches] of Object.entries(this.branches)) {
|
|
241
219
|
for (const branch of Object.values(branches)) {
|
|
242
|
-
if (branch.then) {
|
|
243
|
-
allTargets.add(branch.then);
|
|
244
|
-
}
|
|
245
220
|
if (branch.ends) {
|
|
246
221
|
for (const end of Object.values(branch.ends)) {
|
|
247
222
|
allTargets.add(end);
|
|
@@ -250,7 +225,7 @@ export class Graph {
|
|
|
250
225
|
else {
|
|
251
226
|
allTargets.add(END);
|
|
252
227
|
for (const node of Object.keys(this.nodes)) {
|
|
253
|
-
if (node !== start
|
|
228
|
+
if (node !== start) {
|
|
254
229
|
allTargets.add(node);
|
|
255
230
|
}
|
|
256
231
|
}
|
package/dist/graph/state.cjs
CHANGED
|
@@ -11,7 +11,6 @@ const ephemeral_value_js_1 = require("../channels/ephemeral_value.cjs");
|
|
|
11
11
|
const utils_js_1 = require("../utils.cjs");
|
|
12
12
|
const constants_js_1 = require("../constants.cjs");
|
|
13
13
|
const errors_js_1 = require("../errors.cjs");
|
|
14
|
-
const dynamic_barrier_value_js_1 = require("../channels/dynamic_barrier_value.cjs");
|
|
15
14
|
const ROOT = "__root__";
|
|
16
15
|
class StateGraph extends graph_js_1.Graph {
|
|
17
16
|
constructor(fields) {
|
|
@@ -241,12 +240,6 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
241
240
|
channel: `branch:${start}:${name}:${dest}`,
|
|
242
241
|
value: start,
|
|
243
242
|
}));
|
|
244
|
-
if (branch.then && branch.then !== graph_js_1.END) {
|
|
245
|
-
writes.push({
|
|
246
|
-
channel: `branch:${start}:${name}:then`,
|
|
247
|
-
value: { __names: filteredDests },
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
243
|
return new write_js_1.ChannelWrite(writes, [constants_js_1.TAG_HIDDEN]);
|
|
251
244
|
},
|
|
252
245
|
// reader
|
|
@@ -254,7 +247,7 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
254
247
|
// attach branch subscribers
|
|
255
248
|
const ends = branch.ends
|
|
256
249
|
? Object.values(branch.ends)
|
|
257
|
-
: Object.keys(this.builder.nodes)
|
|
250
|
+
: Object.keys(this.builder.nodes);
|
|
258
251
|
for (const end of ends) {
|
|
259
252
|
if (end === graph_js_1.END) {
|
|
260
253
|
continue;
|
|
@@ -264,18 +257,6 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
264
257
|
new ephemeral_value_js_1.EphemeralValue();
|
|
265
258
|
this.nodes[end].triggers.push(channelName);
|
|
266
259
|
}
|
|
267
|
-
if (branch.then && branch.then !== graph_js_1.END) {
|
|
268
|
-
const channelName = `branch:${start}:${name}:then`;
|
|
269
|
-
this.channels[channelName] =
|
|
270
|
-
new dynamic_barrier_value_js_1.DynamicBarrierValue();
|
|
271
|
-
this.nodes[branch.then].triggers.push(channelName);
|
|
272
|
-
for (const end of ends) {
|
|
273
|
-
if (end === graph_js_1.END) {
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
this.nodes[end].writers.push(new write_js_1.ChannelWrite([{ channel: channelName, value: end }], [constants_js_1.TAG_HIDDEN]));
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
260
|
}
|
|
280
261
|
}
|
|
281
262
|
exports.CompiledStateGraph = CompiledStateGraph;
|
package/dist/graph/state.js
CHANGED
|
@@ -8,7 +8,6 @@ import { EphemeralValue } from "../channels/ephemeral_value.js";
|
|
|
8
8
|
import { RunnableCallable } from "../utils.js";
|
|
9
9
|
import { TAG_HIDDEN } from "../constants.js";
|
|
10
10
|
import { InvalidUpdateError } from "../errors.js";
|
|
11
|
-
import { DynamicBarrierValue } from "../channels/dynamic_barrier_value.js";
|
|
12
11
|
const ROOT = "__root__";
|
|
13
12
|
export class StateGraph extends Graph {
|
|
14
13
|
constructor(fields) {
|
|
@@ -237,12 +236,6 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
237
236
|
channel: `branch:${start}:${name}:${dest}`,
|
|
238
237
|
value: start,
|
|
239
238
|
}));
|
|
240
|
-
if (branch.then && branch.then !== END) {
|
|
241
|
-
writes.push({
|
|
242
|
-
channel: `branch:${start}:${name}:then`,
|
|
243
|
-
value: { __names: filteredDests },
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
239
|
return new ChannelWrite(writes, [TAG_HIDDEN]);
|
|
247
240
|
},
|
|
248
241
|
// reader
|
|
@@ -250,7 +243,7 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
250
243
|
// attach branch subscribers
|
|
251
244
|
const ends = branch.ends
|
|
252
245
|
? Object.values(branch.ends)
|
|
253
|
-
: Object.keys(this.builder.nodes)
|
|
246
|
+
: Object.keys(this.builder.nodes);
|
|
254
247
|
for (const end of ends) {
|
|
255
248
|
if (end === END) {
|
|
256
249
|
continue;
|
|
@@ -260,17 +253,5 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
260
253
|
new EphemeralValue();
|
|
261
254
|
this.nodes[end].triggers.push(channelName);
|
|
262
255
|
}
|
|
263
|
-
if (branch.then && branch.then !== END) {
|
|
264
|
-
const channelName = `branch:${start}:${name}:then`;
|
|
265
|
-
this.channels[channelName] =
|
|
266
|
-
new DynamicBarrierValue();
|
|
267
|
-
this.nodes[branch.then].triggers.push(channelName);
|
|
268
|
-
for (const end of ends) {
|
|
269
|
-
if (end === END) {
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
this.nodes[end].writers.push(new ChannelWrite([{ channel: channelName, value: end }], [TAG_HIDDEN]));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
256
|
}
|
|
276
257
|
}
|
|
@@ -7,8 +7,8 @@ const prompts_1 = require("@langchain/core/prompts");
|
|
|
7
7
|
const index_js_1 = require("../graph/index.cjs");
|
|
8
8
|
const tool_node_js_1 = require("./tool_node.cjs");
|
|
9
9
|
/**
|
|
10
|
-
* Creates a StateGraph agent that relies on a chat
|
|
11
|
-
* @param
|
|
10
|
+
* Creates a StateGraph agent that relies on a chat llm utilizing tool calling.
|
|
11
|
+
* @param llm The chat llm that can utilize OpenAI-style function calling.
|
|
12
12
|
* @param tools A list of tools or a ToolNode.
|
|
13
13
|
* @param messageModifier An optional message modifier to apply to messages before being passed to the LLM.
|
|
14
14
|
* Can be a SystemMessage, string, function that takes and returns a list of messages, or a Runnable.
|
|
@@ -17,7 +17,8 @@ const tool_node_js_1 = require("./tool_node.cjs");
|
|
|
17
17
|
* @param interruptAfter An optional list of node names to interrupt after running.
|
|
18
18
|
* @returns A compiled agent as a LangChain Runnable.
|
|
19
19
|
*/
|
|
20
|
-
function createReactAgent(
|
|
20
|
+
function createReactAgent(props) {
|
|
21
|
+
const { llm, tools, messageModifier, checkpointSaver, interruptBefore, interruptAfter, } = props;
|
|
21
22
|
const schema = {
|
|
22
23
|
messages: {
|
|
23
24
|
value: (left, right) => left.concat(right),
|
|
@@ -31,10 +32,10 @@ function createReactAgent(model, tools, messageModifier, checkpointSaver, interr
|
|
|
31
32
|
else {
|
|
32
33
|
toolClasses = tools;
|
|
33
34
|
}
|
|
34
|
-
if (!("bindTools" in
|
|
35
|
-
throw new Error(`
|
|
35
|
+
if (!("bindTools" in llm) || typeof llm.bindTools !== "function") {
|
|
36
|
+
throw new Error(`llm ${llm} must define bindTools method.`);
|
|
36
37
|
}
|
|
37
|
-
const modelWithTools =
|
|
38
|
+
const modelWithTools = llm.bindTools(toolClasses);
|
|
38
39
|
const modelRunnable = _createModelWrapper(modelWithTools, messageModifier);
|
|
39
40
|
const shouldContinue = (state) => {
|
|
40
41
|
const { messages } = state;
|
|
@@ -60,7 +61,7 @@ function createReactAgent(model, tools, messageModifier, checkpointSaver, interr
|
|
|
60
61
|
.addEdge(index_js_1.START, "agent")
|
|
61
62
|
.addConditionalEdges("agent", shouldContinue, {
|
|
62
63
|
continue: "tools",
|
|
63
|
-
|
|
64
|
+
[index_js_1.END]: index_js_1.END,
|
|
64
65
|
})
|
|
65
66
|
.addEdge("tools", "agent");
|
|
66
67
|
return workflow.compile({
|
|
@@ -12,9 +12,17 @@ export interface AgentState {
|
|
|
12
12
|
messages: BaseMessage[];
|
|
13
13
|
}
|
|
14
14
|
export type N = typeof START | "agent" | "tools";
|
|
15
|
+
export type CreateReactAgentParams = {
|
|
16
|
+
llm: BaseChatModel;
|
|
17
|
+
tools: ToolNode<MessagesState> | StructuredTool[];
|
|
18
|
+
messageModifier?: SystemMessage | string | ((messages: BaseMessage[]) => BaseMessage[]) | ((messages: BaseMessage[]) => Promise<BaseMessage[]>) | Runnable;
|
|
19
|
+
checkpointSaver?: BaseCheckpointSaver;
|
|
20
|
+
interruptBefore?: N[] | All;
|
|
21
|
+
interruptAfter?: N[] | All;
|
|
22
|
+
};
|
|
15
23
|
/**
|
|
16
|
-
* Creates a StateGraph agent that relies on a chat
|
|
17
|
-
* @param
|
|
24
|
+
* Creates a StateGraph agent that relies on a chat llm utilizing tool calling.
|
|
25
|
+
* @param llm The chat llm that can utilize OpenAI-style function calling.
|
|
18
26
|
* @param tools A list of tools or a ToolNode.
|
|
19
27
|
* @param messageModifier An optional message modifier to apply to messages before being passed to the LLM.
|
|
20
28
|
* Can be a SystemMessage, string, function that takes and returns a list of messages, or a Runnable.
|
|
@@ -23,4 +31,4 @@ export type N = typeof START | "agent" | "tools";
|
|
|
23
31
|
* @param interruptAfter An optional list of node names to interrupt after running.
|
|
24
32
|
* @returns A compiled agent as a LangChain Runnable.
|
|
25
33
|
*/
|
|
26
|
-
export declare function createReactAgent(
|
|
34
|
+
export declare function createReactAgent(props: CreateReactAgentParams): CompiledStateGraph<AgentState, Partial<AgentState>, typeof START | "agent" | "tools">;
|
|
@@ -4,8 +4,8 @@ import { ChatPromptTemplate } from "@langchain/core/prompts";
|
|
|
4
4
|
import { END, START, StateGraph } from "../graph/index.js";
|
|
5
5
|
import { ToolNode } from "./tool_node.js";
|
|
6
6
|
/**
|
|
7
|
-
* Creates a StateGraph agent that relies on a chat
|
|
8
|
-
* @param
|
|
7
|
+
* Creates a StateGraph agent that relies on a chat llm utilizing tool calling.
|
|
8
|
+
* @param llm The chat llm that can utilize OpenAI-style function calling.
|
|
9
9
|
* @param tools A list of tools or a ToolNode.
|
|
10
10
|
* @param messageModifier An optional message modifier to apply to messages before being passed to the LLM.
|
|
11
11
|
* Can be a SystemMessage, string, function that takes and returns a list of messages, or a Runnable.
|
|
@@ -14,7 +14,8 @@ import { ToolNode } from "./tool_node.js";
|
|
|
14
14
|
* @param interruptAfter An optional list of node names to interrupt after running.
|
|
15
15
|
* @returns A compiled agent as a LangChain Runnable.
|
|
16
16
|
*/
|
|
17
|
-
export function createReactAgent(
|
|
17
|
+
export function createReactAgent(props) {
|
|
18
|
+
const { llm, tools, messageModifier, checkpointSaver, interruptBefore, interruptAfter, } = props;
|
|
18
19
|
const schema = {
|
|
19
20
|
messages: {
|
|
20
21
|
value: (left, right) => left.concat(right),
|
|
@@ -28,10 +29,10 @@ export function createReactAgent(model, tools, messageModifier, checkpointSaver,
|
|
|
28
29
|
else {
|
|
29
30
|
toolClasses = tools;
|
|
30
31
|
}
|
|
31
|
-
if (!("bindTools" in
|
|
32
|
-
throw new Error(`
|
|
32
|
+
if (!("bindTools" in llm) || typeof llm.bindTools !== "function") {
|
|
33
|
+
throw new Error(`llm ${llm} must define bindTools method.`);
|
|
33
34
|
}
|
|
34
|
-
const modelWithTools =
|
|
35
|
+
const modelWithTools = llm.bindTools(toolClasses);
|
|
35
36
|
const modelRunnable = _createModelWrapper(modelWithTools, messageModifier);
|
|
36
37
|
const shouldContinue = (state) => {
|
|
37
38
|
const { messages } = state;
|
|
@@ -57,7 +58,7 @@ export function createReactAgent(model, tools, messageModifier, checkpointSaver,
|
|
|
57
58
|
.addEdge(START, "agent")
|
|
58
59
|
.addConditionalEdges("agent", shouldContinue, {
|
|
59
60
|
continue: "tools",
|
|
60
|
-
|
|
61
|
+
[END]: END,
|
|
61
62
|
})
|
|
62
63
|
.addEdge("tools", "agent");
|
|
63
64
|
return workflow.compile({
|
package/dist/pregel/index.cjs
CHANGED
|
@@ -480,7 +480,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
480
480
|
bg.push(this.checkpointer.put(checkpointConfig, checkpoint, {
|
|
481
481
|
source: "loop",
|
|
482
482
|
step,
|
|
483
|
-
writes: (0, io_js_1.single)(streamMode === "values"
|
|
483
|
+
writes: (0, io_js_1.single)(this.streamMode === "values"
|
|
484
484
|
? (0, io_js_1.mapOutputValues)(outputKeys, pendingWrites, channels)
|
|
485
485
|
: (0, io_js_1.mapOutputUpdates)(outputKeys, nextTasks)),
|
|
486
486
|
}));
|
package/dist/pregel/index.js
CHANGED
|
@@ -476,7 +476,7 @@ export class Pregel extends Runnable {
|
|
|
476
476
|
bg.push(this.checkpointer.put(checkpointConfig, checkpoint, {
|
|
477
477
|
source: "loop",
|
|
478
478
|
step,
|
|
479
|
-
writes: single(streamMode === "values"
|
|
479
|
+
writes: single(this.streamMode === "values"
|
|
480
480
|
? mapOutputValues(outputKeys, pendingWrites, channels)
|
|
481
481
|
: mapOutputUpdates(outputKeys, nextTasks)),
|
|
482
482
|
}));
|
package/dist/pregel/io.cjs
CHANGED
package/dist/pregel/io.d.ts
CHANGED
|
@@ -14,4 +14,4 @@ export declare function mapOutputValues<C extends PropertyKey>(outputChannels: C
|
|
|
14
14
|
* Map pending writes (a sequence of tuples (channel, value)) to output chunk.
|
|
15
15
|
*/
|
|
16
16
|
export declare function mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(outputChannels: C | Array<C>, tasks: readonly PregelExecutableTask<N, C>[]): Generator<Record<N, any | Record<string, any>>>;
|
|
17
|
-
export declare function single<T>(iter: IterableIterator<T>): T |
|
|
17
|
+
export declare function single<T>(iter: IterableIterator<T>): T | null;
|
package/dist/pregel/io.js
CHANGED
|
@@ -69,7 +69,7 @@ describe("MemorySaver", () => {
|
|
|
69
69
|
it("should save and retrieve checkpoints correctly", async () => {
|
|
70
70
|
const memorySaver = new MemorySaver();
|
|
71
71
|
// save checkpoint
|
|
72
|
-
const runnableConfig = await memorySaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1 });
|
|
72
|
+
const runnableConfig = await memorySaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1, writes: null });
|
|
73
73
|
expect(runnableConfig).toEqual({
|
|
74
74
|
configurable: {
|
|
75
75
|
thread_id: "1",
|
|
@@ -91,6 +91,7 @@ describe("MemorySaver", () => {
|
|
|
91
91
|
await memorySaver.put({ configurable: { thread_id: "1" } }, checkpoint2, {
|
|
92
92
|
source: "update",
|
|
93
93
|
step: -1,
|
|
94
|
+
writes: null,
|
|
94
95
|
});
|
|
95
96
|
// list checkpoints
|
|
96
97
|
const checkpointTupleGenerator = await memorySaver.list({
|
|
@@ -116,7 +117,7 @@ describe("SqliteSaver", () => {
|
|
|
116
117
|
});
|
|
117
118
|
expect(undefinedCheckpoint).toBeUndefined();
|
|
118
119
|
// save first checkpoint
|
|
119
|
-
const runnableConfig = await sqliteSaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1 });
|
|
120
|
+
const runnableConfig = await sqliteSaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1, writes: null });
|
|
120
121
|
expect(runnableConfig).toEqual({
|
|
121
122
|
configurable: {
|
|
122
123
|
thread_id: "1",
|
|
@@ -141,7 +142,7 @@ describe("SqliteSaver", () => {
|
|
|
141
142
|
thread_id: "1",
|
|
142
143
|
checkpoint_id: "2024-04-18T17:19:07.952Z",
|
|
143
144
|
},
|
|
144
|
-
}, checkpoint2, { source: "update", step: -1 });
|
|
145
|
+
}, checkpoint2, { source: "update", step: -1, writes: null });
|
|
145
146
|
// verify that parentTs is set and retrieved correctly for second checkpoint
|
|
146
147
|
const secondCheckpointTuple = await sqliteSaver.getTuple({
|
|
147
148
|
configurable: { thread_id: "1" },
|
|
@@ -120,7 +120,7 @@ describe("createReactAgent", () => {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
const tools = [new SanFranciscoWeatherTool()];
|
|
123
|
-
const reactAgent = createReactAgent(model, tools);
|
|
123
|
+
const reactAgent = createReactAgent({ llm: model, tools });
|
|
124
124
|
const response = await reactAgent.invoke({
|
|
125
125
|
messages: [new HumanMessage("What's the weather like in SF?")],
|
|
126
126
|
});
|
|
@@ -156,7 +156,7 @@ describe("createReactAgent", () => {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
const tools = [new SanFranciscoWeatherTool()];
|
|
159
|
-
const reactAgent = createReactAgent(model, tools);
|
|
159
|
+
const reactAgent = createReactAgent({ llm: model, tools });
|
|
160
160
|
const stream = await reactAgent.stream({
|
|
161
161
|
messages: [new HumanMessage("What's the weather like in SF?")],
|
|
162
162
|
}, { streamMode: "values" });
|
|
@@ -299,7 +299,11 @@ describe("createReactAgent", () => {
|
|
|
299
299
|
new AIMessage("result2"),
|
|
300
300
|
],
|
|
301
301
|
});
|
|
302
|
-
const agent = createReactAgent(
|
|
302
|
+
const agent = createReactAgent({
|
|
303
|
+
llm,
|
|
304
|
+
tools,
|
|
305
|
+
messageModifier: "You are a helpful assistant",
|
|
306
|
+
});
|
|
303
307
|
const result = await agent.invoke({
|
|
304
308
|
messages: [new HumanMessage("Hello Input!")],
|
|
305
309
|
});
|
|
@@ -331,11 +335,14 @@ describe("createReactAgent", () => {
|
|
|
331
335
|
new AIMessage("result2"),
|
|
332
336
|
],
|
|
333
337
|
});
|
|
334
|
-
const agent = createReactAgent(
|
|
338
|
+
const agent = createReactAgent({
|
|
339
|
+
llm,
|
|
340
|
+
tools,
|
|
341
|
+
messageModifier: new SystemMessage("You are a helpful assistant"),
|
|
342
|
+
});
|
|
335
343
|
const result = await agent.invoke({
|
|
336
344
|
messages: [],
|
|
337
345
|
});
|
|
338
|
-
console.log("RESULT THING", result);
|
|
339
346
|
expect(result.messages).toEqual([
|
|
340
347
|
new AIMessage({
|
|
341
348
|
content: "result1",
|
|
@@ -366,7 +373,37 @@ describe("createReactAgent", () => {
|
|
|
366
373
|
new SystemMessage("You are a helpful assistant"),
|
|
367
374
|
...messages,
|
|
368
375
|
];
|
|
369
|
-
const agent = createReactAgent(llm, tools, messageModifier);
|
|
376
|
+
const agent = createReactAgent({ llm, tools, messageModifier });
|
|
377
|
+
const result = await agent.invoke({
|
|
378
|
+
messages: [new HumanMessage("Hello Input!")],
|
|
379
|
+
});
|
|
380
|
+
expect(result.messages).toEqual([
|
|
381
|
+
new HumanMessage("Hello Input!"),
|
|
382
|
+
aiM1,
|
|
383
|
+
new ToolMessage({
|
|
384
|
+
name: "search_api",
|
|
385
|
+
content: "result for foo",
|
|
386
|
+
tool_call_id: "tool_abcd123",
|
|
387
|
+
}),
|
|
388
|
+
aiM2,
|
|
389
|
+
]);
|
|
390
|
+
});
|
|
391
|
+
it("Can use async custom function message modifier", async () => {
|
|
392
|
+
const aiM1 = new AIMessage({
|
|
393
|
+
content: "result1",
|
|
394
|
+
tool_calls: [
|
|
395
|
+
{ name: "search_api", id: "tool_abcd123", args: { query: "foo" } },
|
|
396
|
+
],
|
|
397
|
+
});
|
|
398
|
+
const aiM2 = new AIMessage("result2");
|
|
399
|
+
const llm = new FakeToolCallingChatModel({
|
|
400
|
+
responses: [aiM1, aiM2],
|
|
401
|
+
});
|
|
402
|
+
const messageModifier = async (messages) => [
|
|
403
|
+
new SystemMessage("You are a helpful assistant"),
|
|
404
|
+
...messages,
|
|
405
|
+
];
|
|
406
|
+
const agent = createReactAgent({ llm, tools, messageModifier });
|
|
370
407
|
const result = await agent.invoke({
|
|
371
408
|
messages: [new HumanMessage("Hello Input!")],
|
|
372
409
|
});
|
|
@@ -398,7 +435,7 @@ describe("createReactAgent", () => {
|
|
|
398
435
|
...messages,
|
|
399
436
|
],
|
|
400
437
|
});
|
|
401
|
-
const agent = createReactAgent(llm, tools, messageModifier);
|
|
438
|
+
const agent = createReactAgent({ llm, tools, messageModifier });
|
|
402
439
|
const result = await agent.invoke({
|
|
403
440
|
messages: [
|
|
404
441
|
new HumanMessage("Hello Input!"),
|
|
@@ -1777,8 +1777,9 @@ it("StateGraph start branch then end", async () => {
|
|
|
1777
1777
|
.addConditionalEdges({
|
|
1778
1778
|
source: START,
|
|
1779
1779
|
path: (state) => state.market === "DE" ? "tool_two_slow" : "tool_two_fast",
|
|
1780
|
-
|
|
1781
|
-
|
|
1780
|
+
})
|
|
1781
|
+
.addEdge("tool_two_fast", END)
|
|
1782
|
+
.addEdge("tool_two_slow", END);
|
|
1782
1783
|
const toolTwo = toolTwoBuilder.compile();
|
|
1783
1784
|
expect(await toolTwo.invoke({ my_key: "value", market: "DE" })).toEqual({
|
|
1784
1785
|
my_key: "value slow",
|
|
@@ -1793,71 +1794,41 @@ it("StateGraph start branch then end", async () => {
|
|
|
1793
1794
|
interruptBefore: ["tool_two_fast", "tool_two_slow"],
|
|
1794
1795
|
});
|
|
1795
1796
|
await expect(() => toolTwoWithCheckpointer.invoke({ my_key: "value", market: "DE" })).rejects.toThrowError("thread_id");
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
// parentConfig: [...toolTwoWithCheckpointer.checkpointer.list(thread1, { limit: 2 })].pop().config
|
|
1804
|
-
// })
|
|
1805
|
-
// expect(toolTwoWithCheckpointer.invoke(null, thread1, { debug: 1 })).toEqual({ my_key: "value slow", market: "DE" })
|
|
1806
|
-
// expect(toolTwoWithCheckpointer.getState(thread1)).toEqual({
|
|
1807
|
-
// values: { my_key
|
|
1808
|
-
// : "value slow", market: "DE" },
|
|
1809
|
-
// next: [],
|
|
1810
|
-
// config: (await toolTwoWithCheckpointer.checkpointer!.getTuple(thread1))!.config,
|
|
1811
|
-
// metadata: { source: "loop", step: 1, writes: { tool_two_slow: { my_key: " slow" } } },
|
|
1812
|
-
// parentConfig: [...toolTwoWithCheckpointer.checkpointer!.list(thread1, { limit: 2 })].pop().config
|
|
1813
|
-
});
|
|
1814
|
-
/**
|
|
1815
|
-
* def test_branch_then_node(snapshot: SnapshotAssertion) -> None:
|
|
1816
|
-
class State(TypedDict):
|
|
1817
|
-
my_key: Annotated[str, operator.add]
|
|
1818
|
-
market: str
|
|
1819
|
-
|
|
1820
|
-
# this graph is invalid because there is no path to "finish"
|
|
1821
|
-
invalid_graph = StateGraph(State)
|
|
1822
|
-
invalid_graph.set_entry_point("prepare")
|
|
1823
|
-
invalid_graph.set_finish_point("finish")
|
|
1824
|
-
invalid_graph.add_conditional_edges(
|
|
1825
|
-
source="prepare",
|
|
1826
|
-
path=lambda s: "tool_two_slow" if s["market"] == "DE" else "tool_two_fast",
|
|
1827
|
-
path_map=["tool_two_slow", "tool_two_fast"],
|
|
1828
|
-
)
|
|
1829
|
-
invalid_graph.add_node("prepare", lambda s: {"my_key": " prepared"})
|
|
1830
|
-
invalid_graph.add_node("tool_two_slow", lambda s: {"my_key": " slow"})
|
|
1831
|
-
invalid_graph.add_node("tool_two_fast", lambda s: {"my_key": " fast"})
|
|
1832
|
-
invalid_graph.add_node("finish", lambda s: {"my_key": " finished"})
|
|
1833
|
-
with pytest.raises(ValueError):
|
|
1834
|
-
invalid_graph.compile()
|
|
1835
|
-
|
|
1836
|
-
tool_two_graph = StateGraph(State)
|
|
1837
|
-
tool_two_graph.set_entry_point("prepare")
|
|
1838
|
-
tool_two_graph.set_finish_point("finish")
|
|
1839
|
-
tool_two_graph.add_conditional_edges(
|
|
1840
|
-
source="prepare",
|
|
1841
|
-
path=lambda s: "tool_two_slow" if s["market"] == "DE" else "tool_two_fast",
|
|
1842
|
-
then="finish",
|
|
1843
|
-
)
|
|
1844
|
-
tool_two_graph.add_node("prepare", lambda s: {"my_key": " prepared"})
|
|
1845
|
-
tool_two_graph.add_node("tool_two_slow", lambda s: {"my_key": " slow"})
|
|
1846
|
-
tool_two_graph.add_node("tool_two_fast", lambda s: {"my_key": " fast"})
|
|
1847
|
-
tool_two_graph.add_node("finish", lambda s: {"my_key": " finished"})
|
|
1848
|
-
tool_two = tool_two_graph.compile()
|
|
1849
|
-
assert tool_two.get_graph().draw_mermaid(with_styles=False) == snapshot
|
|
1850
|
-
assert tool_two.get_graph().draw_mermaid() == snapshot
|
|
1851
|
-
|
|
1852
|
-
assert tool_two.invoke({"my_key": "value", "market": "DE"}, debug=1) == {
|
|
1853
|
-
"my_key": "value prepared slow finished",
|
|
1854
|
-
"market": "DE",
|
|
1855
|
-
}
|
|
1856
|
-
assert tool_two.invoke({"my_key": "value", "market": "US"}) == {
|
|
1857
|
-
"my_key": "value prepared fast finished",
|
|
1858
|
-
"market": "US",
|
|
1797
|
+
async function last(iter) {
|
|
1798
|
+
// eslint-disable-next-line no-undef-init
|
|
1799
|
+
let value = undefined;
|
|
1800
|
+
for await (value of iter) {
|
|
1801
|
+
// do nothing
|
|
1802
|
+
}
|
|
1803
|
+
return value;
|
|
1859
1804
|
}
|
|
1860
|
-
|
|
1805
|
+
const thread1 = { configurable: { thread_id: "1" } };
|
|
1806
|
+
expect(await toolTwoWithCheckpointer.invoke({ my_key: "value", market: "DE" }, thread1)).toEqual({ my_key: "value", market: "DE" });
|
|
1807
|
+
expect(await toolTwoWithCheckpointer.getState(thread1)).toEqual({
|
|
1808
|
+
values: { my_key: "value", market: "DE" },
|
|
1809
|
+
next: ["tool_two_slow"],
|
|
1810
|
+
config: (await toolTwoWithCheckpointer.checkpointer.getTuple(thread1))
|
|
1811
|
+
.config,
|
|
1812
|
+
metadata: { source: "loop", step: 0, writes: null },
|
|
1813
|
+
parentConfig: (await last(toolTwoWithCheckpointer.checkpointer.list(thread1, 2))).config,
|
|
1814
|
+
});
|
|
1815
|
+
expect(await toolTwoWithCheckpointer.invoke(null, thread1)).toEqual({
|
|
1816
|
+
my_key: "value slow",
|
|
1817
|
+
market: "DE",
|
|
1818
|
+
});
|
|
1819
|
+
expect(await toolTwoWithCheckpointer.getState(thread1)).toEqual({
|
|
1820
|
+
values: { my_key: "value slow", market: "DE" },
|
|
1821
|
+
next: [],
|
|
1822
|
+
config: (await toolTwoWithCheckpointer.checkpointer.getTuple(thread1))
|
|
1823
|
+
.config,
|
|
1824
|
+
metadata: {
|
|
1825
|
+
source: "loop",
|
|
1826
|
+
step: 1,
|
|
1827
|
+
writes: { tool_two_slow: { my_key: " slow" } },
|
|
1828
|
+
},
|
|
1829
|
+
parentConfig: (await last(toolTwoWithCheckpointer.checkpointer.list(thread1, 2))).config,
|
|
1830
|
+
});
|
|
1831
|
+
});
|
|
1861
1832
|
it("StateGraph branch then node", async () => {
|
|
1862
1833
|
const invalidBuilder = new StateGraph({
|
|
1863
1834
|
channels: {
|
|
@@ -1891,8 +1862,9 @@ it("StateGraph branch then node", async () => {
|
|
|
1891
1862
|
.addConditionalEdges({
|
|
1892
1863
|
source: "prepare",
|
|
1893
1864
|
path: (state) => state.market === "DE" ? "tool_two_slow" : "tool_two_fast",
|
|
1894
|
-
then: "finish",
|
|
1895
1865
|
})
|
|
1866
|
+
.addEdge("tool_two_fast", "finish")
|
|
1867
|
+
.addEdge("tool_two_slow", "finish")
|
|
1896
1868
|
.addEdge("finish", END);
|
|
1897
1869
|
const tool = toolBuilder.compile();
|
|
1898
1870
|
expect(await tool.invoke({ my_key: "value", market: "DE" })).toEqual({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "LangGraph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@jest/globals": "^29.5.0",
|
|
45
|
+
"@langchain/anthropic": "^0.1.21",
|
|
45
46
|
"@langchain/community": "^0.0.43",
|
|
46
47
|
"@langchain/openai": "latest",
|
|
47
48
|
"@langchain/scripts": "^0.0.13",
|