mirror of
https://github.com/microsoft/autogen.git
synced 2025-12-27 23:18:59 +00:00
improve component config, add description support in dump_component (#5203)
<!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? It is currently hard to add a description to a component (defaults to None also) .. you have to call super.dump() modify and return. This PR makes the experience better. - allows you specify `component_description` and `component_label` as an optional class var. label is an optional human readable name for the the component. - will use component_description if provided int he description field when dumped if there is no description, will use the first line of class docstring. Takes advantage of all the good practices we have in writing good docstrings. label defaults to component type. For example ```python model_client=OpenAIChatCompletionClient( model="gpt-4o-2024-08-06" ) config = model_client.dump_component() print(config.model_dump_json()) ``` Note the description field below is no longer None and there is a label ```python { "provider": "autogen_ext.models.openai.OpenAIChatCompletionClient", "component_type": "model", "version": 1, "component_version": 1, "description": "Chat completion client for OpenAI hosted models.", "label": "OpenAIChatCompletionClient", "config": { "model": "gpt-4o-2024-08-06" } } ``` <!-- Please give a short summary of the change and the problem this solves. --> ## Related issue number <!-- For example: "Closes #1234" --> None, felt faster to fix. ## Checks - [x] I've included any doc changes needed for https://microsoft.github.io/autogen/. See https://microsoft.github.io/autogen/docs/Contribute#documentation to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [x] I've made sure all auto checks have passed.
This commit is contained in:
parent
b441d5b43a
commit
6359b6a7be
@ -33,6 +33,9 @@ class ComponentModel(BaseModel):
|
||||
description: str | None = None
|
||||
"""Description of the component."""
|
||||
|
||||
label: str | None = None
|
||||
"""Human readable label for the component. If missing the component assumes the class name of the provider."""
|
||||
|
||||
config: dict[str, Any]
|
||||
"""The schema validated config field is passed to a given class's implmentation of :py:meth:`autogen_core.ComponentConfigImpl._from_config` to create a new instance of the component class."""
|
||||
|
||||
@ -95,6 +98,10 @@ class ComponentToConfig(Generic[ToConfigT]):
|
||||
"""The version of the component, if schema incompatibilities are introduced this should be updated."""
|
||||
component_provider_override: ClassVar[str | None] = None
|
||||
"""Override the provider string for the component. This should be used to prevent internal module names being a part of the module name."""
|
||||
component_description: ClassVar[str | None] = None
|
||||
"""A description of the component. If not provided, the docstring of the class will be used."""
|
||||
component_label: ClassVar[str | None] = None
|
||||
"""A human readable label for the component. If not provided, the component class name will be used."""
|
||||
|
||||
def _to_config(self) -> ToConfigT:
|
||||
"""Dump the configuration that would be requite to create a new instance of a component matching the configuration of this instance.
|
||||
@ -132,13 +139,22 @@ class ComponentToConfig(Generic[ToConfigT]):
|
||||
if not hasattr(self, "component_type"):
|
||||
raise AttributeError("component_type not defined")
|
||||
|
||||
description = self.component_description
|
||||
if description is None and self.__class__.__doc__:
|
||||
# use docstring as description
|
||||
docstring = self.__class__.__doc__.strip()
|
||||
for marker in ["\n\nArgs:", "\n\nParameters:", "\n\nAttributes:", "\n\n"]:
|
||||
docstring = docstring.split(marker)[0]
|
||||
description = docstring.strip()
|
||||
|
||||
obj_config = self._to_config().model_dump(exclude_none=True)
|
||||
model = ComponentModel(
|
||||
provider=provider,
|
||||
component_type=self.component_type,
|
||||
version=self.component_version,
|
||||
component_version=self.component_version,
|
||||
description=None,
|
||||
description=description,
|
||||
label=self.component_label or self.__class__.__name__,
|
||||
config=obj_config,
|
||||
)
|
||||
return model
|
||||
|
||||
@ -33,6 +33,15 @@ class MyComponent(ComponentBase[MyConfig], Component[MyConfig]):
|
||||
return cls(info=config.info)
|
||||
|
||||
|
||||
class ComponentWithDescription(MyComponent):
|
||||
component_description = "Explicit description"
|
||||
component_label = "Custom Component"
|
||||
|
||||
|
||||
class ComponentWithDocstring(MyComponent):
|
||||
"""A component using just docstring."""
|
||||
|
||||
|
||||
def test_custom_component() -> None:
|
||||
comp = MyComponent("test")
|
||||
comp2 = MyComponent.load_component(comp.dump_component())
|
||||
@ -350,3 +359,12 @@ async def test_function_tool() -> None:
|
||||
cancelled_token.cancel()
|
||||
with pytest.raises(Exception, match="Cancelled"):
|
||||
await loaded_async.run_json({"x": 1.0, "y": 2.0}, cancelled_token)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
def test_component_descriptions() -> None:
|
||||
"""Test different ways of setting component descriptions."""
|
||||
assert MyComponent("test").dump_component().description is None
|
||||
assert ComponentWithDocstring("test").dump_component().description == "A component using just docstring."
|
||||
assert ComponentWithDescription("test").dump_component().description == "Explicit description"
|
||||
assert ComponentWithDescription("test").dump_component().label == "Custom Component"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user