Cerebras published the blueprint for its internal knowledge base — data stays put, no habits change, and the AI does the fetching

Three months after launch, it's answering more than 15,000 questions a day — and the specifics behind the four-way scoring, thread distillation, and rank fusion are all out in the open.
By Cerebras07-18 · 12 min read⚑ Tutorial / how-to
🎧 Listen to the podcast0:00 / --:--
0:00 / --:--
Deep Dive · XiaoHu Explains
The 60-second version
  • Three Cerebras engineers published how the company built its internal knowledge base, Cerebras Knowledge. Three months after launch, it's fielding more than 15,000 questions a day — from employees, automated scripts, and agents alike.
  • It doesn't ask anyone to change how they work: material stays in Slack, code repos, and the docs system, and the system goes to each platform to pull the data, all landing in the same Postgres table.
  • Slack is the hardest source to crack. The same batch of candidates gets scored four different ways at once — full-text match, embedding match, rare-term weighting, and time decay — each covering a different blind spot.
  • Chat logs don't go straight into embeddings. A model first distills them into a fixed structure — a one-line question, a summary, the resolution, and the systems and code symbols involved — and only that gets embedded.
  • Six retrievers each produce their own ranking, merged into one via reciprocal rank fusion with the constant set to 60 — so a document that ranks well across several lists beats one that's first on only one.
Intro · Three months in

15,000 questions a day — and some of them come from agents

Three Cerebras engineers recently pulled back the curtain on the company blog, laying out exactly how their internal knowledge base, Cerebras Knowledge, works — from how data gets ingested to how answers get ranked, with every threshold and parameter along the way spelled out.

The system has been live for three months and now fields more than 15,000 questions a day. The people asking aren't just employees — automated scripts and agents ask too.

The problem it solves is one a lot of companies know well. Cerebras's teams span data center operations, chip design, hardware, training, inference, and cloud, and hundreds of new hires join every year. The company's chat channels fill up with the same three questions on repeat: where's this thing, who actually knows this, and what does this term mean.

◆What makes this worth reading is that it isn't a demo-grade RAG tutorial: 15,000 queries a day run against real company data, and every tradeoff and threshold along the way is spelled out — 3,072-dimension vectors, a rare-term cutoff of IDF ≥ 4.0, a 200-character minimum after burst merging, a rank-fusion constant of 60, and only 10 pieces of evidence surviving the final rerank.
Overview of Cerebras Knowledge's six-layer architecture
The original diagram's labels, top to bottom:
① SOURCES — Slack, wiki, code, incident records ② DISTILLATION — a model extracts raw content into a fixed structure ③ EMBEDDINGS — stored in Postgres via pgvector, 3,072 dimensions, indexed with HNSW to find the nearest vectors fast ④ RETRIEVAL — six rankings run in parallel ⑤ FUSION + RERANK — reciprocal rank fusion first, then a small model reranks ⑥ SYNTHESIS — produces a cited answer. Source: Cerebras
The design call · Where the data lives

Why "move everything to one place" never works

The hard part of finding things inside a company was never the search itself — it's that the material is inherently scattered. Every quarter, someone proposes the same "brilliant plan": record everything on one platform from now on, and make it the single source of truth. In practice, that almost never works.

The reason is that information gets created wherever it's most convenient: a suggested edit in a doc, a thread in Slack, a code reference on GitHub, a status field in Jira. Each of these platforms has spent years being refined for its own use case. Discussing a pull request in Google Docs would be a miserable experience.

So Cerebras's first decision was to design a system that asks almost no one to change their existing habits. On the ingestion side, that means going directly to each platform and pulling the data out.

The move-everything plan
  • Ask everyone to write to one unified platform from now on
  • Everyone gets an extra step, and it lapses after a few weeks
  • Historical material stays where it was — neither copy is complete
The connector plan (what they chose)
  • People keep writing wherever is most natural
  • Write one connector per source to pull the data
  • Everything pulled back gets normalized into the same table

The core of the whole thing is a single table

The knowledge base offers three things externally: a place to store internal data, a place to query it, and a layer handling authentication, access control, auditing, and usage stats.

At the core is one Postgres table holding vectors, raw summaries, and metadata side by side, regardless of source. The system keeps pouring in data from across the company to stay continuously queryable. The data interface is deliberately simple: whether it comes from a Slack thread or a netlist file used in chip design, it lands in the same vector table — and once it's in that table, it's queryable through the same interface.

Every data source only needs to define three things: what the data is, how to connect to it, and how often to pull it. Every row it produces has exactly the same field structure.

One source, one connector — same table, same interface
Slack channels
Wiki / Confluence
Code repos
Netlist files
Internal docs
Team-built databases
→
EMBEDDINGS (one table)
document — normalized body text
embedding — 3,072-dim vector
metadata — channel, author, system
source + timestamp
MCP toolsWeb UIAgents
Source: Cerebras (architecture diagram redrawn from the original). This table is the common foundation for everything downstream: adding a new data source requires zero changes on the query side.

This design also leaves a door open for other teams. Some teams already run their own databases and don't want to move that data into Slack or a docs system just to get it into the knowledge base. The workaround is to treat that kind of source as a plugin script: the team submits a pull request with a small Python module that reads from its own system, emits rows matching the table's schema, and registers a data-source record. As long as it writes into the same store using the same fields, nothing else in the pipeline needs to change.

Slack · Hybrid retrieval

The hardest part of Slack is telling which line actually matters

Slack is the data source they care about most and find hardest to handle — it's where the company's freshest engineering discussions happen. They initially tried the cheapest approach: embed the raw text directly and search it. It quickly became clear that vectors alone couldn't catch everything.

The problem comes down to three traits of chat logs. First, information density varies wildly — "okay thanks" and a full paragraph explaining a kernel implementation both look like a single message to the system. Second, messages vary a lot in length, and short messages often beat out longer, more detailed ones on vector similarity. Third, a message's meaning often depends on the conversation around it.

What those three traits add up to

Say you search the channel for "restore hangs after manifest load." The reply that actually solved this might not share a single word with the query — it says "checkpoint got stuck on the NFS mount." The literal closest match might be an eight-month-old workaround that's since been retired. And "okay thanks" resembles almost every question ever asked, at least a little.

Their fix is to have the same content covered by several retrieval methods at once, each patching a different weak spot. Same query, same four candidates — switch the scoring method and who gets boosted and who gets buried changes every time (figures taken from the original post's example).

Query: restore hangs after manifest load
Matches on literal wording. When an engineer pastes an exact error string, a literal match is the strongest possible evidence — no amount of semantic similarity should outrank it. The tradeoff: a reply that describes the same issue in completely different words won't match at all.
Matches on meaning. The person asking says "restore is stuck," the person who solved it says "checkpoint stalled on the NFS mount" — the two might not share a single word, and this layer exists to catch exactly that case. The tradeoff: small talk sits close to every question in vector space.
Weights terms by how rare they are. A short message that happens to use an obscure config-flag name deserves to rank; "okay thanks" scores near zero once rarity is what counts.
Discounts by age. Two messages might both answer the same question, but the infrastructure an eight-month-old reply describes may no longer exist. When relevance is roughly tied, the newer one wins.
2 weeks ago · thread
Checkpoint got stuck on the NFS mount — set CKPT_PREFETCH to 4.
shares no common words different wording, same meaning CKPT_PREFETCH is very rare within two weeks — wins on a tie
1 day ago · single message
ERR_MANIFEST_TIMEOUT: restore hangs after manifest load.
exact word-for-word match error code counts as a rare term
3 hours ago · single message
Okay got it, thanks, I'll try that.
false neighbor — resembles everything a little all common words, scores near zero
8 months ago · thread
Restore hangs after manifest load — switch to LEGACY_FETCHER=1.
nearly word-for-word identical 8 months old — discounted for age
Solid fill = boosted by this score · dashed gray = buried · plain white with no tag = no clear effect from this score. Figures taken from the original post's example. Source: Cerebras
What this shows

Click through all four tabs and the boosted set never matches the buried set. The two-week-old thread — rephrased, carrying a rare parameter name — is the actual answer, but it doesn't match a single word under full-text; only embedding, rare-term weighting, and age decay recognize it. Flip it around: the eight-month-old reply that's almost word-for-word identical gets the top boost under full-text match, and only gets discounted once age decay kicks in. Used alone, any single scoring method either misses the real answer or ranks a stale one first. So all four run in parallel, and their rankings get merged at query time.

Slack · Distillation and backfill

Chat logs don't go straight into embeddings

Raw Slack text becomes keyword-searchable the moment it lands, because they maintain a full-text index on the original text in Postgres. But making embedding search actually useful takes one more processing step.

That step is called distillation: a model reads the entire thread and extracts four things — a one-line question an engineer would actually search for, a short summary, the eventual resolution, and the systems and code symbols mentioned along the way. Those four things get embedded; the verbatim chat log never goes into the vector store. In testing, normalizing threads into this fixed structure produced a clear accuracy gain, and the extra metadata gave semantic matching more to work with.

One thread, three processing stages
① Raw thread
09:14 MayaRestore hangs after manifest load on the big cluster — small runs are fine.
09:17 OwenReproduces with 128 shards, log stops right before cache warmup.
09:18 SamMine hangs on Mondays too, on my laptop.
09:21 MayaSetting CKPT_PREFETCH=4 fixed it — the default is too high for an NFS mount.
→
② Extracted into structured fields
questionWhy does restore hang after manifest load?
summaryLarge-scale restores stall right before cache warmup.
resolutionSet CKPT_PREFETCH=4 for NFS mounts.
systemscheckpoint restore, NFS
code_refsCKPT_PREFETCH
→
③ One embedded row
normalized textquestion + summary + resolution + systems + code symbols
sourceslack_thread
source_idthread_8f42
embedding3,072 dimensions
metadatachannel + participants + time
Source: Cerebras (diagram redrawn from the original). Note that the third message — "Mine hangs on Mondays too" — is off-topic. It appears in the raw log but never makes it into the extracted structure.
How data arrives in real time: Socket Mode and full-thread refetching

On the ingestion side, they installed a Slack bot in the workspace running in Socket Mode: Slack pushes every message event over a persistent connection instead of the bot repeatedly polling the Web API, so it never hits rate limits.

Each event gets acknowledged the moment it arrives, deduplicated by a stable event ID, and flagged for ingestion. There's a subtle design choice in the ingestion step: it doesn't just store the new message in isolation. It first figures out which thread the message belongs to, then refetches the entire conversation from the Slack API — the original message plus every reply — and writes the whole thread back as one row. So a single new reply triggers a refetch of the parent message and all its sibling replies; the stored text, participant list, and last-active time always reflect the current state of the full conversation.

Each Slack channel is also its own independent data source in the system, so ingestion frequency can be tuned per channel — a team can have its high-traffic incident channel refresh more often than the rest.

The message a long thread's summary leaves out

At this point Slack retrieval already worked, but they kept running into the same problem: an important message buried in a long thread doesn't always survive into that thread's summary.

The fix is called bursting. A burst is a run of consecutive messages from the same person. They embed each burst on its own, with the thread's overall topic prepended as context. That way, an answer buried in some tangential sub-thread — whose wording never made it into the thread-level summary — can still surface on its own.

To keep low-value content from flooding the database, each burst has to clear a weighted threshold before it gets embedded, judged on three criteria: it contains a term rare enough across the company's corpus, with a rarity cutoff of IDF ≥ 4.0; it's at least 200 characters once merged; or a message in it got an emoji reaction, counted as a coworker's stamp of approval.

Five messages, two bursts, one gets filtered out
Author Ashort message
Author Aone more line
Author Ba chunk of technical detail
Author Bstates the resolution
Author Cgot it
→
BURST 01 — filtered out
Too short, all common words, no emoji reaction — fails all three criteria.
BURST 02 — embedded
Long enough, contains a rare term, got an emoji reaction — embedded and stored alongside the full-thread record in the same table.
Source: Cerebras (diagram redrawn from the original). Author C's single "got it" forms its own burst and also fails the threshold. So the same thread ends up with two levels of granularity in the database: one record for the whole thread, plus however many bursts clear the bar.
Code repos · Chunking and incremental updates

Keeping a 40GB codebase fresh

Whether to embed the codebase at all was something they went back and forth on. With command-line tools like Claude Code around, building a vector index for code feels almost counterintuitive — grep seems like it should be enough. After talking to peers in the industry and reading Cursor's writeup on semantic search over large codebases, they decided to try it.

The real concern was something else: the company has many internal repos, some over 40GB each, and the question was how to keep an index current at an acceptable cost.

They ended up on CocoIndex, an open-source framework built specifically for codebase embedding. Chunking follows each language's syntactic boundaries, trying coarse-to-fine: start at a high-level boundary like a class; if the resulting chunk is still too big, fall back to method boundaries; if that's still too big, fall back further to smaller blocks of code. The same file ends up producing embeddings at several granularities — one at the file level, one per function, and so on.

Fixed-length chunking, every N tokens
  • Where a chunk splits depends purely on length
  • A function can get sliced in half
  • Chunks often miss context at both ends, unreadable on their own
Syntax-aware chunking, coarse to fine
  • Try a class first, fall back to methods, then to conditionals and loops
  • Every chunk is a complete syntactic unit
  • The same file yields multiple granularities, searchable at any level
Sample code showing syntax-boundary chunking
The original post's chunking example. On the left, the highlighted regions in the code are the identified semantic chunks, with line-end annotations showing which level each was cut at: it tries the class first, descends into the three methods LoadManifest(), WarmShardCache(), and Restore(), and falls back further to the if/for level where a method is still too big; the private-fields block at the end forms its own chunk. The two boxes on the right show the two approaches from the comparison table above (01 NAIVE WINDOWS — fixed-length chunking, 02 LANGUAGE-AWARE — syntax-boundary chunking, with the latter selected in the diagram); in the legend at the bottom, SEMANTIC NODE refers to a semantic chunk and FIXED SPLIT to a fixed-length cut point. Source: Cerebras

Updating is where this approach really pays off. CocoIndex also stores its sync metadata in Postgres, so each commit only re-processes the chunks that actually changed, instead of recomputing the whole repo. Having sync state live in the same store as the vectors turned out to suit them especially well.

As more codebases got connected, onboarding a repo became a config file that teams submit themselves, with allow-lists and block-lists settable by file path.

The query side · Picking tools and gathering evidence

What happens after a question comes in

Every incoming question first goes through a short planning pass: a model decides which tools and data sources the question likely needs, then dispatches the selected tools in parallel.

Plan → parallel evidence-gathering → synthesis
PlanPLANNER
searchUnified embedding search across Slack, wiki, code, and every other source, already merged and reranked internally
search_slackQueries Slack directly
search_codeRuns ripgrep, a fast command-line full-text search tool, against the source repos
subsystem_indexPer-file summaries
recent_prsRecent pull requests relevant to the question
who_knowsPeople who've actually contributed on a given topic
Synthesisanswer + citations
Source: Cerebras (flow diagram redrawn from the original). The planning step works from a compressed index describing which projects exist, which sources sit under each project, and what kind of question each source is good at answering. It picks tools based on that, the execution layer dispatches them in parallel, normalizes what comes back into a unified evidence format, and hands it to a final model pass to synthesize the answer.

On the MCP side, tools get handed straight to the agent to orchestrate

In the web UI, the pipeline above runs end to end: planning picks the tools, execution gathers evidence in parallel and normalizes it into a unified format carrying scores, timestamps, and source hints, and a final model pass produces an answer with citations and caveats. From the user's side, it's just asking a question and getting an answer.

The MCP integration takes the opposite approach: it exposes retrieval as individual, directly callable tools rather than hiding everything behind one big "answer my question" interface. These tools are deliberately kept simple, with as little model involvement as possible, so a client can query them fast and cheap. Each MCP tool maps to one bare retrieval action, with narrow, structured, stable inputs and outputs that any client or agent can call directly. Most of them run a single retrieval path — semantic search, literal search, or a straight ripgrep call — apply a light scoring pass, and return the raw evidence rows.

That leaves orchestration to MCP-capable agents like Claude Code: which tools to call, in what order, and how to assemble the results into a final answer or a code change is all up to the agent. The retrieval layer keeps working regardless of what any of those model judgment calls decide.

Ranking · Rank fusion

Merging six rankings into one

A search result can land at the top purely because it happens to share words with the query, while actually answering a different question. Worse, the scores from the six retrievers aren't directly comparable — a vector's cosine similarity and a full-text relevance score are simply not the same ruler.

Their approach is to ignore the raw scores and look only at rank position. The algorithm is called reciprocal rank fusion, or RRF: every time a document appears on a ranked list, it gets a score bump of 1 divided by (60 plus its rank on that list), with a default weight of 1.0; that 60 is a smoothing constant.

Six rankings, top five each
Embedding
1 CKPT_LOADER.CC
2 CLASS: CHECKPOINTLOADER
3 WIKI: checkpoint format
4 THREAD: NFS stuck
5 INC-82: restore slowdown
Full-text
1 WIKI: checkpoint format
2 CKPT_LOADER.CC
3 RUNBOOK: NFS mount
4 INC-82: restore slowdown
5 THREAD: cache warmup
Thread summary
1 THREAD: NFS stuck
2 THREAD: cache warmup
3 CLASS: CHECKPOINTLOADER
4 WIKI: load stuck
5 INC-82: restore slowdown
Dependency graph
1 CLASS: CHECKPOINTLOADER
2 MANIFEST_PARSER.H
3 RUNBOOK: NFS mount
4 THREAD: NFS stuck
5 WIKI: checkpoint format
Wiki embedding
1 WIKI: checkpoint format
2 WIKI: load stuck
3 RUNBOOK: NFS mount
4 INC-82: restore slowdown
5 CLASS: CHECKPOINTLOADER
Slack full-text
1 THREAD: NFS stuck
2 THREAD: cache warmup
3 BURST: timeout parameter
4 INC-82: restore slowdown
5 CLASS: CHECKPOINTLOADER
Merged final ranking
1 CLASS: CHECKPOINTLOADER0.0792
2 INC-82: restore slowdown0.0776
3 WIKI: checkpoint format0.0640
4 THREAD: NFS stuck0.0640
5 THREAD: cache warmup0.0476
6 RUNBOOK: NFS mount0.0476
Source: Cerebras (interactive diagram redrawn from the original; entry names and scores are the original data). The highlighted document appears on five of the six lists.

Walking through the top-ranked document makes the mechanism clear. CLASS: CheckpointLoader appears on five of the six lists, ranking 1st, 2nd, 3rd, 5th, and 5th:

CLASS: CheckpointLoader Dependency graph rank 1 1 / (60 + 1) = 0.01639 Embedding rank 2 1 / (60 + 2) = 0.01613 Thread summary rank 3 1 / (60 + 3) = 0.01587 Wiki rank 5 1 / (60 + 5) = 0.01538 Slack rank 5 1 / (60 + 5) = 0.01538 total 0.0792 → ranks 1st INC-82: restore slowdown (never once ranked 1st) ranks 4, 5, 5, 4, 4 total 0.0776 → ranks 2nd
What k=60 does

Adding 60 in front of the rank means 1st place and 5th place differ by only 6% in score (0.01639 vs. 0.01538). Without that constant — using the bare reciprocal of rank instead — 5th place would score only a fifth of 1st place. So the 60 flattens out the payoff for ranking near the top, letting consensus beat a single strong vote: a document that ranks well across several retrievers beats one that only takes first place in one of them. INC-82 above is the example — it never once ranked 1st, but landed 2nd overall by consistently appearing on five different lists.

Score from rank position, with and without the constant
With k=60: 5th place loses only 6% Without it: 5th place drops to a fifth High Low 1 5 10 A document's rank on a given list Score at that rank
The vertical axis is the score a given rank position earns on a list, with both curves normalized to their own 1st place. The solid line is the actual k=60 used in production — it stays nearly flat from 1st to 10th. The dashed line is the bare reciprocal of rank with no constant — 2nd place already drops by half. Source: Cerebras (formula and constant taken from the original post; the curves are plotted from that formula).

Three more steps after merging

The fused ranking doesn't go straight to answer-writing. First, duplicate chunks from the same source that got split apart are merged back together; then a cap limits how many results a single file can contribute, producing a more diverse top twenty. Those twenty, along with the original question, go to a small reranking model that scores each one 0 to 10 and keeps the top ten.

From fusion to final evidence — the steps in between
STEP 1Merge duplicate chunks from the same source back into one
STEP 2Cap how many results one file can contribute, for more diversity
STEP 3Keep the top 20 candidates
STEP 4A small reranking model scores each 0–10, keeps the top 10
STEP 5Restore the surrounding paragraphs for each matched passage
Source: Cerebras (illustrated based on the original description). The first three steps subtract and dedupe; the last two filter for quality and backfill context.

Once the ranking is settled, the surrounding context gets restored. If a hit lands in some paragraph of a wiki page, the paragraphs immediately before and after get pulled in too, so a heading, a precondition, or a caveat that got separated during chunking doesn't go missing. What reaches the reader is a complete citation, not an isolated fragment missing its premise.

By the end of this pipeline, what retrieval hands off is a package of evidence: pulled from different retrievers, fused, deduplicated at the source level, reranked against the actual question, and finally padded out with surrounding context.

Organization · Retrieval scope

Searching the whole company makes results worse

As the corpus kept growing, "search everything" stopped being useful pretty fast. A compiler engineer doesn't want data-center runbooks cluttering up their results — and vice versa.

Their fix was to add a layer called project. A project is a named bundle of data sources — a set of Slack channels, code repos, internal databases, and doc spaces organized around a team or a project. Projects are deliberately lightweight: the same data source, like a company-wide incident channel or a central platform repo, can be referenced by multiple projects at once without duplicating it.

New hires get guided into picking or creating a default project closest to their actual work — training infrastructure, compilers, data center ops. That default lives in the user's profile, and every query after that is automatically scoped to it. The upshot: new engineers don't have to spend time figuring out which Slack channels, repos, or doc spaces are relevant to them — the results they get from day one are already relevant.

Company-wide scope
  • A compiler question pulls in data-center runbooks
  • Relevance has to be forced by the algorithm alone
  • New hires can't tell which result to trust
Scoped to a single project
  • Only searches sources this team actually cares about
  • Scope catches relevance before ranking even has to
  • Pick once at onboarding, it applies automatically from then on
This knowledge base works because it meets people wherever the information already lives, instead of forcing everything into one rigid system. Cerebras, "How we built our knowledge base"
The numbers · At a glance

Every concrete figure mentioned in the post

15000+
Questions fielded per day, including employees, automated scripts, and agents
3 months
Time since launch — already one of the most widely used internal tools at the company
3,072 dims
Vector dimensions per record, stored in Postgres via pgvector
IDF ≥ 4.0
The rarity bar a burst must clear on at least one term to get embedded
200 chars
Minimum length after merging a burst — shorter, and it's dropped
k = 60
The rank-fusion smoothing constant, letting consensus beat a single strong vote
20 → 10
20 candidates survive fusion and dedup; the reranker's scores cut that to the top 10
40 GB+
Size of a single internal codebase — only incremental recomputation can keep up
✅ Eight decisions to check off if you're building something similar
Source: Cerebras's official blog post "How we built our knowledge base," by Isaac, Daniel, and Zenghao. All data, parameters, and examples in this piece come from that post and its figures; the architecture diagram and code-chunking diagram are the original post's own graphics, and the rest of the visualizations here are redrawn from the original's interactive diagrams. Cerebras Knowledge is an internal company tool and isn't publicly available.
Source
CerebrasCerebras·Read the source
↑ End of article
✓ This article is free to read in full

Members can copy or download the full Markdown, and let their AI subscribe and ask.

Read the original ↗
📮 New explainers, straight to your inbox

Found this useful? Leave your email — every new explainer, the moment it's out. Unsubscribe anytime.