智能体技能系统设计:从概念到工程实践

1. 从"agent-skills"这个命名说起:它到底指什么

第一次看到"agent-skills"这个词,很多人会下意识地把它理解成某个具体的库或者框架。但如果你真的去翻一圈资料,会发现它更像是一个概念性的命名——描述的是"智能体所具备的技能集合"这件事本身。换句话说,它不是一个能pip install就完事的包,而是一类问题的统称:如何让一个智能体(agent)拥有可复用、可组合、可扩展的能力模块。

我在实际做智能体相关项目的时候,最头疼的从来不是"能不能调用大模型",而是"这个智能体到底会干什么、干得好不好、下次遇到类似任务能不能复用"。这三个问题,恰好就是 agent-skills 要解决的核心。它关注的不是单次对话的质量,而是能力的沉淀与编排。

打个比方,大模型本身像是一个刚毕业、知识面很广但没什么实操经验的年轻人。你让他写一段文案,他能写;你让他查个数据,他也能凑合。但如果你要他"每天早上自动汇总昨天的销售数据、生成图表、写一段分析、再发到群里",他就懵了——因为这需要一串技能按顺序组合起来,还需要每一步都能稳定复现。agent-skills 要做的,就是把这些"技能"拆出来、定义清楚、再组装回去。

所以这篇文章适合谁看?如果你正在做智能体应用、想让自己的 agent 从"玩具"变成"能干活的工具",或者你只是好奇"智能体技能"这个概念到底怎么落地,那接下来的内容应该对你有用。我会从概念拆解讲到目录结构设计,再讲到技能注册、编排、调试和踩坑,尽量把每个环节的"为什么"讲透。

需要先说明一点:agent-skills 目前并没有一个官方统一的强制标准,不同团队、不同框架下的实现差异很大。我下面讲的内容,是基于常见的工程实践总结出来的一套通用思路,你可以把它当成设计参考,而不是唯一答案。

2. 拆解 agent-skills 的核心构成:技能、注册表与执行器

要理解 agent-skills,得先把它拆成几个基本零件。我习惯把它分成三层:技能单元(Skill)、技能注册表(Registry)、技能执行器(Executor)。这三层各司其职,缺一不可。

2.1 技能单元:一个技能应该长什么样

一个"技能"最朴素的定义是:输入 → 处理 → 输出。但真正落地的时候,光有这三样是不够的。我见过太多人把技能写成一个裸函数,结果用起来各种别扭。一个合格的技能单元,通常需要包含这些字段:

  • name:技能的唯一标识,建议用动词开头,比如fetch_weather、summarize_text,而不是weather这种名词。
  • description:给模型看的自然语言描述。这一项极其关键,因为智能体决定"要不要用这个技能"时,靠的就是这段描述。
  • parameters:参数的 schema 定义,包括类型、是否必填、默认值、取值范围。
  • handler:真正的执行逻辑。
  • returns:返回值的结构说明,方便下游技能消费。

为什么 description 这么重要?因为在大模型驱动的智能体里,技能的选择往往是通过"把技能列表塞进 prompt,让模型自己挑"来实现的。描述写得含糊,模型就会挑错技能,或者该用的时候不用。我踩过的坑是:早期把描述写成"获取天气信息",结果模型在用户问"今天出门要不要带伞"时,居然没调用它——因为它没意识到"带伞"和"天气"有关。后来把描述改成"查询指定城市的实时天气,包括温度、降水概率、风力,用于判断出行是否需要雨具",命中率立刻上来了。

2.2 技能注册表:让技能可被发现

注册表的作用是集中管理所有可用技能。它解决的问题是:智能体怎么知道"我现在有哪些技能可以用"?

最简单的注册表就是一个字典,key 是技能名,value 是技能对象。但工程上更推荐做成一个类,支持动态注册和查询:

class SkillRegistry: def __init__(self): self._skills = {} def register(self, skill): if skill.name in self._skills: raise ValueError(f"技能 {skill.name} 已存在") self._skills[skill.name] = skill def get(self, name): return self._skills.get(name) def list_all(self): return list(self._skills.values()) def describe_all(self): return [ { "name": s.name, "description": s.description, "parameters": s.parameters, } for s in self._skills.values() ]

这里有个细节值得说:describe_all返回的是给模型看的精简版,不包含 handler。因为 handler 是代码,塞进 prompt 既浪费 token 又没意义。这个"对内对外两套视图"的设计,是我觉得注册表最容易被忽略但最有价值的地方。

2.3 技能执行器:把模型的选择变成真实动作

执行器负责接收模型给出的"技能名 + 参数",找到对应技能并执行,然后把结果返回给模型。它要处理的事情比想象中多:

  • 参数校验:模型生成的参数经常有类型错误,比如该传数字传了字符串。
  • 异常捕获:技能执行失败不能直接崩掉整个流程,要返回结构化错误。
  • 超时控制:某些技能(比如网络请求)可能卡住,必须有超时。
  • 结果序列化:返回值要能转成模型看得懂的格式。

我一般会把执行器写成这样:

import json class SkillExecutor: def __init__(self, registry, timeout=10): self.registry = registry self.timeout = timeout def execute(self, name, params): skill = self.registry.get(name) if not skill: return {"error": f"未知技能: {name}"} try: validated = skill.validate(params) result = skill.handler(**validated) return {"result": result} except Exception as e: return {"error": str(e), "skill": name}

注意validate这一步。很多人图省事直接handler(**params),结果模型传了个多余参数就报TypeError。加一层校验,把错误在进入业务逻辑前拦下来,能省掉大量调试时间。

3. 技能注册与编排的实操路径:从零搭一个能跑的最小系统

光讲概念没意思,我们直接搭一个最小可运行的系统。目标很简单:让智能体能根据用户输入,自动选择并组合技能完成任务。我会用"查天气 + 生成出行建议"这个场景来演示。

3.1 定义两个基础技能

先写两个技能,一个查天气,一个生成建议。为了不依赖外部服务,查天气这里用模拟数据:

class Skill: def __init__(self, name, description, parameters, handler): self.name = name self.description = description self.parameters = parameters self.handler = handler def validate(self, params): # 简化版校验:只检查必填项 required = [k for k, v in self.parameters.items() if v.get("required")] for key in required: if key not in params: raise ValueError(f"缺少必填参数: {key}") return params weather_skill = Skill( name="fetch_weather", description="查询指定城市的实时天气,返回温度、降水概率和风力,用于判断出行是否需要雨具", parameters={ "city": {"type": "string", "required": True, "desc": "城市名称"} }, handler=lambda city: {"city": city, "temp": 22, "rain_prob": 0.7, "wind": "3级"} ) advice_skill = Skill( name="generate_advice", description="根据天气数据生成出行建议,输入需要包含温度和降水概率", parameters={ "temp": {"type": "number", "required": True}, "rain_prob": {"type": "number", "required": True} }, handler=lambda temp, rain_prob: ( "建议带伞,降水概率较高" if rain_prob > 0.5 else "无需带伞,天气不错" ) )

这两个技能的设计有个讲究:第二个技能的输入,正好是第一个技能输出的子集。这样编排的时候,前一个技能的结果可以直接喂给后一个,不需要额外转换。这种"接口对齐"是技能编排能顺畅跑起来的前提。

3.2 把技能注册进去并暴露给模型

注册很简单,把两个技能塞进注册表:

registry = SkillRegistry() registry.register(weather_skill) registry.register(advice_skill) executor = SkillExecutor(registry)

然后构造给模型的 prompt。核心是把describe_all()的结果序列化后塞进去,让模型知道有哪些技能可用:

import json skill_desc = json.dumps(registry.describe_all(), ensure_ascii=False, indent=2) system_prompt = f"""你是一个可以调用技能的智能体。 可用技能如下: {skill_desc} 当用户请求需要用到技能时,请以如下 JSON 格式回复: {{"skill": "技能名", "params": {{...}}}} 如果不需要技能,直接回复文本即可。 """

这里有个经验:JSON 格式的约束一定要写死,并且给出示例。我试过只写"请返回技能名和参数",模型返回的格式五花八门,有的用自然语言,有的用 YAML,解析起来非常痛苦。给出明确的 JSON 模板后,稳定性提升非常明显。

3.3 编排循环:让技能一个接一个跑起来

真正的智能体不是调一次技能就结束,而是要根据结果决定下一步。这就是编排循环:

def run_agent(user_input, max_steps=5): messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_input} ] for step in range(max_steps): reply = call_llm(messages) # 假设这是你封装的大模型调用 parsed = try_parse_skill_call(reply) if not parsed: return reply # 模型直接给了文本答案,结束 result = executor.execute(parsed["skill"], parsed["params"]) messages.append({"role": "assistant", "content": reply}) messages.append({ "role": "user", "content": f"技能执行结果:{json.dumps(result, ensure_ascii=False)}" }) return "达到最大步数限制"

这个循环的关键在于max_steps。没有这个上限,模型有可能陷入"调技能 → 看结果 → 再调同一个技能"的死循环。我一般设 5 到 8 步,具体看任务复杂度。超过这个步数还没收敛,基本说明任务设计有问题,或者技能描述有歧义。

跑一遍"北京今天要带伞吗",理想流程是:模型先调fetch_weather,拿到rain_prob=0.7,再调generate_advice,最后输出"建议带伞"。整个过程两步技能调用,干净利落。

4. 技能描述与参数设计的坑:模型选错技能的真实原因

系统能跑通只是第一步。真正上线之后,你会发现大部分问题都出在技能描述和参数设计上,而不是代码逻辑。这一节专门讲我踩过的坑。

4.1 描述太短,模型"想不到"用这个技能

前面提过天气技能的例子,这里再展开说。模型选择技能,本质是一个语义匹配过程:它把用户的话和技能描述做相似度比较。描述越短,可匹配的语义特征越少,命中率越低。

我做过一个粗略的对比测试,同样是查天气的技能,三种描述下的命中率差异很明显:

描述写法用户问"明天出门穿什么"时的命中情况
"查天气"经常不命中,模型直接凭常识回答
"查询城市天气信息"偶尔命中,取决于问法
"查询指定城市的实时天气,含温度、降水、风力,用于出行、穿衣、活动安排判断"基本都能命中

结论很直接:描述里要把"使用场景"写进去。不要只写技能做什么,还要写"什么时候该用它"。这跟给人写工作手册是一个道理,你只写"负责报销",别人不知道什么情况找你;你写"负责差旅费、办公用品采购的报销审核",大家就清楚了。

4.2 参数命名含糊,模型传错值

参数名也有讲究。我见过有人把参数命名成arg1、data、info这种,模型根本猜不出该传什么。好的参数名应该自解释:

  • 差:data、input、param
  • 好:city、start_date、max_results

另外,参数描述也要写清楚。比如city这个参数,如果只写"城市",模型可能传"北京市朝阳区"这种带行政区的值;如果写"城市名称,只填城市级别,如'北京'、'上海'",模型就会规范很多。

还有一个隐蔽的坑:枚举值要显式列出。比如一个技能参数unit可以是celsius或fahrenheit,如果你不写清楚,模型可能传C、摄氏、celsius各种变体,导致校验失败。把可选值写进描述,能省掉一堆兼容代码。

4.3 技能粒度过粗或过细

粒度是个平衡问题。太粗,一个技能干太多事,模型不好组合;太细,技能数量爆炸,模型选择困难。

我的经验法则是:一个技能对应一个"原子操作",即不能再拆、且语义完整的最小单元。"查天气"是原子的,"查天气并生成建议"就不是,应该拆成两个。反过来,"把字符串转成大写"这种太细的,如果只是某个技能内部的一步,就没必要单独暴露成技能,藏在 handler 里就行。

判断标准可以问自己一句:这个技能会不会被单独复用?会,就独立出来;不会,就合并。

5. 调试与可观测性:技能调用链怎么追踪

智能体最让人抓狂的地方是"它为什么不按我想的走"。这时候如果没有可观测性,基本就是盲人摸象。我在项目里强制要求加三样东西:调用日志、步骤快照、失败重放。

5.1 调用日志:记录每一次技能调用

每次执行器被调用,都要记下来:谁调的、传了什么参数、返回了什么、耗时多少。格式建议结构化,方便后续分析:

import time import logging logger = logging.getLogger("agent.skills") def logged_execute(executor, name, params): start = time.time() result = executor.execute(name, params) elapsed = time.time() - start logger.info({ "skill": name, "params": params, "result": result, "elapsed_ms": round(elapsed * 1000, 2) }) return result

有了这些日志,你就能回答"模型到底调了哪些技能""哪一步慢了""哪一步报错了"这些关键问题。我遇到过性能问题,最后就是靠日志发现某个技能平均耗时 3 秒,成了整个链路的瓶颈。

5.2 步骤快照:还原模型的决策过程

光有技能日志还不够,还要记录模型每一步的原始输出。因为技能调错,往往是模型决策错了,而不是技能本身有问题。把每轮的 messages 完整存下来,出问题时可以逐轮回看,看模型是在哪一步"想歪了"。

我一般会把整个 messages 列表在每轮结束后 dump 成一个 JSON 文件,按会话 ID 和时间戳命名。这样复现问题时,直接加载对应文件重跑即可。

5.3 失败重放:把线上问题搬到本地

有了快照,就能做重放。写一个脚本,读取快照里的 messages,重新跑一遍编排循环,观察是否复现。如果复现,就可以在本地逐步调试;如果不复现,说明可能是模型随机性导致的,需要多跑几次看概率。

这个能力在排查"偶发失败"时特别有用。智能体因为模型有随机性,同一个输入可能这次成功下次失败。没有重放机制,你根本没法定位。

6. 技能复用与扩展:从单智能体到多智能体协作

当技能积累到一定数量,你会自然想到两件事:能不能跨智能体复用,以及能不能让多个智能体协作。这两个方向都是 agent-skills 概念的延伸。

6.1 技能复用:把注册表做成共享服务

如果每个智能体都自己维护一份技能注册表,重复劳动不说,还容易出现"同一个技能在不同智能体里行为不一致"的问题。更好的做法是把注册表抽成一个独立的技能服务,所有智能体通过接口查询和调用。

这样做的好处是:技能只维护一份,更新一处全局生效;技能的质量可以被统一监控;新智能体接入时,直接复用已有技能池,不用从零开始。

当然,代价是引入了网络调用,延迟会上升。所以我的建议是:技能数量少(比如 20 个以内)时,本地注册表就够了;超过这个量级,再考虑服务化。过早服务化是典型的过度设计。

6.2 多智能体协作:技能作为协作的接口

多智能体协作时,技能可以充当智能体之间的"契约"。比如一个负责数据处理的智能体,对外暴露clean_data、aggregate等技能;一个负责报告的智能体,通过调用这些技能来获取数据。这样两个智能体之间不需要知道对方的内部实现,只通过技能接口交互。

这种设计的好处是解耦。数据处理逻辑变了,只要技能接口不变,报告智能体完全不用改。这跟微服务的思想是一致的,只不过这里的"服务"是技能。

不过要注意,多智能体协作会显著增加调试难度。我建议先用单智能体把技能跑顺,确认每个技能都稳定了,再考虑拆分。一上来就搞多智能体,很容易陷入"不知道是哪个环节出错"的困境。

7. 我在实际项目里总结的几条经验

最后分享几条踩坑踩出来的经验,都是文档里不会写、但实际做项目一定会遇到的东西。

第一条:技能的错误信息要写给模型看,不是写给人看。技能执行失败时返回的 error 字段,模型是会读的。如果你返回"Error 500",模型完全不知道该怎么办;如果你返回"城市名称无法识别,请提供有效的城市名,如'北京'",模型下一轮就可能自己修正参数重试。把错误信息当成给模型的提示来写,能大幅提升自愈能力。

第二条:给技能加"幂等"意识。有些技能(比如写文件、发消息)重复执行会有副作用。如果模型因为某种原因重试了,可能造成重复操作。我的做法是给这类技能加一个可选的idempotency_key参数,相同 key 的重复调用直接返回上次结果。这个细节在演示时看不出来,但上线后能避免很多尴尬。

第三条:技能数量增长后,要做分组。当技能超过三四十个,全塞进 prompt 会让 token 消耗暴涨,模型选择也会变慢变差。这时候可以按领域分组,先让模型选组,再在组内选技能。两级选择比一级选择更稳,也更省 token。

第四条:定期清理僵尸技能。项目迭代过程中,总有一些技能被新技能替代,但没删掉。它们留在注册表里,不仅占 prompt 空间,还可能被模型误选。我一般每个季度过一遍技能列表,把近三个月零调用的技能标记出来,确认无用后删除。

第五条:技能要有版本概念。技能的行为可能变化,比如查天气的技能从返回摄氏改成返回华氏。如果直接改,依赖它的智能体可能就崩了。稳妥的做法是保留旧版本,新版本用新名字(如fetch_weather_v2),让调用方自己决定何时迁移。

这些经验听起来琐碎,但每一条都是真金白银换来的。agent-skills 这个概念本身不复杂,复杂的是把它用稳、用久。希望这些内容能帮你少走点弯路。

相关新闻

利用AI做科研的实践

利用AI做科研的实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/21 5:17:06 阅读更多 →
KafkaProducer 源码深度剖析:RecordAccumulator 封装消息流程

KafkaProducer 源码深度剖析:RecordAccumulator 封装消息流程

为什么需要 RecordAccumulator 前面几篇讲了 send() 怎么序列化、怎么选分区。但选完分区后,消息不是直接发出去的——那样每条消息一次网络请求,吞吐会惨不忍睹。 Kafka Producer 的核心优化就是攒批:同一分区的消息先在内存里攒成一个批次&…

2026/10/21 5:17:06 阅读更多 →
HTML5视频播放实战:从video标签到编码兼容与性能优化

HTML5视频播放实战:从video标签到编码兼容与性能优化

1. 先搞清楚:为什么视频不能直接塞进网页1.1 从GIF到HTML5视频的演进前几年还经常能看到有人用GIF做演示动效,一个十几秒的录屏转成GIF之后动辄几十MB,加载起来页面卡得不行。GIF本质上是图像格式,不是为连续画面临时设计的&#…

2026/10/21 5:16:06 阅读更多 →

最新新闻

SpringBoot整合SSM实验室预约系统:从设计到答辩完整实战

SpringBoot整合SSM实验室预约系统:从设计到答辩完整实战

实验室预约这类系统,在我接触过的毕业设计和实际项目里,出现频率相当高。原因也很直接:它的业务流程足够完整,涉及用户角色、资源管理、状态流转、时间冲突判断这些核心逻辑,却又不像电商或社交系统那样无限膨胀&#…

2026/10/21 5:50:19 阅读更多 →
STM32+PT100工业级温度采集系统设计与实现

STM32+PT100工业级温度采集系统设计与实现

简介:本资源是一套基于STM32单片机的PT100铂电阻高精度温度采集系统完整开发包,面向嵌入式初学者、电子设计竞赛学生及工业测温应用开发者,解决低温至高温范围内稳定、抗干扰温度传感与数字转换的核心问题。压缩包共277个文件,含6…

2026/10/21 5:50:19 阅读更多 →
C++控制台游戏迭代实践:迷宫生成、存档与回合制战斗设计

C++控制台游戏迭代实践:迷宫生成、存档与回合制战斗设计

1. 版本迭代概览:3.17更新到底改了什么"勇闯迷塔"是我用C写的一个控制台小游戏,从最初十几层的纯迷宫探索,到3.17版本加入存档、战斗和新楼层,前后断断续续改了大概一个多月。这次更新正好在3月17日完成打包&#xff0c…

2026/10/21 5:50:19 阅读更多 →
基于CNN卷积神经网络的辣椒类别识别:高性价比计算机视觉毕设实战指南

基于CNN卷积神经网络的辣椒类别识别:高性价比计算机视觉毕设实战指南

每年开题季,都会有一批同学卡在同一个位置上:不想做MNIST手写数字、猫狗分类这种已经被写烂了的题目,又不敢直接挑战语义分割、目标检测这类工程量大得吓人的方向。如果你刚好在这个路口纠结,我推荐一个性价比非常高的选择——基于…

2026/10/21 5:50:19 阅读更多 →
自主移动机器人建图导航实战:lingbot-map模块化方案全解析

自主移动机器人建图导航实战:lingbot-map模块化方案全解析

做自主移动机器人,最磨人的往往不是底盘控制,也不是避障算法,而是那张地图。很多人以为“地图”就是雷达扫一圈输出一张图,实际上它背后牵扯坐标变换、传感器标定、回环检测、粒子滤波、代价地图膨胀这一整条链路。lingbot-map 这…

2026/10/21 5:50:18 阅读更多 →
Elasticsearch集群安全配置:TLS/SSL与密钥库管理全解析

Elasticsearch集群安全配置:TLS/SSL与密钥库管理全解析

给Elasticsearch集群做安全配置这件事,远比想象中麻烦。很多人以为在elasticsearch.yml里加几行TLS/SSL配置就能收工,结果往往是节点之间互相不认证书、Kibana连不上、客户端报handshake failed,最后只能回滚。我这次把一套三节点ES集群从裸H…

2026/10/21 5:49:18 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →