-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add ModelRequestParameters and ModelSettings to the ModelRequest #3405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| from __future__ import annotations as _annotations | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from functools import cached_property | ||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| from . import _utils | ||
| from .builtin_tools import AbstractBuiltinTool | ||
|
|
||
| if TYPE_CHECKING: | ||
| from .tools import ToolDefinition | ||
| else: # pragma: no cover | ||
| ToolDefinition = Any | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? |
||
|
|
||
| if TYPE_CHECKING: | ||
| from ._output import OutputObjectDefinition | ||
| from .output import OutputMode | ||
|
|
||
| __all__ = ('ModelRequestParameters',) | ||
|
|
||
|
|
||
| @dataclass(repr=False, kw_only=True) | ||
| class ModelRequestParameters: | ||
| """Configuration for an agent's request to a model, specifically related to tools and output handling.""" | ||
|
|
||
| function_tools: list[ToolDefinition] = field(default_factory=list) | ||
| builtin_tools: list[AbstractBuiltinTool] = field(default_factory=list) | ||
|
|
||
| output_mode: OutputMode = 'text' | ||
| output_object: OutputObjectDefinition | None = None | ||
| output_tools: list[ToolDefinition] = field(default_factory=list) | ||
| prompted_output_template: str | None = None | ||
| allow_text_output: bool = True | ||
| allow_image_output: bool = False | ||
|
|
||
| @cached_property | ||
| def tool_defs(self) -> dict[str, ToolDefinition]: | ||
| return {tool_def.name: tool_def for tool_def in [*self.function_tools, *self.output_tools]} | ||
|
|
||
| @cached_property | ||
| def prompted_output_instructions(self) -> str | None: | ||
| if self.output_mode == 'prompted' and self.prompted_output_template and self.output_object: | ||
| from ._output import PromptedOutputSchema | ||
|
|
||
| return PromptedOutputSchema.build_instructions(self.prompted_output_template, self.output_object) | ||
| return None | ||
|
|
||
| __repr__ = _utils.dataclasses_no_defaults_repr | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,13 +16,21 @@ | |
| from typing_extensions import deprecated | ||
|
|
||
| from . import _otel_messages, _utils | ||
| from ._model_request_parameters import ModelRequestParameters | ||
| from ._utils import generate_tool_call_id as _generate_tool_call_id, now_utc as _now_utc | ||
| from .exceptions import UnexpectedModelBehavior | ||
| from .settings import ModelSettings | ||
| from .usage import RequestUsage | ||
|
|
||
| if TYPE_CHECKING: | ||
| from .models.instrumented import InstrumentationSettings | ||
|
|
||
| ModelRequestParametersField = ModelRequestParameters | None | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even though we don't serialize these, if we don't do this the TypeAdapter will try to inspect all the fields leading to issues with some httpx types included in the models.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is the only way we can solve that, this should be a comment. But I wonder if @Viicos has another idea. He's out today but will be back on Monday. |
||
| ModelSettingsField = ModelSettings | None | ||
| else: # pragma: no cover | ||
| ModelRequestParametersField = Any | ||
| ModelSettingsField = Any | ||
|
|
||
|
|
||
| AudioMediaType: TypeAlias = Literal['audio/wav', 'audio/mpeg', 'audio/ogg', 'audio/flac', 'audio/aiff', 'audio/aac'] | ||
| ImageMediaType: TypeAlias = Literal['image/jpeg', 'image/png', 'image/gif', 'image/webp'] | ||
|
|
@@ -945,6 +953,22 @@ class ModelRequest: | |
| instructions: str | None = None | ||
| """The instructions for the model.""" | ||
|
|
||
| model_request_parameters: Annotated[ModelRequestParametersField, pydantic.Field(exclude=True, repr=False)] = field( | ||
| default=None, repr=False, compare=False | ||
| ) | ||
| """Full request parameters captured for this request. | ||
|
|
||
| Available for introspection during a run. This field is excluded from serialization. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "during a run" implies it'll be removed after the run, but that's not the case |
||
| """ | ||
|
|
||
| model_settings: Annotated[ModelSettingsField, pydantic.Field(exclude=True, repr=False)] = field( | ||
| default=None, repr=False, compare=False | ||
| ) | ||
| """Effective model settings that were applied to this request. | ||
|
|
||
| Available for introspection during a run. This field is excluded from serialization. | ||
| """ | ||
|
|
||
| kind: Literal['request'] = 'request' | ||
| """Message type identifier, this is available on all parts as a discriminator.""" | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do this in
Model.prepare_requestinstead, as model classes sometimes still perform their own modifications and we want to make sure we see catch the final values that were actually sent to the LLM.