Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions langchain-core/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ runnables.cjs
runnables.js
runnables.d.ts
runnables.d.cts
runnables/graph.cjs
runnables/graph.js
runnables/graph.d.ts
runnables/graph.d.cts
runnables/remote.cjs
runnables/remote.js
runnables/remote.d.ts
Expand Down
1 change: 1 addition & 0 deletions langchain-core/langchain.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const config = {
prompts: "prompts/index",
prompt_values: "prompt_values",
runnables: "runnables/index",
"runnables/graph": "runnables/graph",
"runnables/remote": "runnables/remote",
retrievers: "retrievers/index",
"retrievers/document_compressors": "retrievers/document_compressors/base",
Expand Down
13 changes: 13 additions & 0 deletions langchain-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,15 @@
"import": "./runnables.js",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there! I noticed that this PR introduces a change in dependencies in the package.json file. It would be great if the maintainers could review this change to ensure it aligns with the project's requirements. Thanks for flagging this for review!

"require": "./runnables.cjs"
},
"./runnables/graph": {
"types": {
"import": "./runnables/graph.d.ts",
"require": "./runnables/graph.d.cts",
"default": "./runnables/graph.d.ts"
},
"import": "./runnables/graph.js",
"require": "./runnables/graph.cjs"
},
"./runnables/remote": {
"types": {
"import": "./runnables/remote.d.ts",
Expand Down Expand Up @@ -698,6 +707,10 @@
"runnables.js",
"runnables.d.ts",
"runnables.d.cts",
"runnables/graph.cjs",
"runnables/graph.js",
"runnables/graph.d.ts",
"runnables/graph.d.cts",
"runnables/remote.cjs",
"runnables/remote.js",
"runnables/remote.d.ts",
Expand Down
52 changes: 45 additions & 7 deletions langchain-core/src/runnables/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { drawMermaid, drawMermaidPng } from "./graph_mermaid.js";

const MAX_DATA_DISPLAY_NAME_LENGTH = 42;

export function nodeDataStr(node: Node): string {
export { Node, Edge };

function nodeDataStr(node: Node): string {
if (!isUuid(node.id)) {
return node.id;
} else if (isRunnableInterface(node.data)) {
Expand Down Expand Up @@ -101,14 +103,24 @@ export class Graph {
);
}

addEdge(source: Node, target: Node, data?: string): Edge {
addEdge(
source: Node,
target: Node,
data?: string,
conditional?: boolean
): Edge {
if (this.nodes[source.id] === undefined) {
throw new Error(`Source node ${source.id} not in graph`);
}
if (this.nodes[target.id] === undefined) {
throw new Error(`Target node ${target.id} not in graph`);
}
const edge: Edge = { source: source.id, target: target.id, data };
const edge: Edge = {
source: source.id,
target: target.id,
data,
conditional,
};
this.edges.push(edge);
return edge;
}
Expand All @@ -135,14 +147,40 @@ export class Graph {
return found[0];
}

extend(graph: Graph): void {
// Add all nodes from the other graph, taking care to avoid duplicates
/**
* Add all nodes and edges from another graph.
* Note this doesn't check for duplicates, nor does it connect the graphs.
*/
extend(graph: Graph, prefix: string = "") {
let finalPrefix = prefix;
const nodeIds = Object.values(graph.nodes).map((node) => node.id);
if (nodeIds.every(isUuid)) {
finalPrefix = "";
}

const prefixed = (id: string) => {
return finalPrefix ? `${finalPrefix}:${id}` : id;
};

Object.entries(graph.nodes).forEach(([key, value]) => {
this.nodes[key] = value;
this.nodes[prefixed(key)] = { ...value, id: prefixed(key) };
});

const newEdges = graph.edges.map((edge) => {
return {
...edge,
source: prefixed(edge.source),
target: prefixed(edge.target),
};
});
// Add all edges from the other graph
this.edges = [...this.edges, ...graph.edges];
this.edges = [...this.edges, ...newEdges];
const first = graph.firstNode();
const last = graph.lastNode();
return [
first ? { id: prefixed(first.id), data: first.data } : undefined,
last ? { id: prefixed(last.id), data: last.data } : undefined,
];
}

trimFirstNode(): void {
Expand Down