The Thai recipe
The Thai recipe
TL;DR — the 30-second summarytldr
This chapter is the "crown" of the whole manual — how to make the model answer in Thai well enough to truly replace the cloud you used to pay for; every value you see here passed a criteria-based test (50 real cases, scored by two judge models), not gut feeling
| Metric | BOMLLM (Mac 27B MLX) | Previous cloud (GLM-4.5-Flash) | Result |
|---|---|---|---|
| Overall score (1–10) | 7.24 | 6.02 | wins by 1.20× ✅ |
| LINE Q&A quality | 8.93 | 6.33 | wins by 1.41× ✅ |
| Answer speed (median) | 5.2 s | 35.1 s | ~7× faster ✅ |
| Error rate (30 s) | 4% (2/50) | 0% | accepted honestly ⚠️ |
| Thai purity (thai_ratio) | 0.797 (0.832 strict) | 0.762 | higher ✅ |
| Stray Chinese characters (per 100 answers) | 15 | 43 | less than half ✅ |
When to usewhen to use
Apply this recipe as soon as the model is installed on the machine (chapter 5) — and come back to it every time you change model or version, because "good parameters" belong to one specific pair (model + dataset) and do not transfer for free across models
How-tohow to
Layer 0 first — the completion safety floor (the most important part, yet the one people overlook): the "strong Thai, weak Thai, alternating" behavior we once hit (thai_ratio swinging 0.72–0.92) is rooted not in the prompt but in truncated or empty answers — the answer ceiling (num_predict) was too small and collided with the model's "inner thoughts"; once the floor is raised correctly, the swing shrinks to a band of just 0.036 and all 300/300 answers come back complete:
# Safety floor (set this before tuning any prompt)
num_ctx: 32768 # below this, long Thai reports get their tails cut off
num_predict: 8192 # long-form writing
num_predict_chat: 2048 # normal chat
num_predict_bot: 1024 # LINE/Telegram bots (30-second UX budget)
think: false # bot path only — reason belowSource: a 300/300 completions test, Sep 2026 — details in docs/thai.md
The "thinking budget" trap for bots: a reasoning model with think on plus a small num_predict burns the entire answer quota on inner thoughts, then sends back an empty answer — our LINE bot genuinely hit this; the fix is pinning think:false + an answer ceiling sized to the job (already set up in chapter 7)
Layer 1 — the sampling parameters that passed the gate:
# Config A_bom_nothink — the only one of 4 configs tested to pass the 0.78 gate
temperature: 0.7
top_p: 0.8
top_k: 20
repeat_penalty: 1.05 # above this it wrecks code blocks
# Measured: thai_median 0.7821, Han 12 times/28 answers, 17.92 tok/sHypotheses the experiments knocked down: presence_penalty 1.5 does "not" make Thai worse (A/B n=23, no difference), and DavidAU's sampling formula did not beat the incumbent (0.7500 vs 0.7821)
Layer 2 — the system prompt recipe "Config G": a 4-part structure (the full 4,101-character version lives in the repo and on Hugging Face bomllm/turbo-thai-config):
- Identity + personality (a polite Thai assistant, finance/tech domain)
- Language rule: always answer in Thai (unless the user writes in another language) + absolutely never output Chinese characters (Han ban)
- Style rule: answer the question first, no padding, no made-up numbers
- Two example question-answer pairs (few-shot: one general, one report-style)
Config G's measured result: thai_ratio +0.029 over the rival prompt (the 95% CI excludes zero) and stray Chinese characters cut in half (35 → 15 per 100)
If anything gets stuck → chapter 16
Config exampleconfig example
Paste it in for real use — the LiteLLM route (chapter 7) + the file configs/sampling-recipe.yaml in the repo is the "receipt" for every value:
# The ready-made recipe for a 27B model on the Mac (the recipe running in production)
system_prompt : Config G (Thai only + no Chinese characters + 2 few-shot pairs)
temperature : 0.7 top_p: 0.8 top_k: 20
repeat_penalty: 1.05 presence_penalty: 0.0
num_ctx : 32768
num_predict : 8192 long-form / 2048 chat / 1024 bots
think : false on the bot path, true only on the deep pathDo not remix the values at random — every value here is backed by an experiment, and breakage hurts for real (one typo of repeat_penalty 8.0 = the whole batch of results ruined)
Pro tip — field-tested advicepro tip
FAQfaq
Q: And if the question is in English, which language comes back? — our standard recipe always answers in Thai first (the business owner chose it that way); if you want technical English answered in English, there is a route-level override — but be prepared for the Thai purity number to shift
Q: A new model comes out — do we start over? — the same protocol can simply be re-run (the bench_thai.py script in the repo); a challenger must beat the incumbent with a CI that excludes zero before it gets promoted
For other questions see the FAQ
See alsosee also
- Chapter 5 · Mac Mini — the home of the model that takes this recipe
- Chapter 13 · Bots — where think:false makes the difference
- Hugging Face — the full Thai recipe set
Figuresfigures

Videovideo
Real screen recording for this lesson · click play to hear the summary · not investment advice
▶ Watch the manual video: https://youtu.be/O4hM39cgDCY