promptindex

package
v1.131.2 Latest Latest
Warning

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

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

Documentation

Overview

Package promptindex is the prompt-library consumer of the shared indexjobs framework (#557, epic #525 phase 4). It registers a Source/Sink pair under source_kind = "prompts" so prompts are embedded off the request path. A freshly created prompt, an edited one, and one whose reviewed draft was just approved enqueue their own job at write time (#1256); the reconciler is the backstop for those a write could not produce and for the corpus a provider model swap invalidates.

Like the memory consumer, and unlike api-catalog/tools, prompts store their vectors inline on the prompts 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 of prompts directly: a prompt IS its own indexing unit. SourceID is the prompt id; each unit yields exactly one Item whose text is prompt.IndexText (title + body + description + tags).

Every enabled prompt is indexed regardless of lifecycle status (#1124): ranked search decides visibility at query time — a caller's own drafts and an admin's whole library rank — so the index covers what any caller can rank. Gap detection and coverage filter on enabled only; a disabled prompt is never embedded and never counted as missing coverage.

Index

Constants

View Source
const SourceKind = "prompts"

SourceKind is the indexjobs source_kind this package serves.

Variables

This section is empty.

Functions

This section is empty.

Types

type Sink

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

Sink implements indexjobs.Sink for the prompts kind over the embedding columns of the prompts 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 every row matches "" and only NULL-embedding rows are treated as gaps.

func (*Sink) Coverage

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

Coverage reports the prompts kind's indexed-vs-expected totals (enabled prompts with an embedding vs all enabled prompts). ExpectedKnown is true: every enabled prompt is expected to converge to one vector.

func (*Sink) FindGaps

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

FindGaps returns enabled prompt 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 prompts source kind.

func (*Sink) ListExisting

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

ListExisting returns the prompt'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 prompts. Gap detection is condition-based (embedding IS NULL OR model mismatch), not count-based, so there is no expected count to record per unit.

func (*Sink) Upsert

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

Upsert writes the prompt's vector. The prompt unit holds one item and has no sibling rows, so there is nothing to delete; 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 prompts (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 prompts kind. A unit is one enabled prompt (SourceID = prompt id) and yields exactly one item: the prompt'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 prompts source kind.

func (*Source) LoadItems

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

LoadItems returns the prompt's single embeddable item. A prompt that was deprecated, disabled, or 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 prompts 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 prompt embedding state on the prompts table for the indexjobs prompts consumer. It is intentionally separate from prompt.Store: it touches only the embedding columns (embedding, embedding_model, embedding_text_hash) and is scoped to the backfill path, so it does not widen the request-path store contract. The request-path Store clears these columns when a prompt'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 enabled prompts with an embedding (indexed) and the total number of enabled prompts (expected). Every enabled prompt is expected to carry a vector once converged.

func (*Store) FindGaps

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

FindGaps returns the ids of enabled prompts whose embedding is missing or was produced by a model other than the current provider's. Missing embeddings cover a freshly created prompt (and a content edit, which the request-path Update clears the embedding for); the model mismatch covers a provider model swap. Both converge off the request path when the reconciler enqueues them.

func (*Store) GetIndexText

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

GetIndexText returns the composed embed text for an enabled prompt. Every enabled prompt is embedded regardless of status (#1124): search visibility is decided at query time (a caller's own drafts and an admin's whole library rank), so the index must cover what any caller can rank, not just the approved set. A prompt disabled or deleted between enqueue and claim yields errNotIndexable so the Source returns an empty item set (a clean "nothing to index" completion). The composition is prompt.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 prompt's persisted embedding keyed by item id (the prompt id), for the worker's text-hash + model dedup pass. A prompt 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 prompt. The prompt unit holds exactly one item (the prompt itself); a missing or empty row set is a no-op. updated_at is deliberately left untouched: a background embed is not a user-visible edit, so the prompt'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