skill vs 自定义组件
自定义业务组件和 Skills的区别
这是个很好的架构问题。两者的本质区别在于谁在做决策。
核心区别
| 自定义组件(你封装的类) | Skill(AI 技能) | |
|---|---|---|
| 执行者 | 确定性代码(generate_docx.js) |
AI 模型(每次动态生成代码) |
| 逻辑 | 写死的解析规则 + 固定渲染流程 | AI 读 Skill 指令后临场理解、临场生成 |
| 输入格式 | 必须严格遵循约定(YAML + HTML 注释指令) | 自然语言也行,非标格式也能处理 |
| 输出一致性 | 100% 确定性,同输入同输出 | 每次可能略有差异 |
| 错误模式 | 不支持的格式直接不处理或报错 | 可能生成有 Bug 的代码(你已经体验过了) |
用具体例子说明
你封装的组件
class DocxGenerator:
def generate(self, markdown_path: str) -> str:
"""调用 generate_docx.js 转换"""
subprocess.run(["node", "generate_docx.js", markdown_path])
用户输入必须是:
<!-- table: column_widths=[600,2000,1200] -->
| 序号 | 名称 | 数量 |
如果用户写了个不符合约定的格式,比如没有 <!-- table: --> 指令,表格就只能用默认均分列宽。组件不会"猜"你要什么。
Skill 的做法
Skill 本质是一份给 AI 看的说明书。以 Anthropic 的 docx skill 为例,它告诉 AI:
"用 docx-js 生成文档,ImageRun 要带 type,表格用 DXA 不用 PERCENTAGE..."
然后 AI 根据用户的自然语言请求 + Skill 里的知识,每次动态生成一段新的 JS 代码来执行。
用户可以说:
"帮我生成一个种植报告,标题用黑体 22 号,表格要浅蓝色表头"
AI 会理解意图,自己写代码,自己跑。不需要用户遵循任何固定格式。
专家说的"泛化能力强"是什么意思
Skill 的处理流程:
用户请求(任意格式)→ AI 理解意图 → AI 动态生成代码 → 执行 → 输出
↑
Skill 提供知识指导
你的组件的处理流程:
Markdown(固定格式)→ 确定性解析 → 确定性渲染 → 输出
泛化能力 = 处理未预见输入的能力:
- Skill:用户说"把表格第三列加粗",AI 能理解并处理 —— 即使你从没写过这个功能
- 你的组件:如果代码里没写"单列加粗"的逻辑,就做不到
这就是泛化能力的差异。Skill 借助 AI 的理解能力,可以处理开放性、模糊性的需求。
但 Skill 的代价是
| 风险 | 说明 |
|---|---|
| 不可控 | 每次生成的代码可能不同,可能有 Bug(你之前遇到的 ×9525 问题) |
| 速度慢 | 需要 AI 推理 + 生成代码 + 执行,比直接跑脚本慢很多 |
| 成本高 | 每次调用消耗 AI token |
| 不可复现 | 同样的输入不保证同样的输出 |
实际建议:两者结合
对于你的种植报告场景,最佳方案是两层架构:
确定性层(你的组件): 处理 95% 的标准化报告生成
↓ 格式固定、数据填充、调用 generate_docx.js
AI 层(Skill): 处理 5% 的特殊/灵活需求
↓ 比如用户说"帮我调整一下格式"、"加一段分析总结"
- 标准化的报告(固定模板 + 数据填充):用你的组件,稳定、快、可控
- 需要灵活应变的场景(用户临时要求改格式、加内容):用 Skill,让 AI 处理
一句话总结:你的组件是"流水线工人",Skill 是"有经验但偶尔犯错的工程师"。流水线适合标准化生产,工程师适合处理意外情况。

浙公网安备 33010602011771号