You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently components in AgentChat dont have a built-in serialization story.
This issue is meant to help discuss and architect a setup where all components can be easily serialized to some declarative format and runtime object instantiated.
model_client=OpenAIClient(...)
model_client_spec=model_client.to_dict()
agent_a=AssistantAgent(...)
agent_a_spec=agent_a.to_dict() # agent_a.to_yaml() ... # should be possible to instantiate a new instance of the component from specnew_agent_a=AssistantAgent.from_dict(agent_a_spec)
team_a=RoundRobinGroupChat(participants=[agent_b], mode)
team_a_spec=team_a.to_dict()
team_a_spec_yaml=team_a.to_yaml('configs/team_a.yaml')
termination=Termination(...)
termination_spec=
How
Each top level concept (for lack of a better word) in AgentChat should be treated like a “component” (AGS has the idea of a component factory) - Model, Tool , Agent, Team , Memory , ….
Each component should implement some serialization methods
.to_dict method that specifies how it should be serialized to some declarative specification. .. returns a dict that can be json serialized.
Also implements a to_json and and to_yaml that uses to_dict underneath
.from_dict method that can take the declarative spec above and instantiate a new version of the class
Rough sketch:
fromtypingimportDict, Any, List, OptionalfromdataclassesimportdataclassclassRoundRobinGroupChat(BaseGroupChat):
defto_dict(self) ->Dict[str, Any]:
"""Convert team to dictionary spec."""return {
"provider": "autogen_agentchat.teams.RoundRobinGroupChat",
"component_type": "team",
"version": "1.0.0",
"description": "A round-robin group chat implementation where participants take turns in sequence",
"config": {
"participants": [p.to_dict() forpinself._participants],
"termination_condition": self._termination_condition.to_dict() ifself._termination_conditionelseNone,
"max_turns": self._max_turns
}
}
@classmethoddeffrom_dict(cls, data: Dict[str, Any]) ->'RoundRobinGroupChat':
"""Create team from dictionary spec."""# Validate component typeifdata.get("component_type") !="team":
raiseValueError(f"Invalid component_type. Expected 'team', got '{data.get('component_type')}'")
# Validate providerexpected_provider="autogen_agentchat.teams.RoundRobinGroupChat"ifdata.get("provider") !=expected_provider:
raiseValueError(f"Invalid provider. Expected '{expected_provider}', got '{data.get('provider')}'")
# Get configurationconfig=data.get("config", {})
ifnotconfig:
raiseValueError("Missing required 'config' field")
# Convert nested componentsparticipants= [ChatAgent.from_dict(p) forpinconfig.get("participants", [])]
termination= (TerminationCondition.from_dict(config["termination_condition"])
ifconfig.get("termination_condition") elseNone)
returncls(
participants=participants,
termination_condition=termination,
max_turns=config.get("max_turns")
)
defto_yaml(self, file_path: str=None) ->Optional[str]:
"""Convert to YAML and optionally save to file."""importyamlyaml_str=yaml.dump(self.to_dict(), sort_keys=False)
iffile_path:
withopen(file_path, 'w') asf:
f.write(yaml_str)
returnNonereturnyaml_str@classmethoddeffrom_yaml(cls, yaml_str: str) ->'RoundRobinGroupChat':
"""Create instance from YAML string."""importyamldata=yaml.safe_load(yaml_str)
returncls.from_dict(data)
What Fields Should the Spec Have?
some ideas for required fields inclide
provider: The class used to instantiate the runtime object e.g., autogen_agentchat.teams.RoundRobinGroupChat
component_type: shorthand for some high-level/semantic type of the component e.g., "model", team, agent, termination etc.
version: useful for compatibility across changes
description: optional field to describe what this specific instance of the object is. Extremely useful to consumers during sharing/reuse.
config: the actual data structure to be used ...
Benefits
Native serialization of component specs
Consistency across all applications using the component spec
Responsibility for correctly instantiating and serializing a component is solely held by the developer of the component. As it rightfully should be (apps like AGS should do the bare minimum )
The process for creating component specifications is not both consistent and simplified for all applications.
The developer experience is greatly improved - easy switching between declarative and python code (a common ask).
Create your agentchat team in python code, prototype,
Team.dict() .. save to team.yaml or team.json for distribution/deployment/debugging in AGS (with a single command)
How to run team_a in AutoGen studio?
autogenstudioui--config-dir=configs
Note that this is only focused on serialization - how to return a runtime instance of a component from a declaritive spec and how to obtain that declarative spec from an instance. Now the ability to load/save runtime state is a separate task tracked in #4100 .
Notes
Should ChatAgent enforce a protocol for the new methods? to_dict etc
Do we get any benefits from basing components on pydantic classes wrt to serialization?
What
Currently components in AgentChat dont have a built-in serialization story.
This issue is meant to help discuss and architect a setup where all components can be easily serialized to some declarative format and runtime object instantiated.
How
Rough sketch:
What Fields Should the Spec Have?
some ideas for required fields inclide
provider
: The class used to instantiate the runtime object e.g.,autogen_agentchat.teams.RoundRobinGroupChat
component_type
: shorthand for some high-level/semantic type of the component e.g., "model",team
,agent
,termination
etc.version
: useful for compatibility across changesdescription
: optional field to describe what this specific instance of the object is. Extremely useful to consumers during sharing/reuse.config
: the actual data structure to be used ...Benefits
How to run team_a in AutoGen studio?
Note that this is only focused on serialization - how to return a runtime instance of a component from a declaritive spec and how to obtain that declarative spec from an instance. Now the ability to load/save runtime state is a separate task tracked in #4100 .
Notes
Related to #3624, #4388
Thoughts welcome @husseinmozannar @ekzhu @afourney @gagb @jackgerrits
The text was updated successfully, but these errors were encountered: