New to Kestra?
Use blueprints to kickstart your first workflows.
Answer questions over your documents with Ollama and Qdrant in Kestra. Lists source files and declines off-topic questions. Local, no API keys.
A small, private "ask our docs" API. Send a question to a webhook and get back an answer written by a local LLM from your own documents, together with the files of the passages it was given. If no document is relevant, the question never reaches the LLM and the API says so, instead of letting a small model make something up.
It reads the Qdrant collection maintained by local-rag-knowledge-base-sync, which keeps the index in step with a MinIO bucket.
This blueprint was created by kruxarth.
ask_over_http (Webhook) starts the flow with a JSON body such as {"question": "..."}. With wait and returnOutputs, the HTTP call blocks until the answer is ready and returns the flow outputs. A manual run uses the question input instead.retrieve_context (io.kestra.plugin.ai.rag.Search) embeds the question with nomic-embed-text and looks for chunks with a relevance of at least 0.75 in Qdrant.answer_or_abstain (If):answer (io.kestra.plugin.ai.rag.ChatCompletion) asks qwen2.5:3b to answer from the retrieved chunks only, and log_answer logs the answer with its sources.log_abstain logs a warning and the LLM is not called.answer and sources, the unique source keys of the chunks given to the model.curl -X POST http://localhost:8080/api/v1/main/executions/webhook/company.ai/local-rag-knowledge-base-ask/<KB_WEBHOOK_KEY> \
-H 'Content-Type: application/json' -d '{"question": "How many weeks of parental leave do primary caregivers get?"}'
{"answer": "20 weeks", "sources": ["hr/employee-handbook.pdf"]}
An off-topic question returns {"answer": "The knowledge base does not cover this question.", "sources": []} in under a second, without calling the LLM. On a laptop CPU, answers took 3 to 9 seconds in testing, plus about 20 seconds for the first question while Ollama loads the model.
If on the retrieval result, so it is visible and easy to tune.local-rag-knowledge-base-sync, with the same Qdrant and Ollama services.docker exec ollama ollama pull qwen2.5:3b.localhost in the variables with host.docker.internal.QDRANT_API_KEY: the Qdrant API key, the same one as for the sync flow.KB_WEBHOOK_KEY: the key in the webhook URL. Anyone who knows it can query your documents, so keep it secret.local-rag-knowledge-base-sync.curl as shown above.0.75 threshold is a LangChain4j relevance score, (cosine + 1) / 2. With nomic-embed-text on the test documents, the passage holding the answer scored between 0.72 and 0.92, off-topic questions at most 0.72, and passages from other documents on similar topics up to 0.82. So 0.75 refuses off-topic questions but also some very short ones (Do I need MFA? scored 0.72), and sources can list a related file that did not contribute to the answer. Measure it on your own documents, and again if you change the embedding model.qwen2.5:1.5b is faster but was easily distracted by unrelated chunks. qwen2.5:3b is the smallest model that answered our test questions reliably.memory to answer for follow-up questions.