name: knowledge-graph-memory description: 中文教育场景专用的类型化知识图谱记忆技能。内置 Poem/Student/KnowledgePoint 教育类型,把诗库、知识点、学生进度建成可查询、可校验的关系图(带类型的实体+关系+约束),跨会话、跨技能共享结构化状态。触发场景:(1) 用户说「记住…」「我已知晓 X 什么」「记一下…」,(2) 需要把两类对象关联(诗↔知识点、学生↔进度、人↔项目),(3) 从知识点反查诗、按作者/年级/卷册聚合,(4) 做多步规划想建模依赖,(5) 技能之间需要共享状态。触发词示例:「建个知识图谱」「把 X 关联到 Y」「从知识点反查」「知识点图谱」「结构化记忆」「关系图」「实体关系」。特别适用于古诗词/文言文/课文学习类应用(如已上线小程序「诗里行间拾遗」的诗库-知识点-学生互联),以及任何需要结构化知识沉淀的中文项目。 version: 1.0.1 display_name: "知识图谱记忆·教育版" agent_created: true
把记忆从「一堆 markdown」升级成「一张可验证的图」。内置中文教育类型(诗/知识点/学生),已在已上线的小程序「诗里行间拾遗」真实诗库实测。
一切都是实体(Entity):有类型(type)、属性(properties)、与其他实体的关系(relations)。每次变更都先按类型约束校验,再落库。
Entity: { id, type, properties, relations, created, updated }
Relation: { relation_type, to_id, properties }
| 用户说 / 场景 | 动作 |
|---|---|
| 「记住…」「记一下…」「我已知晓 X 是什么」 | 创建 / 更新实体 |
| 「把 X 关联到 Y」「X 属于 Y」 | 创建关系 |
| 「从知识点反查诗」「按作者 / 卷册 / 学段聚合」 | 图查询 |
| 「显示项目 Z 的所有任务」「X 依赖什么」 | 图遍历 / 依赖查询 |
| 「多步规划」「建复习计划」「排任务」 | 建模为图变换 |
| 「技能间共享状态」「把进度给另一个技能」 | 读写 ontology 对象 |
以下任一关键词出现时,优先走知识图谱而非平铺 markdown: 知识图谱 / 关系图 / 实体关系 / 结构化记忆 / 把 X 关联到 Y / 从知识点反查 / 知识点网络 / 建个图 / 关系建模 / 跨链接查询
| 场景 | 改用 |
|---|---|
| 一次性临时笔记、纯流水记录 | 普通 markdown / Note 文件 |
| 简单键值配置(如 settings) | 配置文件(yaml/json) |
| 需要 ACID 事务、强一致并发写的生产库 | 直接上 SQLite / 数据库 |
| 非结构化长文写作(文章、报告) | 文档工具 |
经验法则:当"反查 / 聚合 / 关联"成为核心需求,且数据会跨会话复用,才上图谱;否则轻量存储更合适。
# 通用
Person: { name, email?, phone?, notes? }
Project: { name, status, goals[], owner? }
Task: { title, status, due?, priority?, assignee?, blockers[] }
Document: { title, path?, url?, summary? }
Note: { content, tags[], refs[] }
# 教育场景(诗里行间拾遗可直接用)
Poem: { title, author, dynasty, grade, content?, mastery? }
Student: { name, grade_level, progress? }
KnowledgePoint: { topic, related_poems[], difficulty? }
# 元
Action: { type, target, timestamp, outcome? }
memory/ontology/graph.jsonl(追加写,绝不覆盖)memory/ontology/schema.yaml每行一条事件,图的最终状态 = 重放全部事件:
{"op":"create","entity":{"id":"poem_001","type":"Poem","properties":{"title":"静夜思","author":"李白","grade":"小学"}}}
{"op":"relate","from":"poem_001","relation_type":"teaches","to":"kp_001"}
mkdir -p memory/ontology && touch memory/ontology/graph.jsonl7w4.net提供免费和付费技能下载。
python3 scripts/ontology.py create --type Poem --props '{"title":"静夜思","author":"李白","grade":"一年级上册"}'
# ↑ 返回形如 "created poe_1783704926535 (Poem)",poe_xxx 就是该实体的动态 id
⚠️
<实体id>是create返回的动态值(如poe_1783704926535),不要硬编码poem_001——会报 "entity not found"。完整排错见下方「排错速查表」。
python3 scripts/ontology.py query --type Task --where '{"status":"open"}'
python3 scripts/ontology.py get --id <实体id>
python3 scripts/ontology.py related --id <实体id> --rel has_task
# id 用 create 返回的实时值;不确定时先 query 拿到 id
python3 scripts/ontology.py relate --from <诗id,如 poe_1783704926535> --rel teaches --to <知识点id,如 kno_1783704926695>
python3 scripts/ontology.py validate
# 备份当前图(自动带时间戳,存 memory/ontology/backup/)
python3 scripts/ontology.py backup
# 从某个备份还原(还原前会自动再备份一次当前状态作为安全网,不会丢数据)
python3 scripts/ontology.py restore --file memory/ontology/backup/graph.20260711_010800.jsonl
# 导出整图为单个 JSON 文件(便于迁移到别的机器 / 人工查看 / 分享)
python3 scripts/ontology.py export --out memory/ontology/export.json
# 规模监控:实体数 / 关系数 / 事件行 / 损坏行 / 文件体积 / 迁移建议
python3 scripts/ontology.py stats
# 自动修复损坏日志:备份后丢弃无法解析的行并重写干净的事件日志
python3 scripts/ontology.py repair
图谱损坏或误操作后:
restore即可回到任意历史备份;restore前会自动把"当前(可能已坏)状态"再存一份,所以永远不会彻底丢失。若graph.jsonl被意外写入半行/乱码,先repair(会自动备份并清理损坏行),再validate确认。日常用stats监控规模,临近万级时规划迁移 SQLite。
types:
Task:
required: [title, status]
status_enum: [open, in_progress, blocked, done]
relations:
teaches:
from_types: [Poem]
to_types: [KnowledgePoint]
不写 schema 也能跑(只做基础校验:类型存在、id 唯一);写了则按 required / 枚举 / 关系方向校验。
Plan: 「给《静夜思》建知识点并排复习任务」
1. CREATE KnowledgePoint { topic:"思乡", related_poems:["静夜思"] }
2. RELATE Poem(静夜思) -> teaches -> KnowledgePoint
3. CREATE Task { title:"复习思乡主题", assignee:学生, status:open }
每一步变更前先校验约束,违反即回滚该步。
下面是把已上线小程序「诗里行间拾遗」的真实诗库(小学/初中/高中三套 JS 数据)导入图谱的完整流程,已在本地实测跑通。
目标:每首诗 → 一个 Poem 实体;每首诗自带 tags(如「思乡」「咏物」「田园」)→ 一个 KnowledgePoint 实体;建 Poem -teaches-> KnowledgePoint 关系。最终得到「从知识点反查诗」的能力。
第一步:初始化
mkdir -p memory/ontology && touch memory/ontology/graph.jsonl
第二步:用 Node 把诗库批量灌进图(诗库是 data/*.js 导出的数组,每条含 id/title/author/dynasty/stage/grade/text/tags)
// build_ontology.js —— 用 ontology.py 的 create/relate 把数据转成事件日志
const fs = require('fs');
const { execFileSync } = require('child_process');
const PY = 'python3';
const ONTO = 'scripts/ontology.py';
function run(args){
return execFileSync(PY, [ONTO, ...args]).toString().trim();
}
const files = ['data/primary.js','data/middle.js','data/high.js'];
const kpCache = {}; // topic -> kp_id
for (const f of files){
const poems = require('./'+f);
for (const p of poems){
const pid = run(['create','--type','Poem','--props',
JSON.stringify({title:p.title, author:p.author, dynasty:p.dynasty||'', grade:p.grade||'', content:p.text||''})]);
for (const tag of (p.tags||[])){
let kid;
if (kpCache[tag]) { kid = kpCache[tag]; }
else {
kid = run(['create','--type','KnowledgePoint','--props', JSON.stringify({topic:tag})]);
kpCache[tag] = kid;
}
run(['relate','--from',pid,'--rel','teaches','--to',kid]);
}
}
}
console.log('done');
第三步:查询验证
# 反查「思乡」主题下有哪些诗(平铺 markdown 做不到的跨链接能力)
python3 scripts/ontology.py query --type KnowledgePoint --where '{"topic":"思乡"}'
# 按作者聚合
python3 scripts/ontology.py query --type Poem --where '{"author":"李白"}'
# 按卷册/学段筛选(数据层 grade 存原始值,如「一年级上册」)
python3 scripts/ontology.py query --type Poem --where '{"grade":"一年级上册"}'
# 校验整图
python3 scripts/ontology.py validate
实测结果:234 首诗 / 44 个知识点 / 468 条关系,全部校验通过;「思乡」主题反查出 11 首诗(静夜思、九月九日忆山东兄弟、泊船瓜洲……);按卷册 一年级上册 筛出 6 首。
合规展示映射(重要):「诗里行间拾遗」为个人主体小程序,按平台合规要求 UI 层不显示学段引导字眼。小程序 utils/poem-data.js 在展示时映射:学段 primary/middle/high → 基础篇/进阶篇/提高篇,X年级 → 第X卷(如 一年级上册→第一卷上册)。图谱数据层保留原始 grade 值(如"一年级上册"),查询按原始值;对外展示时再映射,二者不冲突——这也是图谱作为"底层结构化状态"与"上层展示"解耦的好处。
联合扩展:把文言文子包一起导入,做跨文体反查(进阶)
「诗里行间拾遗」还有独立的文言文子包(subpackages/wenyan/data/wenyan_data.js,86 篇,字段与诗库同构,含 type:'wenyan'、tags、合规映射后的 grade 如「第七卷上册」)。把它和诗库导入同一张图,价值立刻翻倍:
Poem 实体 / 文言 → ClassicalText 实体,两类文本共享同一批 KnowledgePoint(按 tag 去重)poem_count / wenyan_count / cross_genre 字段;cross_genre=true = 诗和文言都覆盖的主题(如「写景」「咏物」「爱国」),这是平铺 markdown 做不到的跨文体聚合批量灌库(数据量大时直接拼 jsonl,比逐条 CLI 快):
// build_combined.js —— 诗 + 文言 联合导入
// ⚠️ 知识点 id 必须用完整 hex,不可截断!
// 中文短 hash(hex8)会碰撞:如「乐府/乐府诗/乐天知命」都生成 kp_e4b990e5 被错误合并
const kpId = (t) => "kp_" + Buffer.from(t, "utf8").toString("hex");
for (const p of [...poems]) { /* Poem + tagged_with -> kp */ }
for (const w of wenyan) { /* ClassicalText + tagged_with -> kp */ }
跨文体反查演示(demo_query.py 读 graph.jsonl):
【1】跨文体主题(诗与文言共同覆盖,共 9 个)
· 写景 诗 46 篇 / 文言文 7 篇
· 咏物 诗 18 篇 / 文言文 1 篇
· 田园 诗 18 篇 / 文言文 1 篇
· 爱国 诗 14 篇 / 文言文 2 篇
· 哲理 诗 7 篇 / 文言文 3 篇
· 劝学 诗 1 篇 / 文言文 4 篇
…(神话 / 讽喻 / 叙事诗)
【2】主题「写景」一次反查 53 篇(诗 46 + 文言 7):
[诗] 春晓、小池、登鹳雀楼、望庐山瀑布、江雪……
[文言] 答谢中书书、记承天寺夜游、小石潭记、
岳阳楼记、醉翁亭记、赤壁赋、登泰山记
【3】作者「苏轼」跨文体聚合(诗 12 + 文言 4):
[诗] 饮湖上初晴后雨(三年级上册)…水调歌头·明月几时有(九年级上册)
[文言] 记承天寺夜游(第八卷上册)、赤壁赋(必修上册)、
书戴嵩画牛、石钟山记
注意【3】里诗用原始 grade(三年级上册)、文言用合规映射值(第八卷上册)——正好印证上一节"数据层 vs 展示层"解耦。
联合实测:诗 234 + 文言文 86 = 320 文本实体,知识点 345 个(含 9 个跨文体),关系 945 条,validate 全部通过(共 665 实体)。完整脚本见 examples/build_combined.js 与 examples/demo_query.py(随技能提供,可直接跑)。
第四步:备份(发布前必做)
python3 scripts/ontology.py backup
service + secret_ref 间接引用,绝不写明文 token| 现象 | 原因 | 解决 |
|---|---|---|
entity xxx not found(明明建过) |
id 是动态生成的(如 poe_1717939200123_8842),不是你传入的名字 |
用 create 打印的真实 id;或 query --where '{"title":"..."}' 反查 |
relate 报 not found |
--from/--to 用了静态占位 poem_001 |
改为 create 返回值;不确定先 query 拿 id |
validate 报 N malformed line(s) skipped |
日志里混入了半行/乱码 | 跑 repair(自动备份+清理),再 validate |
| 高吞吐下实体"神秘消失" | 旧版 id 同毫秒同类型会碰撞(已修复) | v1.0.1+ 用 毫秒_随机 后缀,天然唯一;升级后重跑即可 |
| 多进程同时写偶发丢事件 | 当前为追加写,高频并发不保证原子 | 单写者模型,或迁移 SQLite(见下) |
| 图越用越慢 | 实体量级接近万级 | stats 查看;超 2 万建议迁 SQLite |
所有写入均加文件锁 +
fsync刷盘;id 带随机后缀杜绝碰撞;repair可自愈损坏日志——这是 v1.0.1 可靠性升级的核心。
本地实测(Python 3.13 / Windows,零依赖 CLI):
| 操作 | 实测表现 |
|---|---|
create 单次 CLI 调用 |
~119 ms / 次(瓶颈是 Python 解释器冷启动,非磁盘写入) |
query / validate / stats(20,000 实体) |
均 < 0.3 s(0.23–0.28 s) |
| 20,000 实体文件体积 | ~3.8 MB(jsonl) |
诗里行间拾遗实测 665 实体的图查询是毫秒级。examples/build_combined.js,它直接拼 jsonl 文件,234 首诗 + 86 文言文仅秒级完成)。小规模(几十~几百)逐条 CLI 完全无感。entities/relations 两表,CLI 接口可保持不变,stats 会给出迁移建议)。fsync 刷盘,短时并发安全;高频并发写请采用「单写者」模式(一个 agent 负责写,其余只读),或迁 SQLite 带锁。进程崩溃不会留半行(事件写完才返回)。类型前缀_毫秒_随机,实测 5000 条同毫秒连建 零重复(旧版曾因同毫秒同类型碰撞丢数据,已根治)。repair 会自动备份并丢弃损坏行、重写干净日志,validate 可随时体检。Q:图谱文件损坏或被覆盖了,怎么办?
A:用 python3 scripts/ontology.py restore --file <备份路径> 还原。还原前会自动再备份一次当前状态,所以不会二次丢失。如果从未手动备份,至少 backup 目录里应有初始化后的空状态;日常养成操作前先 backup 的习惯即可。
Q:创建实体时报 entity xxx not found,但明明建过?
A:id 是动态生成的(如 poe_1717939200123),不是你传入的名字。建完会打印真实 id,请复制它用于 relate/related/get。用 --props 里的 title/name 做 query --where 反查更稳妥。
Q:想用的类型(如 Lesson)不在内置列表里,能加吗?
A:能。直接在 create --type Lesson 用即可,SKILL.md 的类型只是约定示例,不做硬限制。若要强制校验必填字段,在 schema.yaml 的 types: 下加 Lesson: { required: [title] }。
Q:数据量很大(上万实体),还用 jsonl 吗?
A:jsonl 适合中小规模(千级~万级),好处是可回放、可审计。两点提醒:① create 单次 CLI 调用约 119ms(瓶颈是 Python 冷启动),所以大批量灌库请直接追加 jsonl 事件行,不要循环 spawn CLI——参考 examples/build_combined.js;② 规模再大(>2 万)建议迁移到 SQLite(按同样 schema 建 entities / relations 两表),CLI 接口可保持不变,stats 会给出迁移建议。读操作(query/validate)即便 2 万实体也亚秒级。
Q:日志文件损坏 / 混入半行乱码,怎么办?
A:先 python3 scripts/ontology.py repair——它会自动备份当前图,丢弃无法解析的行并重写干净的事件日志;再 validate 确认。日常用 backup 养成习惯,出错随时 restore(还原前还会再备份一次,永不丢数据)。
Q:多 agent / 多进程同时写会冲突吗? A:v1.0.1 写入经文件锁串行化 + fsync 刷盘,短时并发安全(不会字节交错、不会留半行)。高频并发写仍建议:① 单写者模型(一个 agent 负责写,其余只读);② 或迁移到带锁的 SQLite。
Q:这个技能和通用版 ontology 有什么不同?
A:概念同源(受 ClawHub @oswalpalash 启发、独立重写),差异在:① 内置 Poem/Student/KnowledgePoint 中文教育类型;② 自带 backup/restore/export 容错命令;③ 提供「诗里行间拾遗」真实诗库的完整落地案例。通用 ontology 是平台已有的中性版本,本技能是教育场景专精版。
受 ClawHub 热门技能 ontology(@oswalpalash)启发,独立重写实现。已去除 OpenClaw 平台依赖、对齐 WorkBuddy 记忆体系,并补充中文教育场景(诗里行间拾遗)类型。原作概念版权归 @oswalpalash 所有。
这个技能质量不错,文档写得非常详细,连触发词和适用场景都列得很清楚,真实案例「诗里行间拾遗」也证明了它确实能用在实际项目中。它内置了诗词、学生、知识点等教育相关的类型,用起来很方便。缺点是它只能通过命令行操作,没有更简单的界面或接口;另外它用 JSONL 存储数据,数据量大时可能会变慢。总体来说,这是一个实用、有真实需求背景的工具包,适合教育类应用使用。