-
Notifications
You must be signed in to change notification settings - Fork 122
Description
While debugging a call inside the library, I discovered that the code constructing request parameters is using locals(). This breaks when stepping through the function in a debugger.
The relevant code:
all_args = locals()
all_args.pop("self")
all_args["model_id"] = all_args.pop("model")
kwargs = all_args.pop("kwargs")
if tools:
all_args["tools"] = prepare_tools(tools, built_in_tools=self.BUILT_IN_TOOLS)
for i, message in enumerate(messages):
if isinstance(message, ChatCompletionMessage):
messages[i] = message.model_dump(
exclude_none=True,
exclude={"reasoning"},
)
all_args["messages"] = messages
return await self._acompletion(CompletionParams(**all_args), **kwargs)This works normally when executed without debugging. However, when stepping through the function in a debugger, the CompletionParams validation fails because all_args unexpectedly contains additional entries. Debuggers inject temporary variables into the local namespace for watch expressions, etc. When locals() is called during a debugging session, it captures these extra variables, which then get passed to CompletionParams(**all_args), causing a validation error.
I've reproduced this with both VSCode's debugger and pdb. This is expected debugger behavior, not a debugger bug, locals() returns the current local namespace, which debuggers necessarily modify to function.
Reproduction
- Set a breakpoint in the
AnyLLM.acompletionfunction. - Step through the code line by line
- Observe that
all_argscontains debugger-injected variables - The call to
CompletionParams(**all_args)fails with extra unexpected arguments
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 6 validation errors for CompletionParams
self
Extra inputs are not permitted [type=extra_forbidden, input_value=<any_llm.providers.mistra...r object at 0x10b3a8e30>, input_type=MistralProvider]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
model
Extra inputs are not permitted [type=extra_forbidden, input_value='mistral-large-latest', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
kwargs
Extra inputs are not permitted [type=extra_forbidden, input_value={}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
all_args
Extra inputs are not permitted [type=extra_forbidden, input_value={'messages': [{'role': 'u...'m Bilel and I'm 28yo"}}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
i
Extra inputs are not permitted [type=extra_forbidden, input_value=0, input_type=int]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
message
Extra inputs are not permitted [type=extra_forbidden, input_value={'role': 'user', 'content...I'm Bilel and I'm 28yo"}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden
Suggested fix
Don't use locals() and use explicit parameter capture instead. Happy to send a PR for this.