dierdanao 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. dierdanao-1.1.0/LICENSE +21 -0
  2. dierdanao-1.1.0/PKG-INFO +209 -0
  3. dierdanao-1.1.0/README.md +175 -0
  4. dierdanao-1.1.0/pyproject.toml +64 -0
  5. dierdanao-1.1.0/setup.cfg +4 -0
  6. dierdanao-1.1.0/src/dierdanao/__init__.py +1 -0
  7. dierdanao-1.1.0/src/dierdanao/cli/__init__.py +1 -0
  8. dierdanao-1.1.0/src/dierdanao/cli/main.py +195 -0
  9. dierdanao-1.1.0/src/dierdanao/contradiction_finder/__init__.py +0 -0
  10. dierdanao-1.1.0/src/dierdanao/contradiction_finder/cli.py +171 -0
  11. dierdanao-1.1.0/src/dierdanao/contradiction_finder/contradiction.py +175 -0
  12. dierdanao-1.1.0/src/dierdanao/contradiction_finder/dictionary.py +36 -0
  13. dierdanao-1.1.0/src/dierdanao/contradiction_finder/models.py +25 -0
  14. dierdanao-1.1.0/src/dierdanao/gap_detector/__init__.py +0 -0
  15. dierdanao-1.1.0/src/dierdanao/gap_detector/cli.py +132 -0
  16. dierdanao-1.1.0/src/dierdanao/gap_detector/clustering.py +64 -0
  17. dierdanao-1.1.0/src/dierdanao/gap_detector/gap_finder.py +94 -0
  18. dierdanao-1.1.0/src/dierdanao/hypothesis_generator/__init__.py +0 -0
  19. dierdanao-1.1.0/src/dierdanao/hypothesis_generator/cli.py +110 -0
  20. dierdanao-1.1.0/src/dierdanao/hypothesis_generator/engine.py +113 -0
  21. dierdanao-1.1.0/src/dierdanao/hypothesis_generator/rules.py +343 -0
  22. dierdanao-1.1.0/src/dierdanao/knowledge_linker/__init__.py +0 -0
  23. dierdanao-1.1.0/src/dierdanao/knowledge_linker/cli.py +113 -0
  24. dierdanao-1.1.0/src/dierdanao/knowledge_synthesis/__init__.py +0 -0
  25. dierdanao-1.1.0/src/dierdanao/knowledge_synthesis/cli.py +174 -0
  26. dierdanao-1.1.0/src/dierdanao/knowledge_synthesis/synthesis.py +257 -0
  27. dierdanao-1.1.0/src/dierdanao/open_mem/__init__.py +0 -0
  28. dierdanao-1.1.0/src/dierdanao/open_mem/cli.py +248 -0
  29. dierdanao-1.1.0/src/dierdanao/open_mem/config.py +138 -0
  30. dierdanao-1.1.0/src/dierdanao/open_mem/embedding.py +53 -0
  31. dierdanao-1.1.0/src/dierdanao/open_mem/memory_engine.py +423 -0
  32. dierdanao-1.1.0/src/dierdanao/open_mem_client/__init__.py +5 -0
  33. dierdanao-1.1.0/src/dierdanao/open_mem_client/client.py +106 -0
  34. dierdanao-1.1.0/src/dierdanao/open_mem_client/exceptions.py +10 -0
  35. dierdanao-1.1.0/src/dierdanao/open_mem_client/models.py +48 -0
  36. dierdanao-1.1.0/src/dierdanao/open_mem_doctor/__init__.py +0 -0
  37. dierdanao-1.1.0/src/dierdanao/open_mem_doctor/checks.py +499 -0
  38. dierdanao-1.1.0/src/dierdanao/open_mem_doctor/cli.py +145 -0
  39. dierdanao-1.1.0/src/dierdanao/open_mem_doctor/models.py +54 -0
  40. dierdanao-1.1.0/src/dierdanao/skills/contradiction-finder/SKILL.md +42 -0
  41. dierdanao-1.1.0/src/dierdanao/skills/dierdanao/SKILL.md +65 -0
  42. dierdanao-1.1.0/src/dierdanao/skills/gap-detector/SKILL.md +44 -0
  43. dierdanao-1.1.0/src/dierdanao/skills/hypothesis-generator/SKILL.md +43 -0
  44. dierdanao-1.1.0/src/dierdanao/skills/knowledge-linker/SKILL.md +43 -0
  45. dierdanao-1.1.0/src/dierdanao/skills/knowledge-synthesis/SKILL.md +52 -0
  46. dierdanao-1.1.0/src/dierdanao/skills/open-mem/SKILL.md +87 -0
  47. dierdanao-1.1.0/src/dierdanao/skills/open-mem-doctor/SKILL.md +67 -0
  48. dierdanao-1.1.0/src/dierdanao.egg-info/PKG-INFO +209 -0
  49. dierdanao-1.1.0/src/dierdanao.egg-info/SOURCES.txt +51 -0
  50. dierdanao-1.1.0/src/dierdanao.egg-info/dependency_links.txt +1 -0
  51. dierdanao-1.1.0/src/dierdanao.egg-info/entry_points.txt +9 -0
  52. dierdanao-1.1.0/src/dierdanao.egg-info/requires.txt +7 -0
  53. dierdanao-1.1.0/src/dierdanao.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pjr0
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.4
2
+ Name: dierdanao
3
+ Version: 1.1.0
4
+ Summary: Second Brain — AI Agent friendly memory engine ecosystem
5
+ Author: pjr0
6
+ License: MIT
7
+ Project-URL: Homepage, https://gitee.com/pjr0/dierdanao
8
+ Project-URL: Source, https://gitee.com/pjr0/dierdanao
9
+ Project-URL: BugTracker, https://gitee.com/pjr0/dierdanao/issues
10
+ Project-URL: Documentation, https://gitee.com/pjr0/dierdanao#readme
11
+ Keywords: memory-engine,ai-agent,knowledge-graph,faiss,second-brain
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Operating System :: POSIX :: Linux
21
+ Classifier: Operating System :: MacOS
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: faiss-cpu>=1.13
27
+ Requires-Dist: numpy>=2.0
28
+ Requires-Dist: typer>=0.12
29
+ Requires-Dist: pyyaml>=6.0
30
+ Requires-Dist: requests>=2.31
31
+ Requires-Dist: tenacity>=8.0
32
+ Requires-Dist: scikit-learn>=1.3.0
33
+ Dynamic: license-file
34
+
35
+ # 🧠 dierdanao — 第二大脑
36
+
37
+ **你的 AI 外脑,让它替你记住、关联、发现。** 完全本地运行,零隐私风险。
38
+
39
+ > **你**:帮我记,我家狗每次我上厕所它都要跟进来盯着
40
+ >
41
+ > **你**:又记一条——狗的祖先是群居动物,野外排便时同伴会互相放哨
42
+ >
43
+ > **你**:依恋理论里有个概念叫"安全基地"——婴儿把妈妈当作探索世界的安全后盾
44
+ >
45
+ > *…几周后,你的知识库里攒了一些宠物行为、动物学、心理学的零散观察…*
46
+ >
47
+ > **你**:看看这些宠物相关的记录有没有关联?
48
+ >
49
+ > **AI**:聚合了 5 条相关记忆。发现一处知识空白——你对"犬类社会认知"的研究很少。另外,基于你记录的机制我推导出一个假设:**如果厕所对狗来说是一个密闭且无法逃跑的空间,它在你排便时仍然选择跟随你,这不是好奇——它在给你当哨兵。它认为排便时的你是脆弱的,在用盯防回馈你给它的安全感。**
50
+
51
+ 你不是动物学家,你只是养了条狗。系统帮你从日常观察中推了一个跨物种的行为学假设。
52
+
53
+ ---
54
+
55
+ ## 为什么你需要它?
56
+
57
+ 每次对话结束,你的 AI 助手就忘了你们讨论过什么。
58
+
59
+ dierdanao 给它装上"记忆硬盘":
60
+
61
+ - **记住一切** — 知识、决策、灵感,语义级存储
62
+ - **随时检索** — 一句话就能找到,不需要精确关键词
63
+ - **自动关联** — 发现隐藏联系,识别矛盾,找到空白
64
+ - **推导新想法** — 从已有知识交叉推导出新假设
65
+
66
+ ---
67
+
68
+ ## 快速安装
69
+
70
+ ### AI 自主安装(推荐)
71
+
72
+ 复制这个链接给你的 AI Agent,它会自动完成全部安装:
73
+
74
+ ```
75
+ https://gitee.com/pjr0/dierdanao/raw/main/AI-INSTALL.md
76
+ ```
77
+
78
+ 如果无法访问 Gitee,也可以复制仓库中的 [`AI-INSTALL.md`](https://gitee.com/pjr0/dierdanao/raw/main/AI-INSTALL.md) 文件内容直接粘贴给 AI。
79
+
80
+ > 注意:AI 需要能访问 gitee.com 来 git clone 仓库。如果网络受限,请先手动下载仓库再让 AI 安装。
81
+
82
+ ### 手动安装
83
+
84
+ ```bash
85
+ git clone https://gitee.com/pjr0/dierdanao.git
86
+ cd dierdanao
87
+ bash install.sh # 自动完成所有安装
88
+ dierdanao init # 部署 AI Agent 技能
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 它是怎么工作的
94
+
95
+ ```
96
+ 你随口记录
97
+
98
+
99
+ ┌─────────────┐ ┌──────────────────┐ ┌───────────────────┐
100
+ │ open-mem │───▶│ knowledge-linker │───▶│ gap-detector │
101
+ │ 语义存储 │ │ 发现隐藏关联 │ │ 识别知识空白 │
102
+ └─────────────┘ └──────────────────┘ └───────────────────┘
103
+
104
+ ┌────────────────────────────┘
105
+
106
+ ┌─────────────────────┐ ┌────────────────────────┐
107
+ │ contradiction-finder│───▶│ hypothesis-generator │
108
+ │ 发现观点冲突 │ │ 从矛盾中生成新假设 │
109
+ └─────────────────────┘ └────────────────────────┘
110
+ ```
111
+
112
+ **当你的记忆到达一定规模,更深层的东西开始浮现:**
113
+
114
+ > 你在研究心理学和社会学,记忆库里并存着:
115
+ >
116
+ > 津巴多监狱实验:情境力量使普通人作恶 / 米尔格拉姆服从实验 / 企业科层组织研究:层级越多发声意愿越低 / 旁观者效应:群体中个人责任感被稀释
117
+ >
118
+ > `contradiction-finder` 标记了深层矛盾:**"个体有道德判断力" vs "群体中个体服从权威"**
119
+ >
120
+ > `gap-detector` 发现你在"权威服从"上积累了大量研究,但对**"如何打破服从"**的记录几乎为零
121
+ >
122
+ > `hypothesis-generator` 推导出一个跨领域假设:**旁观者效应中的"责任分散"和科层组织中的"责任上移"可能共享同一心理机制——组织扁平化 + 匿名举报通道,是否能打破米尔格拉姆式的服从链条?**
123
+ >
124
+ > 两条独立的研究线索,系统帮你架了一座桥。
125
+
126
+ ---
127
+
128
+ ## 8 个工具,一个生态
129
+
130
+ | 工具 | 用途 | 一句话 |
131
+ |------|------|--------|
132
+ | **open-mem** 🧩 | 核心记忆引擎 | 存进去,搜出来 |
133
+ | **open-mem-doctor** 🏥 | 健康诊断 | 14 项检查,一键定位问题 |
134
+ | **knowledge-linker** 🔗 | 关联发现 | 新知识进来,自动关联已有记忆 |
135
+ | **contradiction-finder** ⚡ | 矛盾检测 | 发现知识库中的观点冲突 |
136
+ | **gap-detector** 🕳️ | 空白扫描 | 告诉你该补什么知识 |
137
+ | **hypothesis-generator** 💡 | 假设生成 | 从已有知识推导新想法 |
138
+ | **knowledge-synthesis** 🧪 | 知识合成 | 聚合主题下的记忆,供 AI 提炼总结 |
139
+ | **open-mem-client** 📦 | 客户端库 | 给其他工具调用的 Python SDK |
140
+
141
+ ---
142
+
143
+ ## 教程
144
+
145
+ ### 基础工具
146
+
147
+ | 教程 | |
148
+ |------|------|
149
+ | [构建个人知识库](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/01-personal-knowledge-base.md) | 记、搜、改、删——掌握 open-mem 核心操作 |
150
+ | [健康诊断](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/07-open-mem-doctor.md) | 14 项检查覆盖引擎、工具链、数据完整性,一键定位问题 |
151
+ | [发现知识关联](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/05-knowledge-linker.md) | 新知识进来,自动发现它与已有记忆的隐藏联系 |
152
+ | [发现知识矛盾](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/02-contradiction-detection.md) | 扫描知识库,找出互相对立的观点,避免认知冲突 |
153
+ | [发现知识空白](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/03-gap-detection.md) | 聚类分析告诉你哪些领域积累不够,该补什么 |
154
+ | [生成新假设](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/04-hypothesis-generation.md) | 从已有知识交叉推导,生成可验证的新想法 |
155
+ | [知识合成](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/06-knowledge-synthesis.md) | 按主题聚合记忆,供 AI 提炼深度总结 |
156
+
157
+ ### 实战场景
158
+
159
+ | 教程 | |
160
+ |------|------|
161
+ | [日常 AI 工作流](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/08-daily-ai-workflow.md) | 从"帮我记一下"开始——你随口说,AI 自动归类存入 open-mem;几天后你问"我上次记的那个咖啡相关的东西",AI 搜出来不说,还告诉你"咖啡因阻断腺苷和午睡清除腺苷其实是同一件事的两个面",最后推导出一个你没想到的结论 |
162
+ | [用 dierdanao 做技术调研](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/09-tech-research.md) | 调研新技术方向时,把每次查到的资料、自己的判断、踩的坑全部记进去。积累到一定量后,系统自动找出:哪些信息互相矛盾?哪块你了解得还不够?已有信息能推导出什么新方向?——从信息收集到形成观点 |
163
+ | [管理读书笔记](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/10-reading-notes.md) | 读完一本书记几条核心观点,读完另一本又记几条。当笔记跨了 5 本书,系统开始做你大脑做不到的事——发现《思考快与慢》的系统 1 和《原子习惯》的"环境设计"在说同一件事,推导出"用环境触发代替意志力决策"这个两本书都没明说的结论 |
164
+
165
+ ---
166
+
167
+ ## 配置
168
+
169
+ 启动一个本地 Embedding 服务(如 [llama.cpp](https://github.com/ggerganov/llama.cpp)),或使用任意 OpenAI 兼容接口:
170
+
171
+ ```yaml
172
+ # ~/.open-mem/config.yaml
173
+ embedding:
174
+ base_url: http://localhost:8080/v1
175
+ model: default
176
+ api_key: sk-noop
177
+ ```
178
+
179
+ 也支持环境变量:
180
+
181
+ | 变量 | 默认值 | 说明 |
182
+ |------|--------|------|
183
+ | `OPENMEM_EMBEDDING_BASE_URL` | `http://localhost:8080/v1` | Embedding API 地址 |
184
+ | `OPENMEM_EMBEDDING_API_KEY` | `sk-noop` | API 密钥 |
185
+ | `OPENMEM_DEDUP_THRESHOLD` | `0.92` | 去重阈值 |
186
+ | `OPENMEM_ENABLE_TIME_DECAY` | `false` | 启用时间衰减 |
187
+
188
+ ---
189
+
190
+ ## 卸载
191
+
192
+ ```bash
193
+ # 移除所有 AI 工具的 skill 文件
194
+ dierdanao uninstall
195
+
196
+ # 移除 skill 的同时删除记忆数据
197
+ dierdanao uninstall --purge-data
198
+
199
+ # 完全移除(skill + 数据 + pip 卸载提示)
200
+ dierdanao uninstall --all
201
+ ```
202
+
203
+ ---
204
+
205
+ ## 许可证
206
+
207
+ MIT © 2026 pjr0
208
+
209
+ 欢迎 fork 和自定义改造。如果你基于本项目做了有意思的修改,欢迎提 Pull Request 或联系作者交流。
@@ -0,0 +1,175 @@
1
+ # 🧠 dierdanao — 第二大脑
2
+
3
+ **你的 AI 外脑,让它替你记住、关联、发现。** 完全本地运行,零隐私风险。
4
+
5
+ > **你**:帮我记,我家狗每次我上厕所它都要跟进来盯着
6
+ >
7
+ > **你**:又记一条——狗的祖先是群居动物,野外排便时同伴会互相放哨
8
+ >
9
+ > **你**:依恋理论里有个概念叫"安全基地"——婴儿把妈妈当作探索世界的安全后盾
10
+ >
11
+ > *…几周后,你的知识库里攒了一些宠物行为、动物学、心理学的零散观察…*
12
+ >
13
+ > **你**:看看这些宠物相关的记录有没有关联?
14
+ >
15
+ > **AI**:聚合了 5 条相关记忆。发现一处知识空白——你对"犬类社会认知"的研究很少。另外,基于你记录的机制我推导出一个假设:**如果厕所对狗来说是一个密闭且无法逃跑的空间,它在你排便时仍然选择跟随你,这不是好奇——它在给你当哨兵。它认为排便时的你是脆弱的,在用盯防回馈你给它的安全感。**
16
+
17
+ 你不是动物学家,你只是养了条狗。系统帮你从日常观察中推了一个跨物种的行为学假设。
18
+
19
+ ---
20
+
21
+ ## 为什么你需要它?
22
+
23
+ 每次对话结束,你的 AI 助手就忘了你们讨论过什么。
24
+
25
+ dierdanao 给它装上"记忆硬盘":
26
+
27
+ - **记住一切** — 知识、决策、灵感,语义级存储
28
+ - **随时检索** — 一句话就能找到,不需要精确关键词
29
+ - **自动关联** — 发现隐藏联系,识别矛盾,找到空白
30
+ - **推导新想法** — 从已有知识交叉推导出新假设
31
+
32
+ ---
33
+
34
+ ## 快速安装
35
+
36
+ ### AI 自主安装(推荐)
37
+
38
+ 复制这个链接给你的 AI Agent,它会自动完成全部安装:
39
+
40
+ ```
41
+ https://gitee.com/pjr0/dierdanao/raw/main/AI-INSTALL.md
42
+ ```
43
+
44
+ 如果无法访问 Gitee,也可以复制仓库中的 [`AI-INSTALL.md`](https://gitee.com/pjr0/dierdanao/raw/main/AI-INSTALL.md) 文件内容直接粘贴给 AI。
45
+
46
+ > 注意:AI 需要能访问 gitee.com 来 git clone 仓库。如果网络受限,请先手动下载仓库再让 AI 安装。
47
+
48
+ ### 手动安装
49
+
50
+ ```bash
51
+ git clone https://gitee.com/pjr0/dierdanao.git
52
+ cd dierdanao
53
+ bash install.sh # 自动完成所有安装
54
+ dierdanao init # 部署 AI Agent 技能
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 它是怎么工作的
60
+
61
+ ```
62
+ 你随口记录
63
+
64
+
65
+ ┌─────────────┐ ┌──────────────────┐ ┌───────────────────┐
66
+ │ open-mem │───▶│ knowledge-linker │───▶│ gap-detector │
67
+ │ 语义存储 │ │ 发现隐藏关联 │ │ 识别知识空白 │
68
+ └─────────────┘ └──────────────────┘ └───────────────────┘
69
+
70
+ ┌────────────────────────────┘
71
+
72
+ ┌─────────────────────┐ ┌────────────────────────┐
73
+ │ contradiction-finder│───▶│ hypothesis-generator │
74
+ │ 发现观点冲突 │ │ 从矛盾中生成新假设 │
75
+ └─────────────────────┘ └────────────────────────┘
76
+ ```
77
+
78
+ **当你的记忆到达一定规模,更深层的东西开始浮现:**
79
+
80
+ > 你在研究心理学和社会学,记忆库里并存着:
81
+ >
82
+ > 津巴多监狱实验:情境力量使普通人作恶 / 米尔格拉姆服从实验 / 企业科层组织研究:层级越多发声意愿越低 / 旁观者效应:群体中个人责任感被稀释
83
+ >
84
+ > `contradiction-finder` 标记了深层矛盾:**"个体有道德判断力" vs "群体中个体服从权威"**
85
+ >
86
+ > `gap-detector` 发现你在"权威服从"上积累了大量研究,但对**"如何打破服从"**的记录几乎为零
87
+ >
88
+ > `hypothesis-generator` 推导出一个跨领域假设:**旁观者效应中的"责任分散"和科层组织中的"责任上移"可能共享同一心理机制——组织扁平化 + 匿名举报通道,是否能打破米尔格拉姆式的服从链条?**
89
+ >
90
+ > 两条独立的研究线索,系统帮你架了一座桥。
91
+
92
+ ---
93
+
94
+ ## 8 个工具,一个生态
95
+
96
+ | 工具 | 用途 | 一句话 |
97
+ |------|------|--------|
98
+ | **open-mem** 🧩 | 核心记忆引擎 | 存进去,搜出来 |
99
+ | **open-mem-doctor** 🏥 | 健康诊断 | 14 项检查,一键定位问题 |
100
+ | **knowledge-linker** 🔗 | 关联发现 | 新知识进来,自动关联已有记忆 |
101
+ | **contradiction-finder** ⚡ | 矛盾检测 | 发现知识库中的观点冲突 |
102
+ | **gap-detector** 🕳️ | 空白扫描 | 告诉你该补什么知识 |
103
+ | **hypothesis-generator** 💡 | 假设生成 | 从已有知识推导新想法 |
104
+ | **knowledge-synthesis** 🧪 | 知识合成 | 聚合主题下的记忆,供 AI 提炼总结 |
105
+ | **open-mem-client** 📦 | 客户端库 | 给其他工具调用的 Python SDK |
106
+
107
+ ---
108
+
109
+ ## 教程
110
+
111
+ ### 基础工具
112
+
113
+ | 教程 | |
114
+ |------|------|
115
+ | [构建个人知识库](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/01-personal-knowledge-base.md) | 记、搜、改、删——掌握 open-mem 核心操作 |
116
+ | [健康诊断](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/07-open-mem-doctor.md) | 14 项检查覆盖引擎、工具链、数据完整性,一键定位问题 |
117
+ | [发现知识关联](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/05-knowledge-linker.md) | 新知识进来,自动发现它与已有记忆的隐藏联系 |
118
+ | [发现知识矛盾](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/02-contradiction-detection.md) | 扫描知识库,找出互相对立的观点,避免认知冲突 |
119
+ | [发现知识空白](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/03-gap-detection.md) | 聚类分析告诉你哪些领域积累不够,该补什么 |
120
+ | [生成新假设](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/04-hypothesis-generation.md) | 从已有知识交叉推导,生成可验证的新想法 |
121
+ | [知识合成](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/06-knowledge-synthesis.md) | 按主题聚合记忆,供 AI 提炼深度总结 |
122
+
123
+ ### 实战场景
124
+
125
+ | 教程 | |
126
+ |------|------|
127
+ | [日常 AI 工作流](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/08-daily-ai-workflow.md) | 从"帮我记一下"开始——你随口说,AI 自动归类存入 open-mem;几天后你问"我上次记的那个咖啡相关的东西",AI 搜出来不说,还告诉你"咖啡因阻断腺苷和午睡清除腺苷其实是同一件事的两个面",最后推导出一个你没想到的结论 |
128
+ | [用 dierdanao 做技术调研](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/09-tech-research.md) | 调研新技术方向时,把每次查到的资料、自己的判断、踩的坑全部记进去。积累到一定量后,系统自动找出:哪些信息互相矛盾?哪块你了解得还不够?已有信息能推导出什么新方向?——从信息收集到形成观点 |
129
+ | [管理读书笔记](https://gitee.com/pjr0/dierdanao/raw/main/docs/tutorials/10-reading-notes.md) | 读完一本书记几条核心观点,读完另一本又记几条。当笔记跨了 5 本书,系统开始做你大脑做不到的事——发现《思考快与慢》的系统 1 和《原子习惯》的"环境设计"在说同一件事,推导出"用环境触发代替意志力决策"这个两本书都没明说的结论 |
130
+
131
+ ---
132
+
133
+ ## 配置
134
+
135
+ 启动一个本地 Embedding 服务(如 [llama.cpp](https://github.com/ggerganov/llama.cpp)),或使用任意 OpenAI 兼容接口:
136
+
137
+ ```yaml
138
+ # ~/.open-mem/config.yaml
139
+ embedding:
140
+ base_url: http://localhost:8080/v1
141
+ model: default
142
+ api_key: sk-noop
143
+ ```
144
+
145
+ 也支持环境变量:
146
+
147
+ | 变量 | 默认值 | 说明 |
148
+ |------|--------|------|
149
+ | `OPENMEM_EMBEDDING_BASE_URL` | `http://localhost:8080/v1` | Embedding API 地址 |
150
+ | `OPENMEM_EMBEDDING_API_KEY` | `sk-noop` | API 密钥 |
151
+ | `OPENMEM_DEDUP_THRESHOLD` | `0.92` | 去重阈值 |
152
+ | `OPENMEM_ENABLE_TIME_DECAY` | `false` | 启用时间衰减 |
153
+
154
+ ---
155
+
156
+ ## 卸载
157
+
158
+ ```bash
159
+ # 移除所有 AI 工具的 skill 文件
160
+ dierdanao uninstall
161
+
162
+ # 移除 skill 的同时删除记忆数据
163
+ dierdanao uninstall --purge-data
164
+
165
+ # 完全移除(skill + 数据 + pip 卸载提示)
166
+ dierdanao uninstall --all
167
+ ```
168
+
169
+ ---
170
+
171
+ ## 许可证
172
+
173
+ MIT © 2026 pjr0
174
+
175
+ 欢迎 fork 和自定义改造。如果你基于本项目做了有意思的修改,欢迎提 Pull Request 或联系作者交流。
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "dierdanao"
7
+ version = "1.1.0"
8
+ description = "Second Brain — AI Agent friendly memory engine ecosystem"
9
+ requires-python = ">=3.10"
10
+ authors = [
11
+ {name = "pjr0"},
12
+ ]
13
+ license = {text = "MIT"}
14
+ readme = "README.md"
15
+ keywords = ["memory-engine", "ai-agent", "knowledge-graph", "faiss", "second-brain"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Operating System :: POSIX :: Linux",
26
+ "Operating System :: MacOS",
27
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
28
+ ]
29
+ dependencies = [
30
+ "faiss-cpu>=1.13",
31
+ "numpy>=2.0",
32
+ "typer>=0.12",
33
+ "pyyaml>=6.0",
34
+ "requests>=2.31",
35
+ "tenacity>=8.0",
36
+ "scikit-learn>=1.3.0",
37
+ ]
38
+
39
+ [project.scripts]
40
+ open-mem = "dierdanao.open_mem.cli:app"
41
+ open-mem-doctor = "dierdanao.open_mem_doctor.cli:app"
42
+ contradiction-finder = "dierdanao.contradiction_finder.cli:app"
43
+ gap-detector = "dierdanao.gap_detector.cli:app"
44
+ hypothesis-generator = "dierdanao.hypothesis_generator.cli:app"
45
+ knowledge-linker = "dierdanao.knowledge_linker.cli:app"
46
+ knowledge-synthesis = "dierdanao.knowledge_synthesis.cli:app"
47
+ dierdanao = "dierdanao.cli.main:app"
48
+
49
+ [tool.setuptools.packages.find]
50
+ where = ["src"]
51
+ include = ["dierdanao*"]
52
+
53
+ [tool.setuptools.package-data]
54
+ dierdanao = ["skills/**/*.md"]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
58
+ python_files = ["test_*.py"]
59
+
60
+ [project.urls]
61
+ Homepage = "https://gitee.com/pjr0/dierdanao"
62
+ Source = "https://gitee.com/pjr0/dierdanao"
63
+ BugTracker = "https://gitee.com/pjr0/dierdanao/issues"
64
+ Documentation = "https://gitee.com/pjr0/dierdanao#readme"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__ = "1.1.0"
@@ -0,0 +1,195 @@
1
+ import shutil
2
+ from pathlib import Path
3
+
4
+ import typer
5
+
6
+ app = typer.Typer(
7
+ name="dierdanao",
8
+ help="Second Brain — memory engine ecosystem management",
9
+ )
10
+
11
+
12
+ @app.callback()
13
+ def main():
14
+ """Second Brain — memory engine ecosystem management"""
15
+ pass
16
+
17
+ TOOL_PATHS = {
18
+ "opencode": {
19
+ "project": ".opencode/skills",
20
+ "global": lambda: Path.home() / ".config" / "opencode" / "skills",
21
+ },
22
+ "claude-code": {
23
+ "project": ".claude/skills",
24
+ "global": lambda: Path.home() / ".claude" / "skills",
25
+ },
26
+ "pi": {
27
+ "project": ".pi/skills",
28
+ "global": lambda: Path.home() / ".pi" / "agent" / "skills",
29
+ },
30
+ }
31
+
32
+
33
+ def _get_skill_names() -> list[str]:
34
+ """Return skill names from the bundled skills/ directory."""
35
+ from importlib.resources import files
36
+ skills_dir = files("dierdanao") / "skills"
37
+ if not skills_dir.is_dir():
38
+ return []
39
+ return sorted(d.name for d in skills_dir.iterdir() if d.is_dir())
40
+
41
+
42
+ def _deploy_skill(skill_name: str, dest_dir: Path, force: bool) -> bool:
43
+ """Deploy one SKILL.md to target directory. Returns True if copied."""
44
+ from importlib.resources import files
45
+ src = files("dierdanao") / "skills" / skill_name / "SKILL.md"
46
+ if not src.is_file():
47
+ return False
48
+ dest = dest_dir / skill_name / "SKILL.md"
49
+ if dest.exists() and not force:
50
+ return False
51
+ dest.parent.mkdir(parents=True, exist_ok=True)
52
+ shutil.copy2(str(src), str(dest))
53
+ return True
54
+
55
+
56
+ def _deploy_all(dest_dir: Path, force: bool) -> dict[str, str]:
57
+ """Deploy all skills. Returns {skill_name: status}."""
58
+ results = {}
59
+ for skill_name in _get_skill_names():
60
+ copied = _deploy_skill(skill_name, dest_dir, force)
61
+ if copied:
62
+ results[skill_name] = "copied"
63
+ elif (dest_dir / skill_name / "SKILL.md").exists():
64
+ results[skill_name] = "exists"
65
+ else:
66
+ results[skill_name] = "failed"
67
+ return results
68
+
69
+
70
+ @app.command(name="init")
71
+ def init(
72
+ global_install: bool = typer.Option(
73
+ False, "--global", help="Install to global skill directories"
74
+ ),
75
+ tool: str = typer.Option(
76
+ None, "--tool", help="Target tool: opencode, claude-code, pi (default: all)"
77
+ ),
78
+ force: bool = typer.Option(
79
+ False, "--force", help="Overwrite existing SKILL.md files"
80
+ ),
81
+ ):
82
+ """Deploy SKILL.md files to AI coding agent skill directories."""
83
+ tools = [tool] if tool else list(TOOL_PATHS.keys())
84
+
85
+ for t in tools:
86
+ if t not in TOOL_PATHS:
87
+ typer.secho(f"Unknown tool: {t}", fg=typer.colors.RED, err=True)
88
+ raise typer.Exit(code=1)
89
+
90
+ if global_install:
91
+ dest = TOOL_PATHS[t]["global"]()
92
+ else:
93
+ dest = Path.cwd() / TOOL_PATHS[t]["project"]
94
+
95
+ results = _deploy_all(dest, force)
96
+
97
+ typer.secho(f"\n[{t}] {dest}", fg=typer.colors.BLUE, bold=True)
98
+ for skill_name, status in results.items():
99
+ if status == "copied":
100
+ typer.secho(f" ✓ {skill_name}", fg=typer.colors.GREEN)
101
+ elif status == "exists":
102
+ typer.secho(f" - {skill_name} (already exists)", fg=typer.colors.YELLOW)
103
+ else:
104
+ typer.secho(f" ✗ {skill_name} (failed)", fg=typer.colors.RED)
105
+
106
+ typer.secho("\nDone. Restart your AI agent to load new skills.", bold=True)
107
+
108
+
109
+ @app.command(name="uninstall")
110
+ def uninstall(
111
+ global_install: bool = typer.Option(
112
+ False, "--global", help="Remove from global skill directories"
113
+ ),
114
+ tool: str = typer.Option(
115
+ None, "--tool", help="Target tool: opencode, claude-code, pi (default: all)"
116
+ ),
117
+ purge_data: str = typer.Option(
118
+ "", "--purge-data",
119
+ help="Delete memory data: project, global, both, or empty for interactive mode"
120
+ ),
121
+ all_remove: bool = typer.Option(
122
+ False, "--all", help="Remove skills, data, and show pip uninstall hint"
123
+ ),
124
+ ):
125
+ """Remove deployed SKILL.md files from AI coding agent skill directories."""
126
+ tools = [tool] if tool else list(TOOL_PATHS.keys())
127
+
128
+ for t in tools:
129
+ if t not in TOOL_PATHS:
130
+ typer.secho(f"Unknown tool: {t}", fg=typer.colors.RED, err=True)
131
+ raise typer.Exit(code=1)
132
+
133
+ if global_install or all_remove:
134
+ dest = TOOL_PATHS[t]["global"]()
135
+ else:
136
+ dest = Path.cwd() / TOOL_PATHS[t]["project"]
137
+
138
+ _remove_all(dest)
139
+
140
+ if purge_data or all_remove:
141
+ _remove_data(purge_data if not all_remove else "")
142
+
143
+ if all_remove:
144
+ typer.secho("\nRun 'pip uninstall dierdanao -y' to fully remove the package.", bold=True)
145
+
146
+ typer.secho("\nDone. Restart your AI agent to apply changes.", bold=True)
147
+
148
+
149
+ def _remove_all(dest_dir: Path) -> dict[str, str]:
150
+ """Remove all deployed skills. Returns {skill_name: status}."""
151
+ results = {}
152
+ for skill_name in _get_skill_names():
153
+ skill_path = dest_dir / skill_name
154
+ if skill_path.exists():
155
+ shutil.rmtree(skill_path)
156
+ results[skill_name] = "removed"
157
+ else:
158
+ results[skill_name] = "not_found"
159
+
160
+ tool_label = str(dest_dir)
161
+ typer.secho(f"\n[{tool_label}]", fg=typer.colors.BLUE, bold=True)
162
+ for skill_name, status in results.items():
163
+ if status == "removed":
164
+ typer.secho(f" ✓ {skill_name}", fg=typer.colors.GREEN)
165
+ else:
166
+ typer.secho(f" - {skill_name} (not found)", fg=typer.colors.YELLOW)
167
+ return results
168
+
169
+
170
+ def _remove_data(level: str = "project"):
171
+ """Remove memory data directories based on level: project, global, both, or empty for interactive."""
172
+ valid = {"project", "global", "both", ""}
173
+ if level not in valid:
174
+ typer.secho(f"Unknown purge-data value: {level}. Use project, global, or both.", fg=typer.colors.RED, err=True)
175
+ raise typer.Exit(code=1)
176
+
177
+ if level in ("project", "both", ""):
178
+ project_dir = Path.cwd() / ".open-mem"
179
+ if project_dir.exists():
180
+ shutil.rmtree(project_dir)
181
+ typer.secho(" Memory data removed (.open-mem/)", fg=typer.colors.GREEN)
182
+ elif level != "":
183
+ typer.secho(" No .open-mem/ data found", fg=typer.colors.YELLOW)
184
+
185
+ if level in ("global", "both"):
186
+ global_dir = Path.home() / ".open-mem" / "data"
187
+ if global_dir.exists():
188
+ shutil.rmtree(global_dir)
189
+ typer.secho(" Global data removed (~/.open-mem/data/)", fg=typer.colors.GREEN)
190
+ else:
191
+ typer.secho(" No ~/.open-mem/data/ found", fg=typer.colors.YELLOW)
192
+
193
+
194
+ if __name__ == "__main__":
195
+ app()