@langchain/core 0.1.43 → 0.1.45-rc.0

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.
Files changed (44) hide show
  1. package/dist/callbacks/base.cjs +3 -4
  2. package/dist/callbacks/base.d.ts +1 -0
  3. package/dist/callbacks/base.js +3 -4
  4. package/dist/callbacks/manager.cjs +10 -0
  5. package/dist/callbacks/manager.js +10 -0
  6. package/dist/language_models/base.d.ts +1 -0
  7. package/dist/load/serializable.d.ts +6 -1
  8. package/dist/output_parsers/base.cjs +9 -3
  9. package/dist/output_parsers/base.d.ts +3 -1
  10. package/dist/output_parsers/base.js +9 -3
  11. package/dist/output_parsers/index.cjs +1 -0
  12. package/dist/output_parsers/index.d.ts +1 -0
  13. package/dist/output_parsers/index.js +1 -0
  14. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs +22 -2
  15. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.ts +6 -2
  16. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js +23 -3
  17. package/dist/output_parsers/string.cjs +21 -0
  18. package/dist/output_parsers/string.d.ts +5 -0
  19. package/dist/output_parsers/string.js +21 -0
  20. package/dist/output_parsers/structured.cjs +190 -0
  21. package/dist/output_parsers/structured.d.ts +88 -0
  22. package/dist/output_parsers/structured.js +184 -0
  23. package/dist/output_parsers/transform.cjs +1 -3
  24. package/dist/output_parsers/transform.js +1 -3
  25. package/dist/runnables/base.cjs +44 -1
  26. package/dist/runnables/base.d.ts +6 -25
  27. package/dist/runnables/base.js +45 -2
  28. package/dist/runnables/graph.cjs +164 -0
  29. package/dist/runnables/graph.d.ts +25 -0
  30. package/dist/runnables/graph.js +159 -0
  31. package/dist/runnables/index.d.ts +2 -1
  32. package/dist/runnables/types.cjs +2 -0
  33. package/dist/runnables/types.d.ts +33 -0
  34. package/dist/runnables/types.js +1 -0
  35. package/dist/runnables/utils.cjs +6 -1
  36. package/dist/runnables/utils.d.ts +2 -0
  37. package/dist/runnables/utils.js +4 -0
  38. package/dist/tracers/log_stream.cjs +1 -1
  39. package/dist/tracers/log_stream.js +1 -1
  40. package/dist/tracers/root_listener.cjs +1 -1
  41. package/dist/tracers/root_listener.js +1 -1
  42. package/dist/tracers/run_collector.cjs +1 -1
  43. package/dist/tracers/run_collector.js +1 -1
  44. package/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { BaseOutputParser, FormatInstructionsOptions } from "./base.js";
3
+ export type JsonMarkdownStructuredOutputParserInput = {
4
+ interpolationDepth?: number;
5
+ };
6
+ export interface JsonMarkdownFormatInstructionsOptions extends FormatInstructionsOptions {
7
+ interpolationDepth?: number;
8
+ }
9
+ export declare class StructuredOutputParser<T extends z.ZodTypeAny> extends BaseOutputParser<z.infer<T>> {
10
+ schema: T;
11
+ static lc_name(): string;
12
+ lc_namespace: string[];
13
+ toJSON(): import("../load/serializable.js").SerializedNotImplemented;
14
+ constructor(schema: T);
15
+ /**
16
+ * Creates a new StructuredOutputParser from a Zod schema.
17
+ * @param schema The Zod schema which the output should match
18
+ * @returns A new instance of StructuredOutputParser.
19
+ */
20
+ static fromZodSchema<T extends z.ZodTypeAny>(schema: T): StructuredOutputParser<T>;
21
+ /**
22
+ * Creates a new StructuredOutputParser from a set of names and
23
+ * descriptions.
24
+ * @param schemas An object where each key is a name and each value is a description
25
+ * @returns A new instance of StructuredOutputParser.
26
+ */
27
+ static fromNamesAndDescriptions<S extends {
28
+ [key: string]: string;
29
+ }>(schemas: S): StructuredOutputParser<z.ZodObject<{
30
+ [k: string]: z.ZodString;
31
+ }, "strip", z.ZodTypeAny, {
32
+ [x: string]: string;
33
+ }, {
34
+ [x: string]: string;
35
+ }>>;
36
+ /**
37
+ * Returns a markdown code snippet with a JSON object formatted according
38
+ * to the schema.
39
+ * @param options Optional. The options for formatting the instructions
40
+ * @returns A markdown code snippet with a JSON object formatted according to the schema.
41
+ */
42
+ getFormatInstructions(): string;
43
+ /**
44
+ * Parses the given text according to the schema.
45
+ * @param text The text to parse
46
+ * @returns The parsed output.
47
+ */
48
+ parse(text: string): Promise<z.infer<T>>;
49
+ }
50
+ /**
51
+ * A specific type of `StructuredOutputParser` that parses JSON data
52
+ * formatted as a markdown code snippet.
53
+ */
54
+ export declare class JsonMarkdownStructuredOutputParser<T extends z.ZodTypeAny> extends StructuredOutputParser<T> {
55
+ static lc_name(): string;
56
+ getFormatInstructions(options?: JsonMarkdownFormatInstructionsOptions): string;
57
+ private _schemaToInstruction;
58
+ static fromZodSchema<T extends z.ZodTypeAny>(schema: T): JsonMarkdownStructuredOutputParser<T>;
59
+ static fromNamesAndDescriptions<S extends {
60
+ [key: string]: string;
61
+ }>(schemas: S): JsonMarkdownStructuredOutputParser<z.ZodObject<{
62
+ [k: string]: z.ZodString;
63
+ }, "strip", z.ZodTypeAny, {
64
+ [x: string]: string;
65
+ }, {
66
+ [x: string]: string;
67
+ }>>;
68
+ }
69
+ export interface AsymmetricStructuredOutputParserFields<T extends z.ZodTypeAny> {
70
+ inputSchema: T;
71
+ }
72
+ /**
73
+ * A type of `StructuredOutputParser` that handles asymmetric input and
74
+ * output schemas.
75
+ */
76
+ export declare abstract class AsymmetricStructuredOutputParser<T extends z.ZodTypeAny, Y = unknown> extends BaseOutputParser<Y> {
77
+ private structuredInputParser;
78
+ constructor({ inputSchema }: AsymmetricStructuredOutputParserFields<T>);
79
+ /**
80
+ * Processes the parsed input into the desired output format. Must be
81
+ * implemented by subclasses.
82
+ * @param input The parsed input
83
+ * @returns The processed output.
84
+ */
85
+ abstract outputProcessor(input: z.infer<T>): Promise<Y>;
86
+ parse(text: string): Promise<Y>;
87
+ getFormatInstructions(): string;
88
+ }
@@ -0,0 +1,184 @@
1
+ import { z } from "zod";
2
+ import { zodToJsonSchema, } from "zod-to-json-schema";
3
+ import { BaseOutputParser, OutputParserException, } from "./base.js";
4
+ export class StructuredOutputParser extends BaseOutputParser {
5
+ static lc_name() {
6
+ return "StructuredOutputParser";
7
+ }
8
+ toJSON() {
9
+ return this.toJSONNotImplemented();
10
+ }
11
+ constructor(schema) {
12
+ super(schema);
13
+ Object.defineProperty(this, "schema", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: schema
18
+ });
19
+ Object.defineProperty(this, "lc_namespace", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: ["langchain", "output_parsers", "structured"]
24
+ });
25
+ }
26
+ /**
27
+ * Creates a new StructuredOutputParser from a Zod schema.
28
+ * @param schema The Zod schema which the output should match
29
+ * @returns A new instance of StructuredOutputParser.
30
+ */
31
+ static fromZodSchema(schema) {
32
+ return new this(schema);
33
+ }
34
+ /**
35
+ * Creates a new StructuredOutputParser from a set of names and
36
+ * descriptions.
37
+ * @param schemas An object where each key is a name and each value is a description
38
+ * @returns A new instance of StructuredOutputParser.
39
+ */
40
+ static fromNamesAndDescriptions(schemas) {
41
+ const zodSchema = z.object(Object.fromEntries(Object.entries(schemas).map(([name, description]) => [name, z.string().describe(description)])));
42
+ return new this(zodSchema);
43
+ }
44
+ /**
45
+ * Returns a markdown code snippet with a JSON object formatted according
46
+ * to the schema.
47
+ * @param options Optional. The options for formatting the instructions
48
+ * @returns A markdown code snippet with a JSON object formatted according to the schema.
49
+ */
50
+ getFormatInstructions() {
51
+ return `You must format your output as a JSON value that adheres to a given "JSON Schema" instance.
52
+
53
+ "JSON Schema" is a declarative language that allows you to annotate and validate JSON documents.
54
+
55
+ For example, the example "JSON Schema" instance {{"properties": {{"foo": {{"description": "a list of test words", "type": "array", "items": {{"type": "string"}}}}}}, "required": ["foo"]}}}}
56
+ would match an object with one required property, "foo". The "type" property specifies "foo" must be an "array", and the "description" property semantically describes it as "a list of test words". The items within "foo" must be strings.
57
+ Thus, the object {{"foo": ["bar", "baz"]}} is a well-formatted instance of this example "JSON Schema". The object {{"properties": {{"foo": ["bar", "baz"]}}}} is not well-formatted.
58
+
59
+ Your output will be parsed and type-checked according to the provided schema instance, so make sure all fields in your output match the schema exactly and there are no trailing commas!
60
+
61
+ Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock:
62
+ \`\`\`json
63
+ ${JSON.stringify(zodToJsonSchema(this.schema))}
64
+ \`\`\`
65
+ `;
66
+ }
67
+ /**
68
+ * Parses the given text according to the schema.
69
+ * @param text The text to parse
70
+ * @returns The parsed output.
71
+ */
72
+ async parse(text) {
73
+ try {
74
+ const json = text.includes("```")
75
+ ? text.trim().split(/```(?:json)?/)[1]
76
+ : text.trim();
77
+ return await this.schema.parseAsync(JSON.parse(json));
78
+ }
79
+ catch (e) {
80
+ throw new OutputParserException(`Failed to parse. Text: "${text}". Error: ${e}`, text);
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * A specific type of `StructuredOutputParser` that parses JSON data
86
+ * formatted as a markdown code snippet.
87
+ */
88
+ export class JsonMarkdownStructuredOutputParser extends StructuredOutputParser {
89
+ static lc_name() {
90
+ return "JsonMarkdownStructuredOutputParser";
91
+ }
92
+ getFormatInstructions(options) {
93
+ const interpolationDepth = options?.interpolationDepth ?? 1;
94
+ if (interpolationDepth < 1) {
95
+ throw new Error("f string interpolation depth must be at least 1");
96
+ }
97
+ return `Return a markdown code snippet with a JSON object formatted to look like:\n\`\`\`json\n${this._schemaToInstruction(zodToJsonSchema(this.schema))
98
+ .replaceAll("{", "{".repeat(interpolationDepth))
99
+ .replaceAll("}", "}".repeat(interpolationDepth))}\n\`\`\``;
100
+ }
101
+ _schemaToInstruction(schemaInput, indent = 2) {
102
+ const schema = schemaInput;
103
+ if ("type" in schema) {
104
+ let nullable = false;
105
+ let type;
106
+ if (Array.isArray(schema.type)) {
107
+ const nullIdx = schema.type.findIndex((type) => type === "null");
108
+ if (nullIdx !== -1) {
109
+ nullable = true;
110
+ schema.type.splice(nullIdx, 1);
111
+ }
112
+ type = schema.type.join(" | ");
113
+ }
114
+ else {
115
+ type = schema.type;
116
+ }
117
+ if (schema.type === "object" && schema.properties) {
118
+ const description = schema.description
119
+ ? ` // ${schema.description}`
120
+ : "";
121
+ const properties = Object.entries(schema.properties)
122
+ .map(([key, value]) => {
123
+ const isOptional = schema.required?.includes(key)
124
+ ? ""
125
+ : " (optional)";
126
+ return `${" ".repeat(indent)}"${key}": ${this._schemaToInstruction(value, indent + 2)}${isOptional}`;
127
+ })
128
+ .join("\n");
129
+ return `{\n${properties}\n${" ".repeat(indent - 2)}}${description}`;
130
+ }
131
+ if (schema.type === "array" && schema.items) {
132
+ const description = schema.description
133
+ ? ` // ${schema.description}`
134
+ : "";
135
+ return `array[\n${" ".repeat(indent)}${this._schemaToInstruction(schema.items, indent + 2)}\n${" ".repeat(indent - 2)}] ${description}`;
136
+ }
137
+ const isNullable = nullable ? " (nullable)" : "";
138
+ const description = schema.description ? ` // ${schema.description}` : "";
139
+ return `${type}${description}${isNullable}`;
140
+ }
141
+ if ("anyOf" in schema) {
142
+ return schema.anyOf
143
+ .map((s) => this._schemaToInstruction(s, indent))
144
+ .join(`\n${" ".repeat(indent - 2)}`);
145
+ }
146
+ throw new Error("unsupported schema type");
147
+ }
148
+ static fromZodSchema(schema) {
149
+ return new this(schema);
150
+ }
151
+ static fromNamesAndDescriptions(schemas) {
152
+ const zodSchema = z.object(Object.fromEntries(Object.entries(schemas).map(([name, description]) => [name, z.string().describe(description)])));
153
+ return new this(zodSchema);
154
+ }
155
+ }
156
+ /**
157
+ * A type of `StructuredOutputParser` that handles asymmetric input and
158
+ * output schemas.
159
+ */
160
+ export class AsymmetricStructuredOutputParser extends BaseOutputParser {
161
+ constructor({ inputSchema }) {
162
+ super(...arguments);
163
+ Object.defineProperty(this, "structuredInputParser", {
164
+ enumerable: true,
165
+ configurable: true,
166
+ writable: true,
167
+ value: void 0
168
+ });
169
+ this.structuredInputParser = new JsonMarkdownStructuredOutputParser(inputSchema);
170
+ }
171
+ async parse(text) {
172
+ let parsedInput;
173
+ try {
174
+ parsedInput = await this.structuredInputParser.parse(text);
175
+ }
176
+ catch (e) {
177
+ throw new OutputParserException(`Failed to parse. Text: "${text}". Error: ${e}`, text);
178
+ }
179
+ return this.outputProcessor(parsedInput);
180
+ }
181
+ getFormatInstructions() {
182
+ return this.structuredInputParser.getFormatInstructions();
183
+ }
184
+ }
@@ -18,9 +18,7 @@ class BaseTransformOutputParser extends base_js_1.BaseOutputParser {
18
18
  yield this.parseResult([
19
19
  {
20
20
  message: chunk,
21
- text: typeof chunk.content === "string"
22
- ? chunk.content
23
- : JSON.stringify(chunk.content),
21
+ text: this._baseMessageToString(chunk),
24
22
  },
25
23
  ]);
26
24
  }
@@ -15,9 +15,7 @@ export class BaseTransformOutputParser extends BaseOutputParser {
15
15
  yield this.parseResult([
16
16
  {
17
17
  message: chunk,
18
- text: typeof chunk.content === "string"
19
- ? chunk.content
20
- : JSON.stringify(chunk.content),
18
+ text: this._baseMessageToString(chunk),
21
19
  },
22
20
  ]);
23
21
  }
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.RunnablePick = exports.RunnableAssign = exports._coerceToRunnable = exports.RunnableWithFallbacks = exports.RunnableParallel = exports.RunnableLambda = exports.RunnableMap = exports.RunnableSequence = exports.RunnableRetry = exports.RunnableEach = exports.RunnableBinding = exports.Runnable = exports._coerceToDict = void 0;
7
+ const zod_1 = require("zod");
7
8
  const p_retry_1 = __importDefault(require("p-retry"));
8
9
  const manager_js_1 = require("../callbacks/manager.cjs");
9
10
  const log_stream_js_1 = require("../tracers/log_stream.cjs");
@@ -14,6 +15,7 @@ const async_caller_js_1 = require("../utils/async_caller.cjs");
14
15
  const root_listener_js_1 = require("../tracers/root_listener.cjs");
15
16
  const utils_js_1 = require("./utils.cjs");
16
17
  const index_js_1 = require("../singletons/index.cjs");
18
+ const graph_js_1 = require("./graph.cjs");
17
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
20
  function _coerceToDict(value, defaultKey) {
19
21
  return value &&
@@ -291,6 +293,23 @@ class Runnable extends serializable_js_1.Serializable {
291
293
  }
292
294
  await runManager?.handleChainEnd(finalOutput ?? {}, undefined, undefined, undefined, { inputs: _coerceToDict(finalInput, "input") });
293
295
  }
296
+ getGraph(_) {
297
+ const graph = new graph_js_1.Graph();
298
+ // TODO: Add input schema for runnables
299
+ const inputNode = graph.addNode({
300
+ name: `${this.getName()}Input`,
301
+ schema: zod_1.z.any(),
302
+ });
303
+ const runnableNode = graph.addNode(this);
304
+ // TODO: Add output schemas for runnables
305
+ const outputNode = graph.addNode({
306
+ name: `${this.getName()}Output`,
307
+ schema: zod_1.z.any(),
308
+ });
309
+ graph.addEdge(inputNode, runnableNode);
310
+ graph.addEdge(runnableNode, outputNode);
311
+ return graph;
312
+ }
294
313
  /**
295
314
  * Create a new runnable sequence that runs each individual runnable in series,
296
315
  * piping the output of one runnable into another runnable or runnable-like.
@@ -593,7 +612,7 @@ class Runnable extends serializable_js_1.Serializable {
593
612
  }
594
613
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
595
614
  static isRunnable(thing) {
596
- return thing ? thing.lc_runnable : false;
615
+ return (0, utils_js_1.isRunnableInterface)(thing);
597
616
  }
598
617
  /**
599
618
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -1106,6 +1125,30 @@ class RunnableSequence extends Runnable {
1106
1125
  }
1107
1126
  await runManager?.handleChainEnd(_coerceToDict(finalOutput, "output"));
1108
1127
  }
1128
+ getGraph(config) {
1129
+ const graph = new graph_js_1.Graph();
1130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1131
+ let currentLastNode = null;
1132
+ this.steps.forEach((step, index) => {
1133
+ const stepGraph = step.getGraph(config);
1134
+ if (index !== 0) {
1135
+ stepGraph.trimFirstNode();
1136
+ }
1137
+ if (index !== this.steps.length - 1) {
1138
+ stepGraph.trimLastNode();
1139
+ }
1140
+ graph.extend(stepGraph);
1141
+ const stepFirstNode = stepGraph.firstNode();
1142
+ if (!stepFirstNode) {
1143
+ throw new Error(`Runnable ${step} has no first node`);
1144
+ }
1145
+ if (currentLastNode) {
1146
+ graph.addEdge(currentLastNode, stepFirstNode);
1147
+ }
1148
+ currentLastNode = stepGraph.lastNode();
1149
+ });
1150
+ return graph;
1151
+ }
1109
1152
  pipe(coerceable) {
1110
1153
  if (RunnableSequence.isRunnableSequence(coerceable)) {
1111
1154
  return new RunnableSequence({
@@ -1,28 +1,12 @@
1
+ import type { RunnableInterface, RunnableBatchOptions } from "./types.js";
1
2
  import { CallbackManagerForChainRun } from "../callbacks/manager.js";
2
3
  import { LogStreamCallbackHandler, LogStreamCallbackHandlerInput, RunLogPatch, StreamEvent } from "../tracers/log_stream.js";
3
4
  import { Serializable } from "../load/serializable.js";
4
- import { IterableReadableStream, type IterableReadableStreamInterface } from "../utils/stream.js";
5
+ import { IterableReadableStream } from "../utils/stream.js";
5
6
  import { RunnableConfig } from "./config.js";
6
7
  import { Run } from "../tracers/base.js";
7
- /**
8
- * Base interface implemented by all runnables.
9
- * Used for cross-compatibility between different versions of LangChain core.
10
- *
11
- * Should not change on patch releases.
12
- */
13
- export interface RunnableInterface<RunInput = any, RunOutput = any, CallOptions extends RunnableConfig = RunnableConfig> {
14
- lc_serializable: boolean;
15
- invoke(input: RunInput, options?: Partial<CallOptions>): Promise<RunOutput>;
16
- batch(inputs: RunInput[], options?: Partial<CallOptions> | Partial<CallOptions>[], batchOptions?: RunnableBatchOptions & {
17
- returnExceptions?: false;
18
- }): Promise<RunOutput[]>;
19
- batch(inputs: RunInput[], options?: Partial<CallOptions> | Partial<CallOptions>[], batchOptions?: RunnableBatchOptions & {
20
- returnExceptions: true;
21
- }): Promise<(RunOutput | Error)[]>;
22
- batch(inputs: RunInput[], options?: Partial<CallOptions> | Partial<CallOptions>[], batchOptions?: RunnableBatchOptions): Promise<(RunOutput | Error)[]>;
23
- stream(input: RunInput, options?: Partial<CallOptions>): Promise<IterableReadableStreamInterface<RunOutput>>;
24
- transform(generator: AsyncGenerator<RunInput>, options: Partial<CallOptions>): AsyncGenerator<RunOutput>;
25
- }
8
+ import { Graph } from "./graph.js";
9
+ export { type RunnableInterface, RunnableBatchOptions };
26
10
  export type RunnableFunc<RunInput, RunOutput> = (input: RunInput, options?: ({
27
11
  config?: RunnableConfig;
28
12
  } & RunnableConfig) | Record<string, any> | (Record<string, any> & {
@@ -32,11 +16,6 @@ export type RunnableMapLike<RunInput, RunOutput> = {
32
16
  [K in keyof RunOutput]: RunnableLike<RunInput, RunOutput[K]>;
33
17
  };
34
18
  export type RunnableLike<RunInput = any, RunOutput = any> = RunnableInterface<RunInput, RunOutput> | RunnableFunc<RunInput, RunOutput> | RunnableMapLike<RunInput, RunOutput>;
35
- export type RunnableBatchOptions = {
36
- /** @deprecated Pass in via the standard runnable config object instead */
37
- maxConcurrency?: number;
38
- returnExceptions?: boolean;
39
- };
40
19
  export type RunnableRetryFailedAttemptHandler = (error: any) => any;
41
20
  export declare function _coerceToDict(value: any, defaultKey: string): any;
42
21
  /**
@@ -141,6 +120,7 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
141
120
  protected _transformStreamWithConfig<I extends RunInput, O extends RunOutput>(inputGenerator: AsyncGenerator<I>, transformer: (generator: AsyncGenerator<I>, runManager?: CallbackManagerForChainRun, options?: Partial<CallOptions>) => AsyncGenerator<O>, options?: CallOptions & {
142
121
  runType?: string;
143
122
  }): AsyncGenerator<O>;
123
+ getGraph(_?: RunnableConfig): Graph;
144
124
  /**
145
125
  * Create a new runnable sequence that runs each individual runnable in series,
146
126
  * piping the output of one runnable into another runnable or runnable-like.
@@ -413,6 +393,7 @@ export declare class RunnableSequence<RunInput = any, RunOutput = any> extends R
413
393
  }): Promise<(RunOutput | Error)[]>;
414
394
  batch(inputs: RunInput[], options?: Partial<RunnableConfig> | Partial<RunnableConfig>[], batchOptions?: RunnableBatchOptions): Promise<(RunOutput | Error)[]>;
415
395
  _streamIterator(input: RunInput, options?: RunnableConfig): AsyncGenerator<RunOutput>;
396
+ getGraph(config?: RunnableConfig): Graph;
416
397
  pipe<NewRunOutput>(coerceable: RunnableLike<RunOutput, NewRunOutput>): RunnableSequence<RunInput, Exclude<NewRunOutput, Error>>;
417
398
  static isRunnableSequence(thing: any): thing is RunnableSequence;
418
399
  static from<RunInput = any, RunOutput = any>([first, ...runnables]: [
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  import pRetry from "p-retry";
2
3
  import { CallbackManager, } from "../callbacks/manager.js";
3
4
  import { LogStreamCallbackHandler, RunLog, RunLogPatch, } from "../tracers/log_stream.js";
@@ -6,8 +7,9 @@ import { IterableReadableStream, concat, atee, pipeGeneratorWithSetup, AsyncGene
6
7
  import { DEFAULT_RECURSION_LIMIT, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, } from "./config.js";
7
8
  import { AsyncCaller } from "../utils/async_caller.js";
8
9
  import { RootListenersTracer } from "../tracers/root_listener.js";
9
- import { _RootEventFilter } from "./utils.js";
10
+ import { _RootEventFilter, isRunnableInterface } from "./utils.js";
10
11
  import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js";
12
+ import { Graph } from "./graph.js";
11
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
14
  export function _coerceToDict(value, defaultKey) {
13
15
  return value &&
@@ -284,6 +286,23 @@ export class Runnable extends Serializable {
284
286
  }
285
287
  await runManager?.handleChainEnd(finalOutput ?? {}, undefined, undefined, undefined, { inputs: _coerceToDict(finalInput, "input") });
286
288
  }
289
+ getGraph(_) {
290
+ const graph = new Graph();
291
+ // TODO: Add input schema for runnables
292
+ const inputNode = graph.addNode({
293
+ name: `${this.getName()}Input`,
294
+ schema: z.any(),
295
+ });
296
+ const runnableNode = graph.addNode(this);
297
+ // TODO: Add output schemas for runnables
298
+ const outputNode = graph.addNode({
299
+ name: `${this.getName()}Output`,
300
+ schema: z.any(),
301
+ });
302
+ graph.addEdge(inputNode, runnableNode);
303
+ graph.addEdge(runnableNode, outputNode);
304
+ return graph;
305
+ }
287
306
  /**
288
307
  * Create a new runnable sequence that runs each individual runnable in series,
289
308
  * piping the output of one runnable into another runnable or runnable-like.
@@ -586,7 +605,7 @@ export class Runnable extends Serializable {
586
605
  }
587
606
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
588
607
  static isRunnable(thing) {
589
- return thing ? thing.lc_runnable : false;
608
+ return isRunnableInterface(thing);
590
609
  }
591
610
  /**
592
611
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -1095,6 +1114,30 @@ export class RunnableSequence extends Runnable {
1095
1114
  }
1096
1115
  await runManager?.handleChainEnd(_coerceToDict(finalOutput, "output"));
1097
1116
  }
1117
+ getGraph(config) {
1118
+ const graph = new Graph();
1119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1120
+ let currentLastNode = null;
1121
+ this.steps.forEach((step, index) => {
1122
+ const stepGraph = step.getGraph(config);
1123
+ if (index !== 0) {
1124
+ stepGraph.trimFirstNode();
1125
+ }
1126
+ if (index !== this.steps.length - 1) {
1127
+ stepGraph.trimLastNode();
1128
+ }
1129
+ graph.extend(stepGraph);
1130
+ const stepFirstNode = stepGraph.firstNode();
1131
+ if (!stepFirstNode) {
1132
+ throw new Error(`Runnable ${step} has no first node`);
1133
+ }
1134
+ if (currentLastNode) {
1135
+ graph.addEdge(currentLastNode, stepFirstNode);
1136
+ }
1137
+ currentLastNode = stepGraph.lastNode();
1138
+ });
1139
+ return graph;
1140
+ }
1098
1141
  pipe(coerceable) {
1099
1142
  if (RunnableSequence.isRunnableSequence(coerceable)) {
1100
1143
  return new RunnableSequence({
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Graph = exports.nodeDataStr = void 0;
4
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
5
+ const uuid_1 = require("uuid");
6
+ const utils_js_1 = require("./utils.cjs");
7
+ const MAX_DATA_DISPLAY_NAME_LENGTH = 42;
8
+ function nodeDataStr(node) {
9
+ if (!(0, uuid_1.validate)(node.id)) {
10
+ return node.id;
11
+ }
12
+ else if ((0, utils_js_1.isRunnableInterface)(node.data)) {
13
+ try {
14
+ let data = node.data.toString();
15
+ if (data.startsWith("<") ||
16
+ data[0] !== data[0].toUpperCase() ||
17
+ data.split("\n").length > 1) {
18
+ data = node.data.getName();
19
+ }
20
+ else if (data.length > MAX_DATA_DISPLAY_NAME_LENGTH) {
21
+ data = `${data.substring(0, MAX_DATA_DISPLAY_NAME_LENGTH)}...`;
22
+ }
23
+ return data.startsWith("Runnable") ? data.slice("Runnable".length) : data;
24
+ }
25
+ catch (error) {
26
+ return node.data.getName();
27
+ }
28
+ }
29
+ else {
30
+ return node.data.name ?? "UnknownSchema";
31
+ }
32
+ }
33
+ exports.nodeDataStr = nodeDataStr;
34
+ function nodeDataJson(node) {
35
+ // if node.data is implements Runnable
36
+ if ((0, utils_js_1.isRunnableInterface)(node.data)) {
37
+ return {
38
+ type: "runnable",
39
+ data: {
40
+ id: node.data.lc_id,
41
+ name: node.data.getName(),
42
+ },
43
+ };
44
+ }
45
+ else {
46
+ return {
47
+ type: "schema",
48
+ data: { ...(0, zod_to_json_schema_1.zodToJsonSchema)(node.data.schema), title: node.data.name },
49
+ };
50
+ }
51
+ }
52
+ class Graph {
53
+ constructor() {
54
+ Object.defineProperty(this, "nodes", {
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true,
58
+ value: {}
59
+ });
60
+ Object.defineProperty(this, "edges", {
61
+ enumerable: true,
62
+ configurable: true,
63
+ writable: true,
64
+ value: []
65
+ });
66
+ }
67
+ // Convert the graph to a JSON-serializable format.
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ toJSON() {
70
+ const stableNodeIds = {};
71
+ Object.values(this.nodes).forEach((node, i) => {
72
+ stableNodeIds[node.id] = (0, uuid_1.validate)(node.id) ? i : node.id;
73
+ });
74
+ return {
75
+ nodes: Object.values(this.nodes).map((node) => ({
76
+ id: stableNodeIds[node.id],
77
+ ...nodeDataJson(node),
78
+ })),
79
+ edges: this.edges.map((edge) => edge.data
80
+ ? {
81
+ source: stableNodeIds[edge.source],
82
+ target: stableNodeIds[edge.target],
83
+ data: edge.data,
84
+ }
85
+ : {
86
+ source: stableNodeIds[edge.source],
87
+ target: stableNodeIds[edge.target],
88
+ }),
89
+ };
90
+ }
91
+ addNode(data, id) {
92
+ if (id !== undefined && this.nodes[id] !== undefined) {
93
+ throw new Error(`Node with id ${id} already exists`);
94
+ }
95
+ const nodeId = id || (0, uuid_1.v4)();
96
+ const node = { id: nodeId, data };
97
+ this.nodes[nodeId] = node;
98
+ return node;
99
+ }
100
+ removeNode(node) {
101
+ // Remove the node from the nodes map
102
+ delete this.nodes[node.id];
103
+ // Filter out edges connected to the node
104
+ this.edges = this.edges.filter((edge) => edge.source !== node.id && edge.target !== node.id);
105
+ }
106
+ addEdge(source, target, data) {
107
+ if (this.nodes[source.id] === undefined) {
108
+ throw new Error(`Source node ${source.id} not in graph`);
109
+ }
110
+ if (this.nodes[target.id] === undefined) {
111
+ throw new Error(`Target node ${target.id} not in graph`);
112
+ }
113
+ const edge = { source: source.id, target: target.id, data };
114
+ this.edges.push(edge);
115
+ return edge;
116
+ }
117
+ firstNode() {
118
+ const targets = new Set(this.edges.map((edge) => edge.target));
119
+ const found = [];
120
+ Object.values(this.nodes).forEach((node) => {
121
+ if (!targets.has(node.id)) {
122
+ found.push(node);
123
+ }
124
+ });
125
+ return found[0];
126
+ }
127
+ lastNode() {
128
+ const sources = new Set(this.edges.map((edge) => edge.source));
129
+ const found = [];
130
+ Object.values(this.nodes).forEach((node) => {
131
+ if (!sources.has(node.id)) {
132
+ found.push(node);
133
+ }
134
+ });
135
+ return found[0];
136
+ }
137
+ extend(graph) {
138
+ // Add all nodes from the other graph, taking care to avoid duplicates
139
+ Object.entries(graph.nodes).forEach(([key, value]) => {
140
+ this.nodes[key] = value;
141
+ });
142
+ // Add all edges from the other graph
143
+ this.edges = [...this.edges, ...graph.edges];
144
+ }
145
+ trimFirstNode() {
146
+ const firstNode = this.firstNode();
147
+ if (firstNode) {
148
+ const outgoingEdges = this.edges.filter((edge) => edge.source === firstNode.id);
149
+ if (Object.keys(this.nodes).length === 1 || outgoingEdges.length === 1) {
150
+ this.removeNode(firstNode);
151
+ }
152
+ }
153
+ }
154
+ trimLastNode() {
155
+ const lastNode = this.lastNode();
156
+ if (lastNode) {
157
+ const incomingEdges = this.edges.filter((edge) => edge.target === lastNode.id);
158
+ if (Object.keys(this.nodes).length === 1 || incomingEdges.length === 1) {
159
+ this.removeNode(lastNode);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ exports.Graph = Graph;