【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正在积极探索元宇宙时代的社交…...
告别FTP!用Go写的Filebrowser,一个命令搞定Windows/Linux跨平台文件管理
告别FTP!用Go语言构建的Filebrowser,一条命令实现全平台文件管理革命 在服务器管理和跨平台文件共享的日常工作中,传统FTP工具早已显露出诸多不便:复杂的客户端配置、不直观的界面操作、安全隐患频发。而现代开发者需要的…...
Lusca CSP策略完全指南:构建安全的内容安全策略
Lusca CSP策略完全指南:构建安全的内容安全策略 【免费下载链接】lusca Application security for express apps. 项目地址: https://gitcode.com/gh_mirrors/lu/lusca Lusca是一款专为Express应用打造的安全中间件,提供了全面的内容安全策略&…...
树莓派Web IDE:零配置云端编程环境与Python硬件模拟实践
1. 项目概述:一个“开箱即用”的编程环境革命最近,树莓派基金会悄无声息地扔下了一颗“重磅炸弹”——他们正式推出了一个网页端的代码编辑器。这个消息在创客圈和教育圈里,可能比发布一款新硬件还要让人兴奋。为什么?因为它直接戳…...
避坑指南:RK3566给GC2053提供MCLK,分压电阻怎么选?实测波形告诉你答案
RK3566与GC2053时钟信号分压设计实战:从波形分析到电阻选型 当RK3566处理器需要为GC2053图像传感器提供MCLK时钟信号时,电平转换电路的设计往往成为项目成败的关键。许多工程师在首次设计分压电路时,会陷入"阻值越大功耗越小"的误区…...
STM32F103驱动ST7567 LCD屏:手把手教你移植U8g2库(SPI接口,附完整工程)
STM32F103驱动ST7567 LCD屏:从零开始移植U8g2库实战指南 当你第一次拿到一块ST7567驱动的LCD屏时,可能会被各种引脚定义和初始化代码搞得晕头转向。本文将带你从硬件连接到软件移植,一步步完成U8g2库在STM32F103上的适配过程。不同于简单的代…...
vscode格式化插件
1、在vsocde里安装这个插件2、下载 clangllvm 适配 windows 链接地址:https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.83、添加环境变量 将下载的安装报解压到 C:\Users\你的用户名\AppData\Local\Programs 复制C:\Users\你的用户名\AppData\Loca…...
2026届必备的五大降AI率神器推荐榜单
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能技术不断深入发展着,学术领域对于原创性以及学术诚信的要求愈发严格起来…...
渗透测试中的Windows痕迹清理:从“删库跑路”到“雁过无痕”的反取证艺术
引子:想象一下武侠小说里的场景:绝顶高手在别人家的藏经阁偷学了绝世武功,临走时不但不留下一丝指纹,还顺手把烛台复原、抹平了地上的脚印,甚至故意丢下一枚别的门派的暗器——这,就是网络安全界“痕迹清理…...
保姆级教程:用Docker一键部署RustDesk私有服务器(含Web客户端和API)
零基础构建企业级RustDesk私有化远程控制平台:Docker全栈部署指南 远程协作工具已成为现代工作流中不可或缺的一环,但商业解决方案往往面临价格高昂、数据隐私不可控等问题。RustDesk作为开源远程桌面工具,凭借其跨平台特性和自建服务器能力&…...
转行对谈:转向AI是破茧成蝶还是折翼未来?
01前言|AI时代下的土建人 一、AI浪潮:开启一个崭新的时代 人工智能(AI)已经从学术前沿走向产业中心,成为当前时代最具颠覆性的技术之一。从最早“出圈”的对话式模型ChatGPT的火爆到AI绘画、AI写作等AIGC(生…...
