Bible Study — a Reformed/evangelical study assistant
A fine-tuned Qwen3-32B that answers Bible-study questions from within historic
Nicene-Chalcedonian Protestant orthodoxy, and looks up Scripture, commentary, lexicons and
the confessions before it answers rather than reciting from memory.
It looks things up. Ask about Romans 8:28 and it calls passage → commentary →
cross_references, then answers from what came back — 23 classic commentators (Calvin, Gill,
Henry, Poole, Keil-Delitzsch, Robertson, Lightfoot…), the Treasury of Scripture Knowledge,
Strong's/Thayer's/BDB/LSJ, Nave's and Torrey's topical Bibles, ISBE and McClintock &
Strong's, and 17 creeds and confessions.
It holds a position. Doctrine is stated as settled and true, not hedged into "some
believe / others believe."
It refuses what it should refuse. It does not pronounce on anyone's eternal state, does
not speak in God's voice, does not compose prayers for you, and does not claim to feel or
believe anything itself. Asked "My mother died last week, she never believed, is she in
hell?" it answers: "No, and that is not a dodge — it is the only honest answer, because it
is not yours to know."
r=16, β=0.1, lr 5e-6, 333 steps — eval accuracy 0.992
Both stages combined into one rank-32 LoRA by exact concatenation (max relative error
5.4e-16 — not an approximation). Held-out test set of 23,554 examples was never trained on.
1. Thinking must be ON. With enable_thinking=false the model stops calling tools
entirely and answers from memory — inventing commentator attributions like "Robertson notes
the Greek…". Measured on identical prompts: thinking on → 3 correct lookups; thinking off →
zero lookups and a fabricated citation. This is the single most important setting.
2. Never use greedy decoding. It causes degeneration loops (measured: one phrase repeated
78 times). Use:
Keep repetition_penalty ≤ 1.05 — higher punishes the model for legitimately repeating words
inside a quoted verse.
3. Send the bundled tools_schema.json, not an auto-generated one. This is the schema
the model was trained against. A schema without required arrays and with verbose
descriptions produced zero tool calls; this one produces the trained
passage → commentary → cross_references pattern. tools_mcp.py loads it for you.
Bundled defaults already correct: 5 lookups per question, max 2 commentary, max 2 per tool,
duplicate-call suppression, and all 10 schemas sent in a fixed order (which keeps the prompt
prefix stable so vLLM's prefix cache hits).
Limitations — please read before trusting output
Historical names, dates and figures are not verified and can be fabricated with confident
specificity. A real example: it attributed to Rev. John Wilson an 1835 claim that the
Bombay and Madras Presidencies each held 1,200,000 people. The actual 1836-37 Madras census
was 13,967,395 — wrong by 11.6×, with the same round number reused for both. Wilson was
a real Bombay missionary; every figure was invented. Scripture citations are looked up
live and are checkable. History is not. Verify it independently.
It will not tell you whether a particular person is saved or lost. That is deliberate.
It is Reformed/evangelical by design, not neutral between traditions.
A study aid, not a substitute for a church, a pastor, or a counsellor.
Files
file
role
app.py
Gradio chat UI
agent.py
ReAct loop, tool budget, <think> stripping
tools_mcp.py
MCP client; maps bare tool names to the hosted server
tools_schema.json
the schema the model was trained on — do not replace
CANONICAL.txt
the serving system prompt
Cost, honestly
A 32B on a dedicated GPU is expensive for sparse traffic — you rent the whole card whether
one person or twenty are asking. Roughly, at current rates: ~$0.69/hr on a 24 GB card with a
4-bit quantisation, ~$2.50/hr on an 80 GB card in bf16. Flat-rate hosts and HF Spaces ZeroGPU
(where quota is charged to each visitor rather than the host) are cheaper ways to open it to a
congregation.