【AI Agent系列】【MetaGPT多智能体学习】3. 开发一个简单的多智能体系统,兼看MetaGPT多智能体运行机制
本系列文章跟随《MetaGPT多智能体课程》(https://github.com/datawhalechina/hugging-multi-agent),深入理解并实践多智能体系统的开发。
本文为该课程的第四章(多智能体开发)的第一篇笔记。主要记录下多智能体的运行机制及跟着教程,实现一个简单的多智能体系统。
系列笔记
- 【AI Agent系列】【MetaGPT多智能体学习】0. 环境准备 - 升级MetaGPT 0.7.2版本及遇到的坑
- 【AI Agent系列】【MetaGPT多智能体学习】1. 再理解 AI Agent - 经典案例和热门框架综述
- 【AI Agent系列】【MetaGPT多智能体学习】2. 重温单智能体开发 - 深入源码,理解单智能体运行框架
文章目录
- 系列笔记
- 0. 多智能体间互通的方式 - Enviroment组件
- 0.1 多智能体间协作方式简介
- 0.2 Environment组件 - 深入源码
- 0.2.1 参数介绍
- 0.2.2 add_roles函数 - 承载角色
- 0.2.3 publish_message函数 - 接收角色发布的消息 / 环境中的消息被角色得到
- 0.2.4 run函数 - 运行入口
- 1. 开发一个简单的多智能体系统
- 1.1 多智能体需求描述
- 1.2 代码实现
- 1.2.1 学生智能体
- 1.2.2 老师智能体
- 1.2.3 创建多智能体交流的环境
- 1.2.4 运行
- 1.2.5 完整代码
- 2. 总结
0. 多智能体间互通的方式 - Enviroment组件
0.1 多智能体间协作方式简介
在上次课中,我也曾写过 多智能体运行机制 的笔记(这篇文章:【AI Agent系列】【MetaGPT】【深入源码】智能体的运行周期以及多智能体间如何协作)。其中我自己通过看源码,总结出了MetaGPT多智能体间协作的方式:
(1)每一个Role都在不断观察环境中的信息(_observe函数)
(2)当观察到自己想要的信息后,就会触发后续相应的动作
(3)如果没有观察到想要的信息,则会一直循环观察
(4)执行完动作后,会将产生的msg放到环境中(publish_message),供其它Role智能体来使用。
现在再结合《MetaGPT多智能体》课程的教案,发现还是理解地有些浅了,我只关注了智能体在关注自己想要的信息,观察到了之后就开始行动,而忽略了其背后的基础组件 - Enviroment。
0.2 Environment组件 - 深入源码
MetaGPT中对Environment的定义:环境,承载一批角色,角色可以向环境发布消息,可以被其他角色观察到。短短一句话,总结三个功能:
- 承载角色
- 接收角色发布的消息
- 环境中的消息被角色得到
下面我们分开来细说。
0.2.1 参数介绍
首先来看下 Environment 的参数:
class Environment(ExtEnv):"""环境,承载一批角色,角色可以向环境发布消息,可以被其他角色观察到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, SerializeAsAny["Role"]] = Field(default_factory=dict, validate_default=True)member_addrs: Dict["Role", Set] = Field(default_factory=dict, exclude=True)history: str = "" # For debugcontext: Context = Field(default_factory=Context, exclude=True)
- desc:环境的描述
- roles:字典类型,指定当前环境中的角色
- member_addrs:字典类型,表示当前环境中的角色以及他们对应的状态
- history:记录环境中发生的消息记录
- context:当前环境的一些上下文信息
0.2.2 add_roles函数 - 承载角色
def add_roles(self, roles: Iterable["Role"]):"""增加一批在当前环境的角色Add a batch of characters in the current environment"""for role in roles:self.roles[role.profile] = rolefor role in roles: # setup system message with rolesrole.set_env(self)role.context = self.context
从源码中看,这个函数的功能有两个:
(1)给 Environment 的 self.roles 参数赋值,上面我们已经知道它是一个字典类型,现在看来,它的 key 为 role 的 profile,值为 role 本身。
疑问: role 的 profile 默认是空(
profile: str = ""),可以没有值,那如果使用者懒得写profile,这里会不会最终只有一个 Role,导致无法实现多智能体?欢迎讨论交流。
(2)给添加进来的 role 设置环境信息
Role的 set_env 函数源码如下,它又给env设置了member_addrs。有点绕?
def set_env(self, env: "Environment"):"""Set the environment in which the role works. The role can talk to the environment and can also receivemessages by observing."""self.rc.env = envif env:env.set_addresses(self, self.addresses)self.llm.system_prompt = self._get_prefix()self.set_actions(self.actions) # reset actions to update llm and prefix
通过 add_roles 函数,将 role 和 Environment 关联起来。
0.2.3 publish_message函数 - 接收角色发布的消息 / 环境中的消息被角色得到
Environment 中的 publish_message 函数是 Role 在执行完动作之后,将自身产生的消息发布到环境中调用的接口。Role的调用方式如下:
def publish_message(self, msg):"""If the role belongs to env, then the role's messages will be broadcast to env"""if not msg:returnif not self.rc.env:# If env does not exist, do not publish the messagereturnself.rc.env.publish_message(msg)
通过上面的代码来看,一个Role只能存在于一个环境中?
然后看下 Environment 中源码:
def publish_message(self, message: Message, peekable: bool = True) -> bool:"""Distribute the message to the recipients.In accordance with the Message routing structure design in Chapter 2.2.1 of RFC 116, as already plannedin RFC 113 for the entire system, the routing information in the Message is only responsible forspecifying the message recipient, without concern for where the message recipient is located. How toroute the message to the message recipient is a problem addressed by the transport framework designedin RFC 113."""logger.debug(f"publish_message: {message.dump()}")found = False# According to the routing feature plan in Chapter 2.2.3.2 of RFC 113for role, addrs in self.member_addrs.items():if is_send_to(message, addrs):role.put_message(message)found = Trueif not found:logger.warning(f"Message no recipients: {message.dump()}")self.history += f"\n{message}" # For debugreturn True
其中重点是这三行代码,检查环境中的所有Role是否订阅了该消息(或该消息是否应该发送给环境中的某个Role),如果订阅了,则调用Role的put_message函数,Role的 put_message函数的作用是将message放到本身的msg_buffer中:
for role, addrs in self.member_addrs.items():if is_send_to(message, addrs):role.put_message(message)
这样就实现了将环境中的某个Role的Message放到环境中,并通知给环境中其它的Role的机制。
0.2.4 run函数 - 运行入口
run函数的源码如下:
async def run(self, k=1):"""处理一次所有信息的运行Process all Role runs at once"""for _ in range(k):futures = []for role in self.roles.values():future = role.run()futures.append(future)await asyncio.gather(*futures)logger.debug(f"is idle: {self.is_idle}")
k = 1, 表示处理一次消息?为什么要有这个值,难道还能处理多次?意义是什么?
该函数其实就是遍历一遍当前环境中的所有Role,然后运行Role的run函数(运行单智能体)。
Role的run里面,就是用该环境观察信息,行动,发布信息到环境。这样多个Role的运行就通过 Environment 串起来了,这些之前已经写过了,不再赘述,见:【AI Agent系列】【MetaGPT】【深入源码】智能体的运行周期以及多智能体间如何协作。
1. 开发一个简单的多智能体系统
复现教程中的demo。
1.1 多智能体需求描述
- 两个智能体:学生 和 老师
- 任务及预期流程:学生写诗 —> 老师给改进意见 —> 学生根据意见改进 —> 老师给改进意见 —> … n轮 … —> 结束
1.2 代码实现
1.2.1 学生智能体
学生智能体的主要内容就是根据指定的内容写诗。
因此,首先定义一个写诗的Action:WritePoem。
然后,定义学生智能体,指定它的动作就是写诗(self.set_actions([WritePoem]))
那么它什么时候开始动作呢?通过 self._watch([UserRequirement, ReviewPoem]) 设置其观察的信息。当它观察到环境中有了 UserRequirement 或者 ReviewPoem 产生的信息之后,开始动作。UserRequirement为用户的输入信息类型。
class WritePoem(Action):name: str = "WritePoem"PROMPT_TEMPLATE: str = """Here is the historical conversation record : {msg} .Write a poem about the subject provided by human, Return only the content of the generated poem with NO other texts.If the teacher provides suggestions about the poem, revise the student's poem based on the suggestions and return.your poem:"""async def run(self, msg: str):prompt = self.PROMPT_TEMPLATE.format(msg = msg)rsp = await self._aask(prompt)return rspclass Student(Role):name: str = "xiaoming"profile: str = "Student"def __init__(self, **kwargs):super().__init__(**kwargs)self.set_actions([WritePoem])self._watch([UserRequirement, ReviewPoem])async def _act(self) -> Message:logger.info(f"{self._setting}: ready to {self.rc.todo}")todo = self.rc.todomsg = self.get_memories() # 获取所有记忆# logger.info(msg)poem_text = await WritePoem().run(msg)logger.info(f'student : {poem_text}')msg = Message(content=poem_text, role=self.profile,cause_by=type(todo))return msg
1.2.2 老师智能体
老师的智能体的任务是根据学生写的诗,给出修改意见。
因此创建一个Action为ReviewPoem。
然后,创建老师的智能体,指定它的动作为Review(self.set_actions([ReviewPoem]))
它的触发实际应该是学生写完诗以后,因此,加入self._watch([WritePoem])
class ReviewPoem(Action):name: str = "ReviewPoem"PROMPT_TEMPLATE: str = """Here is the historical conversation record : {msg} .Check student-created poems about the subject provided by human and give your suggestions for revisions. You prefer poems with elegant sentences and retro style.Return only your comments with NO other texts.your comments:"""async def run(self, msg: str):prompt = self.PROMPT_TEMPLATE.format(msg = msg)rsp = await self._aask(prompt)return rspclass Teacher(Role):name: str = "laowang"profile: str = "Teacher"def __init__(self, **kwargs):super().__init__(**kwargs)self.set_actions([ReviewPoem])self._watch([WritePoem])async def _act(self) -> Message:logger.info(f"{self._setting}: ready to {self.rc.todo}")todo = self.rc.todomsg = self.get_memories() # 获取所有记忆poem_text = await ReviewPoem().run(msg)logger.info(f'teacher : {poem_text}')msg = Message(content=poem_text, role=self.profile,cause_by=type(todo))return msg
1.2.3 创建多智能体交流的环境
前面我们已经知道了多智能体之间的交互需要一个非常重要的组件 - Environment。
因此,创建一个供多智能体交流的环境,通过 add_roles 加入智能体。
然后,当用户输入内容时,将该内容添加到环境中publish_message,从而触发相应智能体开始运行。这里cause_by=UserRequirement代表消息是由用户产生的,学生智能体关心这类消息,观察到之后就开始行动了。
classroom = Environment()classroom.add_roles([Student(), Teacher()])classroom.publish_message(Message(role="Human", content=topic, cause_by=UserRequirement,send_to='' or MESSAGE_ROUTE_TO_ALL),peekable=False,
)
1.2.4 运行
加入相应头文件,指定交互次数,就可以开始跑了。注意交互次数,直接决定了你的程序的效果和你的钱包!
import asynciofrom metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.environment import Environmentfrom metagpt.const import MESSAGE_ROUTE_TO_ALLasync def main(topic: str, n_round=3):while n_round > 0:# self._save()n_round -= 1logger.debug(f"max {n_round=} left.")await classroom.run()return classroom.historyasyncio.run(main(topic='wirte a poem about moon'))
1.2.5 完整代码
import asynciofrom metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.environment import Environmentfrom metagpt.const import MESSAGE_ROUTE_TO_ALLclassroom = Environment()class WritePoem(Action):name: str = "WritePoem"PROMPT_TEMPLATE: str = """Here is the historical conversation record : {msg} .Write a poem about the subject provided by human, Return only the content of the generated poem with NO other texts.If the teacher provides suggestions about the poem, revise the student's poem based on the suggestions and return.your poem:"""async def run(self, msg: str):prompt = self.PROMPT_TEMPLATE.format(msg = msg)rsp = await self._aask(prompt)return rspclass ReviewPoem(Action):name: str = "ReviewPoem"PROMPT_TEMPLATE: str = """Here is the historical conversation record : {msg} .Check student-created poems about the subject provided by human and give your suggestions for revisions. You prefer poems with elegant sentences and retro style.Return only your comments with NO other texts.your comments:"""async def run(self, msg: str):prompt = self.PROMPT_TEMPLATE.format(msg = msg)rsp = await self._aask(prompt)return rspclass Student(Role):name: str = "xiaoming"profile: str = "Student"def __init__(self, **kwargs):super().__init__(**kwargs)self.set_actions([WritePoem])self._watch([UserRequirement, ReviewPoem])async def _act(self) -> Message:logger.info(f"{self._setting}: ready to {self.rc.todo}")todo = self.rc.todomsg = self.get_memories() # 获取所有记忆# logger.info(msg)poem_text = await WritePoem().run(msg)logger.info(f'student : {poem_text}')msg = Message(content=poem_text, role=self.profile,cause_by=type(todo))return msgclass Teacher(Role):name: str = "laowang"profile: str = "Teacher"def __init__(self, **kwargs):super().__init__(**kwargs)self.set_actions([ReviewPoem])self._watch([WritePoem])async def _act(self) -> Message:logger.info(f"{self._setting}: ready to {self.rc.todo}")todo = self.rc.todomsg = self.get_memories() # 获取所有记忆poem_text = await ReviewPoem().run(msg)logger.info(f'teacher : {poem_text}')msg = Message(content=poem_text, role=self.profile,cause_by=type(todo))return msgasync def main(topic: str, n_round=3):classroom.add_roles([Student(), Teacher()])classroom.publish_message(Message(role="Human", content=topic, cause_by=UserRequirement,send_to='' or MESSAGE_ROUTE_TO_ALL),peekable=False,)while n_round > 0:# self._save()n_round -= 1logger.debug(f"max {n_round=} left.")await classroom.run()return classroom.historyasyncio.run(main(topic='wirte a poem about moon'))
- 运行结果

2. 总结
总结一下整个流程吧,画了个图。

从最外围环境 classroom开始,用户输入的信息通过 publish_message 发送到所有Role中,通过Role的 put_message 放到自身的 msg_buffer中。
当Role运行run时,_observe从msg_buffer中提取信息,然后只过滤自己关心的消息,例如Teacher只过滤出来自WritePoem的,其它消息虽然在msg_buffer中,但不处理。同时,msg_buffer中的消息会存入memory中。
run完即执行完相应动作后,通过publish_message将结果消息发布到环境中,环境的publish_message又将这个消息发送个全部的Role,这时候所有的Role的msg_buffer中都有了这个消息。完成了智能体间信息的一个交互闭环。
站内文章一览

相关文章:
【AI Agent系列】【MetaGPT多智能体学习】3. 开发一个简单的多智能体系统,兼看MetaGPT多智能体运行机制
本系列文章跟随《MetaGPT多智能体课程》(https://github.com/datawhalechina/hugging-multi-agent),深入理解并实践多智能体系统的开发。 本文为该课程的第四章(多智能体开发)的第一篇笔记。主要记录下多智能体的运行…...
机器学习-面经(part7、无监督学习)
机器学习面经系列的其他部分如下所示: 机器学习-面经(part1) 机器学习-面经(part2)-交叉验证、超参数优化、评价指标等内容 机器学习-面经(part3)-正则化、特征工程面试问题与解答合集机器学习-面经(part4)-决策树共5000字的面试问题与解答…...
teknoparrot命令行启动游戏
官方github cd 到teknoparrot解压目录 cd /d E:\mn\TeknoParrot2_cp1\GameProfiles启动游戏 TeknoParrotUi.exe --profile游戏配置文件游戏配置文件位置/UserProfiles,如果UserProfiles文件夹里没有那就在/GameProfiles,在配置文件里将游戏路径加入之间,或者打开模拟器设置 …...
停止Tomcat服务的方式
运行脚本文件停止 运行Tomcat的bin目录中提供的停止服务的脚本文件 关闭命令 # sh方式 sh shutdown.sh# ./方式 ./shutdown.sh操作步骤 运行结束进程停止 查看Tomcat进程,获得进程id kill进程命令 # 执行命令结束进程 kill -9 65358 操作步骤 注意 kill命令是…...
多线程相关面试题(2024大厂高频面试题系列)
1、聊一下并行和并发有什么区别? 并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU 并行是同一时间动手做多件事情的能力,4核CPU同时执行4个线程 2、说一下线程和进程的区别? 进程是正在运行程序的实例ÿ…...
mysql 时间精度问题
timestamp到2038年,还有14年时间,一个系统如果能活到那一刻也是相当不错了。 这里先看一下个datetime的问题,下面的插入数据的时间戳是2024-03-06 21:20:50.839 INSERT INTO psi_io_balance ( id, as_id, bill_date, order_id, busi_type, direction, c…...
基于python的爬虫原理和管理系统实现(代码下载)
Python实现爬虫的原理如下: 发送请求:使用Python中的库,如Requests或urllib,向目标网站发送HTTP请求,获取网页的内容。 解析网页:使用Python中的库,如BeautifulSoup或lxml,对获取的…...
IOS 设置UIViewController为背景半透明浮层弹窗,查看富文本图片详情
使用场景:UIViewController1 打开 UIViewController2(背景半透明弹窗) 案例:打开富文本网页<img>图片的url查看图片详情 WKWebView WKNavigationDelegate代理方法设置js代码点击事件 ///注册添加图片标签点击js方法 - …...
网络层介绍
网络层是OSI模型中的第三层,也称为网络协议层。它主要负责在源主机和目标主机之间提供数据通信的路径选择和控制。网络层通过使用源和目标主机的网络地址来实现数据包的路由和转发。 以下是网络层的一些主要功能: 路由选择:网络层使用路由选…...
springboot/ssm酒店客房管理系统Java在线酒店预约预定平台web
springboot/ssm酒店客房管理系统Java在线酒店预约预定平台web 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:…...
分布式测试插件 pytest-xdist 使用详解
使用背景: 大型测试套件:当你的测试套件非常庞大,包含了大量的测试用例时,pytest-xdist可以通过并行执行来加速整体的测试过程。它利用多个进程或计算机的计算资源,可以显著减少测试执行的时间。高计算资源需求&#…...
【S32K3 MCAL配置】-1.1-GPIO配置及其应用-点亮LED灯(基于MCAL)
目录(共13页精讲,手把手教你S32K3从入门到精通) 实现的架构:基于MCAL层 前期准备工作: 1 创建一个FREERTOS工程...
【软件工程】软件工程定义、软件危机以及软件生命周期
🌸博主主页:釉色清风🌸文章专栏:软件工程🌸 今日语录:What matters isn’t how others think of your ambitions but how fervently you cling to them. 软件工程系列,主要根据老师上课所讲提及…...
24计算机考研深大经验分享(计算机专业考研综合安排)
文章目录 背景科目选择高数选课一轮二轮冲刺阶段 线代一轮二轮 概率论计算机学科专业基础408数据结构计算机组成原理操作系统计算机网络总结 英语政治 末言 背景 首先贴一下初试成绩。这篇分享主要是给零基础的同学使用的,基础好的同学可以自行了解补充一下…...
【知识整理】MySQL数据库开发设计规范
一、规范背景与目的 MySQL数据库与 Oracle、 SQL Server 等数据库相比,有其内核上的优势与劣势。我们在使用MySQL数据库的时候需要遵循一定规范,扬长避短。 本规范旨在帮助或指导RD、QA、OP等技术人员做出适合线上业务的数据库设计。在数据库变更和处理…...
Vue自定义组件实现v-model
前言 v-model 实际上就是 $emit(input) 以及 props:value 的组合语法糖。 1.封装自定义组件 要在 Vue 中实现自定义组件的 v-model 功能,你可以通过使用 model 选项来定义组件的 prop 和事件。以下是一个示例代码,演示如何实现一个自定义组件并使用 v…...
【Linux】Linux网络故障排查与解决指南
🍎个人博客:个人主页 🏆个人专栏:Linux ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 检查网络连接状态: 检查路由表: 检查DNS配置: 检查网络连接状态: 检查防火墙设…...
跟着cherno手搓游戏引擎【27】升级2DRenderer(添加旋转)
水节,添加了旋转的DrawQuad: Renderer2D.h: #pragma once #include "OrthographicCamera.h" #include"Texture.h" namespace YOTO {class Renderer2D{public://为什么渲染器是静态的:static void Init();static void …...
中医舌苔笔记
舌诊时按照舌尖-舌中-舌根-舌侧的顺序进行观察。 先看舌体再看舌苔,30秒左右。 如果一次望舌判断不清,可令病人休息3~5分钟后,重新观察一次 舌诊脏腑部位分属图 舌体 胖嫩而边有齿痕为气虚、阳虚。 薄白而润为风寒; 薄白而燥…...
Facebook的社交未来:元宇宙时代的数字共融
引言: 随着科技的不断进步和社会的快速发展,人们对于社交网络的需求和期待也在不断演变。在这个数字化时代,元宇宙的概念逐渐引发了人们对社交体验的重新思考。作为全球最大的社交网络之一,Facebook正在积极探索元宇宙时代的社交…...
新手入门:在快马平台动手实现你的第一个ui-ux-pro-max设计页面
作为一个刚接触前端设计的新手,最近在InsCode(快马)平台尝试做了一个UI-UX-Pro-Max级别的登录注册页面,整个过程意外地顺利。这里记录下我的实践过程,希望能帮到同样想入门的朋友。 从零搭建页面框架 先用HTML搭建基础结构,包含表…...
提升效率:用快马AI一键生成windows18-hd19风格的CSS组件库
提升效率:用快马AI一键生成windows18-hd19风格的CSS组件库 最近在做一个需要windows18-hd19设计风格的项目,这种风格的界面元素特别多,手动编写样式简直让人头大。光是调色板、阴影效果这些基础样式就要折腾半天,更别说那些复杂的…...
数字孪生+AI:某国家级技术科研机构:耦合仿真评估部件性能,长期运维监测承压状态
部件仿真|设备安全|能源装备|风险评估 某国家级技术科研机构长期服务于国家级重点工程与大型产业体系,在复杂系统运行保障、风险评估与技术支撑等方面承担着关键角色。其业务覆盖多类型基础设施与工程场景,具备完善的…...
【个人推荐】一些好用的录音转写工具
因为助教课备课的缘故,需要录制讲座的音频以整理知识点。一次讲座的音频内容很长,即使3x速快进播放依然很耗费时间,因此录音转写的需求浮现了出来。于是闲暇之余探索了下市面上的录音转写工具,浅浅记录下体验。 下面主要推荐三款…...
2026权威评测:TOP5毕业论文AIGC降重方案对比与首选建议
全景速览:2026盲审季TOP5降重工具核心对比表 排名工具名称降重与去痕效能核心适用场景致命短板 / 核心优势1Scholingo靠岸妙写★★★★★国内本科/硕博盲审、核心期刊投稿优势:DOM级自定义大纲独家AIGC物理去痕2Paperpal★★★★☆SCI/海外顶刊纯英润色…...
Phi-4-mini-reasoning推理模型5分钟快速上手:数学题逻辑题一键解答
Phi-4-mini-reasoning推理模型5分钟快速上手:数学题逻辑题一键解答 1. 为什么选择Phi-4-mini-reasoning? 如果你经常需要解决数学题、逻辑题或者需要一步步分析的问题,Phi-4-mini-reasoning就是为你量身定制的AI助手。这个模型不像那些通用…...
UI-TARS-desktop环境部署:Ubuntu+Docker下免配置运行Qwen3-4B多模态Agent
UI-TARS-desktop环境部署:UbuntuDocker下免配置运行Qwen3-4B多模态Agent 想体验一个能看懂屏幕、操作软件、帮你处理日常任务的多模态AI助手吗?今天,我们就来手把手教你,如何在Ubuntu系统上,通过Docker一键部署UI-TAR…...
终极指南:如何使用Python实现同花顺自动化程序交易
终极指南:如何使用Python实现同花顺自动化程序交易 【免费下载链接】jqktrader 同花顺自动程序化交易 项目地址: https://gitcode.com/gh_mirrors/jq/jqktrader 在量化投资领域,自动化交易已成为专业投资者的标准配置。本文将详细介绍如何利用jqk…...
OpCore-Simplify:如何将黑苹果EFI配置从3小时缩短到15分钟?
OpCore-Simplify:如何将黑苹果EFI配置从3小时缩短到15分钟? 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在开源系统定制领域…...
SMAPI模组加载器全方位指南:从安装到高效管理星露谷物语模组
SMAPI模组加载器全方位指南:从安装到高效管理星露谷物语模组 【免费下载链接】SMAPI The modding API for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/smap/SMAPI 作为开源工具的SMAPI模组加载器,是星露谷物语玩家扩展游戏体验的…...
