graph

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client interface {
	// EnsureSchema creates indexes and constraints if they don't exist.
	// vectorDim is injected into the vector index DDL (e.g. 768 for nomic-embed-text).
	EnsureSchema(ctx context.Context, vectorDim int) error

	// UpsertEntity creates or updates an entity node.
	UpsertEntity(ctx context.Context, entity models.Entity) error

	// SearchEntities finds entities by fulltext + embedding similarity.
	SearchEntities(ctx context.Context, query string, embedding []float32, project string, limit int) ([]EntityResult, error)

	// GetEntity retrieves a single entity by ID.
	GetEntity(ctx context.Context, id string) (*models.Entity, error)

	// UpsertFact creates a RELATES_TO edge between two entities.
	UpsertFact(ctx context.Context, fact models.Fact) error

	// SearchFacts finds facts by hybrid search (BM25 + cosine + BFS).
	SearchFacts(ctx context.Context, query string, embedding []float32, limit int) ([]FactResult, error)

	// InvalidateFact sets ExpiredAt and InvalidAt on a fact (never deletes).
	InvalidateFact(ctx context.Context, id string, expiredAt, invalidAt time.Time) error

	// GetFactsBetween returns all active facts between two entities.
	GetFactsBetween(ctx context.Context, sourceID, targetID string) ([]models.Fact, error)

	// GetFactsForEntity returns all active facts involving an entity.
	GetFactsForEntity(ctx context.Context, entityID string) ([]models.Fact, error)

	// AppendEpisode adds an episode/session ID to a fact's episodes list.
	AppendEpisode(ctx context.Context, factID, episodeID string) error

	// AppendMemoryToFact adds a memory ID to a fact's source_memory_ids.
	AppendMemoryToFact(ctx context.Context, factID, memoryID string) error

	// GetMemoryFacts returns all facts derived from a given memory.
	GetMemoryFacts(ctx context.Context, memoryID string) ([]models.Fact, error)

	// RecallByGraph returns memory IDs relevant to a query via graph traversal.
	RecallByGraph(ctx context.Context, query string, embedding []float32, limit int) ([]string, error)

	// CreateEpisode stores an episode node in the graph.
	CreateEpisode(ctx context.Context, episode models.Episode) error

	// GetEpisodesForMemory returns all episodes linked to a given memory ID.
	GetEpisodesForMemory(ctx context.Context, memoryID string) ([]models.Episode, error)

	// Healthy returns true if the graph database is reachable.
	Healthy(ctx context.Context) bool

	// Close releases resources.
	Close() error
}

Client defines the interface for graph storage operations. Resolution logic lives in EntityResolver and FactResolver (separate types), matching the pattern where ConflictDetector is separate from Store.

type EntityResolver

type EntityResolver struct {
	// contains filtered or unexported fields
}

EntityResolver implements three-stage entity resolution: 1. Candidate retrieval via graph search 2. Deterministic fast-path (exact name, alias, embedding cosine) 3. Claude Haiku fallback for ambiguous cases

func NewEntityResolver

func NewEntityResolver(graph Client, client llm.LLMClient, model string, threshold float64, maxCands int, logger *slog.Logger) *EntityResolver

NewEntityResolver creates a new EntityResolver. If client is nil, stage 3 (Claude fallback) is disabled and ambiguous entities are treated as new.

func (*EntityResolver) Resolve

func (r *EntityResolver) Resolve(ctx context.Context, extracted models.Entity, embedding []float32, conversationContext string) (string, bool, error)

Resolve performs three-stage entity resolution and returns (resolvedID, isNew, err). If the entity matches an existing one, resolvedID is the existing entity's ID and isNew is false. Otherwise, resolvedID is the extracted entity's ID and isNew is true.

type EntityResult

type EntityResult struct {
	ID    string  `json:"id"`
	Name  string  `json:"name"`
	Type  string  `json:"type"`
	Score float64 `json:"score"`
}

EntityResult is a search result from the graph entity index.

type FactAction

type FactAction string

FactAction represents the resolution outcome for a new fact.

const (
	FactActionInsert     FactAction = "insert"     // new fact, no duplicates
	FactActionSkip       FactAction = "skip"       // exact duplicate, append episode
	FactActionInvalidate FactAction = "invalidate" // contradicts existing, invalidate old
)

type FactExtractor

type FactExtractor struct {
	// contains filtered or unexported fields
}

FactExtractor extracts relationship facts from conversation text using Claude.

func NewFactExtractor

func NewFactExtractor(client llm.LLMClient, model string, logger *slog.Logger) *FactExtractor

NewFactExtractor creates a new fact extractor backed by the Claude API.

func (*FactExtractor) Extract

func (e *FactExtractor) Extract(ctx context.Context, content string, entityNames []string) ([]models.Fact, error)

Extract extracts relationship facts from conversation text. entityNames is the list of known entity names from the extraction step. On API error it logs a warning and returns (nil, nil) for graceful degradation.

NOTE: The returned facts have SourceEntityID and TargetEntityID set to entity NAMES (not UUIDs). The caller is responsible for resolving names to IDs after extraction, since Claude returns names and the ID mapping is external.

type FactResolver

type FactResolver struct {
	// contains filtered or unexported fields
}

FactResolver determines whether a new fact is a duplicate, contradiction, or new by comparing it against existing facts between the same entity pair.

func NewFactResolver

func NewFactResolver(graph Client, client llm.LLMClient, model string, logger *slog.Logger) *FactResolver

NewFactResolver creates a new FactResolver. If client is nil, the resolver will treat all facts as new (graceful degradation).

func (*FactResolver) Resolve

func (r *FactResolver) Resolve(ctx context.Context, newFact models.Fact, conversationContext string) (FactAction, []string, error)

Resolve determines if a new fact is a duplicate, contradiction, or new. Returns (action, affectedFactIDs, error).

type FactResult

type FactResult struct {
	ID              string   `json:"id"`
	Fact            string   `json:"fact"`
	SourceEntityID  string   `json:"source_entity_id"`
	TargetEntityID  string   `json:"target_entity_id"`
	SourceMemoryIDs []string `json:"source_memory_ids"`
	Score           float64  `json:"score"`
}

FactResult is a search result from the graph fact index.

func HybridSearch

func HybridSearch(ctx context.Context, fns []SearchFunc, limit int) ([]FactResult, error)

HybridSearch runs multiple search functions in parallel and merges with RRF.

func RRFMerge

func RRFMerge(lists [][]FactResult, limit int) []FactResult

RRFMerge implements Reciprocal Rank Fusion across multiple ranked lists. Each list contains FactResults sorted by their individual method score. Returns merged results sorted by combined RRF score, deduped by ID.

type MockGraphClient

type MockGraphClient struct {
	// contains filtered or unexported fields
}

MockGraphClient implements Client with in-memory maps for testing.

func NewMockGraphClient

func NewMockGraphClient() *MockGraphClient

NewMockGraphClient creates a new MockGraphClient.

func (*MockGraphClient) AppendEpisode

func (m *MockGraphClient) AppendEpisode(_ context.Context, factID, episodeID string) error

func (*MockGraphClient) AppendMemoryToFact

func (m *MockGraphClient) AppendMemoryToFact(_ context.Context, factID, memoryID string) error

func (*MockGraphClient) Close

func (m *MockGraphClient) Close() error

func (*MockGraphClient) CreateEpisode added in v0.8.0

func (m *MockGraphClient) CreateEpisode(_ context.Context, episode models.Episode) error

CreateEpisode stores an episode in the mock.

func (*MockGraphClient) EnsureSchema

func (m *MockGraphClient) EnsureSchema(_ context.Context, _ int) error

func (*MockGraphClient) GetEntity

func (m *MockGraphClient) GetEntity(_ context.Context, id string) (*models.Entity, error)

func (*MockGraphClient) GetEpisodes added in v0.8.0

func (m *MockGraphClient) GetEpisodes() []models.Episode

GetEpisodes returns all stored episodes (test helper).

func (*MockGraphClient) GetEpisodesForMemory added in v0.8.0

func (m *MockGraphClient) GetEpisodesForMemory(_ context.Context, memoryID string) ([]models.Episode, error)

GetEpisodesForMemory returns all episodes that reference the given memory ID.

func (*MockGraphClient) GetFactsBetween

func (m *MockGraphClient) GetFactsBetween(_ context.Context, sourceID, targetID string) ([]models.Fact, error)

func (*MockGraphClient) GetFactsForEntity

func (m *MockGraphClient) GetFactsForEntity(_ context.Context, entityID string) ([]models.Fact, error)

func (*MockGraphClient) GetMemoryFacts

func (m *MockGraphClient) GetMemoryFacts(_ context.Context, memoryID string) ([]models.Fact, error)

func (*MockGraphClient) Healthy

func (m *MockGraphClient) Healthy(_ context.Context) bool

func (*MockGraphClient) InvalidateFact

func (m *MockGraphClient) InvalidateFact(_ context.Context, id string, expiredAt, invalidAt time.Time) error

func (*MockGraphClient) RecallByGraph

func (m *MockGraphClient) RecallByGraph(_ context.Context, _ string, _ []float32, _ int) ([]string, error)

func (*MockGraphClient) SearchEntities

func (m *MockGraphClient) SearchEntities(_ context.Context, query string, _ []float32, _ string, limit int) ([]EntityResult, error)

func (*MockGraphClient) SearchFacts

func (m *MockGraphClient) SearchFacts(_ context.Context, _ string, _ []float32, limit int) ([]FactResult, error)

func (*MockGraphClient) UpsertEntity

func (m *MockGraphClient) UpsertEntity(_ context.Context, entity models.Entity) error

func (*MockGraphClient) UpsertFact

func (m *MockGraphClient) UpsertFact(_ context.Context, fact models.Fact) error

type SearchFunc

type SearchFunc func(ctx context.Context, limit int) ([]FactResult, error)

SearchFunc is a function that returns a ranked list of fact results.

Jump to

Keyboard shortcuts

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