ATHELOS
AI

Semantic Search

Searching the knowledge base by meaning, not by keyword.

Semantic Search

Semantic search finds articles by what they mean, not by what words they contain. Ask a question in natural language and get relevant results even if they share no vocabulary with your query.

Keyword search — matches the exact words in your query against the words in the article.

Semantic search — matches the meaning of your query against the meaning of the article.

Example query: "how do attackers move laterally in Active Directory"

Keyword search finds articles containing those exact words. If your AD playbook says "kerberoasting" and "delegation abuse" but never "move laterally," keyword search misses it.

Semantic search finds the AD playbook, the Kerberoasting article, the delegation article — because they're about the same thing.

How it works

Semantic search uses embeddings — numeric vectors that represent the meaning of a piece of text.

The pipeline:

  1. Every KB article is converted to a 768-dimensional vector using a local embedding model (nomic-embed-text)
  2. Vectors are stored in Postgres using the pgvector extension
  3. When you search, your query is converted to a vector the same way
  4. ATHELOS computes cosine similarity between your query vector and every article vector
  5. Articles are ranked by similarity, top matches returned

Everything runs locally. The embedding model runs in Ollama. The vector search runs in Postgres.

The embedding model

ATHELOS uses nomic-embed-text by default:

  • 768 dimensions per vector
  • 8,192 token context window
  • Trained specifically for retrieval
  • Fast enough to embed articles in hundreds of milliseconds

Pull it if you haven't:

ollama pull nomic-embed-text

Verify:

ollama list | grep nomic

The pgvector extension

Pgvector is a Postgres extension that adds a vector column type and similarity operators.

ATHELOS installs it automatically when you run migrations. To verify:

docker exec soc_postgres psql -U soc -d soc_solo -c "\\dx" | grep vector

Should show vector in the extensions list.

The embeddings table

Articles are embedded in kb_article_embeddings:

ColumnPurpose
article_idForeign key to kb_articles
modelWhich embedding model was used
dimensionsVector size (768 for nomic)
content_hashSHA-256 of the source text
embeddingThe actual vector

The content hash is how ATHELOS knows when an article needs re-embedding. If the article's text changes, the hash changes, and the embedding is stale.

Automatic embedding on write

When you create or edit a KB article:

  1. ATHELOS composes the text to embed (title + summary + body)
  2. Computes its SHA-256 hash
  3. Compares to the stored hash
  4. If different, generates a new embedding and updates the row
  5. If identical, skips — no wasted work

This is idempotent — editing an article without changing the text doesn't re-embed it.

Reindexing

If you change the embedding model, or want to force a full re-embed:

Settings → AI → Embeddings → Reindex all

Or via CLI:

pnpm reindex:embeddings

This walks every article, recomputes its embedding, and updates the database. Progress is shown in real time.

Reindexing is safe — it doesn't delete anything, just updates embeddings.

Two ways to access it:

1. From the knowledge base

Open Knowledge. The search box has a mode toggle:

  • Keyword — Meilisearch (fast, typo-tolerant)
  • Semantic — pgvector (meaning-based)

Type your query in either mode. In semantic mode, use natural language — full sentences work best.

2. From the command palette

Press Ctrl+K. Type your query. Results include both keyword and semantic matches, ranked together.

Semantic matches are marked with a small icon so you know how they were found.

Query tips

Semantic search rewards natural language. Examples:

Good queries:

  • "how do I exploit unconstrained delegation"
  • "techniques for bypassing EDR"
  • "lateral movement using WMI"
  • "remediating SQL injection in Node.js"

Poor queries:

  • "delegation" — too vague
  • "mimikatz" — a keyword; use keyword search
  • "T1550.002" — an ID; use keyword search

The embedding model understands concepts, not codes. Use it for concepts.

Similarity threshold

By default, ATHELOS shows the top 10 matches. Results below a similarity threshold are filtered out to avoid noise.

Adjust the threshold in Settings → AI:

  • High (0.75) — only very close matches
  • Medium (0.60) — balanced (default)
  • Low (0.45) — broader, more noise

Start with the default. Lower it if you're not finding things. Raise it if results feel irrelevant.

Performance

Semantic search on a typical KB (a few hundred articles) returns in under 100ms. The bottleneck is usually the query embedding computation, which takes 20–50ms on CPU.

For very large KBs (thousands of articles), pgvector's HNSW index keeps search fast. ATHELOS creates the index during migration.

When semantic search isn't available

Semantic search requires:

  • Ollama running
  • The embedding model pulled
  • Embeddings generated for your articles

If any of these is missing, semantic search falls back to keyword search with a small notice.

Check Settings → AI to see the state.

Embedding coverage

The embeddings panel shows:

  • Total articles in the KB
  • Articles with valid embeddings
  • Articles that need re-embedding (stale hash)
  • Coverage percentage

If coverage is below 100%, click Reindex to catch up.

Storage cost

Each embedding is 768 floats — about 3 KB per article. For a few hundred articles, that's under 1 MB. Negligible.

pgvector stores vectors efficiently and the index adds overhead proportional to the number of vectors. Still tiny.

Where to go next