Repository navigation
Conversation
stream_batch built one proto and n Response objects over it, then fed every chunk to responses[0] alone. The content buffers live on the Response instance, so responses[1..n-1] had empty buffers and their content, reasoning_content and encrypted_content stayed "" until responses[0] was read and materialized the shared proto. A caller that printed responses[1].content inside the loop saw nothing; one that read responses[1] before responses[0] after the loop saw an empty answer. A Response can now be created shared_with another one over the same proto: process_chunk and the buffer sync go through that one. The existing sample_batch and defer paths are unchanged. Two tests, sync and aio, fail on main; 871 pass.
|
#202 from @latent-9 reports the same read-order problem in The difference is where the cost goes. #202 calls Leaving this open as the alternative shape; if #202 is preferred, this one can be closed and its intermediate-value assertion added there. |
What
stream_batch(n)builds oneGetChatCompletionResponseproto withnoutputs andnResponse(proto, i)objects over it, then feeds every chunk toresponses[0].process_chunk(chunk). Since the buffering change in_ResponseProtoDecorator,process_chunkappends deltas to buffers on the instance, and_sync_buffers_to_protomaterializes them into the shared proto only when that same instance is read.responses[1..n-1]have their own empty buffers and_proto_in_sync = True, so:responses[1].contentis""on every iteration;responses[1].contentis""untilresponses[0].content(or.proto) has been read once, then it is correct.The same goes for
reasoning_contentandencrypted_content. The docstring promises "oneResponsefor each of thenresponses, updated with each chunk".Repro on
mainwithout a server:The existing
test_stream_batchreadschunks[i][1].content, which comes from the chunk, andlast_response[0]beforelast_response[1], so it did not see this.Change
_ResponseProtoDecoratorandResponsetake an optional keywordshared_with: another decorator over the same proto that receives the stream.process_chunkand_sync_buffers_to_protodelegate to it.stream_batchinsync/chat.pyandaio/chat.pynow createsfirst = Response(proto, 0)andResponse(proto, i, shared_with=first)for the rest.sample_batch,defer_batchand the single-response paths never callprocess_chunkon a sibling and are unchanged.stream_batchis on its way out (PendingDeprecationWarning), but it is still public, so it should return what it documents until it goes.Tests
test_stream_batch_every_response_reads_the_stream_as_it_arrivesintests/sync/chat_test.pyandtests/aio/chat_test.py: readresponses[1].contentinside the loop (expect the partial text) and, in the sync variant, readresponses[1]beforeresponses[0]after the loop. Both fail onmain.pytest -n 4: 871 passed;ruff check,ruff format --check,pyrightclean. CHANGELOG entry under Unreleased / Fixed, which will need a one-line merge with #232 if that lands first.