graph

package
v2.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package graph provides a thread-safe, ordered directed/undirected graph built on top of ConcurrentOrderedMap. Each node can carry an arbitrary payload and an optional embedding vector, enabling graph traversal combined with semantic vector search — ideal for knowledge graphs, agentic memory systems, and RAG pipelines.

Index

Constants

This section is empty.

Variables

View Source
var ErrDuplicateNode = errors.New("graph: node already exists")

ErrDuplicateNode is returned when a node already exists.

View Source
var ErrEdgeNotFound = errors.New("graph: edge not found")

ErrEdgeNotFound is returned when an operation references a missing edge.

View Source
var ErrNodeNotFound = errors.New("graph: node not found")

ErrNodeNotFound is returned when an operation references a missing node.

View Source
var ErrSelfLoop = errors.New("graph: self-loop not allowed")

ErrSelfLoop is returned when a caller tries to add a self-loop.

Functions

This section is empty.

Types

type ConcurrentOrderedGraph

type ConcurrentOrderedGraph[K comparable, V any] struct {
	// contains filtered or unexported fields
}

ConcurrentOrderedGraph is a thread-safe directed or undirected graph whose node-set is backed by a ConcurrentOrderedMap, preserving insertion order for deterministic iteration.

Each node may hold an embedding vector ([]float64) enabling hybrid graph-traversal + semantic-search queries — the core primitive needed for agentic knowledge graphs and memory systems.

Type parameters:

  • K: node identifier type (must be comparable, e.g. string, int, uuid)
  • V: arbitrary payload stored in each node

func NewDirectedGraph

func NewDirectedGraph[K comparable, V any]() *ConcurrentOrderedGraph[K, V]

NewDirectedGraph creates an empty directed graph.

func NewUndirectedGraph

func NewUndirectedGraph[K comparable, V any]() *ConcurrentOrderedGraph[K, V]

NewUndirectedGraph creates an empty undirected graph. Every AddEdge call automatically creates the reverse edge.

func (*ConcurrentOrderedGraph[K, V]) AddEdge

func (g *ConcurrentOrderedGraph[K, V]) AddEdge(from, to K, e EdgeData) error

AddEdge adds a directed edge from → to. For undirected graphs the reverse edge is also added automatically. Returns ErrSelfLoop or ErrNodeNotFound as appropriate.

func (*ConcurrentOrderedGraph[K, V]) AddNode

func (g *ConcurrentOrderedGraph[K, V]) AddNode(id K, data V, vec []float64) error

AddNode inserts a new node. vec may be nil if no embedding is needed. Returns ErrDuplicateNode if the key already exists.

func (*ConcurrentOrderedGraph[K, V]) AllReachable

func (g *ConcurrentOrderedGraph[K, V]) AllReachable(start K) ([]K, error)

AllReachable returns every node reachable from `start` (BFS order).

func (*ConcurrentOrderedGraph[K, V]) BFS

func (g *ConcurrentOrderedGraph[K, V]) BFS(start K, visit func(K, V) bool) error

BFS performs a breadth-first traversal starting from `start`. The visitor function receives (nodeID, nodeData) for every reachable node. Return false from the visitor to stop traversal early.

func (*ConcurrentOrderedGraph[K, V]) BFSWithDepth

func (g *ConcurrentOrderedGraph[K, V]) BFSWithDepth(
	start K,
	maxDepth int,
	visit func(id K, data V, depth int) bool,
) error

BFSWithDepth is BFS with hop-depth limit. Useful for bounded graph exploration in agentic scenarios where you want "context within N hops".

func (*ConcurrentOrderedGraph[K, V]) ConnectedComponents

func (g *ConcurrentOrderedGraph[K, V]) ConnectedComponents() [][]K

ConnectedComponents returns groups of mutually-reachable node IDs. Useful for detecting isolated sub-graphs in an agent's knowledge base.

func (*ConcurrentOrderedGraph[K, V]) DFS

func (g *ConcurrentOrderedGraph[K, V]) DFS(start K, visit func(K, V) bool) error

DFS performs a depth-first traversal starting from `start`. The visitor function receives (nodeID, nodeData). Return false to stop early.

func (*ConcurrentOrderedGraph[K, V]) GetNeighbors

func (g *ConcurrentOrderedGraph[K, V]) GetNeighbors(id K) ([]K, error)

GetNeighbors returns the outgoing neighbour IDs of a node in insertion order.

func (*ConcurrentOrderedGraph[K, V]) GetNode

func (g *ConcurrentOrderedGraph[K, V]) GetNode(id K) (*GraphNode[K, V], bool)

GetNode retrieves a node by ID.

func (*ConcurrentOrderedGraph[K, V]) HasEdge

func (g *ConcurrentOrderedGraph[K, V]) HasEdge(from, to K) bool

HasEdge reports whether an edge from → to exists.

func (*ConcurrentOrderedGraph[K, V]) IsDirected

func (g *ConcurrentOrderedGraph[K, V]) IsDirected() bool

IsDirected returns true if the graph is directed.

func (*ConcurrentOrderedGraph[K, V]) NodeCount

func (g *ConcurrentOrderedGraph[K, V]) NodeCount() int

NodeCount returns the number of nodes.

func (*ConcurrentOrderedGraph[K, V]) Nodes

func (g *ConcurrentOrderedGraph[K, V]) Nodes() []*GraphNode[K, V]

Nodes returns all nodes in insertion order.

func (*ConcurrentOrderedGraph[K, V]) RemoveEdge

func (g *ConcurrentOrderedGraph[K, V]) RemoveEdge(from, to K) error

RemoveEdge removes the edge from → to. For undirected graphs the reverse is also removed.

func (*ConcurrentOrderedGraph[K, V]) RemoveNode

func (g *ConcurrentOrderedGraph[K, V]) RemoveNode(id K) error

RemoveNode deletes a node and all edges that reference it.

func (*ConcurrentOrderedGraph[K, V]) SemanticNeighbors

func (g *ConcurrentOrderedGraph[K, V]) SemanticNeighbors(
	nodeID K,
	queryVec []float64,
	topK int,
) ([]ScoredNode[K, V], error)

SemanticNeighbors is a convenience wrapper that returns the direct neighbours of `nodeID` ranked by semantic similarity to queryVec — no BFS, just the immediate 1-hop neighbourhood.

func (*ConcurrentOrderedGraph[K, V]) ShortestPath

func (g *ConcurrentOrderedGraph[K, V]) ShortestPath(from, to K) (PathResult[K], error)

ShortestPath finds the shortest (lowest-weight) path between `from` and `to` using Dijkstra's algorithm. Edge weights must be non-negative. Returns PathResult with the ordered node IDs and total distance.

func (*ConcurrentOrderedGraph[K, V]) UpsertNode

func (g *ConcurrentOrderedGraph[K, V]) UpsertNode(id K, data V, vec []float64)

UpsertNode adds or fully replaces a node (payload + vector).

func (*ConcurrentOrderedGraph[K, V]) VectorSearchBidirectional

func (g *ConcurrentOrderedGraph[K, V]) VectorSearchBidirectional(
	start K,
	queryVec []float64,
	topK int,
	maxHops int,
	filter func(V) bool,
) ([]ScoredNode[K, V], error)

VectorSearchBidirectional expands the search in both directions on an undirected or directed graph by also following reverse edges. Useful for retrieving the broader context of a node (parents + children + siblings).

func (*ConcurrentOrderedGraph[K, V]) VectorSearchFromNode

func (g *ConcurrentOrderedGraph[K, V]) VectorSearchFromNode(
	start K,
	queryVec []float64,
	topK int,
	maxHops int,
	filter func(V) bool,
) ([]ScoredNode[K, V], error)

VectorSearchFromNode performs a bounded BFS starting at `start`, scoring each visited node by cosine similarity with queryVec, and returns the topK most similar nodes found within maxHops hops.

This is the core primitive for agentic context retrieval: "given the current node (e.g. last tool call, last memory), what are the semantically closest related concepts reachable from here?"

Parameters:

  • start — seed node for the BFS
  • queryVec — embedding of the query (same dimensionality as node vectors)
  • topK — maximum results to return
  • maxHops — maximum BFS depth (use -1 for unlimited)
  • filter — optional payload predicate; nil = no filter

func (*ConcurrentOrderedGraph[K, V]) VectorSearchGlobal

func (g *ConcurrentOrderedGraph[K, V]) VectorSearchGlobal(
	queryVec []float64,
	topK int,
	filter func(V) bool,
) ([]ScoredNode[K, V], error)

VectorSearchGlobal scans every node in the graph and returns the topK nodes whose Vector embedding is most similar (cosine similarity) to queryVec.

filter is an optional predicate over the node payload; pass nil to include all nodes.

Results are returned in descending similarity order.

type EdgeData

type EdgeData struct {
	Weight   float64
	Label    string
	Metadata map[string]any
}

EdgeData holds the metadata associated with a directed connection between two nodes. Weight is used by Dijkstra; Label and Metadata are free-form.

type GraphNode

type GraphNode[K comparable, V any] struct {
	ID     K
	Data   V
	Vector []float64 // optional; nil means "no embedding"
	// contains filtered or unexported fields
}

GraphNode is a single vertex in the graph. It stores the caller's payload (Data), an optional embedding Vector, and its adjacency list as a ConcurrentOrderedMap so that neighbours are themselves thread-safe and ordered by insertion time.

func (*GraphNode[K, V]) Degree

func (n *GraphNode[K, V]) Degree() int

Degree returns the number of outgoing edges.

func (*GraphNode[K, V]) Edge

func (n *GraphNode[K, V]) Edge(to K) (EdgeData, bool)

Edge returns the EdgeData for a specific neighbour, if it exists.

func (*GraphNode[K, V]) Neighbors

func (n *GraphNode[K, V]) Neighbors() []K

Neighbors returns all outgoing neighbour keys in insertion order.

func (*GraphNode[K, V]) UpdateData

func (n *GraphNode[K, V]) UpdateData(fn func(*V) error) error

UpdateData mutates the payload under a write lock.

func (*GraphNode[K, V]) UpdateVector

func (n *GraphNode[K, V]) UpdateVector(vec []float64)

UpdateVector replaces the embedding under a write lock.

type PathResult

type PathResult[K comparable] struct {
	Nodes    []K
	Distance float64
}

PathResult holds a shortest-path result from Dijkstra.

type ScoredNode

type ScoredNode[K comparable, V any] struct {
	Node  *GraphNode[K, V]
	Score float64
}

ScoredNode is a query result: a node together with its similarity score.

func (ScoredNode[K, V]) String

func (s ScoredNode[K, V]) String() string

String implements fmt.Stringer for debug output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL