vault backup: 2026-04-29 19:01:34

This commit is contained in:
2026-04-29 19:01:34 +08:00
parent 84f40fc9d9
commit 65228f9ea8
4 changed files with 765 additions and 624 deletions
+118 -63
View File
@@ -1,61 +1,76 @@
---
Description: ""
date: "2026-03-24"
lastmod: ""
tags: []
title: 第九章:Skill(Console)
weight: 9
create time: 2026-04-29 15:30
---
本章目标:在第八章(RAG + Interrupt/Resume + Checkpoint)基础上,引入 `skill` 中间件,让 Agent 可以发现并加载一组可复用的技能文档(`SKILL.md`),并在需要时通过工具调用使用它们。
# 第九章:Skill(Console)
## 代码位置
## 概述
- 入口代码:[cmd/ch09/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go)
- 同步脚本:[scripts/sync_eino_ext_skills.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/scripts/sync_eino_ext_skills.go)
本章在上一章(RAG + Interrupt/Resume + Checkpoint)的基础上,引入 **Skill** 中间件。通过 Skill 机制,Agent 可以发现并加载一组可复用的"技能文档"(`SKILL.md`),并在需要时自动调用它们——让 Agent 获得结构化的领域知识,而不需要把所有知识写进系统提示词里。
> [!TIP] 核心目标
> 学会用 Skill 中间件把一个稳定的知识集合注入到 Agent 中,并理解 Skill 与 Tool 的区别、注册方式、以及验证方法。
---
## 前置条件
- 与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)
- 准备好 `eino-ext` PR 提供的 skills(`eino-guide` / `eino-component` / `eino-compose` / `eino-agent`)
- 准备好 `eino-ext` PR 提供的 skills 资源:`eino-guide` / `eino-component` / `eino-compose` / `eino-agent`
为什么是这四个?
> [!QUESTION] 为什么是这四个 skill?
>
> ChatWithEino 的定位是「帮用户学习 Eino 框架、并尝试用 AI 辅助写 Eino 代码」。这四个 skill 恰好覆盖了关键知识点:
>
> - **`eino-guide`** — 学习入口与导航(从哪里开始、怎么快速跑起来)
> - **`eino-component`** — Component 接口与各类实现参考(Model / Embedding / Retriever / Tool / Callback 等)
> - **`eino-compose`** — 编排与确定性工作流参考(Graph / Chain / Workflow 等)
> - **`eino-agent`** — ADK / Agent 相关参考(Agent / Runner / Middleware / Filesystem / Human-in-the-loop 等)
ChatWithEino 的定位是“帮用户学习 Eino 框架、并尝试用 AI 辅助写 Eino 代码”。这四个 skills 正好覆盖了这个目标所需的关键知识面:
Skills 来源可以是:
- `eino-guide`:学习入口与导航(从哪里开始、怎么快速跑起来)
- `eino-component`:Component 接口与各类实现参考(Model/Embedding/Retriever/Tool/Callback 等)
- `eino-compose`:编排与确定性工作流参考(Graph/Chain/Workflow 等)
- `eino-agent`:ADK/Agent 相关参考(Agent、Runner、Middleware、Filesystem、Human-in-the-loop 等)
- `eino-ext` 仓库本地路径(同步脚本会自动读取 `<src>/skills/...`)
- 你已安装 skills 的目录(目录下能看到上述四个子目录)
skills 的来源可以是:
---
- `eino-ext` 仓库本地路径(脚本会自动读取 `<src>/skills/...`)
- 或你已安装 skills 的目录(目录下能看到上述四个子目录)
## 正文
## 从 Graph Tool 到 Skill:为什么需要“技能文档”
### 从 Graph Tool 到 Skill:为什么需要"技能文档"
第八章解决的是“复杂工作流如何做成一个可调用的 Tool”(Graph Tool)。但你在构建一个面向框架学习/开发辅助的 Agent 时,还会遇到另一类问题:**如何把一组稳定、可复用的知识与指令注入到 Agent 里,并让它在运行时按需加载?**
第八章我们解决了「复杂工作流如何做成一个可调用的 Tool」的问题。但当你构建一个面向框架学习/开发辅助的 Agent 时,还会遇到另一类挑战:
这就是 Skill 的定位:
> **如何把一组稳定、可复用的知识与指令注入到 Agent 里,并让它在运行时按需加载?**
- **Tool** 更像“动作/能力”:读文件、跑 workflow、调用外部系统
- **Skill** 更像“可复用的知识/指令包”:用一组 markdown(`SKILL.md` + `reference/*.md`)描述“如何做某类事”
这就是 Skill 的切入点:
简单类比:
- **Tool** = "能做什么"(函数/接口级别的能力)
- **Skill** = "怎么做"(可复用的说明书/操作手册)
- **Tool** = “能做什么”(函数/接口)
- **Skill** = “怎么做”(可复用的说明书/操作手册)
```mermaid
graph LR
A["Agent"] --> B["Tool 层<br/>读文件 / 执行流程 / 调外部API"]
A --> C["Skill 层<br/>知识文档 / 最佳实践 / 操作手册"]
C --> D["eino-guide<br/>学习入口"]
C --> E["eino-component<br/>组件参考"]
C --> F["eino-compose<br/>编排参考"]
C --> G["eino-agent<br/>ADK参考"]
```
## 运行
简单说:**Skill 是一种可被模型发现的结构化知识包**。每个 Skill 以 `SKILL.md` 为核心描述文件,辅以 `reference/*.md` 参考资料。
在 `quickstart/chatwitheino` 目录下执行:
### 运行步骤
### 1) 同步 eino-ext skills 到本地目录
在 `quickstart/chatwitheino` 目录下执行以下两步:
为了让 `skill` 中间件可以“发现”这些 skills,需要把它们放到一个统一目录下,并满足扫描约定:
#### 1) 同步 eino-ext skills 到本地目录
- `EINO_EXT_SKILLS_DIR/<skillName>/SKILL.md`
为了让 `skill` 中间件可以"发现"这些 skills,需要把它们放到一个统一目录下,满足扫描约定:
```
EINO_EXT_SKILLS_DIR/<skillName>/SKILL.md
```
同步命令(推荐):
@@ -63,80 +78,120 @@ skills 的来源可以是:
go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
```
说明:
> [!NOTE] `-src` 参数说明
>
> - 形式一:`eino-ext` 仓库根目录 → 脚本自动读取 `<src>/skills/...`
> - 形式二:你已安装 skills 的目录 → 要求目录下包含 `eino-guide/`、`eino-component/` 等子目录
- `-src` 支持两种形式:
- `eino-ext` 仓库根目录(脚本会自动读取 `<src>/skills/...`)
- 你已安装 skills 的目录(目录下应包含 `eino-guide/`、`eino-component/` 等子目录)
- `-dest` 默认是 `./skills/eino-ext`(可以省略)
### 2) 启动 Chapter 9
#### 2) 启动 Chapter 9
```bash
EINO_EXT_SKILLS_DIR=/absolute/path/to/chatwitheino/skills/eino-ext go run ./cmd/ch09
```
输出示例(节选):
控制台输出示例:
```
Skills dir: /.../skills/eino-ext
Enter your message (empty line to exit):
```
## 在 DeepAgent 中启用 Skill
### 在 DeepAgent 中启用 Skill
本章的 “Skill 可被调用” 不是自动发生的,你需要在 Agent 构建时把 `skill` 中间件注册进去。核心就是三步:
Skill 不会被自动加载 —— 你需要在 Agent 构建时显式注册 `skill` 中间件。核心三步:
1. 用本地 filesystem backend(本章用 `eino-ext/adk/backend/local`)提供文件读取/Glob 能力
2. 用 `skill.NewBackendFromFilesystem` 把 `EINO_EXT_SKILLS_DIR` 变成一个 Skill Backend
3. 用 `skill.NewMiddleware` 生成中间件,并把它塞进 DeepAgent 的 `Handlers`
| 步骤 | 操作 | 关键 API |
|------|------|----------|
| 1️⃣ | 创建文件系统 backend | `localbk.NewBackend(ctx, &localbk.Config{})` |
| 2️⃣ | 构建 Skill Backend | `skill.NewBackendFromFilesystem(ctx, cfg)` |
| 3️⃣ | 生成中间件并注入 DeepAgent | `skill.NewMiddleware(ctx, cfg)` |
**关键代码片段(注意:这是简化后的代码片段,不能直接运行,完整代码请参考 ****cmd/ch09/main.go****):**
```mermaid
sequenceDiagram
participant User as 用户
participant Agent as DeepAgent
participant SkillMW as Skill 中间件
participant Backend as Skill Backend
participant FS as 本地文件系统
User->>Agent: 发送消息
Agent->>SkillMW: 处理请求
SkillMW->>Backend: 按 skillName 查找 SKILL.md
Backend->>FS: Glob / Read 文件
FS-->>Backend: 返回 Markdown 内容
Backend-->>SkillMW: 技能上下文
SkillMW-->>Agent: 注入知识到 prompt
Agent->>User: 返回回复
```
**关键代码片段(简化版,完整代码见 `cmd/ch09/main.go`):**
```go
// Step 1: 本地 filesystem backend
backend, _ := localbk.NewBackend(ctx, &localbk.Config{})
// Step 2: 把 $EINO_EXT_SKILLS_DIR 变成 Skill Backend
skillBackend, _ := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{
Backend: backend,
BaseDir: skillsDir, // = $EINO_EXT_SKILLS_DIR
BaseDir: skillsDir, // = os.Getenv("EINO_EXT_SKILLS_DIR")
})
// Step 3: 创建中间件并注册到 DeepAgent
skillMiddleware, _ := skill.NewMiddleware(ctx, &skill.Config{
Backend: skillBackend,
})
agent, _ := deep.New(ctx, &deep.Config{
ChatModel: cm,
Backend: backend,
Backend: backend,
StreamingShell: backend,
Handlers: []adk.ChatModelAgentMiddleware{
skillMiddleware,
// ... 其他中间件,比如 approval/safeTool/retry 等
// ... 其他中间件(approval / safeTool / retry 等)
},
})
```
补充说明:
> [!WARNING] 容错设计
>
> 本 quickstart 保证了"没配置 skills 也能跑":代码中对 `EINO_EXT_SKILLS_DIR` 做了存在性检查,目录不存在则跳过注册 `skillMiddleware`。此时仍可正常对话和使用 RAG 工具。
- 本 quickstart 为了保证 “没配置 skills 也能跑”,在代码里对 `EINO_EXT_SKILLS_DIR` 做了存在性检查:目录存在才注册 `skillMiddleware`;否则跳过(此时仍可对话与使用 RAG 工具)。
- Skill 工具的入参是一个 JSON:`{"skill": "<skillName>"}`,例如 `{"skill":"eino-guide"}`。
### Skill 工具的入参格式
## 快速验证(推荐)
Skill 被注册为 Tool 后,模型的调用入参是一个 JSON 对象:
启动后输入一条指令,明确要求模型调用 skill 工具(用于验证 skills 已被发现且可被加载):
```json
{"skill": "eino-guide"}
```
其中 `"skill"` 键对应要激活的技能名称。
### 快速验证
启动后输入一条明确要求模型调用 skill 工具的指令:
```
Use the skill tool with skill="eino-guide" and tell me what the entry point is for getting started.
```
你应当能在控制台看到类似输出:
你应该看到:
- `[tool result] Launching skill: eino-guide`
- Tool result 中包含 `Base directory for this skill: .../eino-guide`
- `[tool call] ...` — 模型发起了 skill 工具调用
- `[tool result] Launching skill: eino-guide` — 技能被成功激活
- Tool result 中包含 `Base directory for this skill: .../eino-guide` — 确认文件读取正确
## 你会看到什么
### 会话恢复
- 当模型调用 skill 工具时,控制台会打印:
- `[tool call] ...`
- `[tool result] ...`(对结果做了截断展示)
- 会话保存在 `SESSION_DIR`(默认 `./data/sessions`),支持恢复:
- `go run ./cmd/ch09 --session <id>`
会话数据保存在 `SESSION_DIR`(默认 `./data/sessions`),支持通过 `--session` 参数恢复:
```bash
go run ./cmd/ch09 --session <session-id>
```
---
## 关联笔记
- [[Eino/quick_start/chapter_08_graph_tool]] — 上一章:Graph Tool,理解 Tool 作为"动作能力"的基础
- [[Eino/quick_start/chapter_05_middleware]] — Middleware 机制,所有中间件的通用注册方式
- [[Eino/quick_start/chapter_04_tool_and_filesystem]] — Tool 与 Filesystem,文件系统 backend 的来源