A step-by-step guide to using SlimArmor, your personal vector database for semantic search.
SlimArmor lets you store text and search it by meaning, not just keywords.
Example:
- You store: "Dogs are loyal companions"
- You search: "furry pets"
- It finds the dog text, even though the words are different!
This is called semantic search and it's powered by AI embeddings.
Your SlimArmor API lives at:
https://kamenxrider--95fbe492ffe111f0bee942dde27851f2.web.val.run
Open that in a browser to see all available endpoints.
To add text to the database, send a POST request:
curl -X POST https://YOUR_ENDPOINT/upsert \ -H "Content-Type: application/json" \ -d '{ "id": "note-1", "text": "The quick brown fox jumps over the lazy dog", "meta": {"category": "example"} }'
What the fields mean:
id- Unique identifier (you choose)text- The text you want to search latermeta- Optional extra data (tags, categories, etc.)
To find similar text:
curl -X POST https://YOUR_ENDPOINT/search \ -H "Content-Type: application/json" \ -d '{"query": "animals jumping"}'
Response:
{ "results": [ { "id": "note-1", "text": "The quick brown fox jumps over the lazy dog", "distance": 0.52 } ] }
The distance tells you how similar it is:
- 0.0 = Exact match
- 0.5 = Related
- 1.0 = Not related
To only get highly relevant results, add maxDistance:
curl -X POST https://YOUR_ENDPOINT/search \ -H "Content-Type: application/json" \ -d '{"query": "animals jumping", "maxDistance": 0.6}'
This filters out anything with distance > 0.6.
Recommended thresholds:
0.5= Very strict (only best matches)0.6= Balanced (good default)0.7= Loose (more results)
Not sure what threshold to use? Use the calibrate endpoint:
GET /calibrate?q=your+search+query
It will analyze your data and suggest:
- Tight - Top 3 results only
- Balanced - Top 10 results (use this!)
- Loose - All retrieved results
See how much data you have:
GET /stats
Shows:
- Total records
- Storage used
- Estimated capacity
curl -X POST https://YOUR_ENDPOINT/delete \ -H "Content-Type: application/json" \ -d '{"id": "note-1"}'
GET /get?id=note-1
GET /list
curl -X POST "https://YOUR_ENDPOINT/clear?confirm=yes"
import * as db from "https://esm.town/v/kamenxrider/slimarmor/vectordb.ts";
// Setup (run once)
await db.setup();
// Add a record
await db.upsert("my-note", "This is my important note", {
tag: "work"
});
// Search
const results = await db.search("important information", 5, 0.6);
console.log(results);
// Delete
await db.remove("my-note");
Just use the HTTP endpoints with any language that can make HTTP requests.
Use descriptive IDs like blog-post-123 or note-2024-01-15 instead of just numbers.
Shorter, focused text works better than huge documents. If you have long documents, consider splitting them into chunks.
Store extra info in meta so you can filter later:
{ "id": "doc-1", "text": "...", "meta": { "category": "tech", "date": "2024-01-15", "author": "john" } }
Use /calibrate?q=... to find the right maxDistance for your use case.
Check /stats periodically. You have ~47,000 records per GB.
curl -X POST https://YOUR_ENDPOINT/search \ -H "Content-Type: application/json" \ -d '{"query":"machine learning","filters":{"category":"tech"}}'
curl -X POST https://YOUR_ENDPOINT/search \ -H "Content-Type: application/json" \ -d '{"query":"python","hybrid":{"enabled":true,"alpha":0.25}}'
curl -X POST https://YOUR_ENDPOINT/upsert \ -H "Content-Type: application/json" \ -d '[{"id":"a","text":"one"},{"id":"b","text":"two"}]'
curl -X POST https://YOUR_ENDPOINT/upsert_chunked \ -H "Content-Type: application/json" \ -d '{"id":"doc-long","text":"...long text...","chunkSize":800,"overlap":100}'
curl "https://YOUR_ENDPOINT/export?limit=200&offset=0"
SlimArmor supports multiple embedding providers. Set these in Val Town's environment variables:
NEBIUS_API_KEY=your-nebius-key
- 4096 dimensions, high quality
- Great pricing
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=sk-your-key
- 1536 dimensions
- Most popular
EMBEDDING_PROVIDER=openrouter
OPENROUTER_API_KEY=your-key
- Access to many models
- Pay-per-use
EMBEDDING_API_URL=https://your-api.com/v1/embeddings
EMBEDDING_API_KEY=your-key
EMBEDDING_MODEL=model-name
EMBEDDING_DIM=1536
⚠️ Warning: If you switch providers, you must clear and re-insert all data (embeddings are incompatible between providers).
Make sure your API key environment variable is set:
- Nebius:
NEBIUS_API_KEY - OpenAI:
OPENAI_API_KEY - OpenRouter:
OPENROUTER_API_KEY
Try lowering maxDistance (e.g., 0.5 instead of 0.7).
- Check if you have data:
GET /stats - Try raising
maxDistance(e.g., 0.8) - Try a simpler query
Each insert needs an API call to generate embeddings (~460ms). This is normal.
Run:
GET /validate
To include write tests:
GET /validate?write=yes
Requires ALLOW_WRITE_TESTS=1, a valid embedding key, and auth if ADMIN_TOKEN is set.
| Task | Endpoint | Method |
|---|---|---|
| Add/update record | /upsert | POST |
| Search | /search | POST |
| Delete record | /delete | POST |
| Get record | /get?id=... | GET |
| List IDs | /list | GET |
| Check health | /ping | GET |
| View stats | /stats | GET |
| Find threshold | /calibrate?q=... | GET |
| Delete all | /clear?confirm=yes | POST |
import * as db from "https://esm.town/v/kamenxrider/slimarmor/vectordb.ts";
// Add some notes
await db.upsert("note-1", "Meeting with Bob about Q4 budget planning");
await db.upsert("note-2", "Research machine learning frameworks for project");
await db.upsert("note-3", "Call mom for her birthday on Saturday");
// Search for work stuff
const workNotes = await db.search("business meetings finance", 5, 0.6);
// Search for personal stuff
const personalNotes = await db.search("family calls birthdays", 5, 0.6);
- Check
/endpoint for all available endpoints - Check
/statsto see your data - Use
/calibrate?q=...to tune your searches
Happy searching! 🔍