Repository navigation
Python: close native generators when stream invocations end - #14701
Open
DiadkoShmek wants to merge 1 commit into
Open
DiadkoShmek wants to merge 1 commit into
DiadkoShmek wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified in the generator-cleanup changes.
No open issues 🎉
What changed in this PR
This PR adds prompt cleanup of native Python generators when streaming invocations end through KernelFunction.invoke_stream() or Kernel.invoke_stream(), without changing public signatures or ordinary return-value behavior.
Changes:
- Wrap synchronous and asynchronous generators in closing context managers.
- Close the function-invocation stream owned by
Kernel.invoke_stream(). - Add 18 regression cases covering early closure, injected cancellation, exhaustion, exception identity, and ordinary close-bearing results.
| File | Description |
|---|---|
python/tests/unit/functions/test_kernel_function_from_method.py |
Adds retained-generator cleanup and compatibility tests for both entry points. |
python/semantic_kernel/kernel.py |
Closes the owned function-invocation stream with aclosing. |
python/semantic_kernel/functions/kernel_function.py |
Uses closing and aclosing when consuming native generators. |
Review effort: Balanced
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
Closing a native function's streaming invocation after its first item does not promptly close the underlying generator. With a retained reference to that generator, its
finallyblock remains suspended after the invocation ends. The same occurs whenCancelledErroris injected into the suspended invocation. A plugin that releases resources infinallytherefore keeps them live beyond the closed invocation.This reproduces through both
KernelFunction.invoke_stream()andKernel.invoke_stream()with ordinary decorated sync/async native functions.Description
Use
closing/aclosingaround actual Python generators consumed byKernelFunction.invoke_stream, and close the newly created function-invocation stream owned byKernel.invoke_stream. Ordinary returned values and custom close-bearing iterable objects retain their current behavior. Public signatures are unchanged.Validation
Base:
96c9e860db4d7c6da40652d9b421a31b05e98692.aclose, injected cancellation, normal exhaustion, original exception identity and an ordinary close-bearing list that must remain untouched.git diff --check: passed.Test environment: Python 3.13, local editable source and OpenAI 2.26.0 selected from the repository lockfile; not a complete locked all-connectors environment. Full SDK/integration/provider suites were not run.
Scope: the native-generator invocation path. Consumers still need to close a retained stream when leaving their own iteration body, for example with
aclosing. The separateinvoke_prompt_streamforwarding layer and deeper provider wrappers are outside this fix; no general provider-resource guarantee is claimed.Contribution Checklist
AI disclosure: Codex implemented and tested this change, with an independent AI review, as part of an autonomous upstream contribution benchmark. No personal human code review is claimed.