🔍 Memory Semantic Search
把 Markdown 笔记变成能理解语义的搜索引擎
💡 一句话:用 Embedding API + SQLite,让你的 Markdown 支持语义搜索
❓ 解决了什么痛点?
你有很多 Markdown 笔记(比如 MEMORY.md、项目文档),但传统的 Ctrl+F 只能搜字面关键字。如果你想找"怎么部署项目",但笔记里写的是"deployed to Zeabur",就搜不到。
这个 Skill 把笔记内容变成向量,实现语义搜索——就算用词不同,只要意思相近,就能搜出来。
📋 实际运行示例
步骤一:建索引(只需执行一次)
$ python3 scripts/index.py ~/.openclaw/workspace
Workspace: /home/tony/.openclaw/workspace
Found 5 markdown files (MEMORY.md, SOUL.md, ...)
Total chunks: 15
Embedded 10/15 chunks ← 第1批:10个chunk调API
Embedded 15/15 chunks ← 第2批:剩下的5个
Done. Total indexed chunks: 15
✅ 这一步扫描所有 .md 文件,切成小块,调用 embedding API 把每块变成向量,存入 SQLite。文件改了会自动增量更新。
步骤二:语义搜索
$ python3 scripts/search.py "Claw Arena 部署在哪里"
--- Result 1 (score: 0.6655) ---
File: MEMORY.md (lines 29-81)
Claw Arena 从 API key 模式重构为 Skill + API 架构,
部署到 Zeabur,Hong Kong region...
--- Result 2 (score: 0.647) ---
File: MEMORY.md (lines 1-39)
2026-02-10: Claw Arena 重构完成,部署到 Zeabur,
Skill 发布到 ClawHub...
👆 笔记里写的是"部署到 Zeabur",搜的是"部署在哪里"——措辞不同但语义匹配,score 0.67。语义搜索的核心能力。
⚙️ 工作流程
📄扫描 .md 文件
→
✂️切块 (chunk)
→
🤖Embedding API
文本 → 向量
→
💾存入 SQLite
↓ 搜索时 ↓
💬用户提问
→
🤖问题 → 向量
→
📐余弦相似度
本地计算
→
🎯Top-K 结果
📐 余弦相似度:如何判断"意思像不像"?
🌍 直观理解(30秒)
向量 = 指向语义空间的箭头
"部署项目" → 箭头指向 东北方向
"deploy app" → 箭头也指向 东北方向
"中午吃什么" → 箭头指向 西南方向
余弦相似度就是算两个箭头夹角:夹角越小(方向越近),相似度越高;夹角越大,越不相关。
🔢 数学公式
两个向量 A 和 B(例如都是 1024 维)
相似度 = (A·B) / (|A| × |B|)
= (A₁×B₁ + A₂×B₂ + ... + A₁₀₂₄×B₁₀₂₄)
/ (A的长度 × B的长度)
结果范围:-1 ~ 1
-1 → 完全相反方向(意思相反)
0 → 互相垂直(毫无关系)
1 → 方向完全一致(意思几乎一样)
🔄 本 Skill 的计算过程
1. 查询 "Claw Arena 部署在哪里" → Q_vec (1024维)
2. 从 SQLite 读取所有 chunk 向量 C₁, C₂, ...
3. for each C:
score = cosine(Q_vec, C)
4. 按 score 从高到低排序,取 top-5
⚡ 为什么合适?
• 轻量:不需要训练,直接算余弦
• 高效:SQLite 里存的向量,本地直接算,不调 API
• 语义友好:embedding 后的向量天然把意思相近的句子聚在一起
🛠 技术栈
🐍 Python 3(纯 stdlib)
💾 SQLite(向量存储)
🔗 OpenAI 兼容 Embedding API
📐 余弦相似度
零外部依赖,不需要 pip install。API 兼容 OpenAI / 讯飞 / Gemini / Ollama 等。
📊 实测数据
💡 即使扩展到 1000+ chunks,搜索依然是"1 次 API 调用 + 本地向量计算",速度不变,成本仅一次 embedding。
📁 项目结构
memory-semantic-search/
├── SKILL.md # Skill 描述和使用说明
├── README.md # 项目文档(含安装、使用、环境变量)
├── .gitignore # 排除敏感数据和临时文件
└── scripts/
├── index.py # 索引:扫描 → 切块 → embedding → 存储
└── search.py # 搜索:查询 → embedding → 相似度计算 → 排序
⚠️ SQLite 数据库文件(*.sqlite)和 __pycache__ 已加入 .gitignore,不会上传敏感数据。