@langchain/langgraph 0.2.45 → 0.2.46
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/graph/annotation.cjs +0 -1
- package/dist/graph/annotation.d.ts +0 -1
- package/dist/graph/annotation.js +0 -1
- package/dist/graph/graph.cjs +2 -1
- package/dist/graph/graph.d.ts +2 -1
- package/dist/graph/graph.js +2 -1
- package/dist/graph/state.cjs +2 -1
- package/dist/graph/state.d.ts +2 -1
- package/dist/graph/state.js +2 -1
- package/dist/prebuilt/react_agent_executor.cjs +100 -43
- package/dist/prebuilt/react_agent_executor.d.ts +21 -49
- package/dist/prebuilt/react_agent_executor.js +100 -43
- package/dist/pregel/index.cjs +1 -0
- package/dist/pregel/index.js +1 -0
- package/dist/pregel/messages.cjs +27 -15
- package/dist/pregel/messages.d.ts +2 -1
- package/dist/pregel/messages.js +27 -15
- package/dist/pregel/remote.cjs +8 -9
- package/dist/pregel/remote.js +8 -9
- package/dist/web.d.ts +1 -1
- package/package.json +1 -1
package/dist/graph/annotation.js
CHANGED
package/dist/graph/graph.cjs
CHANGED
|
@@ -220,7 +220,7 @@ class Graph {
|
|
|
220
220
|
this.warnIfCompiled("Setting a finish point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
221
221
|
return this.addEdge(key, constants_js_1.END);
|
|
222
222
|
}
|
|
223
|
-
compile({ checkpointer, interruptBefore, interruptAfter, } = {}) {
|
|
223
|
+
compile({ checkpointer, interruptBefore, interruptAfter, name, } = {}) {
|
|
224
224
|
// validate the graph
|
|
225
225
|
this.validate([
|
|
226
226
|
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
@@ -242,6 +242,7 @@ class Graph {
|
|
|
242
242
|
outputChannels: constants_js_1.END,
|
|
243
243
|
streamChannels: [],
|
|
244
244
|
streamMode: "values",
|
|
245
|
+
name,
|
|
245
246
|
});
|
|
246
247
|
// attach nodes, edges and branches
|
|
247
248
|
for (const [key, node] of Object.entries(this.nodes)) {
|
package/dist/graph/graph.d.ts
CHANGED
|
@@ -54,10 +54,11 @@ export declare class Graph<N extends string = typeof END, RunInput = any, RunOut
|
|
|
54
54
|
* @deprecated use `addEdge(key, END)` instead
|
|
55
55
|
*/
|
|
56
56
|
setFinishPoint(key: N): this;
|
|
57
|
-
compile({ checkpointer, interruptBefore, interruptAfter, }?: {
|
|
57
|
+
compile({ checkpointer, interruptBefore, interruptAfter, name, }?: {
|
|
58
58
|
checkpointer?: BaseCheckpointSaver | false;
|
|
59
59
|
interruptBefore?: N[] | All;
|
|
60
60
|
interruptAfter?: N[] | All;
|
|
61
|
+
name?: string;
|
|
61
62
|
}): CompiledGraph<N>;
|
|
62
63
|
validate(interrupt?: string[]): void;
|
|
63
64
|
}
|
package/dist/graph/graph.js
CHANGED
|
@@ -216,7 +216,7 @@ export class Graph {
|
|
|
216
216
|
this.warnIfCompiled("Setting a finish point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
217
217
|
return this.addEdge(key, END);
|
|
218
218
|
}
|
|
219
|
-
compile({ checkpointer, interruptBefore, interruptAfter, } = {}) {
|
|
219
|
+
compile({ checkpointer, interruptBefore, interruptAfter, name, } = {}) {
|
|
220
220
|
// validate the graph
|
|
221
221
|
this.validate([
|
|
222
222
|
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
@@ -238,6 +238,7 @@ export class Graph {
|
|
|
238
238
|
outputChannels: END,
|
|
239
239
|
streamChannels: [],
|
|
240
240
|
streamMode: "values",
|
|
241
|
+
name,
|
|
241
242
|
});
|
|
242
243
|
// attach nodes, edges and branches
|
|
243
244
|
for (const [key, node] of Object.entries(this.nodes)) {
|
package/dist/graph/state.cjs
CHANGED
|
@@ -270,7 +270,7 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
270
270
|
this.waitingEdges.add([startKey, endKey]);
|
|
271
271
|
return this;
|
|
272
272
|
}
|
|
273
|
-
compile({ checkpointer, store, interruptBefore, interruptAfter, } = {}) {
|
|
273
|
+
compile({ checkpointer, store, interruptBefore, interruptAfter, name, } = {}) {
|
|
274
274
|
// validate the graph
|
|
275
275
|
this.validate([
|
|
276
276
|
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
@@ -298,6 +298,7 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
298
298
|
streamChannels,
|
|
299
299
|
streamMode: "updates",
|
|
300
300
|
store,
|
|
301
|
+
name,
|
|
301
302
|
});
|
|
302
303
|
// attach nodes, edges and branches
|
|
303
304
|
compiled.attachNode(constants_js_1.START);
|
package/dist/graph/state.d.ts
CHANGED
|
@@ -117,11 +117,12 @@ export declare class StateGraph<SD extends StateDefinition | unknown, S = SD ext
|
|
|
117
117
|
_addSchema(stateDefinition: StateDefinition): void;
|
|
118
118
|
addNode<K extends string, NodeInput = S>(key: K, action: RunnableLike<NodeInput, U extends object ? U & Record<string, any> : U, LangGraphRunnableConfig<StateType<C>>>, options?: StateGraphAddNodeOptions): StateGraph<SD, S, U, N | K, I, O, C>;
|
|
119
119
|
addEdge(startKey: typeof START | N | N[], endKey: N | typeof END): this;
|
|
120
|
-
compile({ checkpointer, store, interruptBefore, interruptAfter, }?: {
|
|
120
|
+
compile({ checkpointer, store, interruptBefore, interruptAfter, name, }?: {
|
|
121
121
|
checkpointer?: BaseCheckpointSaver | false;
|
|
122
122
|
store?: BaseStore;
|
|
123
123
|
interruptBefore?: N[] | All;
|
|
124
124
|
interruptAfter?: N[] | All;
|
|
125
|
+
name?: string;
|
|
125
126
|
}): CompiledStateGraph<S, U, N, I, O, C>;
|
|
126
127
|
}
|
|
127
128
|
/**
|
package/dist/graph/state.js
CHANGED
|
@@ -267,7 +267,7 @@ export class StateGraph extends Graph {
|
|
|
267
267
|
this.waitingEdges.add([startKey, endKey]);
|
|
268
268
|
return this;
|
|
269
269
|
}
|
|
270
|
-
compile({ checkpointer, store, interruptBefore, interruptAfter, } = {}) {
|
|
270
|
+
compile({ checkpointer, store, interruptBefore, interruptAfter, name, } = {}) {
|
|
271
271
|
// validate the graph
|
|
272
272
|
this.validate([
|
|
273
273
|
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
@@ -295,6 +295,7 @@ export class StateGraph extends Graph {
|
|
|
295
295
|
streamChannels,
|
|
296
296
|
streamMode: "updates",
|
|
297
297
|
store,
|
|
298
|
+
name,
|
|
298
299
|
});
|
|
299
300
|
// attach nodes, edges and branches
|
|
300
301
|
compiled.attachNode(START);
|
|
@@ -8,7 +8,7 @@ const tool_node_js_1 = require("./tool_node.cjs");
|
|
|
8
8
|
const annotation_js_1 = require("../graph/annotation.cjs");
|
|
9
9
|
const message_js_1 = require("../graph/message.cjs");
|
|
10
10
|
const constants_js_1 = require("../constants.cjs");
|
|
11
|
-
function
|
|
11
|
+
function _convertMessageModifierToPrompt(messageModifier) {
|
|
12
12
|
// Handle string or SystemMessage
|
|
13
13
|
if (typeof messageModifier === "string" ||
|
|
14
14
|
((0, messages_1.isBaseMessage)(messageModifier) && messageModifier._getType() === "system")) {
|
|
@@ -24,48 +24,99 @@ function _convertMessageModifierToStateModifier(messageModifier) {
|
|
|
24
24
|
}
|
|
25
25
|
throw new Error(`Unexpected type for messageModifier: ${typeof messageModifier}`);
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
const PROMPT_RUNNABLE_NAME = "prompt";
|
|
28
|
+
function _getPromptRunnable(prompt) {
|
|
29
|
+
let promptRunnable;
|
|
30
|
+
if (prompt == null) {
|
|
31
|
+
promptRunnable = runnables_1.RunnableLambda.from((state) => state.messages).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
32
|
+
}
|
|
33
|
+
else if (typeof prompt === "string") {
|
|
34
|
+
const systemMessage = new messages_1.SystemMessage(prompt);
|
|
35
|
+
promptRunnable = runnables_1.RunnableLambda.from((state) => {
|
|
35
36
|
return [systemMessage, ...(state.messages ?? [])];
|
|
36
|
-
}).withConfig({ runName:
|
|
37
|
-
}
|
|
38
|
-
else if ((0, messages_1.isBaseMessage)(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
else if (typeof stateModifier === "function") {
|
|
46
|
-
stateModifierRunnable = runnables_1.RunnableLambda.from(stateModifier).withConfig({
|
|
47
|
-
runName: "state_modifier",
|
|
37
|
+
}).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
38
|
+
}
|
|
39
|
+
else if ((0, messages_1.isBaseMessage)(prompt) && prompt._getType() === "system") {
|
|
40
|
+
promptRunnable = runnables_1.RunnableLambda.from((state) => [prompt, ...state.messages]).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
41
|
+
}
|
|
42
|
+
else if (typeof prompt === "function") {
|
|
43
|
+
promptRunnable = runnables_1.RunnableLambda.from(prompt).withConfig({
|
|
44
|
+
runName: PROMPT_RUNNABLE_NAME,
|
|
48
45
|
});
|
|
49
46
|
}
|
|
50
|
-
else if (runnables_1.Runnable.isRunnable(
|
|
51
|
-
|
|
47
|
+
else if (runnables_1.Runnable.isRunnable(prompt)) {
|
|
48
|
+
promptRunnable = prompt;
|
|
52
49
|
}
|
|
53
50
|
else {
|
|
54
|
-
throw new Error(`Got unexpected type for '
|
|
51
|
+
throw new Error(`Got unexpected type for 'prompt': ${typeof prompt}`);
|
|
52
|
+
}
|
|
53
|
+
return promptRunnable;
|
|
54
|
+
}
|
|
55
|
+
function _getPrompt(prompt, stateModifier, messageModifier) {
|
|
56
|
+
// Check if multiple modifiers exist
|
|
57
|
+
const definedCount = [prompt, stateModifier, messageModifier].filter((x) => x != null).length;
|
|
58
|
+
if (definedCount > 1) {
|
|
59
|
+
throw new Error("Expected only one of prompt, stateModifier, or messageModifier, got multiple values");
|
|
60
|
+
}
|
|
61
|
+
let finalPrompt = prompt;
|
|
62
|
+
if (stateModifier != null) {
|
|
63
|
+
finalPrompt = stateModifier;
|
|
64
|
+
}
|
|
65
|
+
else if (messageModifier != null) {
|
|
66
|
+
finalPrompt = _convertMessageModifierToPrompt(messageModifier);
|
|
67
|
+
}
|
|
68
|
+
return _getPromptRunnable(finalPrompt);
|
|
69
|
+
}
|
|
70
|
+
function _shouldBindTools(llm, tools) {
|
|
71
|
+
if (!runnables_1.Runnable.isRunnable(llm) || !("kwargs" in llm)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (!llm.kwargs ||
|
|
75
|
+
typeof llm.kwargs !== "object" ||
|
|
76
|
+
!("tools" in llm.kwargs)) {
|
|
77
|
+
return true;
|
|
55
78
|
}
|
|
56
|
-
|
|
79
|
+
const boundTools = llm.kwargs.tools;
|
|
80
|
+
if (tools.length !== boundTools.length) {
|
|
81
|
+
throw new Error("Number of tools in the model.bindTools() and tools passed to createReactAgent must match");
|
|
82
|
+
}
|
|
83
|
+
const toolNames = new Set(tools.map((tool) => tool.name));
|
|
84
|
+
const boundToolNames = new Set();
|
|
85
|
+
for (const boundTool of boundTools) {
|
|
86
|
+
let boundToolName;
|
|
87
|
+
// OpenAI-style tool
|
|
88
|
+
if ("type" in boundTool && boundTool.type === "function") {
|
|
89
|
+
boundToolName = boundTool.function.name;
|
|
90
|
+
}
|
|
91
|
+
// Anthropic-style tool
|
|
92
|
+
else if ("name" in boundTool) {
|
|
93
|
+
boundToolName = boundTool.name;
|
|
94
|
+
}
|
|
95
|
+
// unknown tool type so we'll ignore it
|
|
96
|
+
else {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
boundToolNames.add(boundToolName);
|
|
100
|
+
}
|
|
101
|
+
const missingTools = [...toolNames].filter((x) => !boundToolNames.has(x));
|
|
102
|
+
if (missingTools.length > 0) {
|
|
103
|
+
throw new Error(`Missing tools '${missingTools}' in the model.bindTools().` +
|
|
104
|
+
`Tools in the model.bindTools() must match the tools passed to createReactAgent.`);
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
57
107
|
}
|
|
58
|
-
function
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
108
|
+
function _getModel(llm) {
|
|
109
|
+
// Get the underlying model from a RunnableBinding or return the model itself
|
|
110
|
+
let model = llm;
|
|
111
|
+
if (runnables_1.Runnable.isRunnable(llm) && "bound" in llm) {
|
|
112
|
+
model = llm.bound;
|
|
62
113
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
114
|
+
if (!("invoke" in model &&
|
|
115
|
+
typeof model.invoke === "function" &&
|
|
116
|
+
"_modelType" in model)) {
|
|
117
|
+
throw new Error(`Expected \`llm\` to be a ChatModel or RunnableBinding (e.g. llm.bind_tools(...)) with invoke() and generate() methods, got ${model.constructor.name}`);
|
|
67
118
|
}
|
|
68
|
-
return
|
|
119
|
+
return model;
|
|
69
120
|
}
|
|
70
121
|
const createReactAgentAnnotation = () => annotation_js_1.Annotation.Root({
|
|
71
122
|
messages: (0, annotation_js_1.Annotation)({
|
|
@@ -118,7 +169,7 @@ exports.createReactAgentAnnotation = createReactAgentAnnotation;
|
|
|
118
169
|
* ```
|
|
119
170
|
*/
|
|
120
171
|
function createReactAgent(params) {
|
|
121
|
-
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, } = params;
|
|
172
|
+
const { llm, tools, messageModifier, stateModifier, prompt, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, name, } = params;
|
|
122
173
|
let toolClasses;
|
|
123
174
|
if (!Array.isArray(tools)) {
|
|
124
175
|
toolClasses = tools.tools;
|
|
@@ -126,13 +177,17 @@ function createReactAgent(params) {
|
|
|
126
177
|
else {
|
|
127
178
|
toolClasses = tools;
|
|
128
179
|
}
|
|
129
|
-
|
|
130
|
-
|
|
180
|
+
let modelWithTools;
|
|
181
|
+
if (_shouldBindTools(llm, toolClasses)) {
|
|
182
|
+
if (!("bindTools" in llm) || typeof llm.bindTools !== "function") {
|
|
183
|
+
throw new Error(`llm ${llm} must define bindTools method.`);
|
|
184
|
+
}
|
|
185
|
+
modelWithTools = llm.bindTools(toolClasses);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
modelWithTools = llm;
|
|
131
189
|
}
|
|
132
|
-
const
|
|
133
|
-
// we're passing store here for validation
|
|
134
|
-
const preprocessor = _getModelPreprocessingRunnable(stateModifier, messageModifier);
|
|
135
|
-
const modelRunnable = preprocessor.pipe(modelWithTools);
|
|
190
|
+
const modelRunnable = _getPrompt(prompt, stateModifier, messageModifier).pipe(modelWithTools);
|
|
136
191
|
// If any of the tools are configured to return_directly after running,
|
|
137
192
|
// our graph needs to check if these were called
|
|
138
193
|
const shouldReturnDirect = new Set(toolClasses
|
|
@@ -161,11 +216,12 @@ function createReactAgent(params) {
|
|
|
161
216
|
"prompt" in responseFormat &&
|
|
162
217
|
"schema" in responseFormat) {
|
|
163
218
|
const { prompt, schema } = responseFormat;
|
|
164
|
-
modelWithStructuredOutput = llm.withStructuredOutput(schema);
|
|
219
|
+
modelWithStructuredOutput = _getModel(llm).withStructuredOutput(schema);
|
|
165
220
|
messages.unshift(new messages_1.SystemMessage({ content: prompt }));
|
|
166
221
|
}
|
|
167
222
|
else {
|
|
168
|
-
modelWithStructuredOutput =
|
|
223
|
+
modelWithStructuredOutput =
|
|
224
|
+
_getModel(llm).withStructuredOutput(responseFormat);
|
|
169
225
|
}
|
|
170
226
|
const response = await modelWithStructuredOutput.invoke(messages, config);
|
|
171
227
|
return { structuredResponse: response };
|
|
@@ -219,6 +275,7 @@ function createReactAgent(params) {
|
|
|
219
275
|
interruptBefore,
|
|
220
276
|
interruptAfter,
|
|
221
277
|
store,
|
|
278
|
+
name,
|
|
222
279
|
});
|
|
223
280
|
}
|
|
224
281
|
exports.createReactAgent = createReactAgent;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LanguageModelLike } from "@langchain/core/language_models/base";
|
|
2
2
|
import { BaseMessage, BaseMessageLike, SystemMessage } from "@langchain/core/messages";
|
|
3
3
|
import { Runnable, RunnableToolLike } from "@langchain/core/runnables";
|
|
4
|
-
import { StructuredToolInterface } from "@langchain/core/tools";
|
|
4
|
+
import { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
|
|
5
5
|
import { All, BaseCheckpointSaver, BaseStore } from "@langchain/langgraph-checkpoint";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { CompiledStateGraph, AnnotationRoot } from "../graph/index.js";
|
|
@@ -19,8 +19,10 @@ export type StructuredResponseSchemaAndPrompt<StructuredResponseType> = {
|
|
|
19
19
|
prompt: string;
|
|
20
20
|
schema: z.ZodType<StructuredResponseType> | Record<string, any>;
|
|
21
21
|
};
|
|
22
|
-
export type
|
|
23
|
-
/** @deprecated Use
|
|
22
|
+
export type Prompt = SystemMessage | string | ((state: typeof MessagesAnnotation.State, config: LangGraphRunnableConfig) => BaseMessageLike[]) | ((state: typeof MessagesAnnotation.State, config: LangGraphRunnableConfig) => Promise<BaseMessageLike[]>) | Runnable;
|
|
23
|
+
/** @deprecated Use Prompt instead. */
|
|
24
|
+
export type StateModifier = Prompt;
|
|
25
|
+
/** @deprecated Use Prompt instead. */
|
|
24
26
|
export type MessageModifier = SystemMessage | string | ((messages: BaseMessage[]) => BaseMessage[]) | ((messages: BaseMessage[]) => Promise<BaseMessage[]>) | Runnable;
|
|
25
27
|
export declare const createReactAgentAnnotation: <T extends Record<string, any> = Record<string, any>>() => AnnotationRoot<{
|
|
26
28
|
messages: import("../web.js").BinaryOperatorAggregate<BaseMessage[], Messages>;
|
|
@@ -32,63 +34,32 @@ export declare const createReactAgentAnnotation: <T extends Record<string, any>
|
|
|
32
34
|
}>;
|
|
33
35
|
export type CreateReactAgentParams<A extends AnnotationRoot<any> = AnnotationRoot<any>, StructuredResponseType = Record<string, any>> = {
|
|
34
36
|
/** The chat model that can utilize OpenAI-style tool calling. */
|
|
35
|
-
llm:
|
|
37
|
+
llm: LanguageModelLike;
|
|
36
38
|
/** A list of tools or a ToolNode. */
|
|
37
|
-
tools: ToolNode | (StructuredToolInterface | RunnableToolLike)[];
|
|
39
|
+
tools: ToolNode | (StructuredToolInterface | DynamicTool | RunnableToolLike)[];
|
|
38
40
|
/**
|
|
39
|
-
* @deprecated
|
|
40
|
-
* Use stateModifier instead. stateModifier works the same as
|
|
41
|
-
* messageModifier in that it runs right before calling the chat model,
|
|
42
|
-
* but if passed as a function, it takes the full graph state as
|
|
43
|
-
* input whenever a tool is called rather than a list of messages.
|
|
44
|
-
*
|
|
45
|
-
* If a function is passed, it should return a list of messages to
|
|
46
|
-
* pass directly to the chat model.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* import { ChatOpenAI } from "@langchain/openai";
|
|
51
|
-
* import { MessagesAnnotation } from "@langchain/langgraph";
|
|
52
|
-
* import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
|
53
|
-
* import { type BaseMessage, SystemMessage } from "@langchain/core/messages";
|
|
54
|
-
*
|
|
55
|
-
* const model = new ChatOpenAI({
|
|
56
|
-
* model: "gpt-4o-mini",
|
|
57
|
-
* });
|
|
58
|
-
*
|
|
59
|
-
* const tools = [...];
|
|
60
|
-
*
|
|
61
|
-
* // Deprecated style with messageModifier
|
|
62
|
-
* const deprecated = createReactAgent({
|
|
63
|
-
* llm,
|
|
64
|
-
* tools,
|
|
65
|
-
* messageModifier: async (messages: BaseMessage[]) => {
|
|
66
|
-
* return [new SystemMessage("You are a pirate")].concat(messages);
|
|
67
|
-
* }
|
|
68
|
-
* });
|
|
69
|
-
*
|
|
70
|
-
* // New style with stateModifier
|
|
71
|
-
* const agent = createReactAgent({
|
|
72
|
-
* llm,
|
|
73
|
-
* tools,
|
|
74
|
-
* stateModifier: async (state: typeof MessagesAnnotation.State) => {
|
|
75
|
-
* return [new SystemMessage("You are a pirate.")].concat(messages);
|
|
76
|
-
* }
|
|
77
|
-
* });
|
|
78
|
-
* ```
|
|
41
|
+
* @deprecated Use prompt instead.
|
|
79
42
|
*/
|
|
80
43
|
messageModifier?: MessageModifier;
|
|
81
44
|
/**
|
|
82
|
-
*
|
|
45
|
+
* @deprecated Use prompt instead.
|
|
46
|
+
*/
|
|
47
|
+
stateModifier?: StateModifier;
|
|
48
|
+
/**
|
|
49
|
+
* An optional prompt for the LLM. This takes full graph state BEFORE the LLM is called and prepares the input to LLM.
|
|
83
50
|
*
|
|
84
51
|
* Can take a few different forms:
|
|
85
52
|
*
|
|
86
|
-
* - SystemMessage: this is added to the beginning of the list of messages in state["messages"].
|
|
87
53
|
* - str: This is converted to a SystemMessage and added to the beginning of the list of messages in state["messages"].
|
|
54
|
+
* - SystemMessage: this is added to the beginning of the list of messages in state["messages"].
|
|
88
55
|
* - Function: This function should take in full graph state and the output is then passed to the language model.
|
|
89
56
|
* - Runnable: This runnable should take in full graph state and the output is then passed to the language model.
|
|
57
|
+
*
|
|
58
|
+
* Note:
|
|
59
|
+
* Prior to `v0.2.46`, the prompt was set using `stateModifier` / `messagesModifier` parameters.
|
|
60
|
+
* This is now deprecated and will be removed in a future release.
|
|
90
61
|
*/
|
|
91
|
-
|
|
62
|
+
prompt?: Prompt;
|
|
92
63
|
stateSchema?: A;
|
|
93
64
|
/** An optional checkpoint saver to persist the agent's state. */
|
|
94
65
|
checkpointSaver?: BaseCheckpointSaver;
|
|
@@ -112,6 +83,7 @@ export type CreateReactAgentParams<A extends AnnotationRoot<any> = AnnotationRoo
|
|
|
112
83
|
* The prompt will be used together with the model that is being used to generate the structured response.
|
|
113
84
|
*/
|
|
114
85
|
responseFormat?: z.ZodType<StructuredResponseType> | StructuredResponseSchemaAndPrompt<StructuredResponseType> | Record<string, any>;
|
|
86
|
+
name?: string;
|
|
115
87
|
};
|
|
116
88
|
/**
|
|
117
89
|
* Creates a StateGraph agent that relies on a chat model utilizing tool calling.
|
|
@@ -5,7 +5,7 @@ import { ToolNode } from "./tool_node.js";
|
|
|
5
5
|
import { Annotation } from "../graph/annotation.js";
|
|
6
6
|
import { messagesStateReducer } from "../graph/message.js";
|
|
7
7
|
import { END, START } from "../constants.js";
|
|
8
|
-
function
|
|
8
|
+
function _convertMessageModifierToPrompt(messageModifier) {
|
|
9
9
|
// Handle string or SystemMessage
|
|
10
10
|
if (typeof messageModifier === "string" ||
|
|
11
11
|
(isBaseMessage(messageModifier) && messageModifier._getType() === "system")) {
|
|
@@ -21,48 +21,99 @@ function _convertMessageModifierToStateModifier(messageModifier) {
|
|
|
21
21
|
}
|
|
22
22
|
throw new Error(`Unexpected type for messageModifier: ${typeof messageModifier}`);
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const PROMPT_RUNNABLE_NAME = "prompt";
|
|
25
|
+
function _getPromptRunnable(prompt) {
|
|
26
|
+
let promptRunnable;
|
|
27
|
+
if (prompt == null) {
|
|
28
|
+
promptRunnable = RunnableLambda.from((state) => state.messages).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
29
|
+
}
|
|
30
|
+
else if (typeof prompt === "string") {
|
|
31
|
+
const systemMessage = new SystemMessage(prompt);
|
|
32
|
+
promptRunnable = RunnableLambda.from((state) => {
|
|
32
33
|
return [systemMessage, ...(state.messages ?? [])];
|
|
33
|
-
}).withConfig({ runName:
|
|
34
|
-
}
|
|
35
|
-
else if (isBaseMessage(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
else if (typeof stateModifier === "function") {
|
|
43
|
-
stateModifierRunnable = RunnableLambda.from(stateModifier).withConfig({
|
|
44
|
-
runName: "state_modifier",
|
|
34
|
+
}).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
35
|
+
}
|
|
36
|
+
else if (isBaseMessage(prompt) && prompt._getType() === "system") {
|
|
37
|
+
promptRunnable = RunnableLambda.from((state) => [prompt, ...state.messages]).withConfig({ runName: PROMPT_RUNNABLE_NAME });
|
|
38
|
+
}
|
|
39
|
+
else if (typeof prompt === "function") {
|
|
40
|
+
promptRunnable = RunnableLambda.from(prompt).withConfig({
|
|
41
|
+
runName: PROMPT_RUNNABLE_NAME,
|
|
45
42
|
});
|
|
46
43
|
}
|
|
47
|
-
else if (Runnable.isRunnable(
|
|
48
|
-
|
|
44
|
+
else if (Runnable.isRunnable(prompt)) {
|
|
45
|
+
promptRunnable = prompt;
|
|
49
46
|
}
|
|
50
47
|
else {
|
|
51
|
-
throw new Error(`Got unexpected type for '
|
|
48
|
+
throw new Error(`Got unexpected type for 'prompt': ${typeof prompt}`);
|
|
49
|
+
}
|
|
50
|
+
return promptRunnable;
|
|
51
|
+
}
|
|
52
|
+
function _getPrompt(prompt, stateModifier, messageModifier) {
|
|
53
|
+
// Check if multiple modifiers exist
|
|
54
|
+
const definedCount = [prompt, stateModifier, messageModifier].filter((x) => x != null).length;
|
|
55
|
+
if (definedCount > 1) {
|
|
56
|
+
throw new Error("Expected only one of prompt, stateModifier, or messageModifier, got multiple values");
|
|
57
|
+
}
|
|
58
|
+
let finalPrompt = prompt;
|
|
59
|
+
if (stateModifier != null) {
|
|
60
|
+
finalPrompt = stateModifier;
|
|
61
|
+
}
|
|
62
|
+
else if (messageModifier != null) {
|
|
63
|
+
finalPrompt = _convertMessageModifierToPrompt(messageModifier);
|
|
64
|
+
}
|
|
65
|
+
return _getPromptRunnable(finalPrompt);
|
|
66
|
+
}
|
|
67
|
+
function _shouldBindTools(llm, tools) {
|
|
68
|
+
if (!Runnable.isRunnable(llm) || !("kwargs" in llm)) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!llm.kwargs ||
|
|
72
|
+
typeof llm.kwargs !== "object" ||
|
|
73
|
+
!("tools" in llm.kwargs)) {
|
|
74
|
+
return true;
|
|
52
75
|
}
|
|
53
|
-
|
|
76
|
+
const boundTools = llm.kwargs.tools;
|
|
77
|
+
if (tools.length !== boundTools.length) {
|
|
78
|
+
throw new Error("Number of tools in the model.bindTools() and tools passed to createReactAgent must match");
|
|
79
|
+
}
|
|
80
|
+
const toolNames = new Set(tools.map((tool) => tool.name));
|
|
81
|
+
const boundToolNames = new Set();
|
|
82
|
+
for (const boundTool of boundTools) {
|
|
83
|
+
let boundToolName;
|
|
84
|
+
// OpenAI-style tool
|
|
85
|
+
if ("type" in boundTool && boundTool.type === "function") {
|
|
86
|
+
boundToolName = boundTool.function.name;
|
|
87
|
+
}
|
|
88
|
+
// Anthropic-style tool
|
|
89
|
+
else if ("name" in boundTool) {
|
|
90
|
+
boundToolName = boundTool.name;
|
|
91
|
+
}
|
|
92
|
+
// unknown tool type so we'll ignore it
|
|
93
|
+
else {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
boundToolNames.add(boundToolName);
|
|
97
|
+
}
|
|
98
|
+
const missingTools = [...toolNames].filter((x) => !boundToolNames.has(x));
|
|
99
|
+
if (missingTools.length > 0) {
|
|
100
|
+
throw new Error(`Missing tools '${missingTools}' in the model.bindTools().` +
|
|
101
|
+
`Tools in the model.bindTools() must match the tools passed to createReactAgent.`);
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
54
104
|
}
|
|
55
|
-
function
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
105
|
+
function _getModel(llm) {
|
|
106
|
+
// Get the underlying model from a RunnableBinding or return the model itself
|
|
107
|
+
let model = llm;
|
|
108
|
+
if (Runnable.isRunnable(llm) && "bound" in llm) {
|
|
109
|
+
model = llm.bound;
|
|
59
110
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
111
|
+
if (!("invoke" in model &&
|
|
112
|
+
typeof model.invoke === "function" &&
|
|
113
|
+
"_modelType" in model)) {
|
|
114
|
+
throw new Error(`Expected \`llm\` to be a ChatModel or RunnableBinding (e.g. llm.bind_tools(...)) with invoke() and generate() methods, got ${model.constructor.name}`);
|
|
64
115
|
}
|
|
65
|
-
return
|
|
116
|
+
return model;
|
|
66
117
|
}
|
|
67
118
|
export const createReactAgentAnnotation = () => Annotation.Root({
|
|
68
119
|
messages: Annotation({
|
|
@@ -114,7 +165,7 @@ export const createReactAgentAnnotation = () => Annotation.Root({
|
|
|
114
165
|
* ```
|
|
115
166
|
*/
|
|
116
167
|
export function createReactAgent(params) {
|
|
117
|
-
const { llm, tools, messageModifier, stateModifier, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, } = params;
|
|
168
|
+
const { llm, tools, messageModifier, stateModifier, prompt, stateSchema, checkpointSaver, checkpointer, interruptBefore, interruptAfter, store, responseFormat, name, } = params;
|
|
118
169
|
let toolClasses;
|
|
119
170
|
if (!Array.isArray(tools)) {
|
|
120
171
|
toolClasses = tools.tools;
|
|
@@ -122,13 +173,17 @@ export function createReactAgent(params) {
|
|
|
122
173
|
else {
|
|
123
174
|
toolClasses = tools;
|
|
124
175
|
}
|
|
125
|
-
|
|
126
|
-
|
|
176
|
+
let modelWithTools;
|
|
177
|
+
if (_shouldBindTools(llm, toolClasses)) {
|
|
178
|
+
if (!("bindTools" in llm) || typeof llm.bindTools !== "function") {
|
|
179
|
+
throw new Error(`llm ${llm} must define bindTools method.`);
|
|
180
|
+
}
|
|
181
|
+
modelWithTools = llm.bindTools(toolClasses);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
modelWithTools = llm;
|
|
127
185
|
}
|
|
128
|
-
const
|
|
129
|
-
// we're passing store here for validation
|
|
130
|
-
const preprocessor = _getModelPreprocessingRunnable(stateModifier, messageModifier);
|
|
131
|
-
const modelRunnable = preprocessor.pipe(modelWithTools);
|
|
186
|
+
const modelRunnable = _getPrompt(prompt, stateModifier, messageModifier).pipe(modelWithTools);
|
|
132
187
|
// If any of the tools are configured to return_directly after running,
|
|
133
188
|
// our graph needs to check if these were called
|
|
134
189
|
const shouldReturnDirect = new Set(toolClasses
|
|
@@ -157,11 +212,12 @@ export function createReactAgent(params) {
|
|
|
157
212
|
"prompt" in responseFormat &&
|
|
158
213
|
"schema" in responseFormat) {
|
|
159
214
|
const { prompt, schema } = responseFormat;
|
|
160
|
-
modelWithStructuredOutput = llm.withStructuredOutput(schema);
|
|
215
|
+
modelWithStructuredOutput = _getModel(llm).withStructuredOutput(schema);
|
|
161
216
|
messages.unshift(new SystemMessage({ content: prompt }));
|
|
162
217
|
}
|
|
163
218
|
else {
|
|
164
|
-
modelWithStructuredOutput =
|
|
219
|
+
modelWithStructuredOutput =
|
|
220
|
+
_getModel(llm).withStructuredOutput(responseFormat);
|
|
165
221
|
}
|
|
166
222
|
const response = await modelWithStructuredOutput.invoke(messages, config);
|
|
167
223
|
return { structuredResponse: response };
|
|
@@ -215,5 +271,6 @@ export function createReactAgent(params) {
|
|
|
215
271
|
interruptBefore,
|
|
216
272
|
interruptAfter,
|
|
217
273
|
store,
|
|
274
|
+
name,
|
|
218
275
|
});
|
|
219
276
|
}
|
package/dist/pregel/index.cjs
CHANGED
package/dist/pregel/index.js
CHANGED
package/dist/pregel/messages.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamMessagesHandler = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
4
|
const base_1 = require("@langchain/core/callbacks/base");
|
|
6
5
|
const messages_1 = require("@langchain/core/messages");
|
|
7
6
|
const constants_js_1 = require("../constants.cjs");
|
|
@@ -47,6 +46,12 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
47
46
|
writable: true,
|
|
48
47
|
value: {}
|
|
49
48
|
});
|
|
49
|
+
Object.defineProperty(this, "stableMessageIdMap", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: {}
|
|
54
|
+
});
|
|
50
55
|
Object.defineProperty(this, "lc_prefer_streaming", {
|
|
51
56
|
enumerable: true,
|
|
52
57
|
configurable: true,
|
|
@@ -55,18 +60,26 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
55
60
|
});
|
|
56
61
|
this.streamFn = streamFn;
|
|
57
62
|
}
|
|
58
|
-
_emit(meta, message, dedupe = false) {
|
|
63
|
+
_emit(meta, message, runId, dedupe = false) {
|
|
59
64
|
if (dedupe &&
|
|
60
65
|
message.id !== undefined &&
|
|
61
66
|
this.seen[message.id] !== undefined) {
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
// For instance in ChatAnthropic, the first chunk has an message ID
|
|
70
|
+
// but the subsequent chunks do not. To avoid clients seeing two messages
|
|
71
|
+
// we rename the message ID if it's being auto-set to `run-${runId}`
|
|
72
|
+
// (see https://github.com/langchain-ai/langchainjs/pull/6646).
|
|
73
|
+
let messageId = message.id;
|
|
74
|
+
if (messageId == null || messageId === `run-${runId}`) {
|
|
75
|
+
messageId = this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;
|
|
76
|
+
}
|
|
77
|
+
this.stableMessageIdMap[runId] ??= messageId;
|
|
78
|
+
if (messageId !== message.id) {
|
|
66
79
|
// eslint-disable-next-line no-param-reassign
|
|
67
|
-
message.id =
|
|
80
|
+
message.id = messageId;
|
|
68
81
|
// eslint-disable-next-line no-param-reassign
|
|
69
|
-
message.lc_kwargs.id =
|
|
82
|
+
message.lc_kwargs.id = messageId;
|
|
70
83
|
}
|
|
71
84
|
this.seen[message.id] = message;
|
|
72
85
|
this.streamFn([meta[0], "messages", [message, meta[1]]]);
|
|
@@ -86,12 +99,10 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
86
99
|
this.emittedChatModelRunIds[runId] = true;
|
|
87
100
|
if (this.metadatas[runId] !== undefined) {
|
|
88
101
|
if (isChatGenerationChunk(chunk)) {
|
|
89
|
-
this._emit(this.metadatas[runId], chunk.message);
|
|
102
|
+
this._emit(this.metadatas[runId], chunk.message, runId);
|
|
90
103
|
}
|
|
91
104
|
else {
|
|
92
|
-
this._emit(this.metadatas[runId], new messages_1.AIMessageChunk({
|
|
93
|
-
content: token,
|
|
94
|
-
}));
|
|
105
|
+
this._emit(this.metadatas[runId], new messages_1.AIMessageChunk({ content: token }), runId);
|
|
95
106
|
}
|
|
96
107
|
}
|
|
97
108
|
}
|
|
@@ -100,11 +111,12 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
100
111
|
if (!this.emittedChatModelRunIds[runId]) {
|
|
101
112
|
const chatGeneration = output.generations?.[0]?.[0];
|
|
102
113
|
if ((0, messages_1.isBaseMessage)(chatGeneration?.message)) {
|
|
103
|
-
this._emit(this.metadatas[runId], chatGeneration?.message, true);
|
|
114
|
+
this._emit(this.metadatas[runId], chatGeneration?.message, runId, true);
|
|
104
115
|
}
|
|
105
116
|
delete this.emittedChatModelRunIds[runId];
|
|
106
117
|
}
|
|
107
118
|
delete this.metadatas[runId];
|
|
119
|
+
delete this.stableMessageIdMap[runId];
|
|
108
120
|
}
|
|
109
121
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
122
|
handleLLMError(_err, runId) {
|
|
@@ -125,24 +137,24 @@ class StreamMessagesHandler extends base_1.BaseCallbackHandler {
|
|
|
125
137
|
delete this.metadatas[runId];
|
|
126
138
|
if (metadata !== undefined) {
|
|
127
139
|
if ((0, messages_1.isBaseMessage)(outputs)) {
|
|
128
|
-
this._emit(metadata, outputs, true);
|
|
140
|
+
this._emit(metadata, outputs, runId, true);
|
|
129
141
|
}
|
|
130
142
|
else if (Array.isArray(outputs)) {
|
|
131
143
|
for (const value of outputs) {
|
|
132
144
|
if ((0, messages_1.isBaseMessage)(value)) {
|
|
133
|
-
this._emit(metadata, value, true);
|
|
145
|
+
this._emit(metadata, value, runId, true);
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
}
|
|
137
149
|
else if (outputs != null && typeof outputs === "object") {
|
|
138
150
|
for (const value of Object.values(outputs)) {
|
|
139
151
|
if ((0, messages_1.isBaseMessage)(value)) {
|
|
140
|
-
this._emit(metadata, value, true);
|
|
152
|
+
this._emit(metadata, value, runId, true);
|
|
141
153
|
}
|
|
142
154
|
else if (Array.isArray(value)) {
|
|
143
155
|
for (const item of value) {
|
|
144
156
|
if ((0, messages_1.isBaseMessage)(item)) {
|
|
145
|
-
this._emit(metadata, item, true);
|
|
157
|
+
this._emit(metadata, item, runId, true);
|
|
146
158
|
}
|
|
147
159
|
}
|
|
148
160
|
}
|
|
@@ -15,9 +15,10 @@ export declare class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
15
15
|
metadatas: Record<string, Meta>;
|
|
16
16
|
seen: Record<string, BaseMessage>;
|
|
17
17
|
emittedChatModelRunIds: Record<string, boolean>;
|
|
18
|
+
stableMessageIdMap: Record<string, string>;
|
|
18
19
|
lc_prefer_streaming: boolean;
|
|
19
20
|
constructor(streamFn: (streamChunk: StreamChunk) => void);
|
|
20
|
-
_emit(meta: Meta, message: BaseMessage, dedupe?: boolean): void;
|
|
21
|
+
_emit(meta: Meta, message: BaseMessage, runId: string, dedupe?: boolean): void;
|
|
21
22
|
handleChatModelStart(_llm: Serialized, _messages: BaseMessage[][], runId: string, _parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, name?: string): void;
|
|
22
23
|
handleLLMNewToken(token: string, _idx: NewTokenIndices, runId: string, _parentRunId?: string, _tags?: string[], fields?: HandleLLMNewTokenCallbackFields): void;
|
|
23
24
|
handleLLMEnd(output: LLMResult, runId: string): void;
|
package/dist/pregel/messages.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { v4 } from "uuid";
|
|
2
1
|
import { BaseCallbackHandler, } from "@langchain/core/callbacks/base";
|
|
3
2
|
import { AIMessageChunk, isBaseMessage, } from "@langchain/core/messages";
|
|
4
3
|
import { TAG_HIDDEN, TAG_NOSTREAM } from "../constants.js";
|
|
@@ -44,6 +43,12 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
44
43
|
writable: true,
|
|
45
44
|
value: {}
|
|
46
45
|
});
|
|
46
|
+
Object.defineProperty(this, "stableMessageIdMap", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: {}
|
|
51
|
+
});
|
|
47
52
|
Object.defineProperty(this, "lc_prefer_streaming", {
|
|
48
53
|
enumerable: true,
|
|
49
54
|
configurable: true,
|
|
@@ -52,18 +57,26 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
52
57
|
});
|
|
53
58
|
this.streamFn = streamFn;
|
|
54
59
|
}
|
|
55
|
-
_emit(meta, message, dedupe = false) {
|
|
60
|
+
_emit(meta, message, runId, dedupe = false) {
|
|
56
61
|
if (dedupe &&
|
|
57
62
|
message.id !== undefined &&
|
|
58
63
|
this.seen[message.id] !== undefined) {
|
|
59
64
|
return;
|
|
60
65
|
}
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
// For instance in ChatAnthropic, the first chunk has an message ID
|
|
67
|
+
// but the subsequent chunks do not. To avoid clients seeing two messages
|
|
68
|
+
// we rename the message ID if it's being auto-set to `run-${runId}`
|
|
69
|
+
// (see https://github.com/langchain-ai/langchainjs/pull/6646).
|
|
70
|
+
let messageId = message.id;
|
|
71
|
+
if (messageId == null || messageId === `run-${runId}`) {
|
|
72
|
+
messageId = this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;
|
|
73
|
+
}
|
|
74
|
+
this.stableMessageIdMap[runId] ??= messageId;
|
|
75
|
+
if (messageId !== message.id) {
|
|
63
76
|
// eslint-disable-next-line no-param-reassign
|
|
64
|
-
message.id =
|
|
77
|
+
message.id = messageId;
|
|
65
78
|
// eslint-disable-next-line no-param-reassign
|
|
66
|
-
message.lc_kwargs.id =
|
|
79
|
+
message.lc_kwargs.id = messageId;
|
|
67
80
|
}
|
|
68
81
|
this.seen[message.id] = message;
|
|
69
82
|
this.streamFn([meta[0], "messages", [message, meta[1]]]);
|
|
@@ -83,12 +96,10 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
83
96
|
this.emittedChatModelRunIds[runId] = true;
|
|
84
97
|
if (this.metadatas[runId] !== undefined) {
|
|
85
98
|
if (isChatGenerationChunk(chunk)) {
|
|
86
|
-
this._emit(this.metadatas[runId], chunk.message);
|
|
99
|
+
this._emit(this.metadatas[runId], chunk.message, runId);
|
|
87
100
|
}
|
|
88
101
|
else {
|
|
89
|
-
this._emit(this.metadatas[runId], new AIMessageChunk({
|
|
90
|
-
content: token,
|
|
91
|
-
}));
|
|
102
|
+
this._emit(this.metadatas[runId], new AIMessageChunk({ content: token }), runId);
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
105
|
}
|
|
@@ -97,11 +108,12 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
97
108
|
if (!this.emittedChatModelRunIds[runId]) {
|
|
98
109
|
const chatGeneration = output.generations?.[0]?.[0];
|
|
99
110
|
if (isBaseMessage(chatGeneration?.message)) {
|
|
100
|
-
this._emit(this.metadatas[runId], chatGeneration?.message, true);
|
|
111
|
+
this._emit(this.metadatas[runId], chatGeneration?.message, runId, true);
|
|
101
112
|
}
|
|
102
113
|
delete this.emittedChatModelRunIds[runId];
|
|
103
114
|
}
|
|
104
115
|
delete this.metadatas[runId];
|
|
116
|
+
delete this.stableMessageIdMap[runId];
|
|
105
117
|
}
|
|
106
118
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
119
|
handleLLMError(_err, runId) {
|
|
@@ -122,24 +134,24 @@ export class StreamMessagesHandler extends BaseCallbackHandler {
|
|
|
122
134
|
delete this.metadatas[runId];
|
|
123
135
|
if (metadata !== undefined) {
|
|
124
136
|
if (isBaseMessage(outputs)) {
|
|
125
|
-
this._emit(metadata, outputs, true);
|
|
137
|
+
this._emit(metadata, outputs, runId, true);
|
|
126
138
|
}
|
|
127
139
|
else if (Array.isArray(outputs)) {
|
|
128
140
|
for (const value of outputs) {
|
|
129
141
|
if (isBaseMessage(value)) {
|
|
130
|
-
this._emit(metadata, value, true);
|
|
142
|
+
this._emit(metadata, value, runId, true);
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
}
|
|
134
146
|
else if (outputs != null && typeof outputs === "object") {
|
|
135
147
|
for (const value of Object.values(outputs)) {
|
|
136
148
|
if (isBaseMessage(value)) {
|
|
137
|
-
this._emit(metadata, value, true);
|
|
149
|
+
this._emit(metadata, value, runId, true);
|
|
138
150
|
}
|
|
139
151
|
else if (Array.isArray(value)) {
|
|
140
152
|
for (const item of value) {
|
|
141
153
|
if (isBaseMessage(item)) {
|
|
142
|
-
this._emit(metadata, item, true);
|
|
154
|
+
this._emit(metadata, item, runId, true);
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
157
|
}
|
package/dist/pregel/remote.cjs
CHANGED
|
@@ -41,18 +41,13 @@ const getStreamModes = (streamMode, defaultStreamMode = "updates") => {
|
|
|
41
41
|
if (streamMode !== undefined &&
|
|
42
42
|
(typeof streamMode === "string" ||
|
|
43
43
|
(Array.isArray(streamMode) && streamMode.length > 0))) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else {
|
|
48
|
-
reqSingle = false;
|
|
49
|
-
updatedStreamModes.push(...streamMode);
|
|
50
|
-
}
|
|
44
|
+
reqSingle = typeof streamMode === "string";
|
|
45
|
+
const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];
|
|
46
|
+
updatedStreamModes.push(...mapped);
|
|
51
47
|
}
|
|
52
48
|
else {
|
|
53
49
|
updatedStreamModes.push(defaultStreamMode);
|
|
54
50
|
}
|
|
55
|
-
// TODO: Map messages to messages-tuple
|
|
56
51
|
if (updatedStreamModes.includes("updates")) {
|
|
57
52
|
reqUpdates = true;
|
|
58
53
|
}
|
|
@@ -303,7 +298,11 @@ class RemoteGraph extends runnables_1.Runnable {
|
|
|
303
298
|
...updatedStreamModes,
|
|
304
299
|
...(streamProtocolInstance?.modes ?? new Set()),
|
|
305
300
|
]),
|
|
306
|
-
]
|
|
301
|
+
].map((mode) => {
|
|
302
|
+
if (mode === "messages")
|
|
303
|
+
return "messages-tuple";
|
|
304
|
+
return mode;
|
|
305
|
+
});
|
|
307
306
|
let command;
|
|
308
307
|
let serializedInput;
|
|
309
308
|
if ((0, constants_js_1.isCommand)(input)) {
|
package/dist/pregel/remote.js
CHANGED
|
@@ -38,18 +38,13 @@ const getStreamModes = (streamMode, defaultStreamMode = "updates") => {
|
|
|
38
38
|
if (streamMode !== undefined &&
|
|
39
39
|
(typeof streamMode === "string" ||
|
|
40
40
|
(Array.isArray(streamMode) && streamMode.length > 0))) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
else {
|
|
45
|
-
reqSingle = false;
|
|
46
|
-
updatedStreamModes.push(...streamMode);
|
|
47
|
-
}
|
|
41
|
+
reqSingle = typeof streamMode === "string";
|
|
42
|
+
const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];
|
|
43
|
+
updatedStreamModes.push(...mapped);
|
|
48
44
|
}
|
|
49
45
|
else {
|
|
50
46
|
updatedStreamModes.push(defaultStreamMode);
|
|
51
47
|
}
|
|
52
|
-
// TODO: Map messages to messages-tuple
|
|
53
48
|
if (updatedStreamModes.includes("updates")) {
|
|
54
49
|
reqUpdates = true;
|
|
55
50
|
}
|
|
@@ -300,7 +295,11 @@ export class RemoteGraph extends Runnable {
|
|
|
300
295
|
...updatedStreamModes,
|
|
301
296
|
...(streamProtocolInstance?.modes ?? new Set()),
|
|
302
297
|
]),
|
|
303
|
-
]
|
|
298
|
+
].map((mode) => {
|
|
299
|
+
if (mode === "messages")
|
|
300
|
+
return "messages-tuple";
|
|
301
|
+
return mode;
|
|
302
|
+
});
|
|
304
303
|
let command;
|
|
305
304
|
let serializedInput;
|
|
306
305
|
if (isCommand(input)) {
|
package/dist/web.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { Pregel } from "./pregel/index.js";
|
|
|
5
5
|
export * from "./errors.js";
|
|
6
6
|
export { BaseChannel, type BinaryOperator, BinaryOperatorAggregate, type AnyValue, type WaitForNames, type DynamicBarrierValue, type LastValue, type NamedBarrierValue, type Topic, } from "./channels/index.js";
|
|
7
7
|
export type { EphemeralValue } from "./channels/ephemeral_value.js";
|
|
8
|
-
export { type AnnotationRoot
|
|
8
|
+
export { type AnnotationRoot } from "./graph/index.js";
|
|
9
9
|
export { type RetryPolicy } from "./pregel/utils/index.js";
|
|
10
10
|
export { Send, Command, type CommandParams, isCommand, START, END, type Interrupt, } from "./constants.js";
|
|
11
11
|
export { MemorySaver, type Checkpoint, type CheckpointMetadata, type CheckpointTuple, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, type Item, type GetOperation, type SearchOperation, type PutOperation, type Operation, type OperationResults, BaseStore, AsyncBatchedStore, InMemoryStore, type NameSpacePath, type NamespaceMatchType, type MatchCondition, type ListNamespacesOperation, } from "@langchain/langgraph-checkpoint";
|