Skip to content

fix(mistral): forward stopSequences as Mistral native stop parameter#15200

Merged
aayush-kapoor merged 3 commits into
vercel:mainfrom
cristiandrei1234:fix-mistral-stopsequences
May 12, 2026
Merged

fix(mistral): forward stopSequences as Mistral native stop parameter#15200
aayush-kapoor merged 3 commits into
vercel:mainfrom
cristiandrei1234:fix-mistral-stopsequences

Conversation

@cristiandrei1234
Copy link
Copy Markdown
Contributor

Background

@ai-sdk/mistral accepts stopSequences on the public generateText / streamText API but silently drops the value, emitting only a warning:

[{ "type": "unsupported", "feature": "stopSequences" }]

The Mistral REST API itself supports stop sequences natively via the stop field, which accepts a string or array of strings (Mistral API referencestop: string | array<string>). The adapter's job is to translate stopSequencesstop in the outgoing request, but that translation is missing.

Result: a documented, standard generateText parameter does nothing for Mistral users, with no error surfaced beyond the warning array.

This is an isolated regression specific to @ai-sdk/mistral. Five sibling providers already implement the exact same translation:

Provider Source
@ai-sdk/openai packages/openai/src/chat/openai-chat-language-model.ts:185
@ai-sdk/openai-compatible packages/openai-compatible/src/chat/openai-compatible-chat-language-model.ts:295
@ai-sdk/groq packages/groq/src/groq-chat-language-model.ts:146
@ai-sdk/deepseek packages/deepseek/src/chat/deepseek-chat-language-model.ts:176
@ai-sdk/alibaba packages/alibaba/src/alibaba-chat-language-model.ts:128

All of them do literally stop: stopSequences, in their request baseArgs. Mistral is the odd one out.

Summary

packages/mistral/src/mistral-chat-language-model.ts:

  • Removed the if (stopSequences != null) warnings.push({ type: 'unsupported', feature: 'stopSequences' }) branch.
  • Added stop: stopSequences, to baseArgs, in the same position used by sibling providers (between top_p and random_seed).

The change is minimal and matches an established intra-repo pattern. Vercel's stopSequences?: string[] is a valid subtype of Mistral's documented stop: string | array<string>, so direct assignment is correct.

Manual Verification

Unit tests (deterministic, in-process)

Added a regression test in mistral-chat-language-model.test.ts that:

  1. calls doGenerate with stopSequences: ['foo', 'bar']
  2. asserts the outgoing request body equals { model, messages, stop: ['foo', 'bar'] }
  3. asserts result.warnings does NOT contain { type: 'unsupported', feature: 'stopSequences' }

Validated against the unfixed branch (git stash the source change): the new test fails as expected, plus 7 inline-snapshot tests fail because the snapshots are updated to reflect the new stop field in baseArgs. With the fix applied: all 72 mistral package tests pass.

Live API against api.mistral.ai

Ran a small script that imports the local built @ai-sdk/mistral (with the fix applied) and calls doGenerate on mistral-small-latest with stopSequences: ['Pacific'], prompt asking for facts about the Pacific Ocean:

--- request.body (raw payload sent) ---
{
  model: 'mistral-small-latest',
  max_tokens: 200,
  stop: [ 'Pacific' ],
  messages: [...]
}

--- warnings ---
[]

--- finishReason ---
{ unified: 'stop', raw: 'stop' }

--- content (extracted text) ---
"**Fact 1.** The "

Mistral truncates the output mid-token immediately before "Pacific" and returns finish_reason: "stop", confirming both the field name and the end-to-end behavior. This matches the curl-only verification the reporter already did in #15194 against mistral-large-latest.

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features) — JSDoc unchanged; behavior now matches existing stopSequences documentation in content/docs/.../generate-text#stop-sequences
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Future Work

The reporter flagged that other adapters may emit { type: 'unsupported', feature: 'stopSequences' } while their underlying API actually supports it under a different field name. A repo-wide grep finds 7 other call sites with the same dropping pattern:

packages/xai/src/xai-chat-language-model.ts:123
packages/xai/src/responses/xai-responses-language-model.ts:113
packages/perplexity/src/perplexity-language-model.ts:92
packages/huggingface/src/responses/huggingface-responses-language-model.ts:108
packages/openai/src/responses/openai-responses-language-model.ts:177
packages/open-responses/src/responses/open-responses-language-model.ts:97
packages/prodia/src/prodia-language-model.ts:81  // image-gen, not applicable

Each requires individual verification against the respective provider's API spec — left out of scope here to keep this PR narrow and easy to review. Happy to follow up with separate PRs for providers whose REST APIs actually honor stop sequences (xAI and Perplexity look like obvious candidates given their OpenAI-compatible designs).

Related Issues

Fixes #15194.

@aayush-kapoor
Copy link
Copy Markdown
Collaborator

@cristiandrei1234 can you attach the repro script you used to verify the fix? ideally it produced the warning before and then worked after

@cristiandrei1234
Copy link
Copy Markdown
Contributor Author

I'd already deleted the original ad-hoc script after the verification run, so I rewrote a fresh one against the local build of @ai-sdk/mistral and ran it in both states. Same prompt, same stopSequences: ['Pacific'], the only thing that changes between runs is whether the fix is applied to mistral-chat-language-model.ts (toggled via git checkout HEAD~1 -- ... + pnpm -F @ai-sdk/mistral build).

Gist: https://gist.github.com/cristiandrei1234/ebf0b79e757c3aa470492774a8a34505

Without the fix

--- request.body (raw payload sent to api.mistral.ai) ---
{
"model": "mistral-small-latest",
"max_tokens": 200,
"messages": [
{ "role": "user", "content": [{ "type": "text", "text": "List five facts
about the Pacific Ocean. Number them 1 through 5. Be concise." }] }
]
}

--- warnings ---
[ { "type": "unsupported", "feature": "stopSequences" } ]

--- finishReason ---
{ unified: 'stop', raw: 'stop' }

--- content text ---
"1. Largest Ocean: The Pacific Ocean is the largest and deepest of Earth's
five oceans, covering about 30% of the planet's surface.

  1. Mariana Trench: It contains the Mariana Trench, the deepest known
    point on Earth (Challenger Deep, ~10,984 meters / 36,037 feet deep).

  2. Ring of Fire: The Pacific is bordered by the Ring of Fire, a major
    area of volcanic activity and earthquakes.

  3. Home to Many Species: It supports more than half of the world's marine
    species
    , including coral reefs and whales.

  4. Oldest Water: Some of its deepest waters are over 1,000 years old due
    to slow circulation."

No stop field in the request, the warning is emitted, and the model runs to

  1. Oldest Water: Some of its deepest waters are over 1,000 years old due to slow circulation."

No stop field in the request, the warning is emitted, and the model runs to completion — Pacific appears twice in the output, untruncated. The stop finishReason here is just the natural end-of-message, not a stop-sequence hit.

With the fix applied

--- request.body (raw payload sent to api.mistral.ai) ---
{
"model": "mistral-small-latest",
"max_tokens": 200,
"stop": [ "Pacific" ],
"messages": [
{ "role": "user", "content": [{ "type": "text", "text": "List five facts about the Pacific Ocean. Number them 1 through 5. Be concise." }] }
]
}

--- warnings ---
[]

--- finishReason ---
{ unified: 'stop', raw: 'stop' }

--- content text ---
"1. Largest Ocean: The "

stop: ['Pacific'] is on the wire, no warning, and Mistral truncates mid-token immediately before the stop word with finish_reason: "stop". Happy to fold this into the PR description if you'd like it on the body rather than buried in a comment.

@aayush-kapoor aayush-kapoor enabled auto-merge (squash) May 12, 2026 19:15
@aayush-kapoor aayush-kapoor disabled auto-merge May 12, 2026 19:15
@aayush-kapoor aayush-kapoor merged commit 7acf358 into vercel:main May 12, 2026
18 of 19 checks passed
@aayush-kapoor aayush-kapoor added backport Admins only: add this label to a pull request in order to backport it to the prior version and removed backport Admins only: add this label to a pull request in order to backport it to the prior version labels May 12, 2026
github-actions Bot added a commit that referenced this pull request May 14, 2026
@github-actions github-actions Bot removed the backport Admins only: add this label to a pull request in order to backport it to the prior version label May 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Backport to release-v6.0 created but has conflicts: #15293

aayush-kapoor added a commit that referenced this pull request May 14, 2026
…parameter (#15293)

This is an automated backport of #15200 to the release-v6.0 branch. FYI
@cristiandrei1234
This backport has conflicts that need to be resolved manually.

### `git cherry-pick` output

```
Auto-merging packages/mistral/src/mistral-chat-language-model.test.ts
Auto-merging packages/mistral/src/mistral-chat-language-model.ts
CONFLICT (content): Merge conflict in packages/mistral/src/mistral-chat-language-model.ts
error: could not apply 7acf358... fix(mistral): forward stopSequences as Mistral native stop parameter (#15200)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
```

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Aayush Kapoor <aayushkapoor34@gmail.com>
Co-authored-by: Aayush Kapoor <83492835+aayush-kapoor@users.noreply.github.com>
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.

@ai-sdk/mistral: stopSequences silently dropped instead of forwarded as Mistral's native stop param

2 participants