Documentation
¶
Overview ¶
Package toolselectstore persists oracle-confirmed (query-embedding -> tool) tool-selection examples in Neo4j (the existing vector store) and loads them for the tool_search ranker to fold into its per-tool centroids — the self-improvement substrate for D-06/D-07 (spike 057), the SECOND consumer of the activelearn mechanism after the reasoning learner. It rides the existing mcp-neo4j-cypher client (knowledge.Client); no new migration: a `:ToolSelectionExample` node is created on first MERGE (Neo4j is schemaless, mirroring :ReasoningExample).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type GraphClient ¶
type GraphClient interface {
Read(ctx context.Context, query string, params map[string]any) ([]map[string]any, error)
Write(ctx context.Context, query string, params map[string]any) ([]map[string]any, error)
}
GraphClient is the narrow Cypher seam Store needs. *knowledge.Client satisfies it (Read/Write decode rows to []map[string]any). Copied verbatim from reasoningstore.GraphClient (the proven seam) so this store depends on no Neo4j concrete.
type LabeledVec ¶
LabeledVec is one loaded tool-selection example: the confirmed tool name keyed to the query embedding that should route to it. The ranker folds Vec into the per-tool centroid keyed by Tool (positives-only Rocchio, D-07). Query is carried for provenance/debugging; the centroid math uses only Tool + Vec.
type Store ¶
type Store struct {
Client GraphClient
}
Store reads/writes :ToolSelectionExample nodes. The content hash is the MERGE key, so re-labeling the same query is idempotent (free dedup).
func (*Store) LoadExamples ¶
func (s *Store) LoadExamples(ctx context.Context) ([]LabeledVec, error)
LoadExamples returns every stored example as a LabeledVec. A row whose tool is empty or whose embedding fails to decode is skipped (the same tolerant discipline as reasoningstore.LoadExamples).
func (*Store) Save ¶
Save upserts one oracle-confirmed example keyed by the query's content hash.
Hash input (RESEARCH risk #10 — idempotency): the MERGE key is sha256(query), NOT sha256(query+tool). Re-labeling the SAME query to a (possibly different) tool is therefore an idempotent UPSERT of the single node — the latest oracle label wins and we never accumulate two contradictory examples for one query. Keying on query+tool would instead let a flip-flopping oracle stack both labels, which the anti-amplification guards (min-support, boost cap) would then have to untangle; a query-keyed UPSERT keeps the bank honest at the source.