MetaGPT部分源码解读

Action


SerializationMixin:

Pydantic在序列化一个对象时,会将其序列化为其最顶层父类的形式,而不是它实际子类的形式。这意味着,如果你有一个父类和一个继承自该父类的子类,当你将子类的实例序列化时,得到的字典将只包含父类的字段,而不会包含子类特有的字段。同样,在反序列化时,Pydantic也无法根据数据内容自动选择正确的子类来实例化,而是只能实例化父类。

因此定义了一个名为SerializationMixin的Python类,用于在Pydantic模型中实现多态序列化和反序列化的混合类

    @classmethoddef __get_pydantic_core_schema__(cls, source: type["SerializationMixin"], handler: Callable[[Any], core_schema.CoreSchema]) -> core_schema.CoreSchema:# 调用传入的handler函数,获取模型的默认核心架构schema = handler(source)# 保存原始的核心架构引用,这个引用是Pydantic用于识别模型的一个唯一标识og_schema_ref = schema["ref"]# 在原始的核心架构引用后面添加一个后缀`:mixin`,以便在序列化和反序列化过程中能够识别这个被修改过的架构schema["ref"] += ":mixin"# 创建一个验证器函数,它将在序列化和反序列化过程中被调用,先于标准的Pydantic验证器执行return core_schema.no_info_before_validator_function(cls.__deserialize_with_real_type__,  # 这个类方法将在反序列化过程中被调用schema=schema,  # 修改后的核心架构ref=og_schema_ref,  # 原始的核心架构引用serialization=core_schema.wrap_serializer_function_ser_schema(cls.__serialize_add_class_type__),  # 包装序列化函数)

覆盖了Pydantic的__get_pydantic_core_schema__方法,用于自定义模型的序列化和反序列化过程

    @classmethoddef __serialize_add_class_type__(cls,value,handler: core_schema.SerializerFunctionWrapHandler,) -> Any:# 调用传入的handler函数,这个函数是Pydantic用于序列化模型的默认函数ret = handler(value)# 检查当前类是否有子类,如果没有子类,说明它是一个具体的子类而不是基类if not len(cls.__subclasses__()):# 只有具体的子类才添加`__module_class_name`字段,这个字段包含了子类的全限定类名ret["__module_class_name"] = f"{cls.__module__}.{cls.__qualname__}"# 返回修改后的字典,这个字典将包含额外的类型信息return ret

在序列化过程中被调用,目的是在序列化过程中添加额外的类型信息,以便在反序列化时能够恢复正确的子类类型

    @classmethoddef __deserialize_with_real_type__(cls, value: Any):# 如果传入的值不是字典类型,直接返回该值,因为只有字典类型的值才可能包含序列化的模型数据if not isinstance(value, dict):return value# 如果当前类不是多态基类,或者有子类且序列化的数据中没有`__module_class_name`字段,# 直接返回传入的值,不进行特殊处理if not cls.__is_polymorphic_base or (len(cls.__subclasses__()) and "__module_class_name" not in value):return value# 从序列化的数据中获取`__module_class_name`字段的值,这个值是子类的全限定类名module_class_name = value.get("__module_class_name", None)# 如果没有找到`__module_class_name`字段,抛出ValueError异常if module_class_name is None:raise ValueError("Missing field: __module_class_name")# 从`__subclasses_map__`中获取与全限定类名对应的类类型class_type = cls.__subclasses_map__.get(module_class_name, None)# 如果没有找到对应的类类型,抛出TypeError异常if class_type is None:raise TypeError(f"Trying to instantiate {module_class_name} which not defined yet.")# 使用找到的类类型和传入的数据来实例化子类return class_type(**value)

目的是在反序列化过程中使用之前序列化时保存的类型信息来实例化正确的子类

    def __init_subclass__(cls, is_polymorphic_base: bool = False, **kwargs):# 将is_polymorphic_base参数设置为子类的多态基类标志cls.__is_polymorphic_base = is_polymorphic_base# 将当前子类添加到__subclasses_map__映射中,以便在反序列化时能够找到正确的子类# __subclasses_map__是一个字典,用于存储子类与其全限定类名的映射关系cls.__subclasses_map__[f"{cls.__module__}.{cls.__qualname__}"] = cls# 调用基类的__init_subclass__方法,以便子类可以继承基类的其他设置super().__init_subclass__(**kwargs)

在定义子类时被自动调用,确保在创建子类时子类被正确地注册到__subclasses_map__中,从而在__deserialize_with_real_type__能找到正确的与全限定类名字、对应的类类型

ContexMixin:

用于处理上下文、配置和大型语言模型的相关操作。这个混入类提供了对上下文和配置的访问和设置方法,以及一个大型语言模型的实例

class ContextMixin(BaseModel):"""Mixin class for context and config"""# 定义了一个ConfigDict类型的模型配置,允许任意类型的字段。model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")# Pydantic has bug on _private_attr when using inheritance, so we use private_* instead# - https://github.com/pydantic/pydantic/issues/7142# - https://github.com/pydantic/pydantic/issues/7083# - https://github.com/pydantic/pydantic/issues/7091# Env/Role/Action will use this context as private context, or use self.context as public context# 用于存储一个Context类型的私有上下文。private_context: Optional[Context] = Field(default=None, exclude=True)# Env/Role/Action will use this config as private config, or use self.context.config as public config# 用于存储一个Config类型的私有配置。private_config: Optional[Config] = Field(default=None, exclude=True)# Env/Role/Action will use this llm as private llm, or use self.context._llm instance# 用于存储一个BaseLLM类型的私有大型语言模型。private_llm: Optional[BaseLLM] = Field(default=None, exclude=True)

定义了三个私有字段:private_context、private_config和private_llm,用于存储私有上下文、配置和大型语言模型。

@model_validator(mode="after")def validate_context_mixin_extra(self):self._process_context_mixin_extra()return selfdef _process_context_mixin_extra(self):"""Process the extra field"""# 从model_extra字段中获取额外的参数,这是一个字典,包含了模型创建时传入的所有额外字段kwargs = self.model_extra or {}# 如果context键存在于字典中,则使用self.set_context方法来设置上下文self.set_context(kwargs.pop("context", None))# 如果config键存在于字典中,则使用self.set_config方法来设置配置self.set_config(kwargs.pop("config", None))# 如果llm键存在于字典中,则使用self.set_llm方法来设置大型语言模型self.set_llm(kwargs.pop("llm", None))

确保在模型实例化后,能够正确地设置上下文、配置和大型语言模型

    def set(self, k, v, override=False):"""Set attribute"""# 这个方法用于设置模型的属性。如果override参数为True或者当前没有这个属性的值,# 它将设置这个属性。if override or not self.__dict__.get(k):self.__dict__[k] = vdef set_context(self, context: Context, override=True):"""Set context"""# 这个方法用于设置上下文。如果override参数为True或者当前没有上下文,# 它将设置私有上下文。self.set("private_context", context, override)def set_config(self, config: Config, override=False):"""Set config"""# 这个方法用于设置配置。如果override参数为True或者当前没有配置,# 它将设置私有配置。如果配置不为None,它还会初始化LLM。self.set("private_config", config, override)if config is not None:_ = self.llm  # init llmdef set_llm(self, llm: BaseLLM, override=False):"""Set llm"""# 这个方法用于设置大型语言模型。如果override参数为True或者当前没有大型语言模型,# 它将设置私有大型语言模型。self.set("private_llm", llm, override)@propertydef config(self) -> Config:"""Role config: role config > context config"""# 这个属性用于获取配置。它首先检查是否有私有配置,如果没有,# 则从上下文获取配置。if self.private_config:return self.private_configreturn self.context.config@config.setterdef config(self, config: Config) -> None:"""Set config"""# 这个属性设置器用于设置配置。self.set_config(config)@propertydef context(self) -> Context:"""Role context: role context > context"""# 这个属性用于获取上下文。它首先检查是否有私有上下文,如果没有,# 则创建一个新的上下文实例。if self.private_context:return self.private_contextreturn Context()@context.setterdef context(self, context: Context) -> None:"""Set context"""# 这个属性设置器用于设置上下文。self.set_context(context)@propertydef llm(self) -> BaseLLM:"""Role llm: if not existed, init from role.config"""# 这个属性用于获取大型语言模型(LLM)。如果私有LLM不存在,# 它会从角色的配置中初始化一个LLM。if not self.private_llm:self.private_llm = self.context.llm_with_cost_manager_from_llm_config(self.config.llm)return self.private_llm@llm.setterdef llm(self, llm: BaseLLM) -> None:"""Set llm"""# 这个属性设置器用于设置LLM。self.private_llm = llm

不断设置和获取那三个属性

ProjectRepo:

继承自FileRepository类,FileRepository提供了一系列与文件操作相关的方法,这些操作包括保存文件、获取文件依赖、获取已更改的依赖项、获取文件内容、列出所有文件、保存文档、删除文件等。这些方法主要用于处理存储在Git仓库中的文件,这些功能对于维护Git仓库中的文件和跟踪文件之间的依赖关系非常有用。

GitRepository对象提供了一个全面的接口,用于在Python中与Git仓库交互,包括管理仓库、跟踪变更、提交更改、获取文件列表等

class ProjectRepo(FileRepository):def __init__(self, root: str | Path | GitRepository):# 如果传入的root参数是字符串或Path对象,则创建一个新的GitRepository对象# 如果传入的root参数是一个已存在的GitRepository对象,则直接使用该对象# 如果传入的root参数无效,则抛出一个ValueErrorif isinstance(root, str) or isinstance(root, Path):git_repo_ = GitRepository(local_path=Path(root))elif isinstance(root, GitRepository):git_repo_ = rootelse:raise ValueError("Invalid root")# 调用父类的构造函数,初始化FileRepository对象# git_repo_是GitRepository对象,relative_path是相对于Git仓库根目录的相对路径super().__init__(git_repo=git_repo_, relative_path=Path("."))# 初始化ProjectRepo的属性self._git_repo = git_repo_self.docs = DocFileRepositories(self._git_repo)self.resources = ResourceFileRepositories(self._git_repo)self.tests = self._git_repo.new_file_repository(relative_path=TEST_CODES_FILE_REPO)self.test_outputs = self._git_repo.new_file_repository(relative_path=TEST_OUTPUTS_FILE_REPO)self._srcs_path = Noneself.code_files_exists()def __str__(self):# 返回一个字符串表示,包括Git仓库的工作目录、文档、资源、测试代码和测试输出repo_str = f"ProjectRepo({self._git_repo.workdir})"docs_str = f"Docs({self.docs.all_files})"srcs_str = f"Srcs({self.srcs.all_files})"return f"{repo_str}\n{docs_str}\n{srcs_str}"@propertyasync def requirement(self):# 异步获取REQUIREMENT_FILENAME文件的内容,通常是一个依赖列表return await self.docs.get(filename=REQUIREMENT_FILENAME)@propertydef git_repo(self) -> GitRepository:# 返回与Git仓库交互的GitRepository对象return self._git_repo@propertydef workdir(self) -> Path:# 返回Git仓库的工作目录的路径return Path(self.git_repo.workdir)@propertydef srcs(self) -> FileRepository:# 返回一个用于访问源代码文件的FileRepository对象if not self._srcs_path:raise ValueError("Call with_srcs first.")return self._git_repo.new_file_repository(self._srcs_path)def code_files_exists(self) -> bool:# 检查Git仓库中是否存在代码文件git_workdir = self.git_repo.workdirsrc_workdir = git_workdir / git_workdir.nameif not src_workdir.exists():return Falsecode_files = self.with_src_path(path=git_workdir / git_workdir.name).srcs.all_filesif not code_files:return Falsereturn bool(code_files)def with_src_path(self, path: str | Path) -> ProjectRepo:# 设置源代码文件的路径,并返回当前ProjectRepo对象try:self._srcs_path = Path(path).relative_to(self.workdir)except ValueError:self._srcs_path = Path(path)return self@propertydef src_relative_path(self) -> Path | None:# 返回源代码文件的相对路径return self._srcs_path

pass


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/735320.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP常见报错响应码

HTTP 响应状态代码指示特定 HTTP 请求是否已成功完成。响应分为五类: 信息响应成功响应重定向客户端错误服务器错误 1 、信息响应 100 Continue 这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完 …

云上攻防-云产品篇堡垒机场景JumpServer绿盟SASTeleport麒麟齐治

知识点 1、云产品-堡垒机-产品介绍&攻击事件 2、云产品-堡垒机-安全漏洞&影响产品 章节点: 云场景攻防:公有云,私有云,混合云,虚拟化集群,云桌面等 云厂商攻防:阿里云,腾讯…

k8a 对外服务(ingress)详解(定义,暴露,代理,重写,)

目录 一、 对外服务 service策略的作用 外部访问方案 适用场景和限制 ingress如何实现对外服务 ingress 概念 定义 组成 工作原理 总结 二、 部署 nginx-ingress-controller 创建 ingress-controller pod及相关资源 创建目录: 下载配置文件 修改 集群…

CSS拖曳盒子案例

让我为大家带来一个小案例吧&#xff01; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>* {margin: 0;padding: 0;}.box1 {width: 100px;height: 100px;background-color: black;margin-bot…

iMazing3 2024详细解析数据备份与恢复备份

iMazing 3的备份功能支持增量备份&#xff08;类似苹果电脑里的Time Machine功能&#xff09;&#xff0c;意思是第一次把移动设备的数据全部备份下来&#xff0c;之后的备份就只针对数据有变化的那部分&#xff0c;这样可以节省大量的时间和存储空间&#xff0c;不会让使用者为…

LeetCode59:螺旋矩阵Ⅱ

题目描述 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 代码 class Solution { public:vector…

00-ESP-IDF 环境配置指南

ESP-IDF 环境配置指南 ESP-IDF安装 1.首先我们在浏览器搜索esp-idf&#xff0c;点击第一个选项 2.点击右边栏的安装 3.我们选择手动安装选择需要的系统版本 4.点击链接 5.这里我们选择一个版本&#xff0c;建议不要选择最新的&#xff0c;安装出现问题在网上不好找到解决办…

蓝桥杯备战刷题-滑动窗口

今天给大家带来的是滑动窗口的类型题&#xff0c;都是十分经典的。 1&#xff0c;无重复字符的最长子串 看例三&#xff0c;我们顺便来说一下子串和子序列的含义 子串是从字符串里面抽出来的一部分&#xff0c;不可以有间隔&#xff0c;顺序也不能打乱。 子序列也是从字符串里…

Vue+SpringBoot打造个人健康管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健康咨询模块 三、系统展示四、核心代码4.1 查询健康档案4.2 新增健康档案4.3 查询体检档案4.4 新增体检档案4.5 新增健康咨询 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

【周总结周末日常】

周总结 完成任务开发并且与前端联调通过 完成已开发功能的冒烟测试 修复测试中出现的一些数据显示问题 2024/3/10 晴 温度适宜 这周天气比上周好多了&#xff0c;最起码见到好几次太阳 周六在世纪公园溜达一会儿&#xff0c;偶尔呼吸下大自然&#xff0c;挺棒的…

[2023年]-hadoop面试真题(二)

[2023年]-hadoop面试真题(一) &#xff08;北京&#xff09; Maptask的个数由什么决定?&#xff08;北京&#xff09; 如何判定一个job的map和reduce的数量 ?&#xff08;北京&#xff09; MR中Shuffle过程 ?&#xff08;北京&#xff09; MR中处理数据流程 ?&#xff08;…

c++深拷贝和浅拷贝的区别

在 C 中&#xff0c;深拷贝&#xff08;deep copy&#xff09;和浅拷贝&#xff08;shallow copy&#xff09;是与对象拷贝相关的概念 浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1a; 浅拷贝是指将一个对象的值复制到另一个对象&#xff0c;但如果对象中包含指针成…

【QT】创建第一个QT程序

下面的前7个可以先不看&#xff0c;直接从8开始看 1. 创建Qt程序 一个Qt程序的组成部分&#xff1a;应用程序类&#xff0c;窗口类应用程序类个数&#xff1a;有且只有一个QApplication a;如何查看类对应的模块&#xff1a;光标移动到类上&#xff0c;F1qmake模块的名字 2. …

Redis的主从、哨兵、集群模式的概念及搭建步骤

主从复制 主从模式也叫主从复制&#xff0c;主是主服务器&#xff0c;从是从服务器&#xff0c;主服务器&#xff08;master &#xff09;的数据如果更新了 也会同步到从服务器&#xff08;slave&#xff09;&#xff0c;一个主服务器可以搭配很多个从服务器&#xff0c;主服务…

【设计模式】(四)设计模式之工厂模式

1. 工厂模式介绍 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 工厂模式有三种实现方式&#xff1a; 简单工厂模式工厂方法模式抽象工厂模式 2. 工厂方…

前后端分离项目,如何解决跨域问题?

跨域问题是前后端分离项目中非常常见的一个问题&#xff0c;举例来说&#xff0c;编程猫学习网站的前端服务跑在 8080 端口下&#xff0c;后端服务跑在 9002 端口下&#xff0c;那么前端在请求后端接口的时候就会出现跨域问题。 403 Forbidden 是HTTP协议中的一个状态码&#x…

华容道问题求解_详细设计(五)之hash值和回放功能

&#xff08;续上文&#xff09; 布局的hash 值计算 笔者也参考了之前的一些文章&#xff0c;很多文章提到了怎么节省存贮空间来查找最优解&#xff0c;这不是笔者的目的。笔者的目的比较单一&#xff0c;就是找到最优解就行了。因此并没有在存贮上面进行过多的优化&#xff…

Linux系统adb调试小米手机调试不成功出现Exception occurred while executing ‘put‘:问题解决

参考文章&#xff1a;执行android settings命令报错原因Exception occurred while executing put: java.lang.SecurityException: Pe... - 简书 (jianshu.com) 解决Android U无法通过adb安装应用(Caller has no access to session -1)的问题_performing streamed install-CSDN…

P3405 [USACO16DEC] Cities and States S题解

题目 Farmer John有若干头奶牛。为了训练奶牛们的智力&#xff0c;Farmer John在谷仓的墙上放了一张美国地图。地图上表明了每个城市及其所在州的代码&#xff08;前两位大写字母&#xff09;。 由于奶牛在谷仓里花了很多时间看这张地图&#xff0c;他们开始注意到一些奇怪的…

消息队列 MQ

文章目录 1. MQ 相关概念1.1 什么是 MQ1.2 为什么要用 MQ1.3 MQ 分类1.4 MQ 的选择 1. MQ 相关概念 1.1 什么是 MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO 先入先出&#xff0c;只不过队列中存放的内容是 message 而已&#x…