Fix the loop exit condition in the agenerator#858
Conversation
Add comprehensive tests to verify the fix for the bug where the generation loop would prematurely exit when stop_reason='abort'. The bug was caused by using gconfig.max_new_tokens (which gets decremented in the loop) instead of the original value in the loop condition. Tests include: - test_abort_should_continue_loop_with_fix: verify fix works correctly - test_abort_prematurely_exits_without_fix: reproduce the original bug - test_abort_multiple_times_continues_with_fix: multiple abort scenarios - test_abort_reaches_length_limit_with_fix: length limit handling - Additional tests for tool_calls, length stop reasons, and gconfig behavior Reference: commit 445dca7216e66c24d7a5b47a272761ea81749f8d Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com>
Rewrite tests to directly use RemoteInfEngine instance instead of simulating the loop logic. This provides more realistic testing by: - Creating actual RemoteInfEngine with MockBackend - Mocking arequest_with_retry to avoid needing a real SGLang server - Testing the actual agenerate() method behavior The tests now verify that the fix works correctly in the real codebase, not just in isolated simulation. Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com>
Summary of ChangesHello @yulangz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue in the remote inference engine's token generation process. The previous implementation could lead to incomplete token sequences when an 'abort' signal was encountered, as the loop's termination condition was inadvertently modified during execution. The changes ensure that the generation process reliably reaches its intended token limit, significantly improving the robustness of the inference engine. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request correctly fixes a bug in the agenerate method where the generation loop would exit prematurely due to a mutable loop condition variable. The fix involves caching the original max_new_tokens value and using it for the loop termination check. The change is accompanied by a comprehensive new test suite that validates the fix and documents the original bug, which is excellent. My only suggestion is to improve the variable naming for better code clarity.
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug in RemoteInfEngine.agenerate where the generation loop could exit prematurely when stop_reason="abort" due to using a decremented max_new_tokens in the loop condition, and adds tests to lock in the correct behavior.
Changes:
- Adjusts the
agenerateloop condition to use the originalmax_new_tokensvalue captured before the loop, instead of the mutablegconfig.max_new_tokens. - Adds a dedicated test suite exercising
RemoteInfEngine.ageneratebehavior for variousstop_reasonvalues and verifying the abort/length-limit interaction. - Adds simulation tests documenting the original buggy behavior and confirming that
ModelRequest.copy()andgconfig.max_new_tokensupdates behave as expected.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
areal/core/remote_inf_engine.py |
Fixes the generation loop exit condition by capturing gconfig.max_new_tokens into ori_max_new_tokens before the loop and using that constant in the while condition, preventing premature exit when stop_reason="abort". |
areal/tests/test_remote_inf_engine_abort_loop.py |
Introduces a comprehensive test suite for the abort-loop behavior of RemoteInfEngine.agenerate, including real-engine tests against a mocked backend, simulations of the pre-fix bug, and tests for gconfig mutation and ModelRequest.copy() semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - Each call returns 80 tokens with abort (staying within remaining limit) | ||
| - After 3 calls: 240 tokens, remaining = 10 | ||
| - 4th call: returns 80 tokens with abort, but 240 < 250, so we enter loop | ||
| - After 4th call: 320 tokens >= 250, exit loop |
There was a problem hiding this comment.
In test_abort_reaches_length_limit_with_fix, the scenario described in the docstring (4th call returning 80 tokens and total reaching 320) no longer matches the actual test setup, where the 4th response returns 10 tokens and total tokens are 250 as noted in the inline comment. Please update the docstring steps and totals to reflect the actual response sequence so the test documentation is accurate and not confusing.
| - Each call returns 80 tokens with abort (staying within remaining limit) | |
| - After 3 calls: 240 tokens, remaining = 10 | |
| - 4th call: returns 80 tokens with abort, but 240 < 250, so we enter loop | |
| - After 4th call: 320 tokens >= 250, exit loop | |
| - First 3 calls each return 80 tokens with abort (staying within remaining limit) | |
| - After 3 calls: 240 tokens, remaining = 10 | |
| - 4th call: returns 10 tokens with abort, still respecting remaining max_new_tokens | |
| - After 4th call: 250 tokens == max_new_tokens, so we exit loop due to length limit |
…t#858) * test: add unit tests for abort loop condition fix in RemoteInfEngine Add comprehensive tests to verify the fix for the bug where the generation loop would prematurely exit when stop_reason='abort'. The bug was caused by using gconfig.max_new_tokens (which gets decremented in the loop) instead of the original value in the loop condition. Tests include: - test_abort_should_continue_loop_with_fix: verify fix works correctly - test_abort_prematurely_exits_without_fix: reproduce the original bug - test_abort_multiple_times_continues_with_fix: multiple abort scenarios - test_abort_reaches_length_limit_with_fix: length limit handling - Additional tests for tool_calls, length stop reasons, and gconfig behavior Reference: commit 445dca7216e66c24d7a5b47a272761ea81749f8d Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com> * refactor: use real RemoteInfEngine with mocked arequest_with_retry Rewrite tests to directly use RemoteInfEngine instance instead of simulating the loop logic. This provides more realistic testing by: - Creating actual RemoteInfEngine with MockBackend - Mocking arequest_with_retry to avoid needing a real SGLang server - Testing the actual agenerate() method behavior The tests now verify that the fix works correctly in the real codebase, not just in isolated simulation. Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com> --------- Co-authored-by: Claude (claude-opus-4-5) <noreply@anthropic.com>
…t#858) * test: add unit tests for abort loop condition fix in RemoteInfEngine Add comprehensive tests to verify the fix for the bug where the generation loop would prematurely exit when stop_reason='abort'. The bug was caused by using gconfig.max_new_tokens (which gets decremented in the loop) instead of the original value in the loop condition. Tests include: - test_abort_should_continue_loop_with_fix: verify fix works correctly - test_abort_prematurely_exits_without_fix: reproduce the original bug - test_abort_multiple_times_continues_with_fix: multiple abort scenarios - test_abort_reaches_length_limit_with_fix: length limit handling - Additional tests for tool_calls, length stop reasons, and gconfig behavior Reference: commit 445dca7216e66c24d7a5b47a272761ea81749f8d Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com> * refactor: use real RemoteInfEngine with mocked arequest_with_retry Rewrite tests to directly use RemoteInfEngine instance instead of simulating the loop logic. This provides more realistic testing by: - Creating actual RemoteInfEngine with MockBackend - Mocking arequest_with_retry to avoid needing a real SGLang server - Testing the actual agenerate() method behavior The tests now verify that the fix works correctly in the real codebase, not just in isolated simulation. Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com> --------- Co-authored-by: Claude (claude-opus-4-5) <noreply@anthropic.com>
Description
This test verifies the fix for the bug where the generation loop would
prematurely exit when stop_reason='abort' because:
BUG (before fix):
len(accumulated_output_tokens) < gconfig.max_new_tokensgconfig.max_new_tokensgets decremented in the loopFIX:
original_max_new_tokensin the condition instead ofgconfig.max_new_tokensRelated Issue
Fixes #(issue)
Type of Change
work as expected)
Checklist
jb build docs/gemini review)Breaking Change Details (if applicable):
Additional Context
Need help? Check the Contributing Guide or ask in
GitHub Discussions!