Your company handbook, searchable with citations#
Your handbook is a folder of PDF and Word files on one of your machines: policies, onboarding, benefits, travel. You make that folder a drive, index it in a knowledge base with two small models on CPUs, and ask it questions. Every answer is a passage with its citation — the file, and the page (PDF) or the headings (Word) it is under — so whoever reads it can check it. Then you write a few questions people really ask and measure how well the base finds their answers.
What you need:
- The handbook's files in one folder on a machine of the workspace, here
/srv/handbookoncpu-01. PDF files need a text layer (a PDF exported from a word processor has one; a scan does not — see Troubleshooting). Word files are.docx. - That folder granted to the workspace by an organisation admin, in the workspace's cluster access: Host access — nothing unless granted → Host paths.
- A machine with a data location and, free, 5 CPU cores and about 6 GB of
memory: 2 cores for each model and 1 for the base
(Footprint and cost). It may be
cpu-01itself. - The editor role, and the variables in How the recipes are written.
1. Make the folder a drive#
A drive gives the folder a name the base can read. On one machine keeps the files where they are: the base reads them there (over NFS when it runs on another machine), read-only, and deleting the drive never touches them.
- Astraeus → Drives → New drive. Name:
handbook-files. - Source 1, Kind: On one machine. Machine:
cpu-01. Path on the machine:/srv/handbook. - Mounted in workers at:
/data. Access: Read-only. - Create drive.
$ curl -fsS -X POST "$ASTRALYX_API/drives" -H "Authorization: Bearer $ASTRALYX_TOKEN" \
-H 'content-type: application/json' \
-d '{"metadata": {"name": "handbook-files"},
"spec": {"sources": [{"machine": "cpu-01", "path": "/srv/handbook", "mount_path": "/data", "mode": "ReadOnly"}]}}' \
| jq -r .metadata.name
handbook-files
astra makes drives backed by a data source only; a drive on one machine
is made in the console or the API. If the handbook lives in a bucket
instead, make a drive from that data source:
Keep a base in sync with a data source.
2. Serve the embedding model and the reranker on CPUs#
BGE-M3 embeds passages and questions in more than 100 languages; BGE
Reranker v2 M3 orders the best candidates again. Both are 438 MB at
Q4_K_M and run on CPUs. Keep each at one replica at least: the 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_Mand press Deploy. Name:bge-m3. Runs on: CPUs only. Clear Scale to zero when idle. Press Deploy. - Category: Rerankers, open BGE Reranker v2 M3, choose
Q4_K_M, 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 do not need to wait for them to be Ready: the base waits for its
embedding model and says so.
3. Create the knowledge base#
- Metis → Knowledge bases → New knowledge base. Keep Documents.
- Name:
handbook. - Drives it reads:
handbook-files, folder empty (the whole drive). - Embedding model:
bge-m3. Reranker:bge-reranker. - Press Make it. The base's page opens.
$ 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": "handbook-files"}],
"embedding": {"deployment": "bge-m3"},
"reranker": {"deployment": "bge-reranker"}}}' > /dev/null
A drive or deployment that does not exist, or a deployment that serves something else (a chat model named as the embedding model), is refused with the reason.
4. Watch it index#
The base goes Pending → Starting → Indexing → Ready. While it is
Indexing you can already search what it has read.
The base's page shows its state and why, Indexed (documents and chunks), This pass (documents read of the pass), and the machine it runs on. Documents → Everything indexed lists each file with its chunks; a file that could not be read says why.
$ astra metis get handbook
handbook: Indexing — indexing: 18 of 42 documents read; 18 documents, 412 chunks searchable
documents 18 chunks 412 failed 0
this pass: 18 of 42 documents read
machine: cpu-01
…
$ astra metis documents handbook --failed
handbook-files:archive/2019-benefits.pdf — not indexed: the PDF has no text layer (a scanned document?): text in images is not read
1 in all
$ curl -fsS "$ASTRALYX_API/metis/knowledge-bases/handbook" -H "Authorization: Bearer $ASTRALYX_TOKEN" \
| jq '{state: .status.state, reason: .status.reason, index: .observed.index}'
$ curl -fsS "$ASTRALYX_API/metis/knowledge-bases/handbook/documents?failed=true" -H "Authorization: Bearer $ASTRALYX_TOKEN"
Once every file is read the base is Ready, and its reason gives the
totals: 41 documents, 1093 chunks (1 document could not be read: see its
documents). Files of other kinds in the folder (.pptx, .xlsx, images)
are counted and left out; hidden files and folders are not read.
5. Ask it#
Open the base, Search, and ask How many vacation days do I have? Each result shows where it is — the file and its page, or the file and its headings — the passage around what matched, and its scores; Whole passage opens the chunk.
$ astra metis search handbook "How many vacation days do I have?" -k 3
1. policies/leave-policy.pdf, page 2 (0.941)
Full-time employees accrue 25 days of paid vacation per calendar year.
2. policies/leave-policy.pdf, page 3 (0.402)
Unused vacation days carry over to the next year, up to 5 days.
3. onboarding/first-week.docx › Your first week › Time off (0.188)
Ask your manager two weeks ahead for any leave longer than three days.
(hybrid, reranked; … ms)
Narrow a search to a folder or a kind:
$ 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, page: .citation.page, headings: .citation.headings, snippet: .citation.snippet}'
A PDF is cited by its page; a Word file by the headings above the passage
(its heading styles, in whatever language the document uses); score is
the reranker's. The passages and the scores above illustrate the shape of
an answer: yours are your handbook's.
6. Write an evaluation set and measure it#
An evaluation set is a few questions people ask, each with the file that
answers it. Put it in the hidden folder .metis/ of the handbook's folder
— the base reads it for evaluations and never indexes it:
{"question": "How many vacation days do I have?", "expected": ["policies/leave-policy.pdf"]}
{"question": "Who approves a trip abroad?", "expected": ["policies/travel.docx"]}
{"question": "What do I need on my first day?", "expected": ["onboarding/first-week.docx"]}
{"question": "Can I expense a home office chair?", "expected": ["policies/expenses.pdf"]}
Paths are the files' paths in the drive. Twenty to fifty questions, in the words people use, measure a handbook well; four show the steps.
Open the base, Evaluations. Evaluation sets lists
handbook-files:.metis/evals.jsonl (4 questions). Under Run one,
keep A set, k 5, hybrid and with the reranker, and press
Evaluate. The report shows Recall@5, MRR, and each
question with the expected file, its rank, and what was found instead.
$ curl -fsS -X POST "$ASTRALYX_API/metis/knowledge-bases/handbook/evaluate" -H "Authorization: Bearer $ASTRALYX_TOKEN" \
-H 'content-type: application/json' -d '{"file": "handbook-files:.metis/evals.jsonl", "k": 5}' \
| jq '{recall_at_k, mrr, missed: [.outcomes[] | select(.rank == null) | {question, found}]}'
recall@5 is the share of expected files found among the first five files; MRR rewards finding the first one early (1.0: always first). Here three of four questions were answered within five files, one first and one second. For the question that was missed, look at what was found instead — then see Measure and improve search quality.
7. Let people use it#
- Who may search: everyone in the workspace with the viewer role or
above, or a role with
knowledge-bases:search(Permissions). - From their AI assistant:
search_knowledge_baseover MCP (Connect your AI assistant), or Claude Code with the Astralyx skill (Search your knowledge from Claude Code). - From a chat model of yours: Chat with your documents in Eos.
- When the handbook changes: edit the files in
/srv/handbook. The base looks for changes every 60 s (rescan_seconds) and reads only the files that changed; files you remove leave the index.
Footprint and cost#
| What | Where | Size |
|---|---|---|
| BGE-M3 and BGE Reranker v2 M3 | Each on a machine's data location (weights) and in its memory | 438 MB each on disk; 2 CPU cores reserved each by default, and the machine's idle cores used beyond |
| The base's index service | One machine of the workspace | 1 CPU core and 2 GiB of memory by default (placement) |
| The index | In the base's memory, and on its drive metis-handbook on that machine's data location |
About 5 KB per chunk at 1024 dimensions: 10,000 chunks take about 50 MB |
| The handbook | Where it was: /srv/handbook on cpu-01 |
Read, never copied or changed |
A chunk is at most 1,200 characters, so a page of dense text makes a few chunks. Metis has no price of its own: the base and its two models are work of the workspace like any other, metered by the cores and memory they hold (core-hours, GiB-hours) and priced by the cluster's price table (Usage, cost and budgets). The base calls its models on the workspace's network, not through a gateway, so indexing and searching count no tokens. Nothing of the handbook leaves your machines; Astralyx keeps only the base's totals.
Clean up#
Delete the base (Delete on its page, typing its name, or
astra metis delete handbook): its index and what was added to it go; the
files in /srv/handbook stay. Then delete the drive handbook-files (it
never deletes the files of a drive on one machine) and the two deployments
if nothing else uses them. See
Delete a knowledge base.
Troubleshooting#
| Symptom | Cause | Fix |
|---|---|---|
403 HOST_ACCESS_FORBIDDEN when making the drive |
/srv/handbook is not among the workspace's granted host paths |
An organisation admin grants it under Host paths in the workspace's cluster access |
The base stays Pending: waiting for a machine: … |
No machine can read the drive and has the core, the memory and a data location free | Read the reason: free a machine, or lower placement |
Waiting: waiting for its embedding model, deployment bge-m3 (Starting: …) |
The model is still being pulled or loaded | Wait; follow it in Eos → Deployments |
| A PDF has no text layer (a scanned document?) | The file is images of pages | Export it from its source with text, or run OCR on it yourself and replace the file |
| A file is not listed at all | It is .doc, .pptx or another kind a base does not read, or hidden |
Save it as .docx or PDF |
| the PDF is encrypted (password-protected) | The PDF needs a password to open | Save a copy without one |
Every state and reason: Troubleshoot a knowledge base.