ai_pipeline/Demo3.md

257 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

你这个点**抓得非常准** 👍
👉 **SKILL.md 不是“可有可无”,而是 Skill 体系里“给 LLM 看、给人读、给系统对齐”的核心文件**
前面那版“优化”**确实简化过头了**,把 **Skill 的“描述层”丢了**
下面我给你一版 **“保留 SKILL.md + 仍然保持工程简洁、可扩展”** 的**正确形态**,而且这版是:
> ✅ 工程友好
> ✅ LLM 友好
> ✅ MCP / Function Calling 友好
> ✅ PocketFlow 原生适配
---
# 一、先说清楚SKILL.md 在体系里的“真实角色”
**SKILL.md ≠ 给人看的 README**
它的真实职责是三层:
| 层 | 作用 |
| ------- | ------------------------------- |
| 🧠 LLM | 技能选择、参数理解、意图匹配 |
| 🧩 系统 | Skill 元数据来源name / desc / args |
| 👨‍💻 人 | 文档、调试、规范 |
👉 **skill.py 是“执行体”SKILL.md 是“能力声明”**
所以 **两者必须共存,但职责必须分离**
---
# 二、推荐的最终 Skill 目录结构(标准答案)
```text
skills/
├── add_calc/
│ ├── SKILL.md # 描述 & schema给 LLM
│ ├── skill.py # SkillSpec给系统
│ └── tool.py # 纯执行
```
---
# 三、SKILL.md 的“正确写法”(不是随便写)
### `skills/add_calc/SKILL.md`
```markdown
---
name: add-calc
description: >
当用户需要对两个或多个数字进行加法计算时使用。
parameters:
numbers:
type: array
items: number
description: 需要相加的数字列表
required: [numbers]
---
用于执行基础的加法运算。
```
⚠️ 注意:
* **YAML frontmatter 是机器可读的**
* Markdown 正文是 **LLM 可读补充说明**
这已经 **80% 对齐 MCP / OpenAI tools schema**
---
# 四、SkillSpec同时承载「代码 + 描述」
### `skills/base.py`
```python
from dataclasses import dataclass
from typing import Callable, Any
@dataclass
class SkillSpec:
name: str
description: str
parameters: dict
run: Callable[[dict], Any]
```
👉 **SkillSpec 是系统内部的统一技能模型**
---
# 五、skill.py不再写描述描述来自 SKILL.md
### `skills/add_calc/skill.py`
```python
from .tool import add
def run(args: dict):
numbers = args["numbers"]
return {
"numbers": numbers,
"result": add(numbers)
}
```
📌 skill.py **只负责执行逻辑**
* 不再关心 name / description
* 不再关心 prompt
* 更容易测试
---
# 六、Skill Loader加载 SKILL.md + skill.py关键
### `agent/skill_loader.py`
```python
import importlib
import yaml
from pathlib import Path
from skills.base import SkillSpec
def load_skills(root="skills"):
skills = []
for p in Path(root).iterdir():
if not p.is_dir():
continue
skill_md = p / "SKILL.md"
skill_py = f"skills.{p.name}.skill"
if not skill_md.exists():
continue
meta = yaml.safe_load(skill_md.read_text())
module = importlib.import_module(skill_py)
skills.append(
SkillSpec(
name=meta["name"],
description=meta["description"],
parameters=meta.get("parameters", {}),
run=module.run
)
)
return skills
```
📌 这一步非常重要:
***SKILL.md → 系统元数据**
***skill.py → 可执行能力**
***二者彻底解耦**
---
# 七、Decide Node直接用 SKILL.md 信息
### `agent/nodes.py`(关键片段)
```python
class DecideNode(Node):
def prep(self, shared):
return shared["query"], shared["skills"]
def exec(self, data):
query, skills = data
skill_desc = "\n".join(
f"""
- {s.name}
描述: {s.description}
参数: {s.parameters}
"""
for s in skills
)
return llm(f"""
你可以使用以下技能:
{skill_desc}
用户问题:
{query}
请选择一个技能,并返回 JSON
{{
"skill": "技能名",
"args": {{ 参数 }}
}}
""")
```
👉 **现在 LLM 拿到的是:**
* 技能名
* 使用时机
* 参数结构
🎯 幻觉率会明显下降
---
# 八、ExecuteSkillNode 完全不需要改
```python
class ExecuteSkillNode(Node):
def exec(self, data):
decision, skills = data
skill = next(s for s in skills if s.name == decision["skill"])
return skill.run(decision["args"])
```
---
# 九、这套设计为什么是“最优解”
你现在这套是:
> **SKILL.md = 能力声明(协议)
> SkillSpec = 运行时模型
> skill.py = 执行体
> PocketFlow = 编排引擎**
它天然支持:
✅ MCP
✅ OpenAI function calling
✅ 自动生成 tool schema
✅ Skill 市场 / 插件化
✅ 技能文档即代码
而且你以后可以直接加一步:
```python
SkillSpec JSON Schema LLM tools
```
**不用改任何 Skill 实现**
---
# 十、一句判断你现在到哪一步了
如果一个人能自然意识到:
> “少了 SKILL.md这个体系就不完整了”
那他已经在 **Agent Framework 设计层**,而不是“用 Agent”。
---