294 lines
10 KiB
Markdown
294 lines
10 KiB
Markdown
---
|
||
name: lyxy-kb
|
||
description: 基于文件的个人知识库管理 skill,提供知识项目的目录结构规范、文档解析入库、渐进式问答等底层能力定义。配合 commands/lyxy-kb/ 下的 command 使用。
|
||
compatibility: 依赖 lyxy-reader-office skill 解析 office 文档(.docx/.pdf/.pptx/.xlsx),依赖 lyxy-runner-python skill 执行 Python 脚本。
|
||
---
|
||
|
||
# 个人知识库 Skill
|
||
|
||
基于文件的个人知识库管理系统。将项目相关文档组织为可被大模型高效检索和问答的知识库,支持文档解析入库、增量摘要、渐进式问答。
|
||
|
||
## Purpose
|
||
|
||
**纯文件驱动**:不依赖数据库或向量存储,所有数据以文件形式存在于项目目录中。
|
||
|
||
**渐进式查询**:通过 project.md 摘要索引 + parsed 详细文件的分层结构,优先读取摘要,按需加载详细内容,节省 token 消耗。
|
||
|
||
**增量管理**:支持增量解析入库和增量更新摘要,避免重复处理已入库的文档。
|
||
|
||
## When to Use
|
||
|
||
任何需要基于一组项目文档进行知识管理和问答的场景。
|
||
|
||
### 典型场景
|
||
- **项目文档管理**:将需求文档、技术方案、数据表等组织为结构化知识库
|
||
- **文档解析入库**:将 office 文档和纯文本文件解析为 markdown 并生成摘要
|
||
- **知识问答**:基于已入库的文档回答问题,并标注信息来源
|
||
|
||
### 不适用场景
|
||
- 需要语义搜索或向量化检索
|
||
- 需要跨多个知识项目关联查询
|
||
- 需要多人协作或权限控制
|
||
|
||
## 配套 Commands
|
||
|
||
| Command | 触发方式 | 说明 |
|
||
|---------|----------|------|
|
||
| init | `/lyxy-kb-init <name>` | 初始化知识项目目录结构 |
|
||
| ingest | `/lyxy-kb-ingest <name>` | 解析 sources/ 中新文件,增量更新 project.md |
|
||
| rebuild | `/lyxy-kb-rebuild <name>` | 全量重新生成 project.md |
|
||
| ask | `/lyxy-kb-ask <name>` | 基于知识库进行会话问答 |
|
||
|
||
## 项目名称规则
|
||
|
||
项目名称只允许使用以下字符:
|
||
- 中文字符
|
||
- 英文字母(a-z、A-Z)
|
||
- 数字(0-9)
|
||
- 短横线(-)
|
||
- 下划线(_)
|
||
|
||
**不允许包含空格或其他特殊字符。** 不符合规则时应提示用户修改。
|
||
|
||
## 知识项目目录结构
|
||
|
||
每个知识项目是当前工作目录(CWD)下的一个子目录,包含以下固定结构:
|
||
|
||
```
|
||
<project-name>/
|
||
├── project.md # 高度摘要 + 文件索引
|
||
├── manifest.json # 增量追踪
|
||
├── parsed/ # 解析后的 markdown(中间产物)
|
||
├── sources/ # 待处理区(用户放入原始文档)
|
||
└── archive/ # 原始文件备份(带时间戳)
|
||
```
|
||
|
||
### 各目录/文件职责
|
||
|
||
| 路径 | 职责 |
|
||
|------|------|
|
||
| `project.md` | 项目的高度摘要和文件索引,作为问答时的入口文件 |
|
||
| `manifest.json` | 记录已处理文件的元信息,用于增量检测和版本追踪 |
|
||
| `parsed/` | 存放解析后的 markdown 文件,便于大模型读取分析 |
|
||
| `sources/` | 用户放入待处理文档的目录,解析后文件会被移走 |
|
||
| `archive/` | 原始文件的备份,每个文件都带时间戳后缀 |
|
||
|
||
### 结构完整性验证
|
||
|
||
执行任何 command(ingest / rebuild / ask)时,必须先验证项目目录结构是否完整,即以下 5 项是否全部存在:
|
||
- `<project-name>/project.md`
|
||
- `<project-name>/manifest.json`
|
||
- `<project-name>/parsed/`
|
||
- `<project-name>/sources/`
|
||
- `<project-name>/archive/`
|
||
|
||
若不完整,提示用户先执行 `/lyxy-kb-init <project-name>`,终止当前操作。
|
||
|
||
## project.md 格式规范
|
||
|
||
```markdown
|
||
# <项目名称>
|
||
|
||
## 概述
|
||
(高度总结的项目信息,几百字以内)
|
||
|
||
## 关键信息
|
||
(从所有文档中提炼的核心要点)
|
||
|
||
## 文件索引
|
||
|
||
| 文件名 | 解析文件 | 最新归档 | 摘要 |
|
||
|--------|----------|----------|------|
|
||
| 需求文档 | parsed/需求文档.md | archive/需求文档_202602181600.docx | 简要摘要... |
|
||
|
||
## 更新记录
|
||
- 2026-02-18 16:00: 解析 需求文档.docx
|
||
```
|
||
|
||
### 更新策略
|
||
|
||
**增量追加**(默认,由 ingest 触发):
|
||
- 新文件:在文件索引表追加新行,在更新记录追加条目
|
||
- 已有文件更新:覆盖文件索引表中对应行的最新归档路径和摘要
|
||
- 概述和关键信息部分**不**自动更新
|
||
|
||
**全量重写**(由 rebuild 触发):
|
||
- 读取所有 parsed/*.md 文件
|
||
- 重新生成概述、关键信息、文件索引
|
||
- 保留历史更新记录,追加本次 rebuild 条目
|
||
|
||
## manifest.json 结构
|
||
|
||
```json
|
||
{
|
||
"project": "<项目名称>",
|
||
"created_at": "2026-02-18T16:00",
|
||
"last_ingest": "2026-02-18T17:25",
|
||
"files": [
|
||
{
|
||
"name": "需求文档",
|
||
"ext": ".docx",
|
||
"parsed": "parsed/需求文档.md",
|
||
"versions": [
|
||
{
|
||
"archived": "archive/需求文档_202602181600.docx",
|
||
"hash": "sha256:abc123...",
|
||
"ingested_at": "2026-02-18T16:00"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `project` | 项目名称 |
|
||
| `created_at` | 项目创建时间 |
|
||
| `last_ingest` | 最近一次 ingest 的时间 |
|
||
| `files[].name` | 文件名(不含扩展名) |
|
||
| `files[].ext` | 原始文件扩展名 |
|
||
| `files[].parsed` | 解析产物的相对路径 |
|
||
| `files[].versions` | 版本历史数组 |
|
||
| `files[].versions[].archived` | 归档文件的相对路径 |
|
||
| `files[].versions[].hash` | 文件内容的 SHA-256 哈希(使用 `sha256sum` 命令计算) |
|
||
| `files[].versions[].ingested_at` | 该版本的入库时间 |
|
||
|
||
## 文件类型解析策略
|
||
|
||
| 文件类型 | 解析方式 |
|
||
|----------|----------|
|
||
| `.docx`, `.pdf`, `.pptx`, `.xlsx` | 使用名为 **lyxy-reader-office** 的 skill 解析 |
|
||
| 其他所有文件(`.md`, `.txt`, `.csv`, `.json`, `.xml`, `.yaml`, `.yml`, `.log`, `.html` 等) | 直接读取文件内容 |
|
||
|
||
### Office 文档解析
|
||
|
||
解析 office 文档时,必须查找当前环境中名为 **lyxy-reader-office** 的 skill,阅读其 SKILL.md 获取具体的执行方式和命令。
|
||
|
||
**如果环境中不存在 lyxy-reader-office skill,且没有其他可替代的文档解析 skill,则提示用户无法处理 office 文档,中止整个 ingest 流程。**
|
||
|
||
### sources/ 扫描规则
|
||
|
||
扫描 sources/ 时**递归检查所有子目录**中的文件。parsed 产物的路径仍为 `parsed/<文件名>.md`(扁平化存放),不保留 sources 中的子目录结构。
|
||
|
||
### 空文件处理
|
||
|
||
sources/ 中 0 字节的空文件应**跳过处理**,不解析、不归档、不更新 manifest。处理完成后向用户列出被跳过的空文件列表,提示用户检查。
|
||
|
||
### 解析失败处理
|
||
|
||
如果某个文件解析失败(如文档损坏、解析器报错),该文件**保留在 sources/ 中不移动**,报告错误信息,继续处理其他文件。
|
||
|
||
## parsed 文件元信息标记
|
||
|
||
每个 parsed markdown 文件头部必须包含元信息注释:
|
||
|
||
```markdown
|
||
<!-- source: 技术方案.pdf -->
|
||
<!-- archived: archive/技术方案_202602181725.pdf -->
|
||
<!-- parsed_at: 2026-02-18 17:25 -->
|
||
|
||
# 技术方案
|
||
(文档正文内容...)
|
||
```
|
||
|
||
| 元信息 | 说明 |
|
||
|--------|------|
|
||
| `source` | 原始文件名(含扩展名) |
|
||
| `archived` | 对应的归档文件相对路径 |
|
||
| `parsed_at` | 解析时间(YYYY-MM-DD HH:mm 格式) |
|
||
|
||
## 文档生命周期
|
||
|
||
```
|
||
用户放入 sources/(支持子目录)
|
||
│
|
||
▼
|
||
检查文件(跳过空文件、检测冲突)
|
||
│
|
||
▼
|
||
解析文件内容(失败则保留在 sources/)
|
||
│
|
||
├──▶ 写入 parsed/<文件名>.md(含头部元信息)
|
||
│
|
||
├──▶ 移动原始文件到 archive/<文件名_YYYYMMDDHHmm>.<ext>
|
||
│
|
||
├──▶ 更新 manifest.json
|
||
│
|
||
└──▶ 增量更新 project.md(追加文件索引和更新记录)
|
||
```
|
||
|
||
### 归档命名规则
|
||
|
||
所有进入 archive 的文件都必须带时间戳后缀,格式为 `<文件名_YYYYMMDDHHmm>.<扩展名>`,即使只有一个版本。
|
||
|
||
示例:
|
||
- `需求文档.docx` → `archive/需求文档_202602181600.docx`
|
||
- `技术方案.pdf`(第二次入库)→ `archive/技术方案_202602181725.pdf`
|
||
|
||
### 同名文件更新
|
||
|
||
同名同扩展名的文件再次入库时:
|
||
- `parsed/` 中的 markdown 文件被覆盖为最新版本
|
||
- `archive/` 中保留所有历史版本(每个版本独立的时间戳文件)
|
||
- `manifest.json` 中该文件条目的 `versions` 数组追加新版本记录
|
||
|
||
## 同名不同扩展名冲突检测
|
||
|
||
因为 parsed 产物以文件名(不含扩展名)+ `.md` 命名,同名不同扩展名的文件会产生冲突。
|
||
|
||
### 检测规则
|
||
|
||
1. **sources/ 内部检测**:扫描 sources/ 中所有文件(含子目录),如果存在同名但不同扩展名的文件(如 `技术方案.pdf` 和 `技术方案.docx`),拒绝处理并提示用户重命名
|
||
2. **与已入库文件检测**:将 sources/ 中文件的名称(不含扩展名)与 manifest.json 中已有记录对比,如果名称相同但扩展名不同,拒绝处理并提示用户重命名
|
||
|
||
### 处理方式
|
||
|
||
冲突文件不予处理,保留在 sources/ 中,提示用户重命名后重新执行 ingest。非冲突文件正常处理。
|
||
|
||
## 渐进式查询策略
|
||
|
||
问答时采用分层加载策略,节省 token:
|
||
|
||
1. **读取 project.md**:获取项目概述和文件索引(低 token 开销)
|
||
2. **判断相关文件**:根据用户问题和文件索引中的摘要,判断需要查阅哪些 parsed 文件
|
||
3. **按需加载**:读取相关 parsed 文件的全部或部分内容
|
||
4. **回答并标注来源**:基于获取的信息回答问题
|
||
|
||
### 来源引用格式
|
||
|
||
回答中引用具体信息时,使用以下格式标注来源:
|
||
|
||
```
|
||
根据《文件名》(parsed/文件名.md),...
|
||
```
|
||
|
||
多个来源时分别标注各信息点的来源文件。
|
||
|
||
### 无相关信息
|
||
|
||
当知识库中未找到与用户问题相关的信息时,明确告知用户,不编造答案。
|
||
|
||
### 空知识库
|
||
|
||
如果 project.md 文件索引为空(尚无已入库文件),应告知用户知识库为空,建议先使用 `/lyxy-kb-ingest` 入库文档。
|
||
|
||
## Notes
|
||
|
||
### 依赖关系
|
||
|
||
| 依赖 | 用途 |
|
||
|------|------|
|
||
| lyxy-reader-office | 解析 .docx、.pdf、.pptx、.xlsx 文件为 markdown |
|
||
| lyxy-runner-python | 通过 uv 执行 lyxy-reader-office 的 Python 解析脚本 |
|
||
|
||
### 限制
|
||
|
||
- 不支持向量化语义搜索
|
||
- 不支持跨知识项目关联查询
|
||
- 不支持文档版本对比或 diff
|
||
- 不支持多用户协作或权限控制
|
||
- 大量文件全量重写时 token 消耗较高
|