#2780·smolagents

BUG: MLXModel can truncate at a later stop sequence when multiple stops match.

Author: MMaazesenCreated Sep 9, 2026Updated Sep 11, 2026
Labelsbug

Problem

MLXModel.generate() can truncate generated text at the wrong position when multiple stop sequences are present in the same generated chunk.

The result depends on the order of stop_sequences, rather than consistently stopping at the earliest matching position in the generated text.

The current logic uses any() together with rfind():

python
if any((stop_index := text.rfind(stop)) != -1 for stop in stops):
    text = text[:stop_index]
    break

Because any() short-circuits, it selects the first matching stop sequence according to the configured list order. In addition, rfind() selects the last occurrence of that stop sequence. This does not necessarily correspond to the earliest stopping boundary in the generated text.

Steps to reproduce

The following example exercises the real MLXModel.generate() control flow while replacing the tokenizer and generation stream with small test doubles, so it does not require Apple Silicon or an MLX model download:

python
from types import SimpleNamespace

from smolagents.models import MLXModel, Model


class FakeTokenizer:
    def apply_chat_template(self, messages, tools=None, **kwargs):
        return [101]


def fake_stream_generate(model, tokenizer, prompt, **kwargs):
    yield SimpleNamespace(text="before<EARLY>middle<LATE>after")


model = object.__new__(MLXModel)
Model.__init__(
    model,
    model_id="local-mlx",
    flatten_messages_as_text=True,
)
model.model = object()
model.tokenizer = FakeTokenizer()
model.stream_generate = fake_stream_generate
model.apply_chat_template_kwargs = {}

messages = [
    {
        "role": "user",
        "content": [{"type": "text", "text": "test"}],
    }
]

for stops in (
    ["<LATE>", "<EARLY>"],
    ["<EARLY>", "<LATE>"],
):
    result = model.generate(messages, stop_sequences=stops)
    print(stops, "->", repr(result.content))

Actual behavior and error logs

The output changes when only the order of the configured stop sequences changes:

bash
['<LATE>', '<EARLY>'] -> 'before<EARLY>middle'
['<EARLY>', '<LATE>'] -> 'before'

No exception or traceback is raised.

Expected behavior

Both configurations should stop at the earliest matching position in the generated text and return:

bash
'before'

The result should not depend on the order of stop_sequences.

One possible implementation direction would be to find the first occurrence of every non-empty stop sequence and truncate at the minimum valid index.

Environment

  • OS: Windows 10 Pro 10.0.19045
  • Python version: 3.13.1
  • Package version: source checkout of smolagents main at commit 30bb1161095dbae2271e6bc3cc4c219cc3897a57

Additional context

I searched existing open and closed issues and pull requests using combinations of MLXModel, stop_sequences, rfind, truncation, and stop-sequence ordering, but did not find an existing report for this behavior.

The reproduction verifies the hardware-independent truncation logic through the real MLXModel.generate() method. I have not tested it with a real model on Apple Silicon.

I would be happy to add a focused regression test and fix after the issue is accepted.

AI assistance was used for repository investigation and drafting this report. I reviewed the code path and ran the reproduction myself.


Checklist

  • I have searched the existing issues and have not found a similar bug report.
  • I have provided a minimal, reproducible example.
  • No traceback is applicable because this bug does not raise an exception.
  • I have provided my environment details.
  • I am willing to work on this issue and submit a pull request.