Skip to content

Semantic Search

OpenSearch semantic search uses ML embeddings for natural language log queries. Text is converted to 384-dimensional vectors using sentence-transformers/all-MiniLM-L6-v2 and stored in k-NN indexes for cosine similarity search.

SettingValue
Modelhuggingface/sentence-transformers/all-MiniLM-L6-v2
Pinned Version1.0.1 (see compatibility note below)
Embedding Dims384
Model Grouplogrite-ml-models
Space Typecosinesimil
  1. Text extracted from log message
  2. ML model generates 384-dim embedding vector
  3. Vector stored in embedding field with k-NN index
  4. Queries use cosine similarity for semantic matching
  5. Results ranked by semantic relevance (not keyword frequency)

Semantic-enabled indexes use _semantic suffix:

Semantic IndexSource Index
payment_queries_semanticpayment_queries
external_service_calls_semanticexternal_service_calls
database_queries_semanticdatabase_queries
exceptions_semanticexceptions
Terminal window
# Initial setup (one-time)
opensearch-mgr semantic-setup
# Creates: model group, registers model, deploys model,
# creates ingest pipeline, creates semantic indexes
# Check status
opensearch-mgr semantic-status
# Reindex existing data
opensearch-mgr semantic-reindex payment_queries
opensearch-mgr semantic-reindex --all
# Perform semantic search
opensearch-mgr semantic "payment timeout errors"
opensearch-mgr semantic "slow database queries" --index database_queries_semantic
# Ensure model is loaded (called by health check cron)
opensearch-mgr model-ensure
POST /payment_queries_semantic/_search
{
"query": {
"neural": {
"text_embedding": {
"query_text": "payment timeout errors",
"model_id": "vZ_rRJsB11WWRaeQeT1C",
"k": 10
}
}
}
}
POST /payment_queries_semantic/_search
{
"query": {
"hybrid": {
"queries": [
{
"neural": {
"text_embedding": {
"query_text": "slow payment processing",
"model_id": "vZ_rRJsB11WWRaeQeT1C",
"k": 10
}
}
},
{
"match": {
"message": "slow payment processing"
}
}
]
}
}
}

Documents are automatically embedded on ingestion via a text_embedding pipeline:

PUT _ingest/pipeline/logrite-embedding-pipeline
{
"processors": [
{
"text_embedding": {
"model_id": "vZ_rRJsB11WWRaeQeT1C",
"field_map": {
"message": "embedding"
}
}
}
]
}

The model-health-check.js cron runs every 30 minutes:

Terminal window
# Manual run
node /root/logrite/cli/model-health-check.js

If the model is unloaded (e.g., after OpenSearch restart), it:

  1. Calls opensearch-mgr model-ensure
  2. Waits for model to deploy
  3. Sends Discord alert if model fails to load

The semantic API writes a second ingest pipeline, logrite-upload-embedding, which embeds an upload event’s message into text_embedding with the deployed all-MiniLM-L6-v2 model (384-d, ignore_failure: true). New upload dataset indexes use it as their default_pipeline and map text_embedding as knn_vector, so uploads are searched by meaning. Collector indexes (log-analytics-<ws>-*) have no vector field and are searched by keyword; the API’s responses say which with mode and a KEYWORD_FALLBACK warning — see Semantic Search API.

Collector indexes: the template is ready, the clusters are not (2026-10-19). LogriteOpenSearch exports/templates/log-analytics-template.json now declares text_embedding as a 384-d knn_vector (lucene / hnsw / l2 — naming the method halves the bytes per document against the cluster default) plus embeddingFailed / embeddingError, and exports/apply-pipelines.sh creates logrite-upload-embedding. A knn_vector field cannot be added to an index that exists, so existing collector indexes only gain vectors through a reindex: scripts/semantic-backfill.sh, with the measured costs and the ML breaker it trips (the JVM heap one, at 85%) in docs/SEMANTIC-BACKFILL.md in that repo. As of 2026-10-19 neither the template nor the pipeline script has been applied to dev or prod, so the keyword fallback above still describes every collector index.