Skip to content

Commit

Permalink
mutable graph (#3842)
Browse files Browse the repository at this point in the history
- **Move various graph mutation operations to `MutableGraph`.**
- **Make `EditableGraph` use `MutableGraphImpl`.**
- **Make `InspectableGraph` not mutable.**
- **Move inspect API files to their own dir.**
- **Mark `inspectableGraph` as deprecated.**
- **Reduce the use of `inspectableGraph`.**
- **Make `MutableGraph` aware of imperative graphs.**
- **docs(changeset): Make MutableGraph the main backing store for
editing and inspection.**

Progress on #3836
  • Loading branch information
dglazkov authored Nov 25, 2024
1 parent 45c7e5f commit c6935b7
Show file tree
Hide file tree
Showing 56 changed files with 353 additions and 397 deletions.
5 changes: 5 additions & 0 deletions .changeset/wild-clouds-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@google-labs/breadboard": minor
---

Make MutableGraph the main backing store for editing and inspection.
29 changes: 12 additions & 17 deletions packages/breadboard/src/editor/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { InspectableGraphWithStore } from "../inspector/types.js";
import { GraphDescriptor, GraphIdentifier, NodeIdentifier } from "../types.js";
import {
SingleEditResult,
Expand Down Expand Up @@ -43,7 +42,7 @@ import {
} from "../run/run-imperative-graph.js";
import { AddGraph } from "./operations/add-graph.js";
import { RemoveGraph } from "./operations/remove-graph.js";
import { inspectableGraph } from "../inspector/mutable-graph.js";
import { MutableGraphImpl } from "../inspector/graph/mutable-graph.js";

const validImperativeEdits: EditSpec["type"][] = [
"addmodule",
Expand Down Expand Up @@ -71,7 +70,7 @@ const operations = new Map<EditSpec["type"], EditOperation>([
export class Graph implements EditableGraph {
#version = 0;
#options: EditableGraphOptions;
#inspector: InspectableGraphWithStore;
#mutable: MutableGraphImpl;
#graph: GraphDescriptor;
#eventTarget: EventTarget = new EventTarget();
#history: GraphEditHistory;
Expand All @@ -84,7 +83,7 @@ export class Graph implements EditableGraph {
} else {
this.#graph = graph;
}
this.#inspector = inspectableGraph(this.raw(), options);
this.#mutable = new MutableGraphImpl(graph, options);
this.#options = options;
this.#version = options.version || 0;
this.#history = new GraphEditHistory({
Expand All @@ -97,7 +96,7 @@ export class Graph implements EditableGraph {
setGraph: (graph) => {
this.#graph = graph;
this.#version++;
this.#inspector.resetGraph(graph);
this.#mutable.rebuild(graph);
this.#eventTarget.dispatchEvent(
new ChangeEvent(this.raw(), this.#version, false, "history", [], [])
);
Expand All @@ -112,7 +111,7 @@ export class Graph implements EditableGraph {
affectedModules: ModuleIdentifier[]
) {
this.#version++;
this.#inspector.updateGraph(
this.#mutable.update(
this.#graph,
visualOnly,
affectedNodes,
Expand All @@ -132,8 +131,7 @@ export class Graph implements EditableGraph {

#rollbackGraph(checkpoint: GraphDescriptor, error: string) {
this.#graph = checkpoint;
// TODO: Handle subgraphs.
this.#inspector.resetGraph(this.#graph);
this.#mutable.rebuild(this.#graph);
this.#dispatchNoChange(error);
}

Expand Down Expand Up @@ -210,12 +208,11 @@ export class Graph implements EditableGraph {
}

inspect(id: GraphIdentifier) {
if (!id) return this.#inspector;
const subGraphInspector = this.#inspector.graphs()?.[id];
if (!subGraphInspector) {
const inspectableGraph = this.#mutable.graphs.get(id || "");
if (!inspectableGraph) {
throw new Error(`Unknown sub-graph id: "${id}"`);
}
return subGraphInspector;
return inspectableGraph;
}

async #applyEdits(
Expand Down Expand Up @@ -268,18 +265,16 @@ export class Graph implements EditableGraph {

if (dryRun) {
const graph = checkpoint;
const inspector = inspectableGraph(graph, this.#options);
const mutable = new MutableGraphImpl(graph, this.#options);
context = {
graph,
inspector,
store: inspector,
mutable,
apply,
};
} else {
context = {
graph: this.#graph,
inspector: this.#inspector,
store: this.#inspector,
mutable: this.#mutable,
apply,
};
}
Expand Down
34 changes: 19 additions & 15 deletions packages/breadboard/src/editor/operations/add-edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { GraphIdentifier } from "@breadboard-ai/types";
import {
fixUpStarEdge,
fixupConstantEdge,
unfixUpStarEdge,
} from "../../inspector/graph/edge.js";
import { InspectableGraph } from "../../inspector/types.js";
import {
EditOperation,
EditOperationContext,
EditSpec,
EditableEdgeSpec,
SingleEditResult,
} from "../types.js";
import { InspectableGraph } from "../../inspector/types.js";
import {
fixUpStarEdge,
fixupConstantEdge,
unfixUpStarEdge,
} from "../../inspector/edge.js";
import { toSubgraphContext } from "../subgraph-context.js";
import { GraphIdentifier } from "@breadboard-ai/types";
import { errorNoInspect } from "./error.js";
import { GraphDescriptorHandle } from "../../inspector/graph/graph-descriptor-handle.js";

export class AddEdge implements EditOperation {
async can(
Expand Down Expand Up @@ -107,21 +108,24 @@ export class AddEdge implements EditOperation {
let edge = spec.edge;
const { graphId } = spec;

const subgraphContext = toSubgraphContext(context, graphId);
if (!subgraphContext.success) {
return subgraphContext;
const { graph, mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}
const { graph, inspector, store } = subgraphContext.result;
const can = await this.can(edge, inspector, graphId);
if (!can.success) {
return can;
}
const handle = GraphDescriptorHandle.create(graph, graphId);
if (!handle.success) {
return handle;
}

edge = fixUpStarEdge(edge);
edge = fixupConstantEdge(edge);
// TODO: Figure out how to make this work in multi-edit mode.
store.edgeStore.add(edge, graphId);
graph.edges.push(edge);
mutable.edges.add(edge, graphId);
handle.result.graph().edges.push(edge);
return {
success: true,
affectedNodes: [
Expand Down
4 changes: 2 additions & 2 deletions packages/breadboard/src/editor/operations/add-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AddGraph implements EditOperation {
);
}
const { id, graph: subgraph } = edit;
const { graph, store } = context;
const { graph, mutable } = context;

if (graph.graphs?.[id]) {
return {
Expand All @@ -34,7 +34,7 @@ class AddGraph implements EditOperation {
}
graph.graphs ??= {};
graph.graphs[id] = subgraph;
store.addSubgraph(subgraph, id);
mutable.addSubgraph(subgraph, id);

return {
success: true,
Expand Down
3 changes: 2 additions & 1 deletion packages/breadboard/src/editor/operations/add-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export class AddModule implements EditOperation {
);
}
const { id, module } = spec;
const { graph, inspector } = context;
const { graph, mutable } = context;
const inspector = mutable.graphs.get("")!;
const can = await this.can(id, inspector);
if (!can.success) {
return can;
Expand Down
21 changes: 14 additions & 7 deletions packages/breadboard/src/editor/operations/add-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
SingleEditResult,
} from "../types.js";
import { InspectableGraph } from "../../inspector/types.js";
import { toSubgraphContext } from "../subgraph-context.js";
import { errorNoInspect } from "./error.js";
import { GraphDescriptorHandle } from "../../inspector/graph/graph-descriptor-handle.js";

export class AddNode implements EditOperation {
async can(
Expand Down Expand Up @@ -53,19 +54,25 @@ export class AddNode implements EditOperation {
);
}
const { node, graphId } = spec;
const subgraphContext = toSubgraphContext(context, graphId);
if (!subgraphContext.success) {
return subgraphContext;

const { graph, mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}

const handle = GraphDescriptorHandle.create(graph, graphId);
if (!handle.success) {
return handle;
}

const { graph, inspector, store } = subgraphContext.result;
const can = await this.can(node, inspector);
if (!can.success) {
return can;
}

graph.nodes.push(node);
store.nodeStore.add(node, graphId);
handle.result.graph().nodes.push(node);
mutable.nodes.add(node, graphId);
return {
success: true,
affectedNodes: [{ id: node.id, graphId }],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SingleEditResult,
} from "../types.js";
import { InspectableGraph } from "../../inspector/types.js";
import { toSubgraphContext } from "../subgraph-context.js";
import { errorNoInspect } from "./error.js";

export class ChangeConfiguration implements EditOperation {
async can(
Expand Down Expand Up @@ -50,12 +50,12 @@ export class ChangeConfiguration implements EditOperation {
error: "Configuration wasn't supplied.",
};
}
const subgraphContext = toSubgraphContext(context, graphId);
if (!subgraphContext.success) {
return subgraphContext;
const { mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}

const { inspector } = subgraphContext.result;
const can = await this.can(id, inspector);
if (!can.success) {
return can;
Expand Down
20 changes: 13 additions & 7 deletions packages/breadboard/src/editor/operations/change-edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import {
import { RemoveEdge } from "./remove-edge.js";
import { AddEdge } from "./add-edge.js";
import { edgesEqual, findEdgeIndex } from "../edge.js";
import { fixUpStarEdge } from "../../inspector/edge.js";
import { toSubgraphContext } from "../subgraph-context.js";
import { fixUpStarEdge } from "../../inspector/graph/edge.js";
import { GraphIdentifier } from "@breadboard-ai/types";
import { errorNoInspect } from "./error.js";
import { GraphDescriptorHandle } from "../../inspector/graph/graph-descriptor-handle.js";

export class ChangeEdge implements EditOperation {
async can(
Expand Down Expand Up @@ -58,13 +59,12 @@ export class ChangeEdge implements EditOperation {
);
}
const { from, to, graphId } = spec;
const subgraphContext = toSubgraphContext(context, graphId);

if (!subgraphContext.success) {
return subgraphContext;
const { mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}

const { graph, inspector } = subgraphContext.result;
const can = await this.can(from, to, inspector, graphId);
if (!can.success) {
return can;
Expand All @@ -78,6 +78,12 @@ export class ChangeEdge implements EditOperation {
affectedGraphs: [],
};
}
const handle = GraphDescriptorHandle.create(context.graph, graphId);
if (!handle.success) {
return handle;
}
const graph = handle.result.graph();

const fixedUpEdge = fixUpStarEdge(from);
const edges = graph.edges;
const index = findEdgeIndex(graph, fixedUpEdge);
Expand Down
17 changes: 12 additions & 5 deletions packages/breadboard/src/editor/operations/change-graph-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { toSubgraphContext } from "../subgraph-context.js";
import { GraphDescriptorHandle } from "../../inspector/graph/graph-descriptor-handle.js";
import {
EditOperation,
EditOperationContext,
EditSpec,
SingleEditResult,
} from "../types.js";
import { errorNoInspect } from "./error.js";

export class ChangeGraphMetadata implements EditOperation {
async do(
Expand All @@ -23,12 +24,18 @@ export class ChangeGraphMetadata implements EditOperation {
);
}
const { metadata, graphId } = spec;
const subgraphContext = toSubgraphContext(context, graphId);
if (!subgraphContext.success) {
return subgraphContext;
const { mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}

const { graph } = subgraphContext.result;
const handle = GraphDescriptorHandle.create(context.graph, graphId);
if (!handle.success) {
return handle;
}
const graph = handle.result.graph();

const visualOnly = graph.metadata === metadata;
graph.metadata = metadata;
return {
Expand Down
10 changes: 5 additions & 5 deletions packages/breadboard/src/editor/operations/change-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SingleEditResult,
} from "../types.js";
import { InspectableGraph } from "../../inspector/types.js";
import { toSubgraphContext } from "../subgraph-context.js";
import { errorNoInspect } from "./error.js";

export class ChangeMetadata implements EditOperation {
async can(
Expand Down Expand Up @@ -52,12 +52,12 @@ export class ChangeMetadata implements EditOperation {
);
}
const { id, metadata, graphId, reset = false } = spec;
const subgraphContext = toSubgraphContext(context, graphId);
if (!subgraphContext.success) {
return subgraphContext;
const { mutable } = context;
const inspector = mutable.graphs.get(graphId);
if (!inspector) {
return errorNoInspect(graphId);
}

const { inspector } = subgraphContext.result;
const can = await this.can(id, inspector);
if (!can.success) return can;
const node = inspector.nodeById(id);
Expand Down
5 changes: 3 additions & 2 deletions packages/breadboard/src/editor/operations/change-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*/

import { ModuleIdentifier } from "@breadboard-ai/types";
import { InspectableGraph } from "../../inspector/types.js";
import {
EditOperation,
EditOperationContext,
EditSpec,
SingleEditResult,
} from "../types.js";
import { InspectableGraph } from "../../inspector/types.js";

export class ChangeModule implements EditOperation {
async can(
Expand Down Expand Up @@ -43,7 +43,8 @@ export class ChangeModule implements EditOperation {
);
}
const id = spec.id;
const { graph, inspector } = context;
const { graph, mutable } = context;
const inspector = mutable.graphs.get("")!;
const can = await this.can(id, inspector);
if (!can.success) {
return can;
Expand Down
Loading

0 comments on commit c6935b7

Please sign in to comment.