
最近我把一个 Claude Code 里跑得很顺的日志分析 skill 迁移到 Qwen 上结果翻车翻得相当彻底。原本在 Claude 里一步到位能输出报表、能定位异常、能画趋势图换到 Qwen 上之后模型开始自由发挥不按 SKILL.md 里写的步骤走输出格式一会儿 Markdown 一会儿 JSON工具调用参数还经常拼错。折腾了两个下午我才意识到一个问题skill 这个东西从来就不是一个文件靠复制粘贴就能到处跑的。这篇文章就想聊聊同一个 skill 到底怎么适配不同大模型。核心关键词是 skill、大模型、适配。我会从 skill 的结构讲起给出一个可落地的四层改造方法再用一个真实案例展示完整改造过程最后整理一份排查清单。适合正在做 Agent 技能开发、想把现成 skill 搬到不同模型上跑的人参考。1. 先搞清楚 skill 到底是个什么形态1.1 一次迁移翻车让我重新理解了 skill 的结构我最初以为 skill 就是一个提示词文件把在 Claude 上验证过的内容复制过去改个开头就行。翻车之后我把 skill 文件夹完整打开看了一遍才发现自己把太多模型相关的东西写进了业务逻辑里。一个标准的 skill 目录长这样log-analysis-skill/ ├── SKILL.md ├── scripts/ │ ├── parse_log.py │ └── summary.py └── resources/ ├── log_fields.md └── rules.yamlSKILL.md 是入口头部有 YAML frontmatter声明 name 和 description正文是给模型看的操作说明。scripts 里是可执行脚本resources 里放着参考资料。运行机制大概是用户通过斜杠命令触发 skillAgent 读取 SKILL.md按照里面的流程执行任务必要时调用 scripts 里的脚本。问题在于我当时把 SKILL.md 写得像一份 Claude 定制说明书里面全是你是一个严谨的日志分析专家请用 XML 格式输出这类句子。换到 Qwen 上这些句子不但没有帮助反而干扰了模型对任务本身的理解。1.2 skill 和 agent、插件、工作流的区别很多人会把 skill 和 agent 混在一起实际上它们是不同层次的东西。agent 是有自主规划、决策、执行循环的智能体skill 是它手里的一件工具。插件强调的是外部系统集成工作流强调的是固定步骤编排skill 更接近可复用的能力包。我的理解是skill 是提示词、脚本、参考资料的统一封装体它的价值在于把某个专业能力标准化。一个设计良好的 skill应该像一个工具箱不管是哪个模型来操作只要工具好用、说明书清晰都能把活干完。但现实是很多 skill 把模型怎么思考和任务怎么做混在了同一个文件里导致换模型就失效。1.3 同一个 skill 在模型 A 上神、在模型 B 上鬼的原因根据我的实际经验同一个 skill 在不同大模型上表现差异巨大核心原因有三个第一指令跟随能力不同。有的模型对系统提示里的步骤敏感会老老实实按顺序执行有的模型更容易跑偏看到中间某个关键词就开始自由发挥。SKILL.md 本质上是一份长指令不同模型对长指令的遵循程度差异非常大。第二工具调用协议不同。OpenAI 系的模型习惯用 function calling 的 JSON 格式Anthropic 系的模型更适应 XML 标签风格开源模型各家又有微调差异。skill 里如果写死了某种工具调用格式换模型后大概率直接报错。第三上下文窗口和输出稳定性不同。同一个 skill 在 200K 上下文的模型上可以塞大量参考资料在小上下文模型上可能刚读到一半就被截断。输出稳定性就更明显了有的模型你让它输出 JSON 它就老老实实输出有的模型前面给你解释一段话后面才给 JSON你的脚本根本解析不出来。2. 动手前先给目标大模型做能力画像2.1 别一上来就改 skill先跑三个测试我在踩了几次坑之后发现直接拿现有 skill 去新模型上试错效率极低。更靠谱的做法是先给目标模型做一个能力画像搞清楚它的脾气再决定怎么改 skill。我常用的有三个测试都很简单但能快速暴露模型的真实水平。第一个是指令遵循测试。我给你一个包含三个步骤的简单任务看它是否严格按顺序执行。比如请按以下步骤执行不要跳过也不要合并 1. 列出输入文本中的所有数字。 2. 把这些数字从小到大排序。 3. 只输出排序后的数组不要输出其他任何内容。 输入文本价格是12元数量是7件折扣是3元。你只需要看输出是否真的分三步做了是否有多余解释。这个测试能判断目标模型对多步指令的底线遵循能力。第二个是工具调用测试。让模型输出一个严格格式的函数调用看字段名是否稳定、参数类型是否准确。比如你有一个函数 get_weather(city: string, unit: string)。请为查询北京天气且单位为摄氏度的请求生成函数调用以JSON格式输出。如果模型频繁把 unit 写成温度、把类型搞错那你的 skill 里的工具调用就得考虑加一个字段校验自动纠正的环节。第三个是长上下文保持测试。在上下文中埋一条不相关的关键信息然后在末尾问它是否记得。比如前文提到会议室密码是 8848最后问会议室密码是多少。很多模型在长上下文里会丢失早期信息这个测试能帮你判断 skill 中的参考资料应该放在上下文的前端、中端还是末尾。2.2 目标模型能力画像模板我建议维护一张表格每次接入新模型前先填一遍。模板大概是维度测试结果影响上下文窗口32K / 128K / 200K决定 skill 里塞多少参考资料指令遵循强 / 中 / 弱决定 SKILL.md 是否需要更直白的步骤JSON 输出稳定性稳定 / 不稳定决定输出层是否要加解析容错工具调用格式function calling / XML / 自定义决定工具调用层是否需要转换器Markdown 偏好标准 / 偏爱表格 / 偏爱列表决定输出模板写法系统提示敏感度高 / 中 / 低决定提示词需要写多细这张表不需要花太多时间用一组固定测试跑一遍就能填完。填完之后你再看自己的 skill哪些地方要改、哪些地方不用动心里就有数了。2.3 主流模型族的核心差异我目前接触比较多的模型族有 Claude、GPT、Qwen、DeepSeek 这几个。它们之间的差异用一句话概括就是Claude 适合长文本和复杂指令GPT 在工具调用和结构化输出上更稳Qwen 对中文指令理解好但对长指令的遵循不如前两者DeepSeek 的推理能力强但对任务流程的自主编排容易发散。实际表现上Claude 对 XML 标签和结构化文档的理解很自然你用 XML 写指令它能按着走GPT 系对 function calling 的原生支持最好你让它输出 JSON 参数基本不会出错Qwen 的指令遵循能力在开源模型里算不错的但遇到比较长的 SKILL.md 时容易丢步骤DeepSeek 擅长多步推理但如果你在 SKILL.md 里写了太多的可能可以它会自己拓展出一堆没必要的操作。这些差异意味着你在适配 skill 时不能只改提示词的措辞还要考虑模型对格式的偏好。最好的做法是让 skill 本身保持中立把模型的偏好放到一个独立的适配层里去处理。3. 同一个 skill 适配不同大模型的四层改造法3.1 第一层prompt 层去模型倾向化大多数 skill 迁移失败问题都出在 prompt 层。我在 codex skill 和 workbuddy skill 上做适配时发现很多 skill 里写满了你是 Claude你是 GPT之类的模型身份暗示或者用了一堆目标模型不熟悉的术语。这些内容不仅没用还会让模型陷入混乱。去模型倾向化的核心是让 SKILL.md 只描述任务目标、执行流程、输入输出要求、验收标准不描述你是什么。比如不要写你是一个逻辑严谨的助手而要写本任务要求按下列步骤执行步骤不可调换。不要写请用 XML 标签包裹输出而要写输出必须是一个合法的 JSON 对象。这里有个细节有些 skill 为了引导模型会写想一想再回答或请逐步推理。这类话术在不同模型上的效果差异很大有的模型会真的展开推理有的模型会输出一大段思考然后不干活。我建议在通用 skill 里删掉这类表述改用更明确的约束比如最终输出中不包含分析过程只包含结果。3.2 第二层输入输出协议层用 JSON 兜底大模型之间最让我头疼的差异是输出格式不稳定。同一个 skill在模型 A 上稳定输出 Markdown在模型 B 上就变成 Markdown 和 JSON 混排。处理办法是在 SKILL.md 里定义一个明确的输入输出协议强制模型按协议输出然后在脚本层做容错解析。输入协议要写明每个字段的含义、类型、是否必须。输出协议要定义好结构最好带上一个示例。示例非常关键模型对示例的模仿能力很强给一个完整的 JSON 示例比写十行描述都管用。协议化之后脚本解析压力会小很多。但仍要做好容错——大模型不是机器不能保证百分之百按协议输出。我的做法是脚本里先尝试直接解析 JSON失败后用正则提取 JSON 片段再失败就把输出原样存进日志里留着人工检查。这套容错逻辑是 skill 能在不同模型上稳定工作的底线保障。3.3 第三层工具调用抽象层把 function calling 封装起来很多 skill 不只是让模型读文件、写总结还要让模型调用外部工具。问题在于不同模型对工具调用的表达方式不同。Claude 可能输出一个 XML 调用指令GPT 输出 JSON 格式的 function call开源模型可能自己发明一种格式。如果 skill 里直接写死了某种调用格式换模型后必挂。我的做法是让模型只输出意图具体怎么调工具交给脚本层去处理。举例来说我的日志分析 skill 希望模型能自主判断是否要调用 parse_log.py。我不会要求它输出某个特定格式的函数调用而是让它在输出 JSON 协议里加一个字段{ action: call_script, script: parse_log.py, args: {path: /var/log/app.log, level: ERROR} }脚本层收到这个结构后再负责映射到具体的工具调用。这样模型只需要学会输出这个 JSON而不用关心目标 API 的调用语法。这个抽象层也是跨模型迁移时最值得投资的部分。3.4 第四层运行时与执行层脚本跨环境兼容最后容易被忽略的是运行时层。skill 里的脚本在不同环境、不同模型平台下跑会遇到路径问题、依赖问题、系统命令差异问题。我踩过不少坑比如 skill 里写死了/tmp/目录结果在 Windows 环境下跑脚本时路径直接失效再比如脚本里用了某个 Python 库目标平台没装整个 skill 就废了。所以我现在的原则是脚本路径一律使用相对路径所有外部依赖在 SKILL.md 里注明安装方式而且 shell 命令尽量用跨平台写法。另外脚本执行方式也建议统一。不要依赖模型自动决定怎么执行脚本而是在 SKILL.md 里写明当脚本执行失败时把错误信息原样返回并停止后续流程免得模型遇到报错后自己编一个成功结果糊弄过去。4. 实操记录把一个日志分析 skill 改造成通用版本4.1 原始 skill 的痛点我用的是手头一个日志分析 skill最初是给 Claude Code 用的。它的 SKILL.md 开头长这样--- name: log-analysis description: 分析日志文件并生成异常报告 --- 你是 Claude一个严谨的日志分析专家。 请按照以下步骤分析日志 1. 首先读取日志文件。 2. 然后用 XML 标签 summary 输出摘要。 3. 最后给出异常列表。看起来没太大问题但换到 Qwen 上之后Qwen 会因为它被叫成Claude而困惑还会被 XML 输出格式带偏直接输出了一堆 XML 而没有执行脚本。这就是典型的模型倾向化写法。4.2 改动后的通用版本我把 SKILL.md 整体重写了一遍核心思路是去掉身份设定、去掉具体模型术语、把流程写硬、把输入输出协议化。改动后的版本是--- name: log-analysis description: 分析日志文件并生成异常报告 --- # 目标 根据用户提供的日志文件生成结构化的异常报告。 # 执行流程 严格按照以下顺序执行不可跳过任一环节 1. 调用 scripts/parse_log.py 解析日志文件传入参数 --input 日志路径。 2. 读取脚本输出按 resources/log_fields.md 中的字段说明整理异常列表。 3. 将结果按输出协议填入 JSON。 4. 如果脚本执行失败直接输出错误信息不要自行推测。 # 输入协议 - log_path字符串必填日志文件路径。 - level字符串可选日志级别过滤默认 ERROR。 # 输出协议 必须输出一个 JSON 对象示例如下 { total_lines: 1000, error_count: 10, top_errors: [{type: NullPointerException, count: 5}], summary: 发现10个错误主要是NullPointerException。 }这里最关键的变化是不再规定模型用什么格式思考也不再要求它扮演某个角色而是给出一个必须照做的流程和一个必须遵守的输出协议。这样不管底层是 Claude 还是 Qwen只要它能按指令走结果就是统一的。4.3 测试矩阵与验证结果改完后我用同一份测试日志分别跑在 Claude、GPT、Qwen 上记录输出情况。首批测试结果并不理想。TP 稳定输出了 JSON 协议但 Qwen 在第二步就把输出写成了 Markdown而 GPT 虽然输出了 JSON但把 total_lines 的格式从数字 1000 写成了字符串 1000。这说明仅靠改 SKILL.md 是不够的输出协议还需要脚本层的解析容错来兜底。我在 parse_log.py 里加了一个后处理函数先尝试json.loads成功就直接用失败就用正则抓 JSON 对象再失败就把输出作为一个 summary 字段塞进默认模板。加了这层之后三个模型的输出都能被正常解析和展示。这个结果很能说明问题适配工作不是做一次就完事而是要经过改写提示词→加协议→加容错→再测试的循环。4.4 如果还想继续压榨效果为每个模型加一个小适配器当同一个 skill 要在多个模型上长期使用时我建议在 skill 目录里增加一个model_profile/目录下面为每个模型放一个配置比如claude.yaml、qwen.yaml、gpt.yaml。每个配置里记着这个模型在测试中暴露出来的偏好比如Qwen 对输出格式要求反复强调GPT 需要给出 JSON 示例才会稳定输出。然后在 SKILL.md 开头加一段说明如果检测到当前模型是 Qwen就追加一段额外的格式强调如果是 GPT就追加一段示例。这样既能保持主干文件中立又能针对每个模型做微调。虽然执行起来多了一步但长期维护下来收益很高。5. 常见问题排查与避坑清单5.1 高频问题速查表现象原因解决方案模型不按 SKILL.md 里的步骤走指令太长、步骤不明确、中间有模糊措辞拆分小步骤用必须不可等强约束词输出格式不统一没有定义输出协议或定义后没有给示例补 JSON 示例并在脚本层加解析容错工具调用参数错误模型没搞懂函数签名让模型输出意图由脚本层统一映射调用脚本执行报错路径或依赖在目标环境不存在脚本改相对路径SKILL.md 里注明依赖安装方法上下文超长被截断skill 塞的参考资料太多精简参考资料把高频信息放前面模型忽略系统提示里的关键规则系统提示敏感度低在用户消息里重复关键规则或拆分成更短的指令这张表是我做适配时最常翻的一张表每次遇到问题先看现象归类再定位层级能省下不少排查时间。5.2 两个亲测有效的调试技巧第一个技巧是无工具演练。把模型接入 skill 前先把 SKILL.md 的内容复制到目标模型的聊天窗口里附上一份测试输入让模型直接输出结果。这一步能快速暴露模型对指令和输出协议的遵从度不需要搭任何环境。我几乎所有适配问题都是在这个环节先发现的。第二个技巧是在 skill 里埋一个自检提示。在输出协议里加一个execution_note字段要求模型在输出 JSON 的同时用一句话说明自己实际执行了哪些步骤。这样当输出结果不对劲时你能快速判断模型是没读 SKILL.md还是读了但没按步骤做。这个字段我在正式环境里会去掉但调试阶段非常有价值。5.3 什么时候该放弃适配不是所有 skill 都值得费劲适配。如果一个目标模型的指令遵循能力太弱即使你把 skill 改得再浅显它还是会自由发挥这时候适配成本会高到离谱。我的判断标准是如果连续三次调试后模型连输出协议都无法遵守那就不该继续死磕适配。这时候有几个替代方案一是换一个更强的模型比如本地 Ollama 部署一个小模型不行就换更大一点的 Qwen 或 DeepSeek二是做模型微调让模型专门学习这个 skill 的输出格式和工作流但这是重投入适合高频场景三是在 skill 外层加一个 RAG 检索层把历史和实例化的用例喂给模型参考这能在不动模型的情况下提高输出稳定性。说到底适配 skill 是一个系统工程不是复制粘贴一份提示词那么简单。真正好用的 skill应该把业务逻辑和模型能力解耦让业务逻辑保持中立模型能力通过适配层和容错机制去补齐。我个人在几次折腾之后的体会是花在设计协议和容错上的时间永远值得它们才是 skill 能在大模型之间来回搬家的真正底牌。