多智能体粒子环境(Multi-Agent Particle Env)食用指南--从入门到入土

news/2025/3/13 8:33:17/文章来源:https://www.cnblogs.com/7dragonpig/p/18765876

0.项目地址:

原地址:openai/multiagent-particle-envs: Code for a multi-agent particle environment used in the paper "Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments" (github.com)

国内镜像:项目首页 - multiagent-particle-envs:Code for a multi-agent particle environment used in the paper "Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments" - GitCode

环境列表

代码中的环境名称 沟通 竞争 描述
simple N N 单个智能体看到地标位置,根据它与地标的接近程度进行奖励。不是多智能体环境——用于调试策略。
simple_adversary.py (物理欺骗) N 是 1 个对手(红色),N 个优秀智能体(绿色),N 个地标(通常 N=2)。所有智能体都会观察地标和其他智能体的位置。一个地标是“目标地标”(绿色)。好的智能体根据其中一个与目标地标的接近程度进行奖励,但如果对手靠近目标地标,则获得负面奖励。对手根据它与目标的接近程度获得奖励,但它不知道哪个地标是目标地标。因此,优秀的智能体必须学会“拆分”并覆盖所有地标以欺骗对手。
simple_crypto.py (秘密交流) 两个好智能体人(爱丽丝和鲍勃),一个对手(夏娃)。Alice 必须通过公共频道向 bob 发送私人消息。Alice 和 bob 会根据 bob 重建消息的程度获得奖励,但如果 eve 能够重建消息,则获得负面奖励。Alice 和 bob 有一个私钥(在每集开始时随机生成),他们必须学会使用它来加密消息。
simple_push.py (远离) N 1 个智能体、1 个对手、1 个地标。智能体根据与地标的距离进行奖励。如果对手靠近地标,并且智能体远离地标,则它会得到奖励。因此,对手学会将智能体推离地标。
simple_reference.py N 2 个智能体,3 个不同颜色的地标。每个智能体都想到达他们的目标地标,只有其他智能体知道。奖励是集体的。因此,智能体必须学会传达另一个智能体的目标,并导航到他们的地标。这与 simple_speaker_listener 场景相同,其中两个智能体同时是说话者和听众。
simple_speaker_listener.py (合作交流) N 与 simple_reference 相同,除了一个智能体是不动的“说话者”(灰色)(观察其他智能体的目标),另一个智能体是听者(不能说话,但必须导航到正确的地标)。
simple_spread.py (合作导航) N N N 个智能体,N 个地标。根据任何智能体与每个地标的距离对智能体进行奖励。如果智能体与其他智能体发生冲突,则会受到惩罚。因此,智能体必须学会在避免碰撞的同时覆盖所有地标。
simple_tag.py (捕食者-猎物) N 捕食者-猎物环境。好的智能体(绿色)速度更快,并且希望避免被对手(红色)击中。对手速度较慢,并希望打击优秀的智能体。障碍物(大黑圈)挡住了去路。
simple_world_comm.py 在论文随附的视频中看到的环境。与 simple_tag 相同,除了 (1) 有食物(蓝色小球),好智能体会因为靠近而获得奖励,(2)我们现在有“森林”,可以将智能体隐藏在里面,从外面看不到;(3)有一个“领导对手”,可以随时看到智能体人,并可以与其他对手沟通,帮助协调追击。

如果从头开始就按下面步骤来,不要跳。

1.创建虚拟环境

指令格式:conda create -n env_name python=x.x

输入:

conda create -n mpe python=3.6

安装环境默认路径在 Anaconda 目录下的 envs 里面,如图:一路点Yes

image-20250304140200437

2.激活虚拟环境

conda activate mpe

从base环境进入mpe项目环境,后面的依赖包会下载到项目环境里,避免与其他项目冲突出现版本问题。

image-20250304140317206

3.下载相关依赖包

注意版本问题,新版本gym会报错“prng模块的缺失”,pyglet版本太高也会报错。

依赖包版本如下(能正常跑的):

Python =3.6 gym=0.10.5 tensorflow = 1.14.0 numpy =1.19.5 pyglet = 1.5.9

输入:

pip install gym==0.10.5 tensorflow==1.14.0 pyglet==1.5.9

4.安装openAI的Multiagent-particle-envs

进入“multiagent-particle-envs”目录,安装环境(最后的点 . 不要漏了):

pip install -e.

image-20250304141243909

5.测试环境:

python bin/interactive.py --scenario simple.py

成功的话得到如下画面:

image-20250304142227317

说明包版本啥的没有问题,可以继续。

6. 安装openAI的maddpg算法

  • 下载克隆maddpg开源项目文件openai/maddpggithub.com到mpe的同一目录下,目录结构如图:

    image-20250304145622996

  • 进入maddgp目录:

image-20250304145715412

  • 安装
pip install -e.
  • 测试

    安装完成后,输入如下代码进行测试

    cd experiments
    python train.py --scenario simple
    

    以下画面说明成功:按ctrl+c命令行终止

    image-20250304150050917

    • 开可视化

    找到maddpg->experiments->train.py中,找到display可视化属性,改为True即可看见训练过程

    image-20250304145833270

    如下图说明成功:

image-20250304145507248

7.切换其他环境

maddpg/experiments文件夹下运行如下代码:

cd experiments 
python train.py --scenario simple_tag

image-20250304150951295

如果要可视化,后面加上display属性:

python train.py --scenario simple_tag --display

image-20250304151112007

训练完:默认episodes: 60000

image-20250304192504899

注意:第一次训练时display一定得设置为false,第二次运行train.py时才能导入第一次跑完存储的模型进行可视化。

--display: 展示训练结果, 但不继续训练 (默认: False)

不然会报错:

image-20250304222434354

以上就完成了环境配置。其他的遇到文件夹路径、包导入之类的基本问题,可以自行查阅解决。


8.命令参数说明

主要剖析simple_tag环境

环境选项

  • --scenario: 选择多智能体环境场景脚本名称(如simple_tag.py)(默认: "simple")
  • --max-episode-len :单个episode的最大步长,超过此步长会强制终止 (默认: 25)
  • --num-episodes :总训练episode数量 (默认: 60000)
  • --num-adversaries: 环境中的adversary数量 (默认: 0)(需与场景脚本中定义的一致)
  • --good-policy: 环境中good policy算法(默认: "maddpg"; 选项: {"maddpg", "ddpg"})
  • --adv-policy: 环境中adversary policy算法(默认: "maddpg"; 选项: {"maddpg", "ddpg"})

关键点

image-20250306150126724
  • --num-adversaries 必须与场景脚本(如 simple_tag.py)中定义的对抗者数量一致,否则策略分配会出错,导致曲线收敛可能达不到预期效果。
  • --good-policy--adv-policy 指定不同类别智能体的算法,默认为 maddpg

image-20250306195458885

核心训练参数

  • --lr: Adam优化器的学习率 (默认: 1e-2),如果学习率过高,可能导致策略更新不稳定;过低则学习缓慢。
  • --gamma: 奖励折扣因子(discount factor) (默认: 0.95),这可能影响长期奖励的累积。如果任务需要更长期的规划,可能需要更高的gamma。
  • --batch-size: 从经验回放池中采样的批量大小 (默认: 1024),较大的批次可能影响更新的稳定性,尤其是在初期训练阶段。
  • --num-units: 神经网络隐藏层的单元数 (默认: 64)

保存

  • --exp-name: 实验名称,用于保存结果的文件名前缀 (默认: None)
  • --save-dir: 模型保存目录 (默认: "/tmp/policy/")
  • --save-rate:每完成多少个episode保存一次模型 (默认: 1000)
  • --load-dir: 预训练模型加载目录 (默认: "")

评估

  • --restore: 恢复在load-dir的训练结果, 并且继续训练 (默认: False)
  • --display: 是否实时渲染环境(训练时可视化), 但不继续训练 (默认: False)
  • --benchmark: 是否进入评估模式(不训练,仅测试策略性能,保存结果到 benchmark-dir 文件夹 (默认: False)
  • --benchmark-iters: 执行基准评估的训练周期 (默认: 100000)
  • --benchmark-dir: 存放基准数据的目录 (默认: "./benchmark_files/")
  • --plots-dir: 存放训练曲线的目录 (默认: "./learning_curves/")

(1) None_rewards.pkl

  • 数据类型:列表(final_ep_rewards)。
  • 具体内容
    • 每个元素表示训练过程中 每间隔 save_rate 个 episodes 的平均总奖励
    • 例如,若 save_rate=100,则列表中第 i 个元素对应第 i*100 个 episodes 的平均总奖励。
  • 用途:用于绘制 全局学习曲线,反映整体策略的收敛性和性能变化。

(2) None_agrewards.pkl

  • 数据类型:列表(final_ep_ag_rewards)。

  • 具体内容

    • 每个元素表示训练过程中 每个智能体在间隔 save_rate 个 episodes 内的平均奖励

    • 例如,若有 3 个智能体,save_rate=100,则列表中元素顺序为:

      [智能体1的第100轮平均奖励, 智能体2的第100轮平均奖励, 智能体3的第100轮平均奖励, 智能体1的第200轮平均奖励, ...]
      
  • 用途:用于分析 各智能体的独立学习曲线,观察协作或竞争行为对个体奖励的影响。

Demo

  • 进行训练
    python train.py --scenario simple_push --num-episodes 1000000 --exp-name exp1 --save-dir dir

  • 训练结果可视化
    python train.py --scenario simple_push --load-dir dir --display

  • 继续训练
    python train.py --scenario simple_push --load-dir dir --restore --num-episodes 80000

9.代码注释

训练文件train.py

1. 神经网络模型定义 (mlp_model)

def mlp_model(input, num_outputs, scope, reuse=False, num_units=64, rnn_cell=None):"""定义一个2层全连接神经网络:param input: 输入张量(观测状态):param num_outputs: 输出层维度(对应动作空间):param scope: 变量作用域名称(用于区分不同Agent的网络):param reuse: 是否重用变量(用于共享参数):param num_units: 隐藏层单元数(通过--num-units参数指定)"""with tf.variable_scope(scope, reuse=reuse):out = layers.fully_connected(input, num_units, tf.nn.relu)  # 第一层:64单元,ReLU激活out = layers.fully_connected(out, num_units, tf.nn.relu)    # 第二层:64单元,ReLU激活out = layers.fully_connected(out, num_outputs, None)        # 输出层:线性激活return out

结构示意图

输入层(obs_dim) -> 隐藏层(64) -> 隐藏层(64) -> 输出层(action_dim)

2. 环境创建 (make_env)

def make_env(scenario_name, arglist, benchmark=False):"""根据场景名称创建多智能体环境:param scenario_name: 场景脚本名称(如simple_tag):param arglist: 命令行参数:param benchmark: 是否为评估模式(影响环境是否返回基准数据)"""from multiagent.environment import MultiAgentEnvimport multiagent.scenarios as scenarios# 动态加载场景脚本(如simple_tag.py)scenario = scenarios.load(scenario_name + ".py").Scenario()world = scenario.make_world()  # 调用场景的make_world方法创建世界# 根据模式创建环境if benchmark:env = MultiAgentEnv(world, scenario.reset_world, scenario.reward, scenario.observation, scenario.benchmark_data)else:env = MultiAgentEnv(world, scenario.reset_world, scenario.reward, scenario.observation)return env

3. 智能体训练器初始化 (get_trainers)

def get_trainers(env, num_adversaries, obs_shape_n, arglist):"""为每个智能体创建对应的训练器(MADDPGAgentTrainer):param env: 环境对象:param num_adversaries: 对抗者数量(通过--num-adversaries指定):param obs_shape_n: 所有智能体的观测空间形状列表:param arglist: 命令行参数"""trainers = []model = mlp_model  # 使用的神经网络模型# 为对抗者创建训练器(使用adv-policy参数)for i in range(num_adversaries):trainers.append(MADDPGAgentTrainer(name="agent_%d" % i, model=model, obs_shape=obs_shape_n, act_space=env.action_space[i], agent_index=i, arglist=arglist,local_q_func=(arglist.adv_policy == 'ddpg')  # 若为DDPG则使用局部Q函数))# 为合作者创建训练器(使用good-policy参数)for i in range(num_adversaries, env.n):trainers.append(MADDPGAgentTrainer(name="agent_%d" % i, model=model, obs_shape=obs_shape_n, act_space=env.action_space[i], agent_index=i, arglist=arglist,local_q_func=(arglist.good_policy == 'ddpg')))return trainers

关键逻辑

  • num_adversaries 个Agent被标记为对抗者,使用 adv-policy 参数指定的算法。
  • 剩余Agent为合作者,使用 good-policy 参数。

4. 主训练循环 (train)

def train(arglist):with U.single_threaded_session():  # 创建TensorFlow单线程会话# 环境初始化env = make_env(arglist.scenario, arglist)obs_shape_n = [env.observation_space[i].shape for i in range(env.n)]# 训练器初始化(区分对抗者和合作者)num_adversaries = min(env.n, arglist.num_adversaries)trainers = get_trainers(env, num_adversaries, obs_shape_n, arglist)# TensorFlow变量初始化U.initialize()# 经验回放相关变量episode_rewards = [0.0]  # 累计奖励agent_rewards = [[0.0] for _ in range(env.n)]  # 每个Agent的独立奖励# 主循环obs_n = env.reset()episode_step = 0train_step = 0while True:# 1. 获取动作action_n = [agent.action(obs) for agent, obs in zip(trainers, obs_n)]# 2. 环境交互new_obs_n, rew_n, done_n, info_n = env.step(action_n)episode_step += 1# 3. 存储经验for i, agent in enumerate(trainers):agent.experience(obs_n[i], action_n[i], rew_n[i], new_obs_n[i], done_n[i], terminal)# 4. 更新观察状态obs_n = new_obs_n# 5. 累计奖励记录for i, rew in enumerate(rew_n):episode_rewards[-1] += rewagent_rewards[i][-1] += rew# 6. Episode终止判断if done or (episode_step >= arglist.max_episode_len):obs_n = env.reset()episode_step = 0episode_rewards.append(0)for a in agent_rewards:a.append(0)# 7. 网络更新(非评估模式下)if not (arglist.display or arglist.benchmark):for agent in trainers:agent.preupdate()  # 准备更新(如清空梯度)for agent in trainers:loss = agent.update(trainers, train_step)  # 执行MADDPG的Actor-Critic更新# 8. 定期保存模型if terminal and (len(episode_rewards) % arglist.save_rate == 0):U.save_state(arglist.save_dir, saver=saver)print(f"当前进度: {len(episode_rewards)} episodes, 平均奖励: {np.mean(episode_rewards[-arglist.save_rate:])}")# 9. 终止条件if len(episode_rewards) > arglist.num_episodes:# 保存最终奖励数据with open(os.path.join(arglist.plots_dir, f"{arglist.exp_name}_rewards.pkl"), 'wb') as f:pickle.dump(final_ep_rewards, f)break

关键问题解答:对抗者是否生效?

simple_tag.py 中定义的 num_adversaries = 3 需要与启动命令中的 --num-adversaries 3 匹配:

# 正确启动命令(必须显式指定)
python train.py --scenario simple_tag --num-adversaries 3 --good-policy maddpg --adv-policy maddpg
  • 若未指定:训练器会将所有Agent视为合作者,导致对抗者策略错误。
  • 正确指定时:第一个Agent使用对抗者策略,其余为合作者策略。

simple_tag文件

1. 场景基类与核心定义

from multiagent.core import World, Agent, Landmark
from multiagent.scenario import BaseScenarioclass Scenario(BaseScenario):"""多智能体对抗场景基类,继承自 BaseScenario核心功能:定义世界属性、智能体行为、奖励机制和观测空间"""

2. 世界构建方法 make_world

    def make_world(self):world = World()  # 创建世界对象# --- 世界属性设置 ---world.dim_c = 2  # 通信维度(智能体间传递信息的向量长度)# --- 智能体数量配置 ---num_good_agents = 1    # 合作者(绿色)数量num_adversaries = 3    # 对抗者(红色)数量num_agents = num_adversaries + num_good_agents  # 总智能体数 = 3+1=4num_landmarks = 1      # 地标(障碍物)数量# --- 初始化智能体 ---world.agents = [Agent() for i in range(num_agents)]  # 创建智能体列表for i, agent in enumerate(world.agents):agent.name = 'agent %d' % i      # 智能体名称(agent 0~3)agent.collide = True             # 是否允许碰撞(True=实体碰撞生效)agent.silent = True              # 是否静默(True=不发送通信信号)agent.adversary = True if i < num_adversaries else False  # 前3个为对抗者# --- 物理属性 ---agent.size = 0.075 if agent.adversary else 0.05  # 对抗者尺寸稍大agent.accel = 4.0   # 加速度(控制移动灵敏度的参数,值越大响应越快)agent.max_speed = 1.3  # 最大移动速度(单位:仿真环境坐标系/步)# !! 注意:以下代码存在问题,会导致覆盖已创建的智能体 !!# 正确做法应直接修改已存在智能体的属性,而非重新创建for i in range(num_adversaries):agent = Agent()  # 错误:这里重新创建了新的智能体实例agent.adversary = Trueagent.max_speed = 1.0 + 0.2 * i  # 意图差异化速度但未正确实现agent.accel = 3.0 + 0.5 * i# --- 地标(障碍物)初始化 ---world.landmarks = [Landmark() for i in range(num_landmarks)]for i, landmark in enumerate(world.landmarks):landmark.name = 'landmark %d' % ilandmark.collide = True   # 地标是否可碰撞(True=智能体会被阻挡)landmark.movable = False   # 地标是否可移动landmark.size = 0.2        # 地标尺寸(大于智能体尺寸,形成障碍)landmark.boundary = False  # 是否作为边界(False=普通障碍物)self.reset_world(world)  # 调用重置方法初始化状态return world

3. 世界重置方法 reset_world

    def reset_world(self, world):# --- 智能体颜色设置 ---for i, agent in enumerate(world.agents):# 对抗者红色 [0.85,0.35,0.35],合作者绿色 [0.35,0.85,0.35]agent.color = np.array([0.35,0.85,0.35]) if not agent.adversary else np.array([0.85,0.35,0.35])# --- 地标颜色设置(灰色)---for landmark in world.landmarks:landmark.color = np.array([0.25, 0.25, 0.25])# --- 随机初始位置与速度 ---for agent in world.agents:agent.state.p_pos = np.random.uniform(-1, +1, world.dim_p)  # 位置随机agent.state.p_vel = np.zeros(world.dim_p)  # 初始速度归零agent.state.c = np.zeros(world.dim_c)      # 通信信号归零# 地标随机位置(边界内)for landmark in world.landmarks:if not landmark.boundary:landmark.state.p_pos = np.random.uniform(-0.9, +0.9, world.dim_p)landmark.state.p_vel = np.zeros(world.dim_p)

4. 奖励函数设计

合作者奖励 agent_reward

    def agent_reward(self, agent, world):rew = 0  # 初始化奖励adversaries = self.adversaries(world)  # 获取所有对抗者# --- 碰撞惩罚 ---if agent.collide:for a in adversaries:if self.is_collision(a, agent):rew -= 10  # 被对抗者碰撞一次扣10分# --- 边界惩罚 ---def bound(x):""" 越界惩罚函数,防止智能体逃离战场 """if x < 0.9: return 0if x < 1.0: return (x - 0.9) * 10  # 接近边界时线性惩罚return min(np.exp(2 * x - 2), 10)   # 超出边界时指数惩罚for p in range(world.dim_p):x = abs(agent.state.p_pos[p])  # 检查每个坐标轴是否越界rew -= bound(x)return rew

对抗者奖励 adversary_reward

    def adversary_reward(self, agent, world):rew = 0agents = self.good_agents(world)  # 获取合作者(此处只有1个)# --- 基于距离的奖励塑形(可选)---if shape:  # 当shape=True时启用for adv in self.adversaries(world):# 计算与最近合作者的距离,距离越近奖励越高(负值越小)min_dist = min([np.linalg.norm(a.state.p_pos - adv.state.p_pos) for a in agents])rew -= 0.1 * min_dist# --- 捕获奖励 ---if agent.collide:for ag in agents:if self.is_collision(ag, agent):rew += 10  # 成功捕获合作者加10分return rew

5. 观测空间构建 observation

    def observation(self, agent, world):# --- 实体位置(相对坐标)---entity_pos = []for entity in world.landmarks:  # 地标位置(障碍物)if not entity.boundary:entity_pos.append(entity.state.p_pos - agent.state.p_pos)# --- 其他智能体信息 ---comm = []      # 通信信号(本场景未使用)other_pos = []  # 其他智能体相对位置other_vel = []  # 其他智能体速度(仅合作者)for other in world.agents:if other is agent: continue  # 排除自身comm.append(other.state.c)other_pos.append(other.state.p_pos - agent.state.p_pos)if not other.adversary:  # 只记录合作者的速度other_vel.append(other.state.p_vel)# 合并观测向量:[自身速度, 自身位置, 地标位置, 其他智能体位置, 合作者速度]return np.concatenate([agent.state.p_vel] + [agent.state.p_pos] + entity_pos + other_pos + other_vel)

10.效果图(后续再补充)

实验配置:

6围捕2,障碍物:2

--num-episodes 20000 --max-episode-len 25 --lr 5e-5,其余默认

training_curve

per_agent_training_curve

success_rate_curve

safe_output170

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

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

相关文章

Windows 提权-内核利用_1

本文通过 Google 翻译 Kernel Exploits Part 1 – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充。导航0 前言 1 旧版 Windows 系统内核利用 2 搜寻内核漏洞2.1 枚举内核利用 - 手动 2.2 枚举内核利用 - 自动…

探秘Transformer系列之(12)--- 多头自注意力

从零开始解析Transformer,目标是:(1) 解析Transformer如何运作,以及为何如此运作,让新同学可以入门;(2) 力争融入一些比较新的或者有特色的论文或者理念,让老鸟也可以有所收获。探秘Transformer系列之(12)--- 多头自注意力 目录探秘Transformer系列之(12)--- 多头自注…

设备与onenet服务器之间的mqtt通讯

设备与onenet服务器之间的通讯 1. 登录onenet平台2.创建产品3.设备管理 1)创建两个进行测试功能4.MQTTfx测试password计算工具官网下载:OneNET - 中国移动物联网开放平台1)订阅属性上报结果通知消息 Subscribe的topic: $sys/改成自己的产品ID/改成自己的设备名称/thing/pro…

设计一个优秀 API 的秘诀

本指南深入探讨了顶级 API 设计,强调了它不仅仅是代码的集合。一个设计良好的 API 就像五星级礼宾服务,能够顺畅地引导用户达到他们的预期目标。拿起一杯咖啡,让我们一起探索创建一个功能强大、用户友好的 API 的秘诀吧! 理解 API 基础第一步:拥抱 REST - API 设计的基础 …

T428497 请不要抢走爱丽丝的工作! 题解

T428497 请不要抢走爱丽丝的工作! 题解题目传送门 本题要求扫地机器人半径 \(r\) 的最大值,既然要求最大值,容易想到二分答案。 那问题就转换为给定半径 \(R\) , 判断 \(R\) 满不满足条件,也就是能不能找到一条绕过所有障碍的路径。让我们逆转一下思维,考虑哪些区域是机器…

个人作业:软件案例分析

个人作业:软件案例分析项目 内容这个作业属于哪个课程 首页 - 2025年春季软件工程(罗杰、任健) - 北京航空航天大学 - 班级博客 - 博客园这个作业的要求在哪里 [I.2] 个人作业:软件案例分析我在这个课程的目标是 学习软件开发流程,完成一次完整的软件开发经历,提高开发和…

API 调试与管理工具选型思考:Apifox vs Apipost,企业究竟该如何选择

在企业级 API 调试与管理场景中,选择一款高效的工具至关重要。市面上的调试工具琳琅满目,而 Apifox 和 Apipost 是近几年两款备受开发者关注的 API 工具。二者都宣称为团队协作和接口调试赋能,但对企业来说,究竟谁才是更适合的选择呢?本文将从功能对比、用户体验、企业适配…

pos_cli 命令是如何运行起来的

追踪pos_cli --dump --dir /root/ckpt --pid [your program pid] 是如何运行的 pos_cli是通过mason,由sources包括的这些文件构建而来 #pos/cli/meson.buildproject_name = phoenix_os_cli project_name_abbreviation = pos_cli scan_src_path = meson.current_source_dir() +…

Tavus 发布对话轮次控制模型:能理解对话节奏和意图;百度推出 AI 情感陪伴应用月匣,整合 MiniMax 等模型丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

clickhouse 25.2.1 集群部署

依赖条件 sysctl.conf echo "kernel.threads-max = 262144" >> /etc/sysctl.conf && sysctl -p Huge Pages(按需修改) 编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 参数中添加: GRUB_CMDLINE_LINUX="... transparent_hugepage=never"…

可视化图解算法:链表指定区间反转

对于链表的相关操作,我们总结了一套【可视化+图解】方法,依据此方法来解决链表相关问题,链表操作变得易于理解,写出来的代码可读性高也不容易出错。1. 题目 描述 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 …

ov5640原理讲解

Camera开发-OV5640(MIPI)-CSDN博客