1. 项目概述当大模型学会“动手”SkillZero如何重塑具身智能最近在具身智能的圈子里SkillZero这个名字被讨论得挺多。简单来说这是一个让大型语言模型LLM学会“动手”执行物理世界任务的框架。听起来有点科幻但它的核心思路其实很接地气我们不再需要为机器人编写成千上万条死板的指令而是让一个“大脑”LLM去理解任务目标然后自己规划、尝试、反思最终学会如何操作。这就像教一个孩子搭积木你不需要告诉他“左手拿起红色方块向前移动10厘米旋转30度”你只需要说“搭一座桥”他会自己摸索怎么拿、怎么放、怎么调整。SkillZero做的就是这件事它让LLLMs具备了在模拟或真实环境中通过自主探索来获取和精炼技能的能力。这个项目解决的核心痛点是传统机器人编程或模仿学习的局限。传统方法要么依赖大量、精确的示教数据成本高昂且泛化性差要么规则僵硬无法应对复杂多变的环境。而SkillZero的思路是“授人以渔”赋予模型自主学习和适应能力。它特别适合那些任务目标明确但实现路径复杂、不确定的场景比如在杂乱的书桌上找到特定的钥匙并插入锁孔或者根据口头指令重新布置房间里的家具。对于机器人研究者、强化学习工程师或者任何对“AI如何与物理世界交互”感兴趣的人来说理解SkillZero都极具价值。接下来我会拆解它的核心设计、实操细节并分享在复现和实验过程中的一些真实心得。2. 核心架构与设计哲学拆解SkillZero的命名就很有意思“Skill”代表技能“Zero”暗示其从零开始学习的能力类似于强化学习中的“Zero-shot”或“从零训练”概念。但它的内核并非纯粹的强化学习而是一种基于大模型推理的元学习框架。2.1 三层循环学习机制规划、执行与反思SkillZero的核心是一个三层循环结构这构成了其自主学习的引擎。理解这个结构是理解其所有工作的基础。第一层是高层任务规划。当模型接收到一个自然语言指令例如“把红色的杯子放到桌子左上角”后它不会直接生成电机扭矩指令。相反它首先进行任务分解。这个分解过程完全由LLM驱动模型会基于其对物理常识和任务上下文的理解将复杂任务拆解为一系列原子技能Skill Primitives序列。比如上述任务可能被分解为[“定位红色杯子” “移动到杯子附近” “抓取杯子” “移动到桌子左上角” “放置杯子”]。这些原子技能是预先定义好的、相对通用的基础动作比如move_to(position),grasp(object),place(position)等。这一步的关键在于LLM利用了其庞大的知识库来理解“红色”、“杯子”、“左上角”这些概念在具体环境中的指代并推理出合理的动作顺序。第二层是技能参数化与执行。规划层输出的是技能类型序列但每个技能需要具体的参数才能执行。例如move_to(position)中的position是一个三维坐标。SkillZero在这里引入了一个精妙的“参数化”过程。它再次调用LLM但这次结合了当前的环境观测比如来自摄像头的图像或者模拟器中的状态描述。LLM需要根据视觉信息或状态描述将抽象的“红色杯子”转化为环境中的具体坐标[x, y, z]或者将“桌子左上角”转化为一个可操作的位置。这个过程是动态的因为环境可能变化杯子被移动了。参数化完成后技能就被发送到底层的控制器可能是一个简单的PID控制器或者一个训练好的技能策略网络去执行。第三层也是最体现其智能的一层是技能执行后的反思与精炼。这是SkillZero实现“学习”的关键。一个技能执行后系统会观察结果成功还是失败如果失败原因是什么是参数不准没对准杯子还是技能选择不当该用“抓取”却用了“推动”此时LLM第三次被调用扮演“反思者”的角色。它接收任务描述、已执行的技能序列、环境反馈如“抓取动作执行但目标物体未移动”然后分析失败原因并提出修正方案。修正方案可能包括调整下一个技能的参数“下次抓取时夹爪应再向左偏移2厘米”甚至回溯修改高层的技能规划序列“在抓取前需要先推开挡在前面的书本”。这个反思-修正的循环会持续进行直到任务完成或达到尝试次数上限。注意这个三层循环并不是串行执行一次就结束的。它是一个在任务执行过程中持续运转的闭环。每一次技能执行后的反馈都可能触发对后续规划的微调甚至是对已执行但效果不佳的技能进行“重试”并更新其参数。这使得SkillZero具备了一种在线学习和适应能力。2.2 为什么选择LLM作为核心“大脑”你可能会问为什么一定要用LLM传统的符号规划器或者学习到的策略网络不行吗这涉及到SkillZero设计哲学中最根本的一点利用LLM的常识和推理能力来弥补纯数据驱动方法的不足。首先泛化性与零样本学习。LLM在训练过程中吸收了海量的文本和代码数据其中蕴含了丰富的物理常识、物体属性和空间关系知识。当遇到一个前所未见的新物体或新场景描述时基于规则的系统可能完全无法处理但LLM可以基于语义相似性进行推理。例如指令是“把那个圆柱形的金属罐子拿过来”即使训练数据里没有“金属罐子”这个具体名词LLM也能从“圆柱形”、“金属”这些属性推断出它可能是一个坚硬、可抓取的物体并类比“杯子”或“罐子”来规划动作。这是传统方法难以企及的。其次复杂指令的理解与分解。自然语言指令往往是模糊和多义的。“把客厅收拾一下”这样的指令对于机器人来说是极其复杂的。LLM可以将其分解为“捡起地上的玩具”、“把书放回书架”、“把靠垫摆正”等一系列子任务并推断出合理的执行顺序。这种高层语义理解和逻辑推理能力是目前专用模型所缺乏的。最后反思与解释能力。当任务失败时LLM不仅能提出修正方案还能生成人类可理解的失败原因解释比如“抓取失败是因为夹爪被书本挡住了视线”。这极大地便利了调试和信任建立。相比之下一个深度强化学习策略网络输出一个失败动作我们很难理解它“为什么”这么做。当然依赖LLM也有代价主要是推理速度慢和决策可能不符合物理规律。SkillZero通过将LLM的调用限制在高层规划和反思环节而将快速、低级的控制交给传统控制器在一定程度上缓解了速度问题。对于物理不合理性则通过环境反馈和反思循环来纠正。3. 实操部署与环境搭建详解要真正理解SkillZero最好的方式就是动手把它跑起来。这里我以在模拟环境如PyBullet或RoboSuite中复现一个简单任务为例拆解从环境准备到运行的全过程。我会分享一些官方文档可能没写的细节和坑。3.1 基础环境与依赖安装SkillZero通常需要Python 3.8的环境。第一步是创建虚拟环境这是保持环境纯净的好习惯。conda create -n skillzero python3.8 conda activate skillzero核心依赖主要包括三大块深度学习框架、物理模拟器、以及大模型访问接口。深度学习框架PyTorch是主流选择。根据你的CUDA版本安装对应的PyTorch。# 例如对于CUDA 11.3 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu113物理模拟器PyBullet是一个轻量级、功能强大的选择非常适合研究和快速原型开发。pip install pybullet如果需要更逼真的渲染或特定机器人模型可以考虑Isaac Gym或MuJoCo但配置会更复杂。大模型接口SkillZero需要与LLM交互。你可以使用OpenAI的API方便但需要网络和费用或者在本地部署开源模型如Vicuna, Llama 2/3。使用OpenAI APIpip install openai然后在代码中设置你的API密钥。本地部署以使用transformers库调用Hugging Face模型为例pip install transformers accelerate这将允许你在本地加载如meta-llama/Llama-2-7b-chat-hf这类模型。注意你需要有相应的模型使用权限并且需要足够的GPU内存。SkillZero本体从GitHub克隆仓库并安装。git clone https://github.com/ZJU-REAL/SkillZero.git cd SkillZero pip install -e . # 以可编辑模式安装方便修改代码实操心得在安装pybullet时如果遇到权限问题可以尝试使用--user标志。对于本地LLM部署7B参数的模型是起步要求但为了更好的推理能力建议使用13B或更大模型。这直接关系到规划与反思的质量。务必先单独测试你的LLM接口API或本地能否正常工作再集成到SkillZero中否则调试起来会非常头疼。3.2 模拟环境与机器人模型配置SkillZero需要一个具体的“世界”来练习技能。我们以PyBullet中一个经典的桌面操作场景为例。创建场景在PyBullet中你需要初始化物理引擎、加载地面、设置重力。然后加载一张桌子、一个方块作为杯子和一个机械臂模型如Franka Panda或UR5。import pybullet as p import pybullet_data # 连接物理引擎 physicsClient p.connect(p.GUI) # 用p.DIRECT则不显示图形界面更快 p.setAdditionalSearchPath(pybullet_data.getDataPath()) p.setGravity(0, 0, -9.8) # 加载地面和桌子 planeId p.loadURDF(plane.urdf) tableId p.loadURDF(table/table.urdf, basePosition[0.5, 0, 0]) # 加载一个立方体作为目标物体 cubeId p.loadURDF(cube_small.urdf, basePosition[0.7, 0, 0.65]) # 加载Franka Panda机械臂 robotId p.loadURDF(franka_panda/panda.urdf, basePosition[0, 0, 0], useFixedBaseTrue)这段代码构建了一个简单的世界地面、一张桌子、桌子上有一个方块以及一个机械臂。定义原子技能这是SkillZero与具体环境绑定的关键。你需要用代码实现每个原子技能。例如一个最简单的move_to技能可能通过逆运动学IK计算关节角度然后控制机械臂末端执行器移动到指定位置。class MoveToSkill: def __init__(self, robot_id): self.robot_id robot_id # ... 初始化逆运动学求解器等 def execute(self, target_position): # 1. 获取当前末端位姿 # 2. 计算到目标位置的轨迹或直接计算目标关节角 # 3. 通过位置控制或力矩控制驱动机械臂 # 4. 返回执行结果成功/失败以及可能的反馈信息 pass同样你需要实现grasp,place,open_gripper,close_gripper等技能。每个技能的execute方法应返回一个结构化的结果字典包含成功标志和描述性信息供反思环节使用。封装环境接口SkillZero需要一个统一的接口来获取环境观测和执-行技能。观测通常包括机械臂关节状态、末端位姿、摄像头图像或从图像中提取的目标物体边界框和位置、以及任务相关的信息。你需要编写一个Environment类提供get_observation()和execute_skill(skill_name, parameters)方法。3.3 LLM提示词工程与集成SkillZero的性能极大程度上依赖于给LLM的提示词Prompt设计。通常需要设计三种提示词模板任务规划提示词、技能参数化提示词、反思提示词。任务规划提示词引导LLM将自然语言指令分解为技能序列。你是一个机器人任务规划器。请将以下指令分解为一系列可执行的原子技能。 可用的原子技能有[move_to, grasp, place, open_gripper, close_gripper]。 技能描述 - move_to(position): 移动机械臂末端到指定三维坐标位置。 - grasp(object): 在当前位置执行抓取动作。 - place(position): 在指定位置执行放置动作。 - open_gripper(): 打开夹爪。 - close_gripper(): 关闭夹爪。 指令{instruction} 当前环境观测{observation} 例如桌子上有一个红色方块在坐标(0.7, 0, 0.65)处 请以JSON格式输出包含一个skill_sequence字段值为技能名称的列表。 只输出JSON不要有其他内容。这个提示词明确了角色、可用技能、技能含义并给出了结构化输出的要求。技能参数化提示词引导LLM根据观测将抽象技能转化为具体参数。你是一个机器人参数生成器。请根据当前环境观测为指定的技能生成具体的参数值。 当前技能{skill_name} 环境观测{observation} 例如RGB图像或物体位置列表[(0.7, 0, 0.65, red_cube)] 任务上下文我们要完成的任务是“{instruction}”。 请为技能 {skill_name} 生成参数。例如如果技能是 move_to参数应为 {position: [x, y, z]}。 只输出一个JSON对象包含参数键值对。这里的关键是让LLM学会从观测尤其是视觉信息中“理解”空间并量化。对于复杂场景可能需要结合视觉语言模型VLM先进行物体检测和描述。反思提示词引导LLM分析失败原因并给出建议。你是一个机器人任务反思专家。刚才的执行尝试失败了。 任务目标{instruction} 已执行的技能序列{executed_skills} 每个技能包含名称和参数 环境反馈{feedback} 例如“执行grasp后目标物体未移动夹爪闭合时检测到力传感器数值低” 请分析可能失败的原因并给出后续建议。建议可以包括 1. 调整下一个待执行技能的参数如移动位置、抓取角度。 2. 在现有序列中插入新的技能如先推开障碍物。 3. 回溯并替换之前某个不合适的技能。 请以JSON格式输出包含analysis原因分析和suggestion具体建议字段。反思提示词的质量直接决定了系统能否从错误中学习。反馈信息需要设计得尽可能具有信息量。踩坑记录提示词的设计需要反复迭代和测试。一个常见问题是LLM的输出格式不稳定有时会多出解释性文字破坏JSON解析。解决方法是在提示词中强烈强调“只输出JSON”并在代码中加入健壮的解析和重试机制。另一个坑是LLM对空间坐标的“理解”是模糊的它可能生成超出工作空间范围的坐标。必须在技能执行层加入安全检查和边界限制。4. 核心循环代码实现与调试环境搭好后我们需要实现SkillZero的主循环。这个循环将上述所有组件串联起来。4.1 主循环逻辑实现下面是主循环的简化伪代码展示了整个流程class SkillZeroAgent: def __init__(self, llm_client, env, skill_library): self.llm llm_client self.env env self.skills skill_library # 存放所有技能实例的字典 def run_task(self, instruction, max_steps20): observation self.env.get_observation() skill_sequence self.plan(instruction, observation) for step in range(max_steps): if not skill_sequence: print(任务规划完成或为空。) break current_skill_name skill_sequence[0] # 参数化 parameters self.parameterize(current_skill_name, observation, instruction) # 执行 execution_result self.execute_skill(current_skill_name, parameters) if execution_result[success]: # 技能成功从序列中移除获取新观测 skill_sequence.pop(0) observation self.env.get_observation() if not skill_sequence: print(任务成功完成) break else: # 技能失败进行反思 print(f技能 {current_skill_name} 执行失败。) reflection self.reflect(instruction, skill_sequence, execution_result[feedback]) print(f反思分析{reflection[analysis]}) print(f反思建议{reflection[suggestion]}) # 根据反思建议更新技能序列或参数 updated_plan self.update_plan_based_on_reflection(skill_sequence, reflection, current_skill_name) skill_sequence updated_plan # 注意失败后可能不更新观测或者更新为失败后的观测取决于策略 return step max_steps # 返回是否成功 def plan(self, instruction, obs): prompt self._build_planning_prompt(instruction, obs) response self.llm.generate(prompt) plan self._parse_json_response(response, skill_sequence) return plan def parameterize(self, skill_name, obs, instruction): prompt self._build_parameterization_prompt(skill_name, obs, instruction) response self.llm.generate(prompt) params self._parse_json_response(response) return params def execute_skill(self, skill_name, params): skill_instance self.skills[skill_name] return skill_instance.execute(params) def reflect(self, instruction, executed_skills, feedback): prompt self._build_reflection_prompt(instruction, executed_skills, feedback) response self.llm.generate(prompt) reflection self._parse_json_response(response, [analysis, suggestion]) return reflection这个SkillZeroAgent类封装了核心逻辑。run_task方法启动了“规划-参数化-执行-反思”的循环。循环的退出条件是任务成功技能序列清空或达到最大尝试步数。4.2 关键函数实现细节与避坑指南_parse_json_response函数这是与LLM交互最脆弱的一环。LLM的回复可能包含Markdown代码块、额外的换行或文字。一个健壮的解析器需要处理这些情况。import json import re def _parse_json_response(self, llm_text, expected_keysNone): # 尝试提取JSON部分 json_match re.search(rjson\n(.*?)\n, llm_text, re.DOTALL) if json_match: json_str json_match.group(1) else: # 如果没有代码块尝试直接查找第一个{和最后一个} start llm_text.find({) end llm_text.rfind(}) 1 if start ! -1 and end ! 0: json_str llm_text[start:end] else: # 如果连大括号都找不到返回空或重试 return None try: data json.loads(json_str) if expected_keys: if isinstance(expected_keys, str): if expected_keys not in data: raise KeyError(fKey {expected_keys} not found in response.) else: # list for key in expected_keys: if key not in data: raise KeyError(fKey {key} not found in response.) return data except json.JSONDecodeError as e: print(fJSON解析失败: {e}. 原始文本: {json_str}) # 可以在这里加入重试逻辑或者返回一个默认值 return None这个函数首先尝试匹配Markdown的JSON代码块如果失败则尝试直接提取大括号内的内容。解析失败时根据策略可以选择让LLM重试、使用默认值或抛出异常。update_plan_based_on_reflection函数这是系统的“学习”体现。反思建议可能是多种类型的需要不同的处理策略。def update_plan_based_on_reflection(self, current_plan, reflection, failed_skill): suggestion reflection[suggestion].lower() new_plan current_plan.copy() if adjust parameter in suggestion or 偏移 in suggestion: # 建议调整参数这里简化处理通常需要解析建议中的具体偏移量 # 在实际中可能需要再次调用参数化LLM或者根据规则微调。 # 例如如果建议“向右偏移2cm”我们可以修改下一个move_to技能的x坐标。 print(根据建议调整后续技能参数。) # ... 参数调整逻辑 elif insert in suggestion or 插入 in suggestion: # 建议插入新技能例如在抓取前插入一个“推开障碍物” # 需要从建议文本中提取要插入的技能名这可能需要一个额外的LLM调用或规则匹配。 print(根据建议在序列中插入新技能。) # ... 技能插入逻辑 elif replace in suggestion or 替换 in suggestion: # 建议替换技能例如将“抓取”替换为“吸附” print(根据建议替换技能。) # ... 技能替换逻辑 else: # 默认策略重试当前失败技能可能伴随微小随机扰动 print(未识别明确建议准备重试当前技能。) # 可以选择给当前技能的参数添加一个小的随机噪声以探索不同参数 return new_plan处理自然语言建议是极具挑战性的。一个更高级的实现是让另一个LLM专门负责将文本建议转化为具体的计划修改操作。技能执行中的反馈设计execution_result[feedback]至关重要。它不能只是“成功/失败”的布尔值。好的反馈应该包含可解释的、信息丰富的描述帮助LLM进行反思。例如对于move_to反馈可以包含“末端执行器最终位置与目标位置的欧氏距离为0.02m”而不仅仅是“是否到达”。对于grasp反馈可以包含“夹爪闭合后的宽度”、“夹爪上的力传感器读数”、“目标物体在抓取后是否移动”。例如{success: False, feedback: 夹爪力传感器读数低于阈值疑似未接触到物体。}调试技巧在开发初期不要急于让整个循环跑通。应该分模块测试。首先用固定的技能序列和参数测试你的底层技能控制器是否工作正常。然后用预设的规划序列测试主循环逻辑。接着模拟LLM的返回用硬编码的JSON来测试参数化和反思逻辑。最后再接入真实的LLM。使用p.connect(p.GUI)并添加调试绘图如绘制目标点可以直观地看到机器人的行为是快速定位问题的不二法门。5. 性能优化与高级技巧当基础版本跑通后你会面临效率和质量的问题。以下是一些提升SkillZero实战能力的进阶思路。5.1 加速LLM推理与降低成本LLM调用是主要瓶颈。有几种优化策略提示词压缩与缓存规划、参数化、反思的提示词中环境观测尤其是图像描述可能很长。可以尝试用更紧凑的方式表示观测例如只提取与当前任务相关的物体信息和其边界框坐标而不是完整的自然语言描述。对于重复或相似的子任务可以缓存LLM的响应。使用更小的专用模型对于参数化这种相对简单的任务将“红色杯子”映射为坐标可能不需要GPT-4级别的模型。可以尝试用更小、更快的模型如7B参数的开源模型或者为参数化任务专门微调一个小模型。异步与批处理如果环境模拟允许可以在当前技能执行时就让LLM开始规划下一个技能或反思当前技能进行异步推理。分层技能抽象如果原子技能move_to本身也很复杂需要路径规划可以将其内部再封装一层。让LLM只规划到“移动到A点”而具体的轨迹由下层控制器解决避免LLM处理过于底层的细节。5.2 提升技能执行的成功率LLM的规划可能不靠谱底层控制也可能失败。需要从两方面加固技能库的丰富与鲁棒性增加感知验证技能在执行关键操作前如抓取插入一个verify_position技能用摄像头确认目标物体确实在夹爪前方。设计恢复技能如wiggle轻微晃动用于摆脱卡死retreat后退用于从失败接触中恢复。技能参数化加入噪声对于需要精确对位的技能可以在LLM给出的参数基础上加入一个小的随机搜索范围执行多次尝试选择最成功的一次。改进反思机制多轮反思与投票让LLM对同一个失败进行多次反思然后综合或投票选择最好的建议避免单次反思的偶然性。利用历史经验建立一个外部记忆库记录过去任务的成功/失败轨迹技能序列、参数、结果。在新的任务规划或反思时让LLM检索相似的历史案例作为参考实现“经验”的复用。引入数值反馈的规则修正对于某些明确的失败如“力传感器读数低”可以不用LLM反思直接由规则处理如“将抓取位置沿Z轴向下微调1厘米后重试”。5.3 从模拟到现实的挑战在模拟器中运行良好不代表在真实机器人上也能工作。这里有几道必须跨越的鸿沟感知差距模拟器可以提供完美的物体位姿ground truth但真实世界需要靠摄像头、深度传感器去估计。你需要将SkillZero中的观测获取模块从读取模拟器API替换为运行真实感知流水线如YOLO物体检测RGB-D相机点云获取位姿。LLM的参数化提示词也需要适配从“物体列表”变为“检测到的边界框和类别置信度”。控制差距模拟器中的机器人模型是理想的真实机器人有延迟、抖动、校准误差。你的原子技能如move_to在现实中需要用更鲁棒的控制算法如阻抗控制来实现并且要加入更严格的安全限制如关节限位、碰撞检测。不确定性处理真实世界充满不确定性。物体可能被遮挡、光照会变化、抓取会滑落。SkillZero的反思循环需要变得更频繁、更敏感。你可能需要在每一个技能执行后都进行一个轻量级的“效果验证”而不是等到整个子任务失败。个人体会在真实机器人上部署SkillZero这类框架仿真到现实Sim2Real的技术至关重要。一个有效的策略是在仿真中训练一个鲁棒的底层技能策略例如一个能适应一定位置误差的抓取策略网络然后将这个策略迁移到真实机器人上作为SkillZero的grasp技能。这样LLM负责高层规划和适应性的参数生成而鲁棒的底层技能负责应对执行中的微小误差。这比完全依赖LLM生成底层动作指令要可靠得多。6. 典型问题排查与实战心得在实际运行SkillZero或类似框架时你会遇到各种各样的问题。下面是一个常见问题速查表基于我自己的踩坑经验整理。问题现象可能原因排查步骤与解决方案LLM输出格式错误无法解析JSON1. 提示词未严格限定输出格式。2. LLM特别是小模型遵循指令能力弱。3. 输出中包含额外思考过程。1. 在提示词开头和结尾用###等符号强调格式要求。2. 在代码中实现更健壮的解析如前述正则提取。3. 使用思维链Chain-of-Thought提示明确要求模型“先思考再将最终答案以JSON格式输出”。4. 考虑使用LLM的“JSON mode”如果API支持。技能执行永远失败机器人不动或乱动1. 技能参数如坐标超出机器人工作空间或物理不合理。2. 底层控制器如逆运动学求解器失败。3. 仿真环境时间步或控制频率设置不当。1. 在技能执行前加入参数校验和规范化模块。2. 为move_to等技能实现关节空间路径规划而不是直接给目标点。3. 检查逆运动学求解是否返回有效解若无解则触发反思。4. 调整仿真步长确保控制指令能被稳定执行。反思循环陷入死循环反复尝试同一错误1. 反思提示词未能引导LLM找到真正原因。2. 环境反馈信息不足或噪声太大。3. 更新计划的逻辑有缺陷未能有效改变行为。1. 丰富反馈信息提供更多传感器数据如距离、力、图像片段描述。2. 在反思提示词中要求模型考虑“与上一次尝试不同的方案”。3. 实现“重试计数器”对同一技能失败超过N次后强制采取备用方案如换一种技能。4. 引入随机性在重试时对参数加入探索噪声。任务分解不合理步骤冗余或逻辑错误1. LLM对任务或技能的理解有偏差。2. 可用技能库定义不清晰或不够用。1. 在规划提示词中提供更详细的技能描述和成功案例。2. 在技能库中增加更复合的宏技能Macro Skill如pick_and_place(object, destination)降低规划复杂度。3. 对LLM的规划结果进行后处理合并连续的move_to操作。运行速度极慢无法完成复杂任务1. LLM API调用延迟高。2. 模拟渲染或物理计算耗时。3. 反思循环过于频繁。1. 考虑使用本地量化模型或异步调用API。2. 在不需可视化调试时使用p.DIRECT模式连接PyBullet。3. 并非每次失败都需要反思可以设定一个置信度阈值只有低置信度的失败才触发深度反思。4. 将长时间运行的任务分解为可保存和加载的检查点。最后再分享一个小技巧在项目初期不要追求全自动和完美。建立一个“人机协作”模式非常有用。例如让LLM生成规划序列后先展示给人看确认无误后再执行。或者在反思环节将LLM的分析和建议呈现给人由人来做最终决策。这不仅能帮你快速验证框架流程还能收集高质量的人类决策数据用于后续微调LLM或训练一个模仿学习策略。SkillZero代表的是一种范式它的强大之处在于将人类的常识通过LLM与机器的精确控制结合起来而在这个结合过程中人暂时还无法完全离开这个循环。