MetaGPT源码 (ContextMixin 类)

目录

    • 理解 ContextMixin
      • 什么是 ContextMixin?
      • 主要组件
      • 实现细节
    • 测试 ContextMixin
      • 示例:ModelX
        • 1. 配置优先级
        • 2. 多继承
        • 3. 多继承重写
        • 4. 配置优先级

在本文中,我们将探索 ContextMixin 类,它在多重继承场景中的集成及其在 Python 配置和上下文管理中的应用。此外,我们将通过测试验证其功能,以了解它如何简化模型配置的处理。让我们深入了解代码片段的详细解释。


理解 ContextMixin

什么是 ContextMixin?

ContextMixin 是一个用于高效管理上下文和配置的 Python 类。继承该类的模型或对象能够:

  1. 通过灵活的优先级规则处理上下文(private_context)和配置(private_config)。
  2. 管理与 LLM(private_llm)实例的交互。
  3. 支持动态设置属性的覆盖机制。

主要组件

  • 私有上下文和配置

    • private_contextprivate_config 被设计为内部属性,为每个实例提供灵活的作用域。
    • 这些属性默认值为 None,但可以显式覆盖。
  • LLM 管理

    • 通过 private_llm 集成 LLM,支持从配置动态初始化。

实现细节

以下是核心 ContextMixin 类:

from typing import Optionalfrom pydantic import BaseModel, ConfigDict, Field, model_validatorfrom metagpt.config2 import Config
from metagpt.context import Context
from metagpt.provider.base_llm import BaseLLMclass ContextMixin(BaseModel):"""Mixin class for context and config"""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 contextprivate_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 configprivate_config: Optional[Config] = Field(default=None, exclude=True)# Env/Role/Action will use this llm as private llm, or use self.context._llm instanceprivate_llm: Optional[BaseLLM] = Field(default=None, exclude=True)@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"""kwargs = self.model_extra or {}self.set_context(kwargs.pop("context", None))self.set_config(kwargs.pop("config", None))self.set_llm(kwargs.pop("llm", None))def set(self, k, v, override=False):"""Set attribute"""if override or not self.__dict__.get(k):self.__dict__[k] = vdef set_context(self, context: Context, override=True):"""Set context"""self.set("private_context", context, override)def set_config(self, config: Config, override=False):"""Set config"""self.set("private_config", config, override)if config is not None:_ = self.llm  # init llmdef set_llm(self, llm: BaseLLM, override=False):"""Set llm"""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"""# print(f"class:{self.__class__.__name__}({self.name}), llm: {self._llm}, llm_config: {self._llm_config}")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"""self.private_llm = llm

ContextMixin 通过 Pydantic 进行模型验证和数据管理,在处理任意字段时提供了灵活性。


测试 ContextMixin

示例:ModelX

为了演示 ContextMixin 的工作原理,我们创建了一个简单的模型 ModelX,继承自 ContextMixin, 验证 ModelX 能正确继承默认属性,同时保留 ContextMixin 的功能。

ContextMixin 可以无缝集成到多重继承的层次结构中,
ModelY 结合了 ContextMixinWTFMixin,继承了两者的字段和功能。

class ModelX(ContextMixin, BaseModel):a: str = "a"b: str = "b"class WTFMixin(BaseModel):c: str = "c"d: str = "d"class ModelY(WTFMixin, ModelX):passdef test_config_mixin_1():new_model = ModelX()assert new_model.a == "a"assert new_model.b == "b"
test_config_mixin_1()
1. 配置优先级
from metagpt.configs.llm_config import LLMConfigmock_llm_config = LLMConfig(llm_type="mock",api_key="mock_api_key",base_url="mock_base_url",app_id="mock_app_id",api_secret="mock_api_secret",domain="mock_domain",
)
mock_llm_config_proxy = LLMConfig(llm_type="mock",api_key="mock_api_key",base_url="mock_base_url",proxy="http://localhost:8080",
)def test_config_mixin_2():i = Config(llm=mock_llm_config)j = Config(llm=mock_llm_config_proxy)obj = ModelX(config=i)assert obj.config == iassert obj.config.llm == mock_llm_configobj.set_config(j)# obj already has a config, so it will not be setassert obj.config == i
test_config_mixin_2()
2. 多继承
def test_config_mixin_3_multi_inheritance_not_override_config():"""Test config mixin with multiple inheritance"""i = Config(llm=mock_llm_config)j = Config(llm=mock_llm_config_proxy)obj = ModelY(config=i)assert obj.config == iassert obj.config.llm == mock_llm_configobj.set_config(j)# obj already has a config, so it will not be setassert obj.config == iassert obj.config.llm == mock_llm_configassert obj.a == "a"assert obj.b == "b"assert obj.c == "c"assert obj.d == "d"print(obj.__dict__.keys())print(obj.__dict__)assert "private_config" in obj.__dict__.keys()test_config_mixin_3_multi_inheritance_not_override_config()
dict_keys(['private_context', 'private_config', 'private_llm', 'a', 'b', 'c', 'd'])
{'private_context': None, 'private_config': Config(extra_fields=None, project_path='', project_name='', inc=False, reqa_file='', max_auto_summarize_code=0, git_reinit=False, llm=LLMConfig(extra_fields=None, api_key='mock_api_key', api_type=<LLMType.OPENAI: 'openai'>, base_url='mock_base_url', api_version=None, model=None, pricing_plan=None, access_key=None, secret_key=None, session_token=None, endpoint=None, app_id='mock_app_id', api_secret='mock_api_secret', domain='mock_domain', max_token=4096, temperature=0.0, top_p=1.0, top_k=0, repetition_penalty=1.0, stop=None, presence_penalty=0.0, frequency_penalty=0.0, best_of=None, n=None, stream=True, seed=None, logprobs=None, top_logprobs=None, timeout=600, context_length=None, region_name=None, proxy=None, calc_usage=True, use_system_prompt=True), embedding=EmbeddingConfig(extra_fields=None, api_type=None, api_key=None, base_url=None, api_version=None, model=None, embed_batch_size=None, dimensions=None), omniparse=OmniParseConfig(extra_fields=None, api_key='', base_url=''), proxy='', search=SearchConfig(extra_fields=None, api_type=<SearchEngineType.DUCK_DUCK_GO: 'ddg'>, api_key='', cse_id='', search_func=None, params={'engine': 'google', 'google_domain': 'google.com', 'gl': 'us', 'hl': 'en'}), browser=BrowserConfig(extra_fields=None, engine=<WebBrowserEngineType.PLAYWRIGHT: 'playwright'>, browser_type='chromium'), mermaid=MermaidConfig(extra_fields=None, engine='nodejs', path='mmdc', puppeteer_config='', pyppeteer_path='/usr/bin/google-chrome-stable'), s3=None, redis=None, repair_llm_output=False, prompt_schema='json', workspace=WorkspaceConfig(extra_fields=None, path=WindowsPath('d:/llm/metagpt/workspace'), use_uid=False, uid=''), enable_longterm_memory=False, code_review_k_times=2, agentops_api_key='', metagpt_tti_url='', language='English', redis_key='placeholder', iflytek_app_id='', iflytek_api_secret='', iflytek_api_key='', azure_tts_subscription_key='', azure_tts_region=''), 'private_llm': <metagpt.provider.openai_api.OpenAILLM object at 0x00000128F0753910>, 'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd'}
3. 多继承重写
mock_llm_config_zhipu = LLMConfig(llm_type="zhipu",api_key="mock_api_key.zhipu",base_url="mock_base_url",model="mock_zhipu_model",proxy="http://localhost:8080",
)def test_config_mixin_4_multi_inheritance_override_config():"""Test config mixin with multiple inheritance"""i = Config(llm=mock_llm_config)j = Config(llm=mock_llm_config_zhipu)obj = ModelY(config=i)assert obj.config == iassert obj.config.llm == mock_llm_configobj.set_config(j, override=True)# override obj.configassert obj.config == jassert obj.config.llm == mock_llm_config_zhipuassert obj.a == "a"assert obj.b == "b"assert obj.c == "c"assert obj.d == "d"print(obj.__dict__.keys())assert "private_config" in obj.__dict__.keys()assert obj.config.llm.model == "mock_zhipu_model"
test_config_mixin_4_multi_inheritance_override_config()
dict_keys(['private_context', 'private_config', 'private_llm', 'a', 'b', 'c', 'd'])
4. 配置优先级
from pathlib import Path
import pytest
from metagpt.actions import Action
from metagpt.config2 import Config
from metagpt.const import CONFIG_ROOT
from metagpt.environment import Environment
from metagpt.roles import Role
from metagpt.team import Team@pytest.mark.asyncio
async def test_config_priority():"""If action's config is set, then its llm will be set, otherwise, it will use the role's llm"""home_dir = Path.home() / CONFIG_ROOTgpt4t = Config.from_home("gpt-4-turbo.yaml")if not home_dir.exists():assert gpt4t is Nonegpt35 = Config.default()gpt35.llm.model = "gpt35"gpt4 = Config.default()gpt4.llm.model = "gpt-4-0613"a1 = Action(name="Say", instruction="Say your opinion with emotion and don't repeat it", config=gpt4t)a2 = Action(name="Say", instruction="Say your opinion with emotion and don't repeat it")a3 = Action(name="Vote", instruction="Vote for the candidate, and say why you vote for him/her")# it will not work for a1 because the config is already setA = Role(name="A", profile="Democratic candidate", goal="Win the election", actions=[a1], watch=[a2], config=gpt4)# it will work for a2 because the config is not setB = Role(name="B", profile="Republican candidate", goal="Win the election", actions=[a2], watch=[a1], config=gpt4)# dittoC = Role(name="C", profile="Voter", goal="Vote for the candidate", actions=[a3], watch=[a1, a2], config=gpt35)env = Environment(desc="US election live broadcast")Team(investment=10.0, env=env, roles=[A, B, C])assert a1.llm.model == "gpt-4-turbo" if Path(home_dir / "gpt-4-turbo.yaml").exists() else "gpt-4-0613"assert a2.llm.model == "gpt-4-0613"assert a3.llm.model == "gpt35"await test_config_priority()

如果有任何问题,欢迎在评论区提问。

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

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

相关文章

VScode、Windsurf、Cursor 中 R 语言相关快捷键设置

前言 在生物信息学数据分析中&#xff0c;R语言是一个不可或缺的工具。为了提高R语言编程效率&#xff0c;合理设置快捷键显得尤为重要。本文介绍在VSCode Windsurf Cursor 中一些实用的R语言快捷键设置&#xff0c;让非 Rstudio 的 IDE 用起来得心应手&#x1f611; 操作种…

分布式任务调度平台xxl-job源码学习

XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 官网&#xff1a;https://www.xuxueli.com/xxl-job/ github&#xff1a;https://github.com/xuxueli/xxl-…

Macbookpro M1 IDEA中安装mysql

一&#xff1a;安装与连接数据库 1. 首先在mysql中创建一个初始数据库&#xff1a;idea_db&#xff0c;如示&#xff1a; 2.打开IDEA,如果最右侧没有database窗口&#xff0c;则在插件那里下载“Database navigator”,稍后重启一下即可&#xff1b; 点击最右侧Database---->…

leetcode 3264. K 次乘运算后的最终数组 I 简单

给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a; 找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…

根据契约进行分析--录像店案例研究01

Richard Mitchell 著&#xff0c;zhen_lei 译 本文包括录像店案例研究的一些片段&#xff0c;用来说明根据契约进行分析的原理。本文假定读者已经从其它渠道学习了一些关于根据契约进行分析的方法。 完整的一套模型可以写成一本书。这些选择的片段用来说明开发的某些方面&…

Linux内核结构及源码概述

参考&#xff1a;深入分析LINUX内核源码 深入分析Linux内核源码 (kerneltravel.net) Linux 是一个庞大、高效而复杂的操作系统&#xff0c;虽然它的开发起始于 Linus Torvalds 一个人&#xff0c;但随着时间的推移&#xff0c;越来越多的人加入了 Linux 的开发和对它的不断完善…

[Unity] Text文本首行缩进两个字符

Text文本首行缩进两个字符的方法比较简单。通过代码把"\u3000\u3000"加到文本字符串前面即可。 比如&#xff1a; 效果&#xff1a; 代码&#xff1a; TMPtext1.text "\u3000\u3000" "选择动作类型&#xff1a;";

单片机:实现控制LED灯亮灭(附带源码)

使用单片机控制LED灯的亮灭是一个非常基础的嵌入式应用项目&#xff0c;适合初学者学习如何操作GPIO&#xff08;通用输入输出&#xff09;端口以及如何控制外设。通过该项目&#xff0c;您可以学习如何通过按键输入、定时器控制或其他触发条件来控制LED灯的开关状态。 1. 项目…

jQuery理论

jQuery定义 jQuery是一个快速、简洁的JavaScript库&#xff0c;它能够简化HTML文档遍历、事件处理、动画设计和Ajax交互。jQuery的设计目标是通过尽可能少的代码实现更多的功能&#xff0c;并且提供一种优雅的方式来处理HTML文档、处理事件、创建动画效果以及实现Ajax交互。. …

容器内部时间和Node时间不同步问题

之前在《 Docker及Kubernetes使用过程中出现的问题&#xff08;FAQ&#xff09;》中的“FAQ30 容器内部时间和Node时间不同”分享过容器内部和容器服务器之间时间不一致的问题&#xff1b;这通常会导致各种问题&#xff0c;比如日志记录、定时任务等。 问题原因&#xff1a;问…

组合模式(Composite Pattern):树形结构的优雅处理方案

目录 1. 什么是组合模式2. 组合模式的结构3. UML类图4. 代码实现5. 常见应用场景6. 优缺点分析7. 最佳实践建议 1. 什么是组合模式 组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表现"整体-部分&…

AI开源南京分享会回顾录

AI 开源南京分享会&#xff0c;已于2024年11月30日下午在国浩律师&#xff08;南京&#xff09;事务所5楼会议厅成功举办。此次活动由 KCC南京、PowerData、RISC-Verse 联合主办&#xff0c;国浩律师&#xff08;南京&#xff09;事务所协办。 活动以“开源视角的 AI 对话”为主…

OpenCV 图像变换与处理实战

OpenCV快速通关 第一章&#xff1a;OpenCV 简介与环境搭建 第二章&#xff1a;OpenCV 图像基本操作 第三章&#xff1a;OpenCV 图像变换与处理实战 OpenCV 图像变换与处理实战 OpenCV快速通关OpenCV 图像变换与处理实战一、OpenCV 基础与图像处理概览二、图像变换理论精析三、…

Ubuntu22.04安装docker desktop遇到的bug

1. 确认已启用 KVM 虚拟化 如果加载了模块&#xff0c;输出应该如下图。说明 Intel CPU 的 KVM 模块已开启。 否则在VMware开启宿主机虚拟化功能&#xff1a; 2. 下一步操作&#xff1a; Ubuntu | Docker Docs 3. 启动Docker桌面后发现账户登陆不上去&#xff1a; Sign in | …

【深度学习入门】深度学习介绍

1.1 深度学习介绍 学习目标 目标 知道深度学习与机器学习的区别了解神经网络的结构组成知道深度学习效果特点 应用 无 区别 特征提取方面 机器学习的特征工程步骤是要靠手动完成的&#xff0c;而且需要大量领域专业知识深度学习通常由多个层组成&#xff0c;它们通常将更简…

实现按键按下(低电平)检测到下降沿

按照流程进行编程 步骤1&#xff1a; 初始化函数 包括时基工作参数配置 输入通道配置 更新中断使能 使能捕获、捕获中断及计数器 HAL_TIM_IC_Init(&ic_handle) //时基参数配置 HAL_TIM_IC_ConfigChannel(&ic_handle,&ic_config,TIM_CHANNEL_2) //输…

【Linux金典面试题(上)】41道Linux金典面试问题+详细解答,包含基本操作、系统维护、网络配置、脚本编程等问题。

大家好&#xff0c;我是摇光~&#xff0c;用大白话讲解所有你难懂的知识点 之前写了一篇关于 python 的面试题&#xff0c;感觉大家都很需要&#xff0c;所以打算出一个面试专栏。 【数据分析岗】Python金典面试题 这个专栏主要针对面试大数据岗位、数据分析岗位、数据运维等…

【Ubuntu】使用ip link工具创建虚拟局域网并配置?

&#x1f98b;&#x1f98b;&#x1f98b;如何使用ip link工具创建虚拟局域网&#xff1f; sudo ip link add link enx888bd66b7000 name enx.120 type vlan id 120 上述命令使用ip link工具在Linux系统中创建了一个新的虚拟局域网&#xff08;VLAN&#xff09;接口&#xff0c…

汽车车牌标记支持YOLO,COCO,VOC三种格式标记,4000张图片的数据集

本数据集支持YOLO&#xff0c;COCO&#xff0c;VOC三种格式标记汽车车牌&#xff0c;无论是新能源汽车还是油车都能识别标记&#xff0c;该数据集一共包含4000张图片 数据集分割 4000总图像数 训练组 70&#xff05; 2800图片 有效集 20&#xff05; 800图片 测…

Docker 如何在容器未运行时修改内部配置文件

今天遇到一个数据库分组查询的问题&#xff1a;sql_modeonly_full_group_by&#xff0c;即查询 SQL 的字段列表中包含了未分组的字段&#xff0c;在 mysql7 版本下需要修改数据库的配置文件 my.cnf 中的 sql_mode&#xff0c;去除掉值中的 ONLY_FULL_GROUP_BY。 第一次进入 do…