Operational notes Observatory

Tencent’s Hy4 Preview: the Reasoning Default Flips, Silently

7 min read

Two identical railway signal lamps on two curved arms rising from the same post, aimed in different directions, black and white photograph against a cloudy sky
Same lamp, same arm: only the angle tells you where each one points, and from the ground you cannot see it until you walk underneath.

On 27 August 2026, at 08:52:40 UTC — recorded by the createdAt field of the Hugging Face API — Tencent published Hy4 preview: 770 billion total parameters, mixture-of-experts, Apache 2.0 licence. It succeeds Hy3 preview, in production since April and still alive: Tencent’s own press release, dated 28 August, states that free access to Hy3 remains open until 30 September. Two generations of the same family, served through the same OpenAI-compatible client, running in the same month. We downloaded the chat template of both — the file that turns a conversation into text before the engine generates anything — to see what changes for anyone who points an existing integration from one to the other without touching a line of code. What changes is the default behaviour of every single call, and no error announces it.

The facts, in order

  • Hy4 preview: repository tencent/Hy4-preview, createdAt 2026-08-27T08:52:40Z. At the time of verification, 3 September 2026, the repository shows 3,516 downloads and 399 likes. Apache 2.0 licence, declared in the tags and confirmed by the LICENSE file: standard text, Tencent copyright 2026, no clause beyond the attribution the licence itself requires.
  • Hy3 preview, the predecessor: createdAt 2026-04-13T06:07:57Z, licence other — not Apache, a Tencent-authored text. The company’s own release announcement, dated 28 August, states: “Free access to Hy3 on both platforms has also been extended until September 30.” The two generations keep running in parallel; neither replaces the other overnight.
  • Architecture: 78 layers, 256 routed experts plus one shared, eight active per token, a sparse-attention mechanism the card describes as inspired by DeepSeek and GLM. That is not this note’s subject: what matters here is not the parameter count but how the model decides whether to reason before it answers.
  • The mechanism: both chat_template.jinja files — the file every inference engine applies before generating a response — read a parameter called reasoning_effort. At high, the response opens with an extended thinking block, wrapped between the <think:opensource> and </think:opensource> tags; at no_think, that block stays empty and the answer arrives direct.

The default that flipped

Hy4 preview’s card is honest about it, but only in one spot on the page, in prose, under the Quickstart section: “Defaults to “high” (deep chain-of-thought), which suits complex tasks such as math, coding, and reasoning.” What neither card states is that this is a reversal from the predecessor, not an isolated design choice made from scratch.

Hy3 preview’s chat_template.jinja, at line 36, reads: if reasoning_effort is not defined, or is not one of the three accepted values, the template sets it to no_think — a direct answer. That is exactly the behaviour you get by not passing the parameter at all: just the messages, nothing else. Hy4 preview’s equivalent file changes that very line: at lines 32-33, if reasoning_effort is not defined, the template now sets it to high — extended reasoning. Same source condition, not reasoning_effort is defined, opposite outcome.

The most direct evidence sits in the code both cards publish as their first usage example. Hy3 preview’s quickstart, line 172, explicitly passes extra_body={"chat_template_kwargs": {"reasoning_effort": "no_think"}}, with a comment above it that reads “(default, direct response)”: anyone copying that block got the direct answer twice over — once from the explicit parameter, once from the default confirming it. Hy4 preview’s quickstart, lines 145-152, has the exact same skeleton — same client, same method, the same temperature=0.9 and top_p=1.0 — but no extra_body, no chat_template_kwargs, no trace of reasoning_effort anywhere in it. Anyone who copies this block today, the way they copied Hy3’s a month ago, gets the opposite behaviour: not because the code is wrong, but because the default it silently relies on changed underneath it, inside a file that ships with neither repository’s calling code and that almost nobody reads before repointing an endpoint.

A second switch, outside both cards

Reading past the default line, Hy4 preview’s template holds a condition that appears in neither card, in neither of the two languages Tencent publishes them in, nor on the vLLM recipe page dedicated to the model — checked directly. The Chinese card names reasoning_effort once, for the same default, and fallback_strategy never. At lines 42-45: if a field named fallback_strategy is defined and equals reasoning_toolcall_retry, the template forces reasoning_effort back to high, regardless of whatever value the caller passed — including an explicit no_think — and in the same branch it also sets add_generation_prompt to false, which suppresses the fresh assistant-turn marker the template would otherwise append.

This is not a stray leftover in one isolated file. The FP8 checkpoint of the same model — the one the card recommends for production — was created, per the API, at 08:57:54 UTC the same day: five minutes after the bf16 checkpoint. Its chat_template.jinja is nearly identical to the main one, with exactly one line different between the two files: the very line handling fallback_strategy, extended to keep the last assistant turn open when that value is set. Whoever maintains this file adapted it on purpose in the quantised variant too — this is not a copy-paste slip. In Hy3 preview, this field does not exist, in any line of its template.

What breaks loudly, for contrast

Not everything that changes between the two generations stays silent. Hy3 preview accepted three values for reasoning_effort: high, low, no_think. Hy4 accepts two: pass low — valid yesterday — and it trips, at lines 34-39, an exception with the message “reasoning_effort error : low, should be no_think/high”, composed by the template itself. How the inference server surfaces that to the caller we have not verified by running it, but the difference in treatment is written into the file: an unsupported value stops generation; a missing one does not. Whoever wrote this template can clearly tell the two cases apart, and chose which one to flag.

What we could not verify

We did not run either Hy3 or Hy4 preview: this reading is on the files in each repository, not on live inference, and we do not know the exact message vLLM or SGLang hand back to the caller when the template’s exception fires. We do not know which component of a serving pipeline actually sets fallback_strategy: reasoning_toolcall_retry in production, nor how often: a GitHub code search through the API returned a 401, requiring a token we did not have, and a web search turned up no public documentation of the field. We did not measure the extra token cost of the extended thinking block on a real workload: we know the default switches it on, not how much it adds to the bill of whoever inherits it unknowingly. Every page and API endpoint cited in this note answered with a plain HTTP 200 when we checked it; none of the figures above comes from a page that failed, redirected, or required authentication we lacked.

What to do about it

  • Before moving a call from one checkpoint to another in the same family, diff the two chat_template.jinja files: public files a few hundred lines long, and they say more than the card’s prose does.
  • Always pass reasoning_effort explicitly: relying on the default means relying on a line the vendor can change generation to generation, with no obligation to flag it.
  • Search for undocumented fields before going to production: a grep across every variable read with is defined finds, in a minute, what no card lists.
  • If a retry layer or a tool-calling orchestration layer of yours adds extra parameters to the engine call, check that none of them silently override a choice you made explicitly upstream.
  • Log which checkpoint and which chat-template version you are running in production: a silent update to the second can change the behaviour of the first without touching a single weight.

The leap Tencent declares from Hy3 to Hy4 preview lives in the benchmark tables. The leap that matters to whoever puts it into production lives in a short file that no card fully describes, and that decides whether every answer opens with a thought or with a word.

Migrating an integration from an open-weight model to its successor, or deciding which one to run in production? Half an hour with one of our experts: we read the chat template, the config and the launch flags together, before a customer finds the default the hard way.

Sources