Build a knowledge base from a drive and search it#
You make a knowledge base of the documents on one of your drives and ask it questions. Its two models — BGE-M3 for embeddings (multilingual, 1024 dimensions) and BGE Reranker v2 M3 — are small enough to run on CPUs, next to the documents. Then you add an evaluation set and measure how well it finds what it should.
Before you begin#
- A drive with your documents (Markdown, text, HTML, PDF or Word), below
docs. Any drive works — a folder on one machine, a shared filesystem — or a drive from a data source, such as a bucket. Below, its documents are in the folderhandbook. - A machine of the workspace with a few free CPU cores and 4 GB of RAM for the two models, with a data location.
- To use the CLI,
astrasigned in, withastra use <org>/<workspace>(Install the CLI); for the API, a token inASTRALYX_TOKENandASTRALYX_API=https://api.astralyx.cloud/v1.
1. Serve the embedding model and the reranker#
Both must keep at least one replica: the knowledge base calls them on the workspace's network, which does not wake a deployment scaled to zero.
- Eos → Models → Library, Category: embedding, open
BGE-M3, choose
Q4_K_M(438 MB) and press Deploy. Name:bge-m3. Runs on: CPUs only. Clear Scale to zero when idle. Press Deploy. - Back in the library, Category: Rerankers, open BGE Reranker v2
M3, choose
Q4_K_M(438 MB) and deploy it the same way asbge-reranker.
$ for c in bge-m3:567m bge-reranker-v2-m3:568m; do
curl -fsS -X POST "$ASTRALYX_API/eos/catalog-models" -H "Authorization: Bearer $ASTRALYX_TOKEN" \
-H 'content-type: application/json' -d "{\"catalog\": \"$c\"}" | jq -r .metadata.name
done
bge-m3-567m-q4-k-m
bge-reranker-v2-m3-568m-q4-k-m
$ curl -fsS -X POST "$ASTRALYX_API/eos/deployments" -H "Authorization: Bearer $ASTRALYX_TOKEN" -H 'content-type: application/json' \
-d '{"metadata": {"name": "bge-m3"}, "spec": {"model": "bge-m3-567m-q4-k-m", "accelerator": "cpu", "replicas": {"min": 1, "max": 1}}}' > /dev/null
$ curl -fsS -X POST "$ASTRALYX_API/eos/deployments" -H "Authorization: Bearer $ASTRALYX_TOKEN" -H 'content-type: application/json' \
-d '{"metadata": {"name": "bge-reranker"}, "spec": {"model": "bge-reranker-v2-m3-568m-q4-k-m", "accelerator": "cpu", "replicas": {"min": 1, "max": 1}}}' > /dev/null
You can create the knowledge base before they are Ready: it waits for
them and says so.
2. Create the knowledge base#
- Metis → Knowledge bases → New knowledge base.
- Name:
handbook. - Sources: drive
docs, folderhandbook. Add more drives or folders if you like. - Embedding model:
bge-m3. Reranker:bge-reranker. - Press Create.
$ curl -fsS -X POST "$ASTRALYX_API/metis/knowledge-bases" -H "Authorization: Bearer $ASTRALYX_TOKEN" -H 'content-type: application/json' \
-d '{"metadata": {"name": "handbook"},
"spec": {"sources": [{"drive": "docs", "path": "handbook"}],
"embedding": {"deployment": "bge-m3"},
"reranker": {"deployment": "bge-reranker"}}}'
A drive or deployment that does not exist, or a deployment that is not an embedding model (or a reranker), is refused with the reason.
3. Watch it index#
The base goes Pending → Starting → Indexing → Ready. While it is
Indexing, it says how many documents of the pass it has read, and you can
already search what is indexed.
Open the knowledge base: its state, documents, chunks and progress, and the documents that could not be read, each with why.
A scanned PDF without a text layer, a password-protected document or a file
over 64 MB is listed there; the rest is indexed. If the base shows
Waiting, its reason names what it waits for — usually an embedding model
that is not serving yet.
4. Search it#
Open the knowledge base and type a question in Search. Each result shows its passage and citation: the document, its page or headings and line.
$ curl -fsS -X POST "$ASTRALYX_API/metis/knowledge-bases/handbook/search" -H "Authorization: Bearer $ASTRALYX_TOKEN" \
-H 'content-type: application/json' -d '{"query": "How many vacation days do I have?", "top_k": 3}' \
| jq '.results[] | {score, document: .citation.document, headings: .citation.headings, snippet: .citation.snippet}'
Your AI assistant can search it too, with the search_knowledge_base tool
(Connect your AI assistant).
5. Measure it with an evaluation set#
Write questions people ask, each with the documents that answer it, one per
line, in the hidden folder .metis/ of the source drive — it is read by
evaluations and never indexed:
{"question": "How many vacation days do I have?", "expected": ["handbook/leave.md"]}
{"question": "Who approves travel?", "expected": ["handbook/travel.md"]}
{"question": "What do I do on my first day?", "expected": ["handbook/onboarding.pdf"]}
Paths are the documents' paths in the drive. Then evaluate:
Or keep the set on your own computer: --cases evals.jsonl.
recall@k is the share of expected documents found among the first k;
MRR rewards finding the first one early (1.0: always first). Questions
not found are listed, with what was found instead. The base keeps the last
evaluation's numbers. At most 500 questions; an evaluation must finish
within a minute.
6. Index again#
New and changed files are picked up within rescan_seconds (60 s by
default); a drive from a data source is indexed again at each new revision.
To look now — or, with a full reindex, to read every document again:
Changing the embedding model or the chunking reads every document again by itself.
Troubleshooting#
| Symptom | Cause | Fix |
|---|---|---|
Failed: there is no deployment … |
The embedding model or reranker is not deployed | Deploy it (step 1), or name another |
Failed: deployment … serves chat, not embedding |
A chat model was named as the embedding model | Name an embedding deployment |
Waiting: waiting for its embedding model … |
The embedding deployment is not serving | Check it in Eos → Deployments |
| A warning … results by keywords only | The embedding model did not answer this search | Check the deployment; keep it at one replica at least |
| A PDF listed as no text layer (a scanned document?) | The PDF is images of pages | Export it with text, or add a text version |
| A document refused it … lower chunking.size | A chunk is longer than the embedding model's window | Lower chunking.size |
503 KNOWLEDGE_BASE_NOT_READY on a search |
Its index is not serving yet | Wait for Indexing or Ready; the message says its state and why |