knowledgepageindex

package
v1.89.2 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package knowledgepageindex is the knowledge-page consumer of the shared indexjobs framework (#633). It registers a Source/Sink pair under source_kind = "portal-knowledge-pages" so the reconciler embeds canonical knowledge pages off the request path: a newly created page (whose vector is still NULL) or one left stale by a content edit or a provider model swap self-heals on the next sweep.

Like the asset, prompt, and memory consumers, pages store their vectors inline on the portal_knowledge_pages table (one embedding per row), not in a dedicated vector table. So this package's Store reads and writes the embedding / embedding_model / embedding_text_hash columns directly: a page IS its own indexing unit. SourceID is the page id; each unit yields exactly one Item whose text is portal.KnowledgePageIndexText (title + body + tags). The body is indexed (unlike assets, whose body lives unindexed in S3), so page CONTENT is semantically searchable.

Only non-deleted pages are indexed. Gap detection and coverage both filter on deleted_at IS NULL, so a soft-deleted page is never embedded and never counted as missing coverage.

Index

Constants

View Source
const SourceKind = "portal-knowledge-pages"

SourceKind is the indexjobs source_kind this package serves.

Variables

This section is empty.

Functions

func RegisterConsumer

func RegisterConsumer(reg interface {
	Register(indexjobs.Source, indexjobs.Sink) error
}, db *sql.DB, currentModel string,
) error

RegisterConsumer registers the knowledge-pages Source/Sink pair on the shared indexjobs registry. Keeping the wiring here (rather than inline in the platform) keeps the platform package thin. currentModel is the embedding provider's model identifier.

Types

type Sink

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

Sink implements indexjobs.Sink for the portal-knowledge-pages kind over the embedding columns of the portal_knowledge_pages table. currentModel is the provider model the gap query diffs stored rows against, so a model swap re-embeds rows stamped with the previous model.

func NewSink

func NewSink(store *Store, currentModel string) *Sink

NewSink returns a Sink backed by the given store. currentModel is the embedding provider's model identifier (embedding.ModelName); pass "" on a deployment whose provider does not name its model, in which case only NULL-embedding rows are treated as gaps.

func (*Sink) Coverage

func (s *Sink) Coverage(ctx context.Context) (indexjobs.Coverage, error)

Coverage reports the portal-knowledge-pages kind's indexed-vs-expected totals (non-deleted pages with an embedding vs all non-deleted pages). ExpectedKnown is true: every non-deleted page is expected to converge to one vector.

func (*Sink) FindGaps

func (s *Sink) FindGaps(ctx context.Context) ([]string, error)

FindGaps returns non-deleted page ids whose embedding is missing or was produced by a model other than the current one.

func (*Sink) Kind

func (*Sink) Kind() string

Kind reports the portal-knowledge-pages source kind.

func (*Sink) ListExisting

func (s *Sink) ListExisting(ctx context.Context, key indexjobs.Key) (map[string]indexjobs.Vector, error)

ListExisting returns the page's persisted vector keyed by item id for the worker's dedup pass.

func (*Sink) StampExpected

func (*Sink) StampExpected(context.Context, indexjobs.Key, int) error

StampExpected is a no-op for pages. Gap detection is condition-based (embedding IS NULL OR model mismatch), not count-based.

func (*Sink) Upsert

func (s *Sink) Upsert(ctx context.Context, key indexjobs.Key, rows []indexjobs.Vector) error

Upsert writes the page's vector. The page unit holds one item and has no sibling rows, so it delegates to the shared store write.

func (*Sink) UpsertBatch

func (s *Sink) UpsertBatch(ctx context.Context, key indexjobs.Key, rows []indexjobs.Vector) error

UpsertBatch is identical to Upsert for pages (single-item unit, no rows outside the batch to preserve).

type Source

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

Source implements indexjobs.Source for the portal-knowledge-pages kind. A unit is one page (SourceID = page id) and yields exactly one item: the page's composed embed text. The worker embeds it and the Sink writes the vector back onto the same row.

func NewSource

func NewSource(store *Store) *Source

NewSource returns a Source backed by the given store.

func (*Source) Kind

func (*Source) Kind() string

Kind reports the portal-knowledge-pages source kind.

func (*Source) LoadItems

func (s *Source) LoadItems(ctx context.Context, sourceID string) ([]indexjobs.Item, error)

LoadItems returns the page's single embeddable item. A page soft-deleted between enqueue and claim yields an empty slice (a clean completion that writes no vector), per the Source contract.

func (*Source) OnSucceeded

func (*Source) OnSucceeded(string)

OnSucceeded is a no-op: the ranked search reads embeddings from the portal_knowledge_pages table directly on every query, so there is no in-memory cache to refresh after a backfill writes a vector.

type Store

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

Store reads and writes knowledge-page embedding state on the portal_knowledge_pages table for the indexjobs knowledge-pages consumer. It is intentionally separate from portal.KnowledgePageStore: it touches only the embedding columns and is scoped to the backfill path, so it does not widen the request-path store contract. The request-path Create/Update clears these columns when a page's indexed text changes; this Store writes them back.

func NewStore

func NewStore(db *sql.DB) *Store

NewStore returns a Store over the given database.

func (*Store) Coverage

func (s *Store) Coverage(ctx context.Context) (indexed, expected int, err error)

Coverage returns the number of non-deleted pages with an embedding (indexed) and the total number of non-deleted pages (expected).

func (*Store) FindGaps

func (s *Store) FindGaps(ctx context.Context, currentModel string) ([]string, error)

FindGaps returns the ids of non-deleted pages whose embedding is missing or was produced by a model other than the current provider's.

func (*Store) GetIndexText

func (s *Store) GetIndexText(ctx context.Context, id string) (string, error)

GetIndexText returns the composed embed text for a non-deleted page. A page soft-deleted between enqueue and claim yields errNotIndexable so the Source returns an empty item set. The composition is knowledgepage.IndexText, the same one the request-path search ranks against.

func (*Store) ListVectors

func (s *Store) ListVectors(ctx context.Context, id string) (map[string]indexjobs.Vector, error)

ListVectors returns the page's persisted embedding keyed by item id (the page id), for the worker's text-hash + model dedup pass. A page with no embedding yields an empty map, so the worker embeds it.

func (*Store) UpsertVectors

func (s *Store) UpsertVectors(ctx context.Context, id string, rows []indexjobs.Vector) error

UpsertVectors writes the embedding back onto the page. The page unit holds exactly one item; a missing or empty row set is a no-op. updated_at is left untouched: a background embed is not a user-visible edit, so the page's "last modified" timestamp must not move.

Jump to

Keyboard shortcuts

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