Repository navigation
Refactor LLM APIs, pricing, and prompting modules - #9
Open
devin-ai-integration[bot] wants to merge 9 commits into
Open
devin-ai-integration[bot] wants to merge 9 commits into
devin-ai-integration[bot] wants to merge 9 commits into
Conversation
Task 1: Refactor ChatModel.__call__() and AnthropicChatModel.__call__() to use shared retry helpers from llm_utils.py instead of inline loops. Task 2: Create unified get_pricing(model_name, provider) dispatcher in tracking.py. Rename provider-specific functions to private helpers with public aliases for backward compatibility. Task 3: Remove deprecated ChatModelArgs class (no external consumers). Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
Task 4: Create src/agentlab/agents/prompting/ package with: - flags.py: Flags, ObsFlags, ActionFlags - base.py: PromptElement, Shrinkable, Trunkater, fit_tokens - elements.py: all concrete prompt element classes - __init__.py: re-exports for backward compatibility Update dynamic_prompting.py to be a thin re-export shim. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
Task 5: Replace inline AssistantBench hack in EnvArgs.make_env() with a generic pre_env_setup_hooks callback list. Benchmarks can now register hooks instead of hard-coding task_name checks. Task 6: Add deprecation warning when legacy UI_COPILOT_RESULTS_DIR env var is used. Backward compatibility preserved with DeprecationWarning. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
Task 7: Move CheatMiniWoBLLM_ParseRetry, CheatMiniWoBLLMArgs_ParseRetry, CheatLLM_LLMError, and CheatLLMArgs_LLMError from test_agent.py into a shared tests/helpers/mock_llms.py module for reuse across test files. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
Task 8: Replace asdict(self) with copy.deepcopy(self) in Block.make() to safely handle non-serializable fields. Update docstring accordingly. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
…tantbench hack - ChatModel.get_stats() referenced self.retries which was no longer set after the retry logic was moved to shared helpers. Initialize it in __init__. - Re-add the assistantbench.test output_file hack alongside the new pre_env_setup_hooks mechanism. Add TODO to migrate it to a hook. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
- is_openai_response_valid now checks for usage=None (known OpenRouter issue) and returns False to trigger a retry instead of crashing with AttributeError on completion.usage.prompt_tokens. - generic_call_api_with_retries accepts an optional stats dict that gets populated with the attempt count on success. - call_openai_api_with_retries passes stats through to the generic helper. - ChatModel.__call__ uses the stats dict to update self.retries so get_stats() reports the actual retry count. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
…t_time through - AnthropicChatModel tracker guard now checks isinstance(TRACKER.instance, LLMTracker) consistent with ChatModel, preventing TypeError when TRACKER.instance is None. - call_openai_api_with_retries now accepts initial_retry_delay_seconds and forwards it to generic_call_api_with_retries. - ChatModel.__call__ passes self.min_retry_wait_time as initial_retry_delay_seconds so the parameter is no longer silently ignored. Co-Authored-By: Lukas Burger <lukaskburger@gmail.com>
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.
Summary
Eight independent refactoring tasks to reduce duplication, clean up deprecated code, and improve modularity:
chat_api.py): Replaced inline retry loops inChatModel.__call__()andAnthropicChatModel.__call__()with sharedcall_openai_api_with_retries()/call_anthropic_api_with_retries()fromllm_utils.py.tracking.py): Newget_pricing(model_name, provider)dispatcher. Provider-specific functions renamed to_get_pricing_*(private), with public aliases kept for backward compatibility.ChatModelArgs(chat_api.py): Class had no external consumers — removed entirely.dynamic_prompting.pyintoprompting/subpackage (flags.py,base.py,elements.py,__init__.py). Original file is now a thin re-export shim.loop.py): Added a genericpre_env_setup_hookscallback list onEnvArgs. The existing inlineassistantbench.testcheck is preserved alongside the new hooks mechanism (with a TODO to migrate it to a hook in the future).UI_COPILOT_RESULTS_DIR(exp_utils.py): EmitsDeprecationWarningwhen the legacy env var is used.tests/helpers/mock_llms.py: MovedCheatMiniWoBLLM_ParseRetry,CheatLLMArgs_LLMError, etc. out oftest_agent.py.Block.make()cloning (tool_use_agent.py): Replacedasdict(self)withcopy.deepcopy(self)to handle non-serializable fields.Bug fixes from post-review
After the initial implementation, four bugs were identified and fixed:
usage=Nonecrash:is_openai_response_valid()now returnsFalsewhenresponse.usage is None, triggering a retry instead of crashing withAttributeErroroncompletion.usage.prompt_tokens.ChatModel.retriesalways 0:generic_call_api_with_retries()now accepts an optionalstatsdict and populates it with the attempt count.ChatModel.__call__()passes this dict and updatesself.retriesfrom it, soget_stats()reports accurate retry counts.AnthropicChatModeltracker guard: Addedisinstance(tracking.TRACKER.instance, tracking.LLMTracker)check, consistent withChatModel, to preventTypeErrorwhenTRACKER.instanceisNone.min_retry_wait_timepassthrough:call_openai_api_with_retries()now acceptsinitial_retry_delay_secondsandChatModel.__call__()forwardsself.min_retry_wait_timethrough it, so the parameter is no longer silently ignored.Review & Testing Checklist for Human
handle_error()inChatModel.__call__are still covered by the shared retry helpers (especially edge cases aroundopenai.APIErrorsubtypes and Anthropic-specific errors).deepcopyvsasdictsemantics:asdictreconstructed a fresh instance from serialized field values;deepcopyclones the full object state. Verify thatBlocksubclasses don't carry mutable state that_init()expects to be clean/absent.agentlab.agents.dynamic_promptingare still available (check__init__.pyagainst the original file's public API).pre_env_setup_hooksfield is serialization-safe (dataclass_jsonexclusion via metadata) and that the TODO to migrate the inline check to a hook is acceptable.Recommended test plan: Run
pytest -m 'not pricy' tests/and verify all tests pass, especiallytests/agents/test_agent.py. Local testing showed 60 passed, 8 pre-existing failures (missingMINIWOB_URL), 15 skipped, 20 deselected — all consistent with themainbranch baseline.Notes
get_pricing_openai(),get_pricing_anthropic(), etc.dynamic_prompting.pyremains importable with all original symbols re-exported.pre_env_setup_hooksonEnvArgsis excluded fromDataClassJsonMixinserialization via metadata.darglintCI failures by adding properReturns:/Args:docstring sections to the new and modified pricing functions intracking.py._get_pricing_openai()and_get_pricing_anthropic()return{}whenlangchain_communityis not installed; this is pre-existing behavior, not a regression. Thelitellmprovider works independently.Link to Devin session: https://app.devin.ai/sessions/3b7524eb1b214fd3bc948b39d0d0e87d
Requested by: @lburgers