ENTH
PART 3 · Putting it to work

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

MetricBOMLLM (Mac 27B MLX)Previous cloud (GLM-4.5-Flash)Result
Overall score (1–10)7.246.02wins by 1.20× ✅
LINE Q&A quality8.936.33wins by 1.41× ✅
Answer speed (median)5.2 s35.1 s~7× faster ✅
Error rate (30 s)4% (2/50)0%accepted honestly ⚠️
Thai purity (thai_ratio)0.797 (0.832 strict)0.762higher ✅
Stray Chinese characters (per 100 answers)1543less 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 below

Source: 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/s

Hypotheses 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):

  1. Identity + personality (a polite Thai assistant, finance/tech domain)
  2. Language rule: always answer in Thai (unless the user writes in another language) + absolutely never output Chinese characters (Han ban)
  3. Style rule: answer the question first, no padding, no made-up numbers
  4. 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 path

Do 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

★ PROD LESSON
Do not judge Thai output by eye — a listener "feeling it is okay" does not count — use meters (thai_ratio + stray-Han counting) with statistics (paired bootstrap, 10,000 rounds) exactly as the repo does, otherwise you will quietly trade real quality for a placebo
★ PRO TIP
Stray Chinese characters at 15/100 — staying honest — Config G cuts the leakage from 43 to 15, but not to zero — mixed-language + strict-JSON prompts can still hit it; extra defenses: filter the output one more layer on the bot side, or route the nasty cases to Tier 3

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

Figuresfigures

Benchmark results image from the repository — scores and speed compared with the previous cloud
Results table of the 50 real test cases (source: benchmarks/ in the repo — the measuring script is included so you can re-run it yourself)

Videovideo

Real screen recording for this lesson · click play to hear the summary · not investment advice

▶ Watch the manual video: https://youtu.be/O4hM39cgDCY