Documentation
¶
Overview ¶
Package retrieval implements graph-augmented retrieval: a LangChain-style "Retriever" interface backed by hybrid search + graph traversal. See docs/F2_GRAPHRAG_DESIGN.md for the design.
Algorithm sketch:
- Seed retrieval — tenant-scoped hybrid search (FTS + LSA via RRF)
- Multi-source BFS expansion from seeds (bounded by MaxHops AND a hard 50-node cap; dense graphs at 3 hops can return thousands)
- Score combination — alpha * normalized_seed_score + beta * exp(-d/tau) where d is graph-distance from the contributing seed
- Top-K filter
- Token-budget drop (lowest-score chunks dropped whole)
Tenant scoping rests on audit Track A (PRs #17-#27): every storage call uses *ForTenant. The pkg/api/audit_regression_test.go suite (A7 #27) catches any cross-tenant regression at the contract level.
Index ¶
Constants ¶
const ( DefaultK = 10 DefaultMaxTokens = 4096 DefaultMaxHops = 2 DefaultAlpha = 0.7 DefaultBeta = 0.3 DefaultTau = 2.0 // HardNodeCap is the absolute ceiling on visited nodes during BFS // expansion, regardless of MaxHops or the candidate pool. Prevents // pathological blow-up in dense graphs where 3-hop expansion can // return thousands of nodes. Quality-impacting (may hide relevant // nodes in dense graphs) but correctness-preserving. HardNodeCap = 50 )
Defaults from F2 spike (#28) §2 Q4–Q6. Configurable per-request via Options; out-of-range values are clamped or replaced.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Chunk ¶
type Chunk struct {
NodeID uint64 `json:"node_id"`
Score float64 `json:"score"`
Content string `json:"content"`
Label string `json:"label,omitempty"` // first label, hint for downstream
SourcePath []uint64 `json:"source_path"` // [seedID, ..., NodeID]
}
Chunk is one ranked retrieval result. Content is the text payload (suitable for an LLM prompt); SourcePath is the BFS path from the contributing seed to this node — the graph-specific signal that distinguishes graph-augmented retrieval from plain vector RAG.
Without SourcePath, downstream consumers can't explain *why* a chunk is in context. F2 spike §2 Q6 calls this out as the load-bearing graph signal.
type Options ¶
type Options struct {
// K caps the number of chunks returned (after token-budget drop).
K int
// MaxTokens is the token budget. Chunks are dropped whole, lowest
// score first, until the total estimated tokens fits.
MaxTokens int
// MaxHops bounds the BFS depth from any seed. 0 = seeds only.
MaxHops int
// Alpha weights the normalized seed score (0..1) in the final
// ranking. Beta weights the graph-distance term exp(-d/Tau).
// Together they need not sum to 1 — they're independent dials.
Alpha float64
Beta float64
Tau float64
// Labels optionally restricts seed-stage candidates to nodes with
// at least one of these labels. Expansion is unrestricted (the
// graph signal is the point; labels apply at seed-time only).
Labels []string
}
Options configures one retrieval call. Zero values fall back to the package defaults (see constants above).
type Result ¶
Result bundles ranked chunks + diagnostics. Degraded forwards the hybrid-search degraded flag ("no-lsa-index", "query-out-of-vocabulary") so callers can surface degradation reasons. TookMs is wall-clock for the full retrieval pipeline.
type Retriever ¶
type Retriever struct {
Graph *storage.GraphStorage
SearchIdx *search.TenantIndexes
LSAIdx *search.TenantLSAIndexes
}
Retriever holds the dependencies needed to perform retrieval. Construct one per Server (it's stateless beyond the references it holds; safe to share across requests).
func NewRetriever ¶
func NewRetriever(graph *storage.GraphStorage, searchIdx *search.TenantIndexes, lsaIdx *search.TenantLSAIndexes) *Retriever
NewRetriever wires the retrieval primitives.
func (*Retriever) Retrieve ¶
func (r *Retriever) Retrieve(ctx context.Context, query, tenantID string, opts Options) (*Result, error)
Retrieve performs graph-augmented retrieval for the caller's tenant. Returns ranked chunks ready for LLM context injection.
All graph access uses *ForTenant variants (audit Track A). The returned chunks include SourcePath metadata — the BFS path from the contributing seed — for downstream citation / explanation.