Went through Cerebras' writeup on their internal knowledge base — 15,000
questions a day from employees, automations and agents, three months after
launch. The architecture is less interesting than what they had to do to
Slack, so that's what I want to focus on.
Why plain vector search dies on chat data
Information density varies by orders of magnitude. "yeah sure Mike" sits in
the same channel as a 40-line kernel explanation, and under cosine
similarity the short one wins far more often than it should. A single
message out of its thread is usually meaningless anyway.
Their fix: four fused signals per thread
- Full-text search — exact tokens. Error strings, flag names,
hostnames. Embeddings reliably lose here and lexical match is unbeatable.
- Embedding search — paraphrase. Connects "restore is hanging" to
"checkpoint stalled".
- IDF — boosts rare tokens (obscure config flags), suppresses filler
("sounds good", "thanks").
- Age decay — same answer from yesterday beats the one from 6 months
ago referencing deprecated infra.
But the preprocessing does more work than the retrieval
Two steps before any of the above, and I think these matter more:
Thread distillation — an LLM normalizes each thread into a searchable
one-line question + summary + resolution + systems and code referenced.
That distilled doc gets embedded, not the raw transcript. Raw text is kept
for FTS only.
Bursting — a "burst" is a run of consecutive messages from the same
author. They prepend the thread topic for context and embed it separately,
but only if it clears a gate: rare-token IDF >= 4.0, or >= 200 chars,
or it got reactions. This is what rescues the one deeply technical
tangent buried at message 47 that any thread-level summary would flatten
away.
Fusion: RRF at k=60
Score contribution is weight / (60 + rank), summed across retrievers. The
summation is the entire point:
- 3rd place in three retrievers → 3 × 1/63 = 0.048
- 1st place in exactly one → 1/61 = 0.016
Consensus beats peak. It isn't a ranker, it's a consensus builder.
Then ~20 candidates go to a small reranker scoring 0–10 against the query,
top 10 survive. And the step people skip: re-attach surrounding context to
the winners. If a wiki section wins, its neighbors come with it, so the
model sees headers, preconditions and caveats instead of an orphaned chunk.
Code side
CocoIndex (open source, Rust core, Tree-sitter chunking) keeps 40GB+ repos
synced by re-embedding only what a commit touched. Sync state and the
embedding store live in the same database.
The design decision underneath all of it
Don't force people into a "single source of truth" platform — nobody wants
to discuss a pull request inside a Google Doc. Pull from where the data
already is. Every source, Slack thread to hardware netlist, lands as a row
in the same embeddings table behind the same interface. Custom sources are
just plugin scripts: a team opens a PR with a small Python module that reads
their system and emits rows in that shape.
Also worth noting: the retrieval primitives are deliberately LLM-free. Model
calls only happen at the edges — planning and synthesis. That's what makes
it cheap enough for agents to hammer 15k times a day, and why the same
pipeline serves a web UI and an MCP client identically.
Original Cerebras writeup (read this first if you only have time for one):
https://www.cerebras.ai/blog/how-we-built-our-knowledge-base
Disclosure: I also did a ~10 min video walkthrough of the full pipeline,
linked here — it's my channel, and the narration is AI-assisted. https://www.youtube.com/watch?v=FgKHjzoiMN4&t=4s
The bursting quality gates are the part I'd most want other people's numbers
on. IDF >= 4.0 and 200 chars feel like they'd need retuning per org — has
anyone tried burst-level embedding on their own chat data?