migrate from pydantic v1 to v2

This commit is contained in:
better629 2023-12-26 14:44:09 +08:00
parent 0569fc5560
commit 66925dd791
29 changed files with 143 additions and 158 deletions

View file

@ -10,7 +10,7 @@ from __future__ import annotations
from typing import Any, Optional, Union
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from metagpt.actions.action_node import ActionNode
from metagpt.llm import LLM
@ -26,19 +26,18 @@ action_subclass_registry = {}
class Action(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
name: str = ""
llm: BaseGPTAPI = Field(default_factory=LLM, exclude=True)
context: Union[dict, CodingContext, CodeSummarizeContext, TestingContext, RunCodeContext, str, None] = ""
prefix = "" # aask*时会加上prefix作为system_message
desc = "" # for skill manager
prefix: str = "" # aask*时会加上prefix作为system_message
desc: str = "" # for skill manager
node: ActionNode = Field(default=None, exclude=True)
# builtin variables
builtin_class_name: str = ""
class Config:
arbitrary_types_allowed = True
def __init_with_instruction(self, instruction: str):
"""Initialize action with instruction"""
self.node = ActionNode(key=self.name, expected_type=str, instruction=instruction, example="", schema="raw")
@ -58,8 +57,8 @@ class Action(BaseModel):
super().__init_subclass__(**kwargs)
action_subclass_registry[cls.__name__] = cls
def dict(self, *args, **kwargs) -> "DictStrAny":
obj_dict = super().dict(*args, **kwargs)
def dict(self, *args, **kwargs) -> dict[str, Any]:
obj_dict = super().model_dump(*args, **kwargs)
if "llm" in obj_dict:
obj_dict.pop("llm")
return obj_dict

View file

@ -11,7 +11,7 @@ NOTE: You should use typing.List instead of list to do type annotation. Because
import json
from typing import Any, Dict, List, Optional, Tuple, Type
from pydantic import BaseModel, create_model, root_validator, validator
from pydantic import BaseModel, create_model, field_validator, model_validator
from tenacity import retry, stop_after_attempt, wait_random_exponential
from metagpt.config import CONFIG
@ -136,13 +136,15 @@ class ActionNode:
"""基于pydantic v1的模型动态生成用来检验结果类型正确性"""
new_class = create_model(class_name, **mapping)
@validator("*", allow_reuse=True)
@field_validator("*", mode="before")
@classmethod
def check_name(v, field):
if field.name not in mapping.keys():
raise ValueError(f"Unrecognized block: {field.name}")
return v
@root_validator(pre=True, allow_reuse=True)
@model_validator(mode="before")
@classmethod
def check_missing_fields(values):
required_fields = set(mapping.keys())
missing_fields = required_fields - set(values.keys())
@ -269,7 +271,9 @@ class ActionNode:
output_class = self.create_model_class(output_class_name, output_data_mapping)
if schema == "json":
parsed_data = llm_output_postprecess(output=content, schema=output_class.schema(), req_key=f"[/{TAG}]")
parsed_data = llm_output_postprecess(
output=content, schema=output_class.model_json_schema(), req_key=f"[/{TAG}]"
)
else: # using markdown parser
parsed_data = OutputParser.parse_data_with_mapping(content, output_data_mapping)
@ -278,7 +282,7 @@ class ActionNode:
return content, instruct_content
def get(self, key):
return self.instruct_content.dict()[key]
return self.instruct_content.model_dump()[key]
def set_recursive(self, name, value):
setattr(self, name, value)
@ -337,7 +341,7 @@ class ActionNode:
tmp = {}
for _, i in self.children.items():
child = await i.simple_fill(schema=schema, mode=mode, timeout=timeout)
tmp.update(child.instruct_content.dict())
tmp.update(child.instruct_content.model_dump())
cls = self.create_children_class()
self.instruct_content = cls(**tmp)
return self

View file

@ -50,7 +50,7 @@ class RebuildClassView(Action):
# try:
# node = await REBUILD_CLASS_VIEW_NODE.fill(context=f"```{code_type}\n{src_code}\n```", llm=self.llm, to=format)
# class_view = node.instruct_content.dict()["Class View"]
# class_view = node.instruct_content.model_dump()["Class View"]
# except Exception as e:
# class_view = RepoParser.rebuild_class_view(src_code, code_type)
# await graph_db.insert(subject=concat_namespace(filename, class_name), predicate=GraphKeyword.HAS_CLASS_VIEW, object_=class_view)

View file

@ -8,7 +8,7 @@
from typing import Any, Optional
import pydantic
from pydantic import Field, root_validator
from pydantic import Field, model_validator
from metagpt.actions import Action
from metagpt.config import CONFIG, Config
@ -114,10 +114,10 @@ class SearchAndSummarize(Action):
engine: Optional[SearchEngineType] = CONFIG.search_engine
search_func: Optional[Any] = None
search_engine: SearchEngine = None
result: str = ""
result = ""
@root_validator
@model_validator(mode="before")
@classmethod
def validate_engine_and_run_func(cls, values):
engine = values.get("engine")
search_func = values.get("search_func")

View file

@ -187,7 +187,7 @@ class WritePRD(Action):
if not CONFIG.project_name:
if isinstance(prd, (ActionOutput, ActionNode)):
ws_name = prd.instruct_content.dict()["Project Name"]
ws_name = prd.instruct_content.model_dump()["Project Name"]
else:
ws_name = CodeParser.parse_str(block="Project Name", text=prd)
CONFIG.project_name = ws_name

View file

@ -17,7 +17,7 @@ from langchain.document_loaders import (
UnstructuredWordDocumentLoader,
)
from langchain.text_splitter import CharacterTextSplitter
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from tqdm import tqdm
from metagpt.config import CONFIG
@ -117,13 +117,12 @@ class IndexableDocument(Document):
Advanced document handling: For vector databases or search engines.
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
data: Union[pd.DataFrame, list]
content_col: Optional[str] = Field(default="")
meta_col: Optional[str] = Field(default="")
class Config:
arbitrary_types_allowed = True
@classmethod
def from_path(cls, data_path: Path, content_col="content", meta_col="metadata"):
if not data_path.exists():

View file

@ -15,7 +15,7 @@ import asyncio
from pathlib import Path
from typing import Iterable, Set
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from metagpt.config import CONFIG
from metagpt.logs import logger
@ -29,14 +29,13 @@ class Environment(BaseModel):
Environment, hosting a batch of roles, roles can publish messages to the environment, and can be observed by other roles
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
desc: str = Field(default="") # 环境描述
roles: dict[str, Role] = Field(default_factory=dict)
members: dict[Role, Set] = Field(default_factory=dict)
history: str = "" # For debug
class Config:
arbitrary_types_allowed = True
def __init__(self, **kwargs):
roles = []
for role_key, role in kwargs.get("roles", {}).items():

View file

@ -7,7 +7,7 @@
from typing import Optional
from pydantic import Field
from pydantic import ConfigDict, Field
from metagpt.logs import logger
from metagpt.memory import Memory
@ -22,13 +22,12 @@ class LongTermMemory(Memory):
- update memory when it changed
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
memory_storage: MemoryStorage = Field(default_factory=MemoryStorage)
rc: Optional["RoleContext"] = None
msg_from_recover: bool = False
class Config:
arbitrary_types_allowed = True
def recover_memory(self, role_id: str, rc: "RoleContext"):
messages = self.memory_storage.recover_memory(role_id)
self.rc = rc

View file

@ -41,7 +41,7 @@ class Memory(BaseModel):
def serialize(self, stg_path: Path):
"""stg_path = ./storage/team/environment/ or ./storage/team/environment/roles/{role_class}_{role_name}/"""
memory_path = stg_path.joinpath("memory.json")
storage = self.dict()
storage = self.model_dump()
write_json_file(memory_path, storage)
@classmethod

View file

@ -26,7 +26,7 @@ from enum import Enum
from pathlib import Path
from typing import Any, Iterable, Set, Type
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr
from metagpt.actions import Action, ActionOutput
from metagpt.actions.action import action_subclass_registry
@ -108,9 +108,7 @@ class RoleContext(BaseModel):
RoleReactMode.REACT
) # see `Role._set_react_mode` for definitions of the following two attributes
max_react_loop: int = 1
class Config:
arbitrary_types_allowed = True
model_config = ConfigDict(arbitrary_types_allowed=True)
def check(self, role_id: str):
# if hasattr(CONFIG, "long_term_memory") and CONFIG.long_term_memory:
@ -134,6 +132,8 @@ role_subclass_registry = {}
class Role(BaseModel):
"""Role/Agent"""
model_config = ConfigDict(arbitrary_types_allowed=True, exclude=["_llm"])
name: str = ""
profile: str = ""
goal: str = ""
@ -141,11 +141,11 @@ class Role(BaseModel):
desc: str = ""
is_human: bool = False
_llm: BaseGPTAPI = Field(default_factory=LLM) # Each role has its own LLM, use different system message
_role_id: str = ""
_states: list[str] = []
_actions: list[Action] = []
_rc: RoleContext = Field(default_factory=RoleContext)
_llm: BaseGPTAPI = PrivateAttr(default_factory=LLM) # Each role has its own LLM, use different system message
_role_id: str = PrivateAttr(default="")
_states: list[str] = PrivateAttr(default=[])
_actions: list[Action] = PrivateAttr(default=[])
_rc: RoleContext = PrivateAttr(default_factory=RoleContext)
subscription: set[str] = set()
# builtin variables
@ -154,20 +154,16 @@ class Role(BaseModel):
builtin_class_name: str = ""
_private_attributes = {
"_llm": None,
"_role_id": _role_id,
"_states": [],
"_actions": [],
"_rc": RoleContext(),
"_subscription": set(),
# "_llm": None,
# "_role_id": _role_id,
# "_states": [],
# "_actions": [],
# "_rc": RoleContext(),
# "_subscription": set(),
}
__hash__ = object.__hash__ # support Role as hashable type in `Environment.members`
class Config:
arbitrary_types_allowed = True
exclude = ["_llm"]
def __init__(self, **kwargs: Any):
for index in range(len(kwargs.get("_actions", []))):
current_action = kwargs["_actions"][index]
@ -179,7 +175,7 @@ class Role(BaseModel):
current_action = subclass(**current_action)
break
kwargs["_actions"][index] = current_action
RoleContext.model_rebuild()
super().__init__(**kwargs)
# 关于私有变量的初始化 https://github.com/pydantic/pydantic/issues/655
@ -187,25 +183,25 @@ class Role(BaseModel):
self._private_attributes["_role_id"] = str(self._setting)
self.subscription = {any_to_str(self), self.name} if self.name else {any_to_str(self)}
for key in self._private_attributes.keys():
if key in kwargs:
object.__setattr__(self, key, kwargs[key])
if key == "_rc":
_rc = RoleContext(**kwargs["_rc"])
object.__setattr__(self, "_rc", _rc)
else:
if key == "_rc":
# # Warning, if use self._private_attributes["_rc"],
# # self._rc will be a shared object between roles, so init one or reset it inside `_reset`
object.__setattr__(self, key, RoleContext())
else:
object.__setattr__(self, key, self._private_attributes[key])
# for key in self._private_attributes.keys():
# if key in kwargs:
# object.__setattr__(self, key, kwargs[key])
# if key == "_rc":
# _rc = RoleContext(**kwargs["_rc"])
# object.__setattr__(self, "_rc", _rc)
# else:
# if key == "_rc":
# # # Warning, if use self._private_attributes["_rc"],
# # # self._rc will be a shared object between roles, so init one or reset it inside `_reset`
# object.__setattr__(self, key, RoleContext())
# else:
# object.__setattr__(self, key, self._private_attributes[key])
self._llm.system_prompt = self._get_prefix()
# deserialize child classes dynamically for inherited `role`
object.__setattr__(self, "builtin_class_name", self.__class__.__name__)
self.__fields__["builtin_class_name"].default = self.__class__.__name__
self.model_fields["builtin_class_name"].default = self.__class__.__name__
if "actions" in kwargs:
self._init_actions(kwargs["actions"])
@ -231,7 +227,7 @@ class Role(BaseModel):
else stg_path
)
role_info = self.dict(exclude={"_rc": {"memory": True, "msg_buffer": True}, "_llm": True})
role_info = self.model_dump(exclude={"_rc": {"memory": True, "msg_buffer": True}, "_llm": True})
role_info.update({"role_class": self.__class__.__name__, "module_name": self.__module__})
role_info_path = stg_path.joinpath("role_info.json")
write_json_file(role_info_path, role_info)

View file

@ -25,7 +25,7 @@ from json import JSONDecodeError
from pathlib import Path
from typing import Any, Dict, List, Optional, Set, Type, TypeVar
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr
from metagpt.config import CONFIG
from metagpt.const import (
@ -108,7 +108,7 @@ class Message(BaseModel):
role: str = "user" # system / user / assistant
cause_by: str = ""
sent_from: str = ""
send_to: Set = Field(default_factory={MESSAGE_ROUTE_TO_ALL})
send_to: Set = Field(default={MESSAGE_ROUTE_TO_ALL})
def __init__(self, content: str = "", **kwargs):
ic = kwargs.get("instruct_content", None)
@ -142,26 +142,26 @@ class Message(BaseModel):
new_val = val
super().__setattr__(key, new_val)
def dict(self, *args, **kwargs) -> "DictStrAny":
def dict(self, *args, **kwargs) -> dict[str, Any]:
"""overwrite the `dict` to dump dynamic pydantic model"""
obj_dict = super(Message, self).dict(*args, **kwargs)
obj_dict = super(Message, self).model_dump(*args, **kwargs)
ic = self.instruct_content
if ic:
# compatible with custom-defined ActionOutput
schema = ic.schema()
schema = ic.model_json_schema()
# `Documents` contain definitions
if "definitions" not in schema:
# TODO refine with nested BaseModel
mapping = actionoutout_schema_to_mapping(schema)
mapping = actionoutput_mapping_to_str(mapping)
obj_dict["instruct_content"] = {"class": schema["title"], "mapping": mapping, "value": ic.dict()}
obj_dict["instruct_content"] = {"class": schema["title"], "mapping": mapping, "value": ic.model_dump()}
return obj_dict
def __str__(self):
# prefix = '-'.join([self.role, str(self.cause_by)])
if self.instruct_content:
return f"{self.role}: {self.instruct_content.dict()}"
return f"{self.role}: {self.instruct_content.model_dump()}"
return f"{self.role}: {self.content}"
def __repr__(self):
@ -224,19 +224,18 @@ class AIMessage(Message):
class MessageQueue(BaseModel):
"""Message queue which supports asynchronous updates."""
_queue: Queue = Field(default_factory=Queue)
model_config = ConfigDict(arbitrary_types_allowed=True)
_private_attributes = {"_queue": Queue()}
_queue: Queue = PrivateAttr(default_factory=Queue)
class Config:
arbitrary_types_allowed = True
# _private_attributes = {"_queue": Queue()}
def __init__(self, **kwargs: Any):
for key in self._private_attributes.keys():
if key in kwargs:
object.__setattr__(self, key, kwargs[key])
else:
object.__setattr__(self, key, Queue())
# def __init__(self, **kwargs: Any):
# for key in self._private_attributes.keys():
# if key in kwargs:
# object.__setattr__(self, key, kwargs[key])
# else:
# object.__setattr__(self, key, Queue())
def pop(self) -> Message | None:
"""Pop one message from the queue."""
@ -312,28 +311,28 @@ class BaseContext(BaseModel, ABC):
class CodingContext(BaseContext):
filename: str
design_doc: Optional[Document]
task_doc: Optional[Document]
code_doc: Optional[Document]
design_doc: Optional[Document] = None
task_doc: Optional[Document] = None
code_doc: Optional[Document] = None
class TestingContext(BaseContext):
filename: str
code_doc: Document
test_doc: Optional[Document]
test_doc: Optional[Document] = None
class RunCodeContext(BaseContext):
mode: str = "script"
code: Optional[str]
code: Optional[str] = None
code_filename: str = ""
test_code: Optional[str]
test_code: Optional[str] = None
test_filename: str = ""
command: List[str] = Field(default_factory=list)
working_directory: str = ""
additional_python_paths: List[str] = Field(default_factory=list)
output_filename: Optional[str]
output: Optional[str]
output_filename: Optional[str] = None
output: Optional[str] = None
class RunCodeResult(BaseContext):

View file

@ -1,7 +1,7 @@
import asyncio
from typing import AsyncGenerator, Awaitable, Callable
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from metagpt.logs import logger
from metagpt.roles import Role
@ -33,10 +33,9 @@ class SubscriptionRunner(BaseModel):
>>> asyncio.run(main())
"""
tasks: dict[Role, asyncio.Task] = Field(default_factory=dict)
model_config = ConfigDict(arbitrary_types_allowed=True)
class Config:
arbitrary_types_allowed = True
tasks: dict[Role, asyncio.Task] = Field(default_factory=dict)
async def subscribe(
self,

View file

@ -11,7 +11,7 @@
import warnings
from pathlib import Path
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from metagpt.actions import UserRequirement
from metagpt.config import CONFIG
@ -34,6 +34,8 @@ class Team(BaseModel):
dedicated to env any multi-agent activity, such as collaboratively writing executable code.
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
env: Environment = Field(default_factory=Environment)
investment: float = Field(default=10.0)
idea: str = Field(default="")
@ -45,14 +47,11 @@ class Team(BaseModel):
if "env_desc" in kwargs:
self.env.desc = kwargs["env_desc"]
class Config:
arbitrary_types_allowed = True
def serialize(self, stg_path: Path = None):
stg_path = SERDESER_PATH.joinpath("team") if stg_path is None else stg_path
team_info_path = stg_path.joinpath("team_info.json")
write_json_file(team_info_path, self.dict(exclude={"env": True}))
write_json_file(team_info_path, self.model_dump(exclude={"env": True}))
self.env.serialize(stg_path.joinpath("environment")) # save environment alone

View file

@ -9,7 +9,7 @@ from typing import Optional
from urllib.parse import urlparse
import httplib2
from pydantic import BaseModel, validator
from pydantic import BaseModel, ConfigDict, Field, field_validator
from metagpt.config import CONFIG
from metagpt.logs import logger
@ -25,15 +25,13 @@ except ImportError:
class GoogleAPIWrapper(BaseModel):
google_api_key: Optional[str] = None
google_cse_id: Optional[str] = None
google_api_key: Optional[str] = Field(default=None, validate_default=True)
google_cse_id: Optional[str] = Field(default=None, validate_default=True)
loop: Optional[asyncio.AbstractEventLoop] = None
executor: Optional[futures.Executor] = None
model_config = ConfigDict(arbitrary_types_allowed=True)
class Config:
arbitrary_types_allowed = True
@validator("google_api_key", always=True)
@field_validator("google_api_key", mode="before")
@classmethod
def check_google_api_key(cls, val: str):
val = val or CONFIG.google_api_key
@ -45,7 +43,7 @@ class GoogleAPIWrapper(BaseModel):
)
return val
@validator("google_cse_id", always=True)
@field_validator("google_cse_id", mode="before")
@classmethod
def check_google_cse_id(cls, val: str):
val = val or CONFIG.google_cse_id

View file

@ -8,13 +8,15 @@
from typing import Any, Dict, Optional, Tuple
import aiohttp
from pydantic import BaseModel, Field, validator
from pydantic import BaseModel, ConfigDict, Field, field_validator
from metagpt.config import CONFIG
class SerpAPIWrapper(BaseModel):
search_engine: Any #: :meta private:
model_config = ConfigDict(arbitrary_types_allowed=True)
search_engine: Any = None #: :meta private:
params: dict = Field(
default={
"engine": "google",
@ -23,13 +25,11 @@ class SerpAPIWrapper(BaseModel):
"hl": "en",
}
)
serpapi_api_key: Optional[str] = None
# should add `validate_default=True` to check with default value
serpapi_api_key: Optional[str] = Field(default=None, validate_default=True)
aiosession: Optional[aiohttp.ClientSession] = None
class Config:
arbitrary_types_allowed = True
@validator("serpapi_api_key", always=True)
@field_validator("serpapi_api_key", mode="before")
@classmethod
def check_serpapi_api_key(cls, val: str):
val = val or CONFIG.serpapi_api_key

View file

@ -9,21 +9,19 @@ import json
from typing import Any, Dict, Optional, Tuple
import aiohttp
from pydantic import BaseModel, Field, validator
from pydantic import BaseModel, ConfigDict, Field, field_validator
from metagpt.config import CONFIG
class SerperWrapper(BaseModel):
search_engine: Any #: :meta private:
search_engine: Any = None #: :meta private:
payload: dict = Field(default={"page": 1, "num": 10})
serper_api_key: Optional[str] = None
serper_api_key: Optional[str] = Field(default=None, validate_default=True)
aiosession: Optional[aiohttp.ClientSession] = None
model_config = ConfigDict(arbitrary_types_allowed=True)
class Config:
arbitrary_types_allowed = True
@validator("serper_api_key", always=True)
@field_validator("serper_api_key", mode="before")
@classmethod
def check_serper_api_key(cls, val: str):
val = val or CONFIG.serper_api_key

View file

@ -5,7 +5,7 @@ from typing import Generator, Optional
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
from pydantic import BaseModel
from pydantic import BaseModel, PrivateAttr
class WebPage(BaseModel):
@ -13,11 +13,8 @@ class WebPage(BaseModel):
html: str
url: str
class Config:
underscore_attrs_are_private = True
_soup: Optional[BeautifulSoup] = None
_title: Optional[str] = None
_soup: Optional[BeautifulSoup] = PrivateAttr(default=None)
_title: Optional[str] = PrivateAttr(default=None)
@property
def soup(self) -> BeautifulSoup:

View file

@ -62,7 +62,7 @@ def serialize_message(message: "Message"):
ic = message_cp.instruct_content
if ic:
# model create by pydantic create_model like `pydantic.main.prd`, can't pickle.dump directly
schema = ic.schema()
schema = ic.model_json_schema()
mapping = actionoutout_schema_to_mapping(schema)
message_cp.instruct_content = {"class": schema["title"], "mapping": mapping, "value": ic.dict()}

View file

@ -10,7 +10,7 @@ fire==0.4.0
typer
# godot==0.1.1
# google_api_python_client==2.93.0
lancedb==0.1.16
lancedb==0.4.0
langchain==0.0.352
loguru==0.6.0
meilisearch==0.21.0
@ -19,7 +19,7 @@ openai==1.6.0
openpyxl
beautifulsoup4==4.12.2
pandas==2.0.3
pydantic==1.10.8
pydantic==2.5.3
#pygame==2.1.3
#pymilvus==2.2.8
pytest==7.2.2
@ -33,16 +33,15 @@ tqdm==4.64.0
#unstructured[local-inference]
# selenium>4
# webdriver_manager<3.9
anthropic==0.3.6
anthropic==0.8.1
typing-inspect==0.8.0
aiofiles
typing_extensions==4.7.0
typing_extensions==4.9.0
libcst==1.0.1
qdrant-client==1.4.0
qdrant-client==1.7.0
pytest-mock==3.11.1
# open-interpreter==0.1.7; python_version>"3.9"
ta==0.10.2
semantic-kernel==0.4.0.dev0
semantic-kernel==0.4.3.dev0
wrapt==1.15.0
#aiohttp_jinja2
#azure-cognitiveservices-speech~=1.31.0

View file

@ -10,7 +10,7 @@ from metagpt.roles.architect import Architect
def test_architect_serialize():
role = Architect()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
assert "name" in ser_role_dict
assert "_states" in ser_role_dict
assert "_actions" in ser_role_dict
@ -19,7 +19,7 @@ def test_architect_serialize():
@pytest.mark.asyncio
async def test_architect_deserialize():
role = Architect()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
new_role = Architect(**ser_role_dict)
# new_role = Architect.deserialize(ser_role_dict)
assert new_role.name == "Bob"

View file

@ -20,14 +20,14 @@ from tests.metagpt.serialize_deserialize.test_serdeser_base import (
def test_env_serialize():
env = Environment()
ser_env_dict = env.dict()
ser_env_dict = env.model_dump()
assert "roles" in ser_env_dict
def test_env_deserialize():
env = Environment()
env.publish_message(message=Message(content="test env serialize"))
ser_env_dict = env.dict()
ser_env_dict = env.model_dump()
new_env = Environment(**ser_env_dict)
assert len(new_env.roles) == 0
assert len(new_env.history) == 25
@ -47,7 +47,7 @@ def test_environment_serdeser():
environment.add_role(role_c)
environment.publish_message(message)
ser_data = environment.dict()
ser_data = environment.model_dump()
assert ser_data["roles"]["Role C"]["name"] == "RoleC"
new_env: Environment = Environment(**ser_data)
@ -64,7 +64,7 @@ def test_environment_serdeser_v2():
pm = ProjectManager()
environment.add_role(pm)
ser_data = environment.dict()
ser_data = environment.model_dump()
new_env: Environment = Environment(**ser_data)
role = new_env.get_role(pm.profile)

View file

@ -25,7 +25,7 @@ def test_memory_serdeser():
memory = Memory()
memory.add_batch([msg1, msg2])
ser_data = memory.dict()
ser_data = memory.model_dump()
new_memory = Memory(**ser_data)
assert new_memory.count() == 2

View file

@ -12,7 +12,7 @@ from metagpt.schema import Message
@pytest.mark.asyncio
async def test_product_manager_deserialize():
role = ProductManager()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
new_role = ProductManager(**ser_role_dict)
assert new_role.name == "Alice"

View file

@ -11,7 +11,7 @@ from metagpt.roles.project_manager import ProjectManager
def test_project_manager_serialize():
role = ProjectManager()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
assert "name" in ser_role_dict
assert "_states" in ser_role_dict
assert "_actions" in ser_role_dict
@ -20,7 +20,7 @@ def test_project_manager_serialize():
@pytest.mark.asyncio
async def test_project_manager_deserialize():
role = ProjectManager()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
new_role = ProjectManager(**ser_role_dict)
assert new_role.name == "Eve"

View file

@ -34,7 +34,7 @@ def test_roles():
def test_role_serialize():
role = Role()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
assert "name" in ser_role_dict
assert "_states" in ser_role_dict
assert "_actions" in ser_role_dict
@ -42,7 +42,7 @@ def test_role_serialize():
def test_engineer_serialize():
role = Engineer()
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
assert "name" in ser_role_dict
assert "_states" in ser_role_dict
assert "_actions" in ser_role_dict
@ -51,7 +51,7 @@ def test_engineer_serialize():
@pytest.mark.asyncio
async def test_engineer_deserialize():
role = Engineer(use_code_review=True)
ser_role_dict = role.dict(by_alias=True)
ser_role_dict = role.model_dump(by_alias=True)
new_role = Engineer(**ser_role_dict)
assert new_role.name == "Alex"

View file

@ -31,7 +31,7 @@ def test_message_without_postprocess():
out_data = {"field1": ["field1 value1", "field1 value2"]}
ic_obj = ActionNode.create_model_class("code", out_mapping)
message = MockMessage(content="code", instruct_content=ic_obj(**out_data))
ser_data = message.dict()
ser_data = message.model_dump()
assert ser_data["instruct_content"] == {"field1": ["field1 value1", "field1 value2"]}
new_message = MockMessage(**ser_data)

View file

@ -33,7 +33,7 @@ def test_team_deserialize():
]
)
assert len(company.env.get_roles()) == 3
ser_company = company.dict()
ser_company = company.model_dump()
new_company = Team(**ser_company)
assert len(new_company.env.get_roles()) == 3
@ -71,7 +71,7 @@ async def test_team_recover():
company.run_project(idea)
await company.run(n_round=4)
ser_data = company.dict()
ser_data = company.model_dump()
new_company = Team(**ser_data)
new_role_c = new_company.env.get_role(role_c.profile)

View file

@ -38,7 +38,7 @@ class TestGetProjectRoot:
def test_any_to_str(self):
class Input(BaseModel):
x: Any
x: Any = None
want: str
inputs = [
@ -56,7 +56,7 @@ class TestGetProjectRoot:
def test_any_to_str_set(self):
class Input(BaseModel):
x: Any
x: Any = None
want: Set
inputs = [

View file

@ -21,8 +21,8 @@ from metagpt.utils.dependency_file import DependencyFile
async def test_dependency_file():
class Input(BaseModel):
x: Union[Path, str]
deps: Optional[Set[Union[Path, str]]]
key: Optional[Union[Path, str]]
deps: Optional[Set[Union[Path, str]]] = None
key: Optional[Union[Path, str]] = None
want: Set[str]
inputs = [