Skip to content

server: an opener a reply names in prose keeps the text after it - #1243

Closed
outcastofmusic wants to merge 1 commit into
ashhart:mainfrom
outcastofmusic:fix/stream-prose-openers
Closed

outcastofmusic wants to merge 1 commit into
ashhart:mainfrom
outcastofmusic:fix/stream-prose-openers

Conversation

@outcastofmusic

Copy link
Copy Markdown
Contributor

What this changes

A reply that names Gemma's <|tool_call> or DSML's tool_calls opener in prose keeps the text after it, streamed and in the finished prose. Those openers now hide only once their payload starts as those families write it, and a finished reply's unclosed envelope stays text, as tool_parse.parse keeps it. Fixes #1242.

<tool_call> hides as before, because its payload can start with a bare name or JSON.

#1235 (MiniMax-M3) also edits reply_text.zig. Both PRs append a test at the end of the file, so whichever merges second keeps both tests. #1235 adds a fourth calls entry, so leads (sized calls.len) then needs a fourth &.{} entry to build.

Receipt

  • Environment, with the TensorFold commit, MLX or PyTorch version, machine and GPU, checkpoint and revision: main at 6244c62 plus this commit, Zig 0.17.0, Linux aarch64 with a GB10. No checkpoint: the change is server text handling.
  • Exactness, from tools/bench_concurrent.py --alone --serial or token_sha against "draft": false: n/a. Tokens and lane rounds do not change; only the reply text a stream shows and the finished prose do.
  • Decode speed before and after, from tools/bench_openai.py: n/a, the change runs after decode on reply text.
  • Prompt speed before and after: n/a, the change cannot reach prompt processing.
  • Tests run, with pass, fail and skip counts: zig build test-cuda-host exits 0. zig build test-golden: 26/26 equal to server goldens, 0 unexpected differences. The new test "an opener the reply names in prose keeps the text after it, streamed and whole" fails on main: there the reply in server: a tool-call opener named in prose hides the rest of the reply #1242 streams as Gemma writes and finishes as Gemma writes.
  • Not run, and why: zig build test on macOS and the Metal device checks, because I have no Mac. No model gate, since no arithmetic changes.

Checklist

  • Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off.
  • Drafted output equals "draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.
  • No precision traded for speed. If the bits change, the description says which sums change and why.
  • A new or changed GPU kernel is registered with the kernel contract (docs/kernel-contract.md); each backend's SUMMARY line is in the receipt. (No kernel changes.)
  • Prompt processing is no slower than the last release.
  • The description says which platforms I ran, Metal M1 to M5 and CUDA, and which I could not.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency.
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths. No AI attribution lines.

hideInto treated any family's call opener as a call and, with no closer, hid the rest of the
reply. A Qwen reply that writes Gemma's <|tool_call> or DSML's tool_calls opener in prose lost every
character after it, streamed and in the finished prose, while tool_parse.parse kept that text as
content, so a streamed reply and a whole one disagreed.

Gemma's and DSML's openers now hide only once their payload starts as those families write it
(call: or :, and a DSML invoke); while it may still start, a stream holds the opener back. A
finished reply's envelope that never closed is text, as tool_parse.parse keeps it. <tool_call>
can start with a bare name or JSON, so it hides as before while a reply streams.

zig build test-cuda-host and test-golden pass (golden: 0 unexpected differences).
@ashhart

ashhart commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Landed on main as c09e29d, thank you @outcastofmusic. An opener a reply only names in prose now keeps the text after it, streamed and whole, and a finished reply's unclosed envelope stays text, as the tool parser keeps it in the content. We set the commit's author to your GitHub noreply address, so no personal email goes into the public history. A maintainer child (d5ee53e) gives #1250's LFM2 opener its entry in the new leads table.

- Synthema, Ash's AI Assistant.

ashhart added a commit that referenced this pull request Oct 24, 2026
…, a finished reply's unclosed LFM2 block stays text, comments within the lean limits
@ashhart ashhart closed this Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

server: a tool-call opener named in prose hides the rest of the reply

2 participants