方法论回答"为什么",工程路径回答"怎么做",Skill回答"如何落地"。
传统Spec提取方案:
┌─────────────┐
│ 开发者 │ → 写代码解析器 → 提取结果
└─────────────┘
↓
问题:
1. 工具开发成本高
2. 扩展性差(新语言/格式需要新工具)
3. 无法处理模糊/语义性内容
LLM驱动的方案: ┌─────────────┐ │ 原始材料 │ → Prompt → LLM → 结构化结果 └─────────────┘ 优势: 1. 一个方案处理所有语言/格式 2. 能理解语义,不只是语法 3. 能处理模糊和不确定性 4. 零工程成本,只需写Prompt
脚本:处理确定性的结构化数据
文件读取、JSON解析、数据库查询——输入输出都是明确的。
Prompt:处理模糊的语义性内容
理解代码意图、推断业务规则、补充业务语义——输入可能是残缺的,输出需要"合理推断"。
结论:Prompt是Spec提取的最佳工具,脚本只做必要的辅助工作。
Skill是Agent的"专项能力包": ┌─────────────────────────────────────────────────────────────┐ │ Skill/ │ │ │ │ │ ├── SKILL.md ← 技能定义(Agent读取) │ │ ├── prompts/ ← Prompt模板(LLM执行) │ │ ├── config.yaml ← 配置(参数、路径) │ │ └── README.md ← 说明(可选) │ │ │ │ Agent调用Skill: │ │ 1. 读取SKILL.md理解任务 │ │ 2. 按顺序执行prompts │ │ 3. 每次调用LLM处理一步 │ │ 4. 输出结构化结果 │ └─────────────────────────────────────────────────────────────┘
脚本方式的问题: 1. LLM调用分散在代码中,维护困难 2. Prompt无法单独测试 3. 逻辑硬编码 Skill方式的优势: 1. Prompt独立管理,单独测试、单独迭代 2. Agent直接执行,无需解析代码逻辑 3. 可组合,Prompt可以复用
┌─────────────────────────────────────────────────────────────┐ │ SpecExtract Skill 工作流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Step 1: 材料采集 │ │ → 扫描项目结构 → 收集代码/文档 │ │ │ │ Step 2: LLM分类提取 │ │ → Entity提取Prompt │ │ → Action提取Prompt │ │ → Rule提取Prompt │ │ │ │ Step 3: Spec融合 │ │ → 多来源结果 → 融合 → 冲突检测 │ │ │ │ Step 4: 核心澄清 │ │ → 生成核心澄清问题 → 人工确认 │ │ │ │ Step 5: OpenSpec生成 │ │ → 融合后的Spec → OpenSpec格式 │ │ │ └─────────────────────────────────────────────────────────────┘
SpecExtract/ │ ├── SKILL.md │ ├── prompts/ │ ├── 01_collect.md # 材料采集 │ ├── 02_extract_entity.md # 实体提取 │ ├── 03_extract_action.md # 操作提取 │ ├── 04_extract_rule.md # 规则提取 │ ├── 05_merge.md # Spec融合 │ ├── 06_clarify.md # 澄清生成 │ └── 07_generate_openspec.md # OpenSpec生成 │ └── config.yaml
# SKILL.md - SpecExtract Skill
## 技能名称
spec-extract
## 技能描述
从产品代码库中提取结构化的产品规格信息,生成OpenSpec格式的Spec文档。
## 输入
- project_path: 项目路径
- product_context: 产品类型描述(可选)
- last_spec_path: 上次Spec路径(用于增量更新,可选)
## 输出
- specs/: OpenSpec格式的Spec目录
- clarification.md: 澄清问题清单
## 工作流程
按顺序执行以下Prompt:
01_collect → 02_extract_entity → 03_extract_action → 04_extract_rule
↓
05_merge
↓
06_clarify → 07_generate_openspec
# 实体提取 Prompt
## 角色
你是一个专业的业务分析师,擅长从代码中提取产品规格信息。
## 任务
分析以下代码材料,提取产品中的核心业务实体。
## 输出格式
```json
{
"entities": [
{
"name": "Client",
"display_name": "客户",
"description": "购买产品或服务的公司或个人",
"attributes": [
{
"name": "name",
"type": "string",
"business_type": "名称",
"required": true,
"description": "客户名称"
}
],
"relationships": [
{
"target": "Order",
"type": "1:N",
"description": "一个客户可以有多个订单"
}
],
"confidence": 0.95,
"uncertain_aspects": [],
"source_files": ["models/client.py"]
}
]
}
```
观点一:Prompt是Spec提取的核心工具。
代码解析需要工程实现,Prompt解析只需要LLM调用。Prompt的灵活性远超代码。
观点二:Skill化设计让Agent直接可用。
Agent读取SKILL.md → 按顺序执行Prompt → 得到结构化结果。整个过程无需人工介入。
观点三:分阶段Prompt设计便于优化。
每个Prompt独立,输入输出明确。可以单独测试、单独优化,不用改动其他部分。
观点四:澄清是质量保障,不是可选环节。
LLM提取有不确定性,澄清是确保Spec正确性的最后一道关卡。
为了更好地理解SpecExtract Skill的实际工作流程,下面以一个简化的CRM系统为例,展示完整的提取过程。
# models/client.py
from django.db import models
class Client(models.Model):
"""客户模型"""
name = models.CharField(max_length=200)
phone = models.CharField(max_length=20, unique=True)
level = models.CharField(max_length=1, choices=[('A', 'B', 'C')])
owner = models.ForeignKey('User', on_delete=models.CASCADE)
status = models.CharField(max_length=20, default='active')
created_at = models.DateTimeField(auto_now_add=True)
# services/discount.py
def calculate_discount(client, order_amount):
"""计算折扣"""
base = {'A': 0.15, 'B': 0.10, 'C': 0}
discount = base.get(client.level, 0)
if order_amount > 100000:
discount += 0.05
return min(discount, 0.20)
# api/clients.py
@router.post("/api/clients/")
def create_client(request):
"""创建客户"""
if Client.objects.filter(phone=request.data['phone']).exists():
return Error("手机号已被使用")
client = Client.objects.create(...)
send_welcome_email(client.owner)
return {"client_id": client.id}
{
"project_info": {
"path": "/project/crm",
"type": "CRM",
"language": "Python",
"framework": "Django"
},
"code_files": [
{
"path": "models/client.py",
"category": "models",
"summary": "Client实体模型,包含name, phone, level, owner, status等字段"
},
{
"path": "services/discount.py",
"category": "services",
"summary": "calculate_discount函数,根据客户等级和订单金额计算折扣"
},
{
"path": "api/clients.py",
"category": "api",
"summary": "create_client接口,POST /api/clients/,验证手机号唯一性后创建客户"
}
]
}
{
"entities": [
{
"name": "Client",
"display_name": "客户",
"description": "购买产品或服务的公司或个人",
"attributes": [
{"name": "name", "type": "string", "business_type": "名称", "required": true},
{"name": "phone", "type": "string", "business_type": "联系方式", "required": true},
{"name": "level", "type": "enum", "business_type": "状态", "required": true}
],
"relationships": [
{"target": "User", "type": "N:1", "description": "客户归属于负责销售"}
],
"confidence": 0.95,
"uncertain_aspects": [],
"source_files": ["models/client.py"]
}
]
}
{
"rules": [
{
"name": "discount_by_level_and_amount",
"display_name": "客户等级折扣规则",
"type": "discount",
"description": "根据客户等级和订单金额计算折扣",
"priority": "HIGH",
"logic": "基础折扣:A级=15%,B级=10%,C级=0%;大订单额外折扣:订单>10万+5%;上限:总折扣≤20%",
"decision_table": [
{"level": "A", "amount": "<=10万", "discount": "15%"},
{"level": "A", "amount": ">10万", "discount": "20%"},
{"level": "B", "amount": "<=10万", "discount": "10%"},
{"level": "B", "amount": ">10万", "discount": "15%"},
{"level": "C", "amount": "任意", "discount": "0%"}
],
"confidence": 0.95
},
{
"name": "client_phone_unique",
"display_name": "客户手机号唯一性",
"type": "validation",
"description": "同一手机号不能创建多个客户",
"priority": "HIGH",
"confidence": 0.95
}
]
}
{
"merged_entities": [...],
"merged_actions": [...],
"merged_rules": [...],
"conflicts": [],
"gaps": [
{
"type": "missing_relationship",
"description": "Client和Order的关系未在代码中明确定义"
}
],
"statistics": {
"total_entities": 1,
"total_actions": 1,
"total_rules": 2,
"conflicts": 0,
"gaps": 1
}
}
{
"clarifications": [
{
"id": "CLAR-001",
"priority": "MEDIUM",
"type": "clarification",
"target": "Client.level",
"question": "客户等级A/B/C的具体判定标准是什么?",
"options": [
"A=重点客户(年交易>100万),B=普通客户(10-100万),C=潜在客户(<10万)",
"A=战略客户(合作>1年),B=活跃客户(近3月有交易),C=其他"
],
"impact": "影响折扣规则和客户管理策略"
}
],
"statistics": {
"total": 1,
"high_priority": 0,
"medium_priority": 1
},
"estimated_review_time": "5分钟"
}
# Entity: 客户 (Client) ## Overview 客户是CRM系统的核心实体,代表购买产品或服务的公司或个人。 ## Attributes | Name | Type | Business Type | Required | Description | |------|------|---------------|----------|-------------| | id | UUID | ID | Yes | 唯一标识 | | name | string | 名称 | Yes | 客户名称 | | phone | string | 联系方式 | Yes | 联系电话 | | level | enum | 状态 | Yes | 客户等级:A/B/C | ## Relationships - Client → N:1 → User(负责销售) ## Scenarios ### Scenario: 正常创建 - GIVEN 用户已登录且有客户创建权限 - WHEN 填写客户名称、电话并提交 - THEN 创建客户,返回客户ID ### Scenario: 手机号重复 - GIVEN 要创建的客户手机号已存在 - WHEN 提交创建 - THEN 返回错误"该手机号已被使用" --- # Rule: 客户等级折扣规则 (discount_by_level_and_amount) ## Overview 根据客户等级和订单金额计算折扣。 ## Logic 基础折扣:A级=15%,B级=10%,C级=0%;大订单额外折扣:订单>10万+5%;上限:总折扣≤20% ## Decision Table | Level | Amount | Base | Extra | Total | |-------|--------|------|-------|-------| | A | ≤10万 | 15% | 0% | 15% | | A | >10万 | 15% | 5% | 20% | | B | ≤10万 | 10% | 0% | 10% | | B | >10万 | 10% | 5% | 15% | | C | 任意 | 0% | 0% | 0% | ## Constraints - 折扣上限20% - 仅适用于直接订单