mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-03 07:43:58 +00:00
feat(kbtree): 知识库分类树的独立只读服务 + agent 技能 + WebUI 树浏览
让**外部 agent** 也能按分类树用这套知识库。HomeAgent 自己的 agent 仍
直接调内部方法(knowledge_search/create 等),走进程内直调,不经此服务。
一、内核树视图(internal/knowledge/tree.go)
为什么不复用 TreeIndex:那个是**内部导出物**,面向 .index.json 落盘,
每个条目带 top-20 的 TF-IDF 特征向量。直接序列化给外部有三个问题:
体积(200 条时 .index.json 已 246KB 且冗余存了 preview,而正本在
content.md)、泄漏(稀疏特征表 = 分词/IDF 内部表示)、语义错位
(外部要的是"有哪些分类、每类下有什么")。
新增 TreeView/Subtree/Categories/CategoryCounts:不含向量,带条目数
与可读摘要,支持 MaxDepth 懒加载、IncludeItems 只看结构。
节点 Name 是**本级段名**("go")、Path 是完整路径("tech/go")——
最初把全路径写进 Name,前端拼层级会得到 "tech/tech/go",已修。
二、kbtree 插件:独立 HTTP 服务(默认 127.0.0.1:9892)
为何不挂在 WebUI 的 /api/v1/knowledge* 下:
1. 不共享鉴权与端口。WebUI 的 api_key 是给人操作界面用的,把它分发给
外部 agent 等于把管理面凭据扩散出去。本服务用**独立 token** +
独立端口,可单独关闭(token 未配置则启动时随机生成)。
2. 只读。写入要决定分类归属与媒体处理,外部自行拼装容易造出越界/重名
条目 —— 写入留给内核工具。
3. 形状按树组织,而不是平铺搜索接口。
端点:/tree(可指定 category/depth/items)、/categories、/counts、
/search、/ (自述)。全部需 token(X-API-Key / Bearer / ?token=),
非 GET 一律 405。无知识库时 Start 直接失败,不占端口。
鉴权与 Slowloris/超时设置照 remotedevice 范式。
三、agent 技能(assets/skills/knowledge-base/SKILL.md)
指令文档型 skill:教模型"先看树 → 定位分类 → 分类内检索",并列出
易错点(name 已含分类别再拼、只看第一条、404 附现有分类)。
加载与校验由 internal/plugin/skill_bundled_test.go 守住 —— 这条断言
的由来:非白名单的二级标题会被 extractToolDefs 当成工具定义,报错
"invalid tool name",而提示与真正原因(标题层级)毫无关联。
kbtree 的测试还会校验文档提到的端点与代码一致,防漂移。
四、WebUI 树浏览(前端真正用起来,而非留一个没人调的端点)
面板加可折叠的分类树:逐级点选即把搜索范围切到该子树(原先是让人
手打分类名)。当前范围有可见标签与「全库」复位。
This commit is contained in:
131
assets/skills/knowledge-base/SKILL.md
Normal file
131
assets/skills/knowledge-base/SKILL.md
Normal file
@ -0,0 +1,131 @@
|
||||
---
|
||||
name: knowledge-base
|
||||
description: 按分类树检索 HomeAgent 知识库。当需要查阅项目知识、架构约定、历史决策,或用户提到"知识库/knowledge/知识库有哪些/这个项目的约定是什么"时使用。支持树形导航、分类内检索、以图搜知识。
|
||||
version: 1.1.0
|
||||
author: HomeAgent
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
先看树定位分类,再做定向检索。接口由 HomeAgent 的 `kbtree` 插件提供,
|
||||
只读、需 token。详见下方"接入"。
|
||||
|
||||
HomeAgent 知识库按**分类树**组织(`tech/go/并发`、`life/sleep` …)。
|
||||
|
||||
### 何时用
|
||||
|
||||
- 用户问"这个项目/内核的某个约定是什么" → 先看树,找对分类再检索
|
||||
- 用户提到"知识库"或某个看起来像分类名的词(如 `tech/go`)→ 查该子树
|
||||
- 用户给了图片并问"知识库里有相关的吗" → 见"以图搜知识"
|
||||
|
||||
### 接入
|
||||
|
||||
服务默认监听 `127.0.0.1:9892`(配置项 `kbtree.listen_addr`),只读,
|
||||
每次请求需带 token(配置项 `kbtree.token`;未配置则启动时随机生成)。
|
||||
|
||||
```bash
|
||||
BASE=http://127.0.0.1:9892
|
||||
AUTH="X-API-Key: $KB_TOKEN" # 或 Authorization: Bearer <token> 或 ?token=
|
||||
```
|
||||
|
||||
先摸清可用接口:
|
||||
|
||||
```bash
|
||||
curl -s -H "$AUTH" "$BASE/"
|
||||
```
|
||||
|
||||
### 核心工作流:先看树,再定向检索
|
||||
|
||||
**别一上来就全文搜索。** 知识库是分层的,先定位分类能显著提高命中率,
|
||||
也能避免把范围外的弱匹配当答案。
|
||||
|
||||
#### 第 1 步 · 看有哪些分类
|
||||
|
||||
```bash
|
||||
curl -s -H "$AUTH" "$BASE/categories"
|
||||
# {"categories":["cook","life","tech","tech/go","tech/rust"]}
|
||||
|
||||
# 内容最多的分类(按条目数倒序)
|
||||
curl -s -H "$AUTH" "$BASE/counts"
|
||||
# {"counts":[{"category":"tech","count":3}, ...], "total":5}
|
||||
```
|
||||
|
||||
#### 第 2 步 · 浏览树结构
|
||||
|
||||
```bash
|
||||
# 整棵树,只要结构
|
||||
curl -s -H "$AUTH" "$BASE/tree?items=0"
|
||||
|
||||
# 只要第一层 —— 分类多时用来做懒加载
|
||||
curl -s -H "$AUTH" "$BASE/tree?depth=1&items=0"
|
||||
|
||||
# 某棵子树,带条目详情
|
||||
curl -s -H "$AUTH" "$BASE/tree?category=tech/go"
|
||||
```
|
||||
|
||||
节点里 `name` 是**本级段名**(`"go"`),`path` 是**完整路径**
|
||||
(`"tech/go"`)。拼层级用 `name`,把 `path` 拿去请求子节点。
|
||||
`item_count` 是本级条目数,`total_count` 是整棵子树。
|
||||
|
||||
#### 第 3 步 · 分类内检索
|
||||
|
||||
```bash
|
||||
# 关键词 + 分类子树(推荐)
|
||||
curl -s -H "$AUTH" "$BASE/search?q=goroutine&category=tech"
|
||||
|
||||
# 全库
|
||||
curl -s -H "$AUTH" "$BASE/search?q=goroutine&limit=5"
|
||||
```
|
||||
|
||||
`category` 是**前缀匹配**:`tech` 会命中 `tech/go`、`tech/rust` 下的条目;
|
||||
传 `tech/go` 只命中它自己的子树。
|
||||
|
||||
### 以图搜知识(多模态)
|
||||
|
||||
若知识条目挂了图片,它在**多模态统一空间**里有向量,能被图片本身检索到。
|
||||
前提是宿主已接入多模态向量 provider(否则只是记录了媒体,不参与召回)。
|
||||
|
||||
判断是否就绪:HomeAgent 自身的知识库接口会返回稠密路状态
|
||||
(`dense.enabled` / `dense.ready` / `dense.total`)。若为未启用,
|
||||
**不要承诺"能以图搜"**。
|
||||
|
||||
本服务只提供**按关键词检索**——把图片字节提交给嵌入服务计算向量不在此接口内。所以:
|
||||
- 用户给了图 → 用图的**可见内容**(或你先读图得到的文字)当关键词检索
|
||||
- 或用本机可用的读图工具先看图,再拿描述来检索
|
||||
|
||||
### 读结果
|
||||
|
||||
`/search` 每条结果:
|
||||
|
||||
| 字段 | 含义 |
|
||||
|---|---|
|
||||
| `name` | 知识名(**已含分类前缀**,如 `tech/go/并发`) |
|
||||
| `content` | 正文全文 |
|
||||
|
||||
`/tree` 里的条目额外有 `preview`(前 120 字)、`size`、`updated_at`、
|
||||
`media`(挂载的媒体 digest/mime/kind)。
|
||||
|
||||
### 易错点
|
||||
|
||||
- **`name` 已经含分类**。不要再拼 `category + "/" + name`,会得到
|
||||
`tech/go/tech/go/并发`。
|
||||
- **检索会返回弱匹配。** 词法路会给所有条目打一个低分,靠排序把强命中顶到
|
||||
前面。**只看第一条**;第一条明显不相关就换个分类或关键词,别把第 2、3 条
|
||||
当答案。
|
||||
- **分类不存在返回 404**,并在 `categories` 字段里附上现有分类 —— 用它自查
|
||||
拼写。
|
||||
- **`items=0` 只是不要正文**,`total_count` 仍准确,可用于判断规模。
|
||||
- **本服务只读**。写方法返回 405。要写知识请用 HomeAgent 主 agent 的
|
||||
`knowledge_create`(或 WebUI 界面),不要试图绕过它直接写这个接口。
|
||||
- 知识名里不能有 `..`、空格(会被规范成 `_`)、点开头的段。
|
||||
|
||||
### 写入
|
||||
|
||||
本服务不提供写入。若你在 HomeAgent 主 agent 内部,写入用内核工具:
|
||||
|
||||
```
|
||||
knowledge_create name="tech/go/调度" content="正文..."
|
||||
```
|
||||
|
||||
`name` 用 `/` 表示分类层级(如 `tech/go/调度`)。写完它**立刻可检索**
|
||||
(词法 IDF 是增量维护的,不必重启)。
|
||||
6
assets/skills/knowledge-base/skill.json
Normal file
6
assets/skills/knowledge-base/skill.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "knowledge-base",
|
||||
"description": "按分类树检索 HomeAgent 知识库:树形导航、分类内检索、以图搜知识",
|
||||
"version": "1.1.0",
|
||||
"author": "HomeAgent"
|
||||
}
|
||||
Reference in New Issue
Block a user