feat(mistralai): native content-block streaming events#38022
feat(mistralai): native content-block streaming events#38022Nick Hollon (nick-hollon-lc) wants to merge 1 commit into
Conversation
| for key, block in iter_protocol_blocks(new_chunk): | ||
| yield from tracker.feed(key, block) |
There was a problem hiding this comment.
🟠 Unindexed tool calls overwrite text blocks
This feeds Mistral chunks into BlockStreamTracker using the generic iter_protocol_blocks keys. For the text-then-tool stream added in the tests, neither the text blocks nor the tool-call chunk carry an index, so iter_protocol_blocks gives both source key 0. The tracker then treats the tool call as an update to the already-open text block: no content-block-start is emitted for the tool call, the accumulated text is replaced, and content-block-finish only returns the tool call. Users streaming a response that contains text before an unindexed tool call lose the finalized text block and get an inconsistent block lifecycle. The native converter should assign stable distinct keys for Mistral text vs tool-call chunks (or ensure tool calls get their own index) before feeding the tracker.
(Refers to lines 97-98)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
a3ef4d9 to
f7d7e0b
Compare
9590053 to
b7a60ac
Compare
Gives
ChatMistralAInative_stream_chat_model_events/_astream_chat_model_eventshooks sostream_events(version="v3")maps Mistral's stream directly to content-block events.How it works
A bespoke converter (
convert_mistral_stream/ async twin) mirrors_streamexactly — threading(index, index_type, default_class)through the existing_convert_chunk_to_message_chunkhelper (injected to avoid a circular import) and skipping no-choices chunks — then feeds each resultingAIMessageChunk's content blocks into the sharedBlockStreamTracker. This surfaces text, tool calls, and (underoutput_version="v1") reasoning blocks, accumulates usage, and labelsmodel_provideras"mistralai".message-startcarries the stream's LangChain run id threaded from core, consistent with the other native paths and the bridge.Worth careful review
_stream/_astream(same index/index_type threading and no-choices skip), so it can't double-count blocks or drop the usage that Mistral attaches to a content chunk.message_idis keyword-only on the hooks, kept out of the request**kwargs.thinking → texttype change advances into distinctreasoningandtextblocks; model-level tests drivestream_events(version="v3")through the native hook. Live-model reasoning specifics are covered by the existing magistral integration test.