Documentation
¶
Overview ¶
Package embedding provides text embedding infrastructure for VaultMind.
Index ¶
- Constants
- Variables
- func Acceleration() string
- func BGEM3TokenizerPath() string
- func BGEM3TokenizerPin() (revision, sum, url string)
- func BackendName() string
- func CapSymbolRuns(s string) string
- func CheckRuntime(context.Context) error
- func ColBERTHead(hiddenStates [][]float32, weights [][]float32, bias []float32) [][]float32
- func CosineSimilarity(a, b []float32) float64
- func DefaultCacheDir() string
- func DefaultModel() string
- func DenseHead(hiddenStates [][]float32) []float32
- func DownloadBGEM3(cacheDir string) (string, error)
- func ExpectedDenseDims(model string) (dims int, known bool)
- func L2Normalize(vec []float32) []float32
- func LoadLinearWeights(path string) (weight [][]float32, bias []float32, err error)
- func MaxSimAll(queryTokens [][]float32, docs [][][]float32, workers int) []float64
- func MaxSimScore(queryTokens, docTokens [][]float32) float64
- func ModelForDenseDims(dims int) (model string, known bool)
- func QuerySpanWindow(text string, forwardTokens int) string
- func ReadBGEM3Tokenizer() ([]byte, error)
- func SparseDotProduct(a, b map[int32]float32) float64
- func SparseHead(hiddenStates [][]float32, tokenIDs, specialMask []uint32, weights []float32, ...) map[int32]float32
- func SparsePositionWeights(hiddenStates [][]float32, specialMask []uint32, weights []float32, ...) []float32
- func TokenizerFetchHint() string
- func TokenizerMissIsFatal(ci string) bool
- func TruncateForEmbedding(text string, maxTokens int) string
- func WhitespaceTokenSpans(text string) [][2]int
- type BGEM3Embedder
- func (e *BGEM3Embedder) AnalyzeQuery(ctx context.Context, text string) (QueryTokens, error)
- func (e *BGEM3Embedder) Close() error
- func (e *BGEM3Embedder) Dims() int
- func (e *BGEM3Embedder) Embed(ctx context.Context, text string) ([]float32, error)
- func (e *BGEM3Embedder) EmbedBatch(ctx context.Context, texts []string) ([][]float32, error)
- func (e *BGEM3Embedder) EmbedColBERT(ctx context.Context, text string) ([][]float32, error)
- func (e *BGEM3Embedder) EmbedFull(ctx context.Context, text string) (*BGEM3Output, error)
- func (e *BGEM3Embedder) EmbedFullBatch(ctx context.Context, texts []string) ([]*BGEM3Output, error)
- func (e *BGEM3Embedder) EmbedSparse(ctx context.Context, text string) (map[int32]float32, error)
- func (e *BGEM3Embedder) TokenSpans(text string, forwardTokens int) ([][2]int, error)
- type BGEM3Output
- type Embedder
- type FullEmbedder
- type HugotConfig
- type HugotEmbedder
- type QueryTokens
- type SidecarBGEM3Config
- type SidecarBGEM3Embedder
- func (e *SidecarBGEM3Embedder) Close() error
- func (e *SidecarBGEM3Embedder) Device() string
- func (e *SidecarBGEM3Embedder) Dims() int
- func (e *SidecarBGEM3Embedder) Embed(ctx context.Context, text string) ([]float32, error)
- func (e *SidecarBGEM3Embedder) EmbedBatch(ctx context.Context, texts []string) ([][]float32, error)
- func (e *SidecarBGEM3Embedder) EmbedFull(ctx context.Context, text string) (*BGEM3Output, error)
- func (e *SidecarBGEM3Embedder) EmbedFullBatch(_ context.Context, texts []string) ([]*BGEM3Output, error)
Constants ¶
const ( BackendNameORT = "ort" BackendNameGo = "go" )
Backend names reported by BackendName(), which is defined per build tag in session_ort.go (ORT) and session_go.go (pure-Go). Declared here in a non-tagged file so callers in either build can compare against them without duplicating the literals (SSOT).
const ( DefaultModelName = "sentence-transformers/all-MiniLM-L6-v2" DefaultDims = 384 DefaultMaxTokens = 510 // MiniLM max is 512 minus 2 for CLS/SEP tokens DefaultOnnxFilePath = "onnx/model.onnx" )
Default model configuration for the all-MiniLM-L6-v2 embedder.
const ( BGEM3ModelName = "BAAI/bge-m3" BGEM3Dims = 1024 BGEM3MaxTokens = 8190 // 8192 minus 2 for CLS/SEP BGEM3OnnxFilePath = "onnx/model.onnx" // BGEM3EmbedMaxTokens is the per-note token cap the embedder truncates to. // The model accepts BGEM3MaxTokens, but forward memory grows faster than // the token count. Peak memory of a full embed (ORT CPU, model included): // 12–16 GB at 8190, about 6 GB at 2048, about 3 GB at 1024. On labelled // sets, 1024 kept Hit@3 within one query of 8190. Search text (FTS) still // holds the whole note; only the vectors read the first 1024 tokens. BGEM3EmbedMaxTokens = 1024 )
BGE-M3 model configuration.
const ( ModelMiniLM = "minilm" ModelBGEM3 = "bge-m3" )
CLI model tokens — the values the --model flag and RunEmbed receive. Distinct from the HuggingFace IDs above (DefaultModelName / BGEM3ModelName); named here so the token→dimension mapping has a single source of truth.
const RepeatedNonAlnumCap = 16
RepeatedNonAlnumCap is the longest run of consecutive characters that are neither letters, digits, nor whitespace kept in text that will be tokenized. A longer run carries no ranking signal. The tokenizer's lattice on that run grows much faster than the length: one punctuation character at 2 KB already takes a third of a second, and an unspaced mix of punctuation stalls the same way. Exactly this many characters of the run are kept. Letters, digits, and whitespace are never shortened.
Variables ¶
var ConstructBGEM3 = func(ctx context.Context, cfg HugotConfig) (Embedder, error) { if cfg == (HugotConfig{}) { cfg = BGEM3Config() } return NewBGEM3Embedder(ctx, cfg) }
ConstructBGEM3 builds the BGE-M3 embedder. Ranking and embed-on-write both go through it, so a test can count how many times a process loads the model. The production value is NewBGEM3Embedder.
A zero config is the default, resolved inside the seam so a stub does not run DefaultCacheDir. Evaluating BGEM3Config at the call site renames ~/.vaultmind/models before the stub runs.
var ConstructMiniLM = func(ctx context.Context, cfg HugotConfig) (Embedder, error) { if cfg == (HugotConfig{}) { cfg = DefaultHugotConfig() } return NewHugotEmbedder(ctx, cfg) }
ConstructMiniLM builds the MiniLM embedder. Same seam as ConstructBGEM3. A zero config is the default, resolved here for the same reason.
Functions ¶
func Acceleration ¶
func Acceleration() string
Acceleration mirrors the ORT-build's Acceleration() so callers don't need to special-case build tags. Pure-Go has no GPU path; "go-cpu" names the slow path explicitly.
func BGEM3TokenizerPath ¶ added in v0.10.13
func BGEM3TokenizerPath() string
BGEM3TokenizerPath is the legacy cache file ReadBGEM3Tokenizer reads. CI fetches tokenizer.json into ~/.vaultmind/models. Reading that file must not rename the directory into the XDG cache, so this does not call DefaultCacheDir.
func BGEM3TokenizerPin ¶ added in v0.10.13
func BGEM3TokenizerPin() (revision, sum, url string)
BGEM3TokenizerPin is the pinned tokenizer.json: revision, sha256, and the URL that serves only that file. Model weights are a different file.
func BackendName ¶
func BackendName() string
BackendName identifies which hugot backend the binary was built against. Consumers (e.g. the index command) use this to warn when BGE-M3 indexing is about to run on the slow pure-Go path so operators don't mistake "hours-long indexing" for a hang or OOM. Reported by the build tag.
func CapSymbolRuns ¶ added in v0.10.13
CapSymbolRuns shortens every run of characters that are neither letters, digits, nor whitespace, when the run is longer than RepeatedNonAlnumCap, to its first RepeatedNonAlnumCap characters. A string with no such run is returned unchanged, so a short or ordinary query stays byte-identical. The ranking query and document embedding both use this function (Principle 7).
func CheckRuntime ¶ added in v0.9.0
CheckRuntime is a no-op on the pure-Go build: there is no native runtime to be the wrong version. See the ORT build's CheckRuntime.
func ColBERTHead ¶
ColBERTHead projects each non-CLS token through a linear layer and L2-normalizes. Input: hiddenStates[seq_len][dims], weights[out_dims][in_dims], bias[out_dims]. Output: [seq_len-1][out_dims] (CLS at index 0 is skipped).
func CosineSimilarity ¶ added in v0.4.0
CosineSimilarity is the cosine between two vectors, or 0 when they are unusable (mismatched length, empty, or zero-magnitude).
It lives in the embedding package because both the retrieval layer (internal/query, business) and the distillation layer (internal/distill, infrastructure) need it, and ADR-009 forbids distill importing query. Putting it in the shared infrastructure both may use is the only placement that gives them one definition. A second copy would drift — and this project has an arc about a similarity number that silently meant the wrong thing, so one definition is the point.
func DefaultCacheDir ¶
func DefaultCacheDir() string
DefaultCacheDir returns the model cache directory — the XDG cache dir.
Weights are ~2.2 GB, so relocating must never mean re-downloading. On first use an existing legacy cache is renamed into place: instant when both live under $HOME, as they normally do. If the rename fails (separate filesystem, permissions), the legacy directory keeps being used rather than silently starting an empty cache beside a full one.
func DefaultModel ¶
func DefaultModel() string
DefaultModel returns the embedding model to use when the operator hasn't picked one explicitly. Adapts to the backend the binary was built against:
- ORT-tagged binaries → "bge-m3" (4-way hybrid retrieval — fast on this build path; what the README's retrieval description is built around).
- Pure-Go binaries → "minilm" (BGE-M3 indexing on pure-Go takes hours per medium vault; minilm is the always-fast baseline).
The default is conservative: it never picks a model the binary can't run reasonably. Users who want minilm on an ORT binary (e.g. for fast re-indexing during development) can pass --model minilm explicitly. Users who want bge-m3 on a pure-Go binary can opt in via --model bge-m3 + --allow-slow-backend.
The 2026-05-05 dogfood surfaced this gap: the prior hardcoded "minilm" default contradicted the system's own framing. A user running `vaultmind index --embed` on an ORT-capable build silently got MiniLM-only embeddings, learning about it only from doctor's post-hoc warning. The runtime-aware default closes that gap by matching the model to what the binary can actually run well.
func DenseHead ¶
DenseHead extracts the CLS token embedding (index 0) and L2-normalizes it. Input: hiddenStates[seq_len][dims]. Output: [dims] unit vector.
func DownloadBGEM3 ¶
DownloadBGEM3 makes sure the pinned BGE-M3 files are in the cache and match their hashes, downloading what is missing or wrong. Returns the path to the model directory.
func ExpectedDenseDims ¶ added in v0.2.2
ExpectedDenseDims returns the dense-embedding dimensionality a CLI model token produces, and whether the token is recognized. It is a pure lookup — it never loads a model — so callers can compare a vault's stored dimension against a requested model without paying the (multi-GB, multi-second) embedder load.
func L2Normalize ¶
L2Normalize returns a unit vector. Returns zero vector if magnitude is zero.
func LoadLinearWeights ¶
LoadLinearWeights loads a PyTorch nn.Linear layer's weight and bias from a .pt file. Returns weight as [out_features][in_features] and bias as [out_features]. The .pt file must be a state_dict saved via torch.save(state_dict, path).
func MaxSimAll ¶ added in v0.10.1
MaxSimAll scores every doc against the query with MaxSimScore, spread over up to workers goroutines, and returns the scores in doc order. Each doc's score is independent and computed exactly as MaxSimScore does, so the result is identical to scoring one at a time — only faster on several cores.
Why: ColBERT MaxSim over the candidate notes was 1.22 s of a 3.4 s three-vault ask, all on one core.
func MaxSimScore ¶
MaxSimScore computes the ColBERT MaxSim score between query and document token matrices. For each query token, finds max similarity across all doc tokens, then sums. Assumes both query and doc tokens are L2-normalized (from ColBERTHead), so dot product = cosine.
func ModelForDenseDims ¶ added in v0.2.2
ModelForDenseDims is the reverse of ExpectedDenseDims: the CLI model token that produces embeddings of the given dense dimension, and whether it is recognized. Used to name the model behind a vault's stored embeddings in diagnostics.
func QuerySpanWindow ¶ added in v0.10.13
QuerySpanWindow returns the prefix a span read may see for forwardTokens. forwardTokens <= 0 leaves the text unchanged. The width is querySpanCharsPerToken bytes per token, broken on a word when one is near the cut. Callers compare a bounded embed against this prefix.
func ReadBGEM3Tokenizer ¶ added in v0.10.13
ReadBGEM3Tokenizer reads the pinned tokenizer.json from the model cache. It does not load model weights.
func SparseDotProduct ¶
SparseDotProduct computes the dot product between two sparse vectors. Only overlapping keys contribute.
func SparseHead ¶
func SparseHead(hiddenStates [][]float32, tokenIDs, specialMask []uint32, weights []float32, bias float32) map[int32]float32
SparseHead pools SparsePositionWeights by vocabulary id. Duplicate token IDs keep the maximum weight. Positions the mask marks (CLS, SEP, PAD, UNK) are absent from the map.
func SparsePositionWeights ¶ added in v0.10.13
func SparsePositionWeights(hiddenStates [][]float32, specialMask []uint32, weights []float32, bias float32) []float32
SparsePositionWeights is the per-position ReLU(dot(hidden, w)+bias), before vocab-id max-pooling. Index i aligns with hiddenStates[i]. Positions the special mask marks are 0: the forward pass marks CLS, SEP, PAD, and UNK. Non-positive ReLU values are 0. Salient-term selection uses these weights, not the pooled map: pooling would give every occurrence of a token id the same weight.
func TokenizerFetchHint ¶ added in v0.10.13
func TokenizerFetchHint() string
TokenizerFetchHint names the cache path and how to fetch only tokenizer.json.
func TokenizerMissIsFatal ¶ added in v0.10.13
TokenizerMissIsFatal reports that a missing tokenizer must fail a test. GitHub Actions sets CI=true. Any other value, including empty, skips.
func TruncateForEmbedding ¶
TruncateForEmbedding truncates text to fit within the model's token limit. Uses a character-based approximation (2 chars/token, empirically derived). Breaks at word boundaries when possible.
Tail loss: content beyond maxTokens × 2 chars is dropped before tokenization — the head is embedded correctly but the tail is invisible to semantic retrieval (lexical FTS still sees the full body). For long-form notes where the tail carries information not in the head, this under-covers retrieval. Tracked as a quality improvement in vaultmind#30 (chunk-and-pool); not a silent failure or robustness bug, just a coverage limit. Build the chunking fix when retrieval visibly misses tail content; don't preempt.
func WhitespaceTokenSpans ¶ added in v0.10.13
WhitespaceTokenSpans is the one whitespace split. A keyword-only ask has no BGE-M3 tokenizer, so each whitespace word is one token. alignTokenWords uses the same split, and the two cannot drift (Principle 7).
Types ¶
type BGEM3Embedder ¶
type BGEM3Embedder struct {
// contains filtered or unexported fields
}
BGEM3Embedder produces dense, sparse, and ColBERT embeddings using BGE-M3.
func NewBGEM3Embedder ¶
func NewBGEM3Embedder(ctx context.Context, cfg HugotConfig) (*BGEM3Embedder, error)
NewBGEM3Embedder creates a BGE-M3 embedder with all three heads.
func NewSpanEmbedder ¶ added in v0.10.13
func NewSpanEmbedder(tokenizerJSON []byte, modelMax int) (*BGEM3Embedder, error)
NewSpanEmbedder builds an embedder that can only read token spans. It does not load the ONNX model. modelMax is the model cap stored on the embedder. TokenSpans sizes its window from the forward bound it is given. A test passes BGEM3MaxTokens so a mutation back to that cap is the real model limit.
func (*BGEM3Embedder) AnalyzeQuery ¶ added in v0.10.13
func (e *BGEM3Embedder) AnalyzeQuery(ctx context.Context, text string) (QueryTokens, error)
AnalyzeQuery returns the per-token weights of the one forward pass for text. The caller embeds that same string afterwards, and the memo makes it one pass. Word spans come from the query-only tokenizer. A span-read failure leaves the forward-pass weights in place and does not fail the query. Those weights already have CLS, SEP, PAD, and UNK zeroed.
func (*BGEM3Embedder) Close ¶
func (e *BGEM3Embedder) Close() error
Close releases the hugot session.
func (*BGEM3Embedder) Dims ¶
func (e *BGEM3Embedder) Dims() int
Dims returns the embedding dimensionality (1024).
func (*BGEM3Embedder) EmbedBatch ¶
EmbedBatch returns dense embeddings (Embedder interface compatibility).
func (*BGEM3Embedder) EmbedColBERT ¶
EmbedColBERT produces only the ColBERT per-token embeddings (used by ColBERTRetriever).
func (*BGEM3Embedder) EmbedFull ¶
func (e *BGEM3Embedder) EmbedFull(ctx context.Context, text string) (*BGEM3Output, error)
EmbedFull produces all three embedding types for a single text. The same text is computed once while remembered: every retrieval lane calls this for the query, and each wants a different one of the three outputs.
func (*BGEM3Embedder) EmbedFullBatch ¶
func (e *BGEM3Embedder) EmbedFullBatch(ctx context.Context, texts []string) ([]*BGEM3Output, error)
EmbedFullBatch produces all three embedding types for multiple texts. Bypasses hugot's Postprocess to access raw per-token hidden states.
func (*BGEM3Embedder) EmbedSparse ¶
EmbedSparse produces only the sparse embedding (used by SparseRetriever).
func (*BGEM3Embedder) TokenSpans ¶ added in v0.10.13
func (e *BGEM3Embedder) TokenSpans(text string, forwardTokens int) ([][2]int, error)
TokenSpans reports content-token byte spans for text without a forward pass. The read uses the query-only tokenizer, pre-cut to the span window for forwardTokens (the bound in use, not the model cap). forwardTokens <= 0 reads the whole string. The special mask only skips CLS and SEP. Spans are clamped to that window: the tokenizer can report an end a few bytes past the string it saw, and the cut must stay inside the prefix that was tokenized. An empty content list is a non-nil slice, so the caller can tell "tokenized, nothing" from a tokenizer error. The model clamp in preprocessWithinTokenLimit is what keeps an oversized note from hanging.
type BGEM3Output ¶
type BGEM3Output struct {
Dense []float32 // [1024] CLS-pooled, unit length
Sparse map[int32]float32 // vocab_id -> weight (non-zero only)
ColBERT [][]float32 // [seq_len-1][1024] per-token, unit length
TokenWeights []float32
TokenWord []int
Words []string
TokenOffsets [][2]int
}
BGEM3Output contains all three embedding types from a BGE-M3 forward pass.
TokenWeights, TokenWord and Words are the query-token view used to choose salient terms. TokenWeights are per-position ReLU weights before vocab-id max-pooling, with the CLS position dropped so they line up with ColBERT. A sidecar pass does not fill them.
type Embedder ¶
type Embedder interface {
// Embed produces a single embedding vector for the given text.
Embed(ctx context.Context, text string) ([]float32, error)
// EmbedBatch produces embedding vectors for multiple texts.
EmbedBatch(ctx context.Context, texts []string) ([][]float32, error)
// Dims returns the dimensionality of the embedding vectors.
Dims() int
// Close releases resources (model session, etc.).
Close() error
}
Embedder converts text into dense vector representations.
type FullEmbedder ¶
type FullEmbedder interface {
Embedder
EmbedFullBatch(ctx context.Context, texts []string) ([]*BGEM3Output, error)
}
FullEmbedder extends Embedder with multi-output capability (BGE-M3).
type HugotConfig ¶
type HugotConfig struct {
// ModelPath is the local path to the ONNX model directory.
// If empty, the model will be downloaded from HuggingFace.
ModelPath string
// ModelName is the HuggingFace model ID (e.g., "sentence-transformers/all-MiniLM-L6-v2").
// Used for downloading if ModelPath is not set.
ModelName string
// CacheDir is where downloaded models are stored.
CacheDir string
// Dims is the embedding dimensionality (e.g., 384 for MiniLM, 1024 for BGE-M3).
Dims int
// OnnxFilePath specifies which ONNX file to use when a model has multiple variants.
// E.g., "onnx/model.onnx" for the default, "onnx/model_O2.onnx" for optimized.
OnnxFilePath string
// MaxTokens is the model's context window size. Texts longer than this (in approximate
// tokens) are truncated before embedding. 0 means no truncation.
MaxTokens int
}
HugotConfig configures the HugotEmbedder.
func DefaultHugotConfig ¶
func DefaultHugotConfig() HugotConfig
DefaultHugotConfig returns the standard HugotConfig for all-MiniLM-L6-v2.
type HugotEmbedder ¶
type HugotEmbedder struct {
// contains filtered or unexported fields
}
HugotEmbedder wraps the hugot library to produce embeddings using ONNX models.
func NewHugotEmbedder ¶
func NewHugotEmbedder(ctx context.Context, cfg HugotConfig) (*HugotEmbedder, error)
NewHugotEmbedder creates an embedder using hugot with the Go backend. For ORT backend (faster, supports larger models), build with -tags ORT.
func (*HugotEmbedder) Close ¶
func (e *HugotEmbedder) Close() error
Close releases the hugot session.
func (*HugotEmbedder) Dims ¶
func (e *HugotEmbedder) Dims() int
Dims returns the dimensionality of the embedding vectors.
func (*HugotEmbedder) EmbedBatch ¶
EmbedBatch produces embedding vectors for multiple texts. Texts exceeding the model's token limit are truncated automatically.
The limit is enforced on the ACTUAL token count, not only the char estimate. #69 relaxed that estimate to 4 chars/token believing an exact guard stood behind it — true for BGE-M3, false here. Citation-dense notes tokenize near 2 chars/token, so up to ~1100 tokens reached a 512-position model and failed their whole batch (stranger test, 2026-09-23: 28 of 60 notes unembedded). fitTextsWithinTokenLimit is the same measured loop BGE-M3 uses; it costs one extra tokenization and nothing when every text already fits.
type QueryTokens ¶ added in v0.10.13
type QueryTokens struct {
Weights []float32
Word []int
Words []string
// Offsets are byte ranges into the text the tokenizer saw, aligned with
// Weights. A token with no span has end <= start.
Offsets [][2]int
}
QueryTokens is one query's per-token view of the forward pass, aligned with ColBERT (the CLS position is already dropped).
Weights are the per-position ReLU sparse weights BEFORE vocab-id max-pooling. Word is -1 when a token has no word: a special token, an empty offset, or a pass that did not report offsets. Sidecar output has none of these fields, and salient word selection does not run for it.
type SidecarBGEM3Config ¶
type SidecarBGEM3Config struct {
// Python is the interpreter path. Must have torch + transformers
// installed and be on a platform where torch.backends.mps.is_available()
// returns true (Apple Silicon). When empty, falls back to "python3" on
// PATH.
Python string
// ScriptPath is the absolute path to embed_server.py. When empty, the
// embedder looks for the script alongside this Go file (resolved via
// the project's $CLAUDE_PROJECT_DIR or the executable's directory).
ScriptPath string
}
SidecarBGEM3Config controls how the sidecar process is launched.
type SidecarBGEM3Embedder ¶
type SidecarBGEM3Embedder struct {
// contains filtered or unexported fields
}
SidecarBGEM3Embedder runs BGE-M3 inference in an external Python process that uses PyTorch + MPS (Apple Silicon GPU). The Go side handles tokenization context (none — Python sidecar tokenizes with HF tokenizer loaded from cache) and the heads run inside the sidecar so the per-modality tensors flow through MPS without round-tripping to CPU mid-batch.
Why a sidecar instead of in-process: in-process ORT (via hugot) saturates CPU during indexing on Apple Silicon — there's no GPU acceleration path (vaultmind#34). The sidecar pattern moves heavy inference behind a JSON contract, isolating vaultmind core from the inference engine choice. Today the engine is PyTorch+MPS; tomorrow it could be CoreML or MLX without touching the Go side.
Lifecycle: the embedder spawns the Python subprocess in NewSidecarBGEM3. Close() tears it down. Per-batch round-trips happen via Send (write JSON line to stdin, read JSON line from stdout). Mutex serializes access since the protocol is synchronous request/response on a single FD pair.
func NewSidecarBGEM3 ¶
func NewSidecarBGEM3(cfg SidecarBGEM3Config) (*SidecarBGEM3Embedder, error)
NewSidecarBGEM3 spawns the Python sidecar and waits for its ready signal. Returns an error if the subprocess fails to start, the Python imports fail, or the model can't be loaded. The caller MUST defer Close() to reap the subprocess.
func (*SidecarBGEM3Embedder) Close ¶
func (e *SidecarBGEM3Embedder) Close() error
Close terminates the sidecar process. Safe to call multiple times.
func (*SidecarBGEM3Embedder) Device ¶
func (e *SidecarBGEM3Embedder) Device() string
Device reports the device the sidecar selected ("mps" or "cpu"). Useful for the doctor / index summary so the operator sees acceleration.
func (*SidecarBGEM3Embedder) Dims ¶
func (e *SidecarBGEM3Embedder) Dims() int
Dims reports the dense embedding dimensionality.
func (*SidecarBGEM3Embedder) EmbedBatch ¶
EmbedBatch produces dense embeddings for a batch via the sidecar.
func (*SidecarBGEM3Embedder) EmbedFull ¶
func (e *SidecarBGEM3Embedder) EmbedFull(ctx context.Context, text string) (*BGEM3Output, error)
EmbedFull is the singleton form of EmbedFullBatch.
func (*SidecarBGEM3Embedder) EmbedFullBatch ¶
func (e *SidecarBGEM3Embedder) EmbedFullBatch(_ context.Context, texts []string) ([]*BGEM3Output, error)
EmbedFullBatch sends a batch of texts to the sidecar and parses the response. Tokens are sparse-key strings in the JSON; we parse to int32 here so the sidecar protocol stays portable across languages.