Retrieval API with Qdrant
An API that stores passages in Qdrant and returns the ones closest to a question, with embeddings computed in the container and no API key. About $21.19 a month.
What you build
POST /ingestwith{"texts": [...]}embeds and stores up to 256 passages.POST /askwith{"question": "...", "limit": 3}returns the closest ones.- Both need
Authorization: Bearer <token>.GET /healthzdoes not.
Embeddings come from BAAI/bge-small-en-v1.5, run inside the container with
fastembed. There is no embeddings API to pay for, and the model is part of
the image, so the first request does not wait for a download.
What Gagarin creates
| Name | Kind | Size | Holds |
|---|---|---|---|
vectors | qdrant | s, 5 GB disk | the passages and their vectors |
auth | external | none | AUTH_TOKEN |
api | service | s | the API, at a public HTTPS address |
The commands
Run from this directory, with Docker running.
gg init search
gg resource add search/vectors qdrant --storage 5
gg resource add search/auth external --env-file .env.auth
gg ship search/api:8080 --deps vectors --deps auth
gg domain add search/apiMake .env.auth with echo "TOKEN=$(openssl rand -hex 32)" > .env.auth and
add it to .gitignore. Gagarin publishes it as AUTH_TOKEN, and the qdrant
gives the service VECTORS_URL and VECTORS_API_KEY.
Try it with the address gg domain add printed:
curl -H "Authorization: Bearer <token>" -H 'content-type: application/json' \
-d '{"texts":["Paris is the capital of France."]}' https://<address>/ingest
curl -H "Authorization: Bearer <token>" -H 'content-type: application/json' \
-d '{"question":"What is the French capital?"}' https://<address>/askWhat it costs
About $21.19 a month: two size-s containers at $10.22 each and 5 GB of disk at $0.75. A qdrant serving real traffic wants size m, which makes it about $41.63. Traffic is free. Rates: https://gagarin.cloud/pricing
What can go wrong
gg shipfails before it builds: Docker is not running.docker infosays.- The image is about 800 MB, most of it the model and its runtime. The first push takes a minute or two on a slow uplink.
/askreturns nothing: nothing was ingested yet, or it went to another project's qdrant.gg status searchlists what the project holds.- The qdrant keeps a nightly backup for 14 days:
gg resource backups search/vectors.
Run it locally
cp .env.example .env # put a token in it
docker compose up --buildClean up
gg destroy searchGagarin emails the project owner a button to approve the deletion. The vectors go with it.