Skip to main content
Glama
alexiuhubhiu

my-kb

by alexiuhubhiu

my-kb 个人知识库

本地离线、可溯源、中文友好的 MCP 文档检索服务(个人 agent 生态知识底座)。

使用者请从这里开始 → docs/USER_GUIDE.md 白话手册:这东西是什么、资料放哪儿、怎么入库、搜不到怎么办、怎么让 AI 带出处作答。

  • 格式:Markdown / txt / PDF(文本层)/ docx;扫描件 PDF 可选 RapidOCR 摄取通道

  • 检索:SQLite FTS5 trigram + bm25 + 学科术语扩展(弱语义);短查询/引擎不可用自动 LIKE 回退

  • 溯源:每块固化 domain / doc_id / 文档标题 / 章节链(section_path) / 页码或偏移(page_or_offset)

  • 离线硬约束:零网络调用、零 API key、零 embedding/向量依赖

  • 接口:MCP(FastMCP stdio,4 个 kb_* 工具)与 CLI(6 子命令)复用同一批 handler

快速开始

# 1) 安装(全新 venv;OCR 通道额外安装 [ocr] extra:rapidocr_onnxruntime,pip 装包自带模型、之后纯离线)
python -m venv .venv
.venv/Scripts/pip install -e ".[dev,ocr]"

# 2) 摄取(增量;可用 --glossary 指定术语表;默认读 <kb_root>/_glossary/<domain>.md)
my-kb ingest --domain ds --source D:\kb_root\ds --glossary D:\kb_root\_glossary\ds.md

# 2b) 扫描件(无文本层 PDF):显式 --ocr 触发 RapidOCR 摄取(溯源标注 第N页(OCR))
my-kb ingest --domain math --source D:\kb_root\math --ocr

# 3) 检索
my-kb search --domain ds "什么是平衡二叉树" -k 3

Related MCP server: rag-retriever-mcp

CLI 命令

命令

用途

my-kb ingest --domain <d> --source <dir> [--glossary <f>] [--ocr] [--prune] [--force-ocr]

增量摄取:新增/变更;--ocr 对扫描 PDF 走 OCR;--prune 才允许废弃 source 内缺失文档;--force-ocr 强制重建已入库废块 PDF

my-kb rebuild --domain <d> --source <dir> [--glossary <f>] [--ocr]

整 domain 权威重建

my-kb sync [--root <kb_root>] [--domain <d>] [--ocr] [--prune] [--dry-run]

批量增量摄取:遍历 <root>/<domain> 逐域入库(跳过 _/. 前缀目录),术语表取 <root>/_glossary/<domain>.md;目录名与 domain 不同名时读 <root>/_domains.md 映射;--dry-run 只比对不写库

my-kb status [--domain <d>]

库/域统计

my-kb search --domain <d> "<query>" [-k 5] [--no-expand]

自测检索(与 kb_search 同引擎)

my-kb terms --domain <d> [--file <f>]

打印/校验术语表解析

my-kb backup [--keep 10]

手动备份 db → data/backup/

my-kb web [--host 127.0.0.1] [--port 8787] [--no-open]

启动本地 Web 控制台(见下一节)

Web 控制台(本地 GUI,v0.3)

不想敲命令时用这个:一个只监听 127.0.0.1 的本地页面,能看域健康状况、搜资料、跑同步/入库/废弃/备份,长任务日志实时滚动。

# 方式一:双击(Windows 启动器;优先用仓库内 .venv,其次按 PATH 解析)
scripts\start_gui.bat

# 方式二:CLI 子命令(与 serve.py 共用同一份启动逻辑)
my-kb web --port 8787

# 方式三:直接起 ASGI
python serve.py --port 8787
  • 默认地址 http://127.0.0.1:8787/,启动后自动开浏览器(加 --no-open 可关掉)。

  • 只本机可访问:Host/Origin 白名单仅 127.0.0.1/localhost;非 GET 请求要求 Content-Type: application/json(挡跨站表单)。用 curl 手测记得带 -H "Content-Type: application/json"

  • 启动器怎么挑解释器:MY_KB_PYTHON → 仓库内 .venv\Scripts\python.exepy -3python,每个候选都由 scripts\check_env.py 自检(能 import fastapi, uvicorn 并且能真的构造 FastAPI())。全都不合格时会把每个候选的失败原因打在屏幕上并暂停,不会一闪而过。

  • 根目录清单存在 data/gui_config.json(首次启动自动生成,页面「设置」里改)。默认两个根:资料域 D:\kb_root、产出域 D:\knowledge\subjects;目录不存在的根会留空路径并提示去设置里配。

  • 写操作全部走单线程任务队列(串行,避免抢 SQLite 写锁);任务日志用 SSE 推送——断线重连带 Last-Event-ID 续传,缓冲超过 2000 条会先提示「已截断」。

  • prune 仍然只是废弃status=deprecated,不删源文件);rebuild(整域重建)会物理清空该域索引,页面会二次确认。

  • 前端是零构建原生 HTML/JS(无 CDN、无 node_modules),只有 web/static/ 下三个文件。

  • 术语表面板会诊断「只做了扩展词、没有独立词条」的词——直接查这些词是 0 结果(踩过两次的那个坑)。

MCP 工具

工具

说明

kb_search(domain, query, top_k=5, expand=True)

词面检索 + 溯源片段;0 结果给 hint

kb_domains()

domain 统计(选域前探测)

kb_ingest(domain, source, mode="incremental", glossary="", ocr=False)

摄取;mode=rebuild 重建该域;ocr=True 对扫描 PDF 走 RapidOCR

kb_forget(domain, rel_path="", doc_id=0)

按 rel_path/doc_id 废弃文档

启动 MCP server(stdio):python server.py 或由 MCP 客户端运行器拉起。

知识库根目录约定(D:\kb_root

资料根与代码库、学习产出目录三者分离:

D:\kb_root\                资料根(教材/讲义/习题等第三方资料,不进代码库)
  _glossary\<domain>.md    术语表(权威;每 domain 一个)
  _raw\<domain>\...        暂不入库的原始件(如 OCR 效果差的板书),`_` 前缀 → sync 自动跳过
  <domain>\...             一级子目录名即 domain(如 gaoshu / hcie)
D:\knowledge\subjects\     产出根(笔记/思维导图/实验),与资料分离
  _domains.md              目录名 → domain id 映射(中文/连字符目录名必需)
  _glossary\<domain>.md    产出域术语表(与资料域同构,各自镜像)
  <科目目录>\...            一级子目录名经 _domains.md 映到 domain(如 hcie-datacom → hcie_notes)
  • 一条命令更新整个知识库my-kb sync --root D:\kb_root --ocr(逐域增量、幂等、默认不废弃)。

  • 新增一门课 = 建 D:\kb_root\<拼音小写 domain>\ + _glossary\<domain>.md,无需改代码。

  • 摄取是运维动作(CLI),不暴露给 LLM;客户端只拿到只读的 kb_ask / kb_coverage

资料域 / 产出域(双域分工)

同一科目的第三方资料自产产出分成两个 domain,kb_ask 返回的溯源因此能区分 「教材原话」与「我自己的总结」。命名约定:裸名 = 资料域,_notes 后缀 = 产出域

根目录

内容

domain 示例

资料域

D:\kb_root

教材 / 讲义 / 习题 / 实验手册(只读)

hcie

产出域

D:\knowledge\subjects

笔记 / 思维导图 / 实验记录(LLM 写入)

hcie_notes

产出根的一级目录是人读的中文/连字符名,而 domain id 只允许 [a-z0-9_-], 故用 _domains.md 解耦(一行 目录名 = domain_id# 注释与空行忽略; 未映射的目录若名字本身非法则跳过该域并打印提示,不中断整批)。

my-kb sync --root D:\knowledge\subjects --domain hcie_notes

Obsidian 兼容

产出域的笔记常由 Obsidian 编辑,摄取时按 md 做三项归一,避免编辑器语法污染索引:

  • YAML frontmatter 整块置空(保留行号,溯源「行N」不错位);

  • 围栏代码块内的 # 不当标题(VRP / Python 配置注释极常见),围栏行本身不入正文;

  • [[双链]] / ![[嵌入]] 归一化为可见文本[[目标|别名]]→别名、[[目标#锚点]]→目标)。

扫描时跳过路径中任一层以 ._ 开头的条目:

  • . 开头是工具目录(.git / .obsidian / .trash / .workbuddy),尤其 .trash 装的是被删笔记;

  • _ 开头是「存档但不索引」约定(与根目录 _glossary / _raw 同源)。典型用法是产出域里的 _索引/ 主题索引页——它们是 Obsidian 关系图谱的骨架,但入库只会跟正文抢检索排名。

索引页由 scripts/gen_vault_index.py 生成(--dry-run 预览、缺省刷新全部登记科目 + vault/_索引/知识库总览.md 总览页)。原因:Obsidian 图谱只认 [[双链]],不认目录结构, 没有枢纽页就是一地孤岛。脚本是纯增量产物,不改动正文;科目配置见其 SUBJECTS 登记表。

客户端挂载(任意 MCP 客户端)

my-kb-bridge 是标准 stdio MCP 服务,任何 MCP 客户端(Kun / Claude Code / Codex / …)都能挂, 差别只在各自的配置文件位置。最小配置(command 换成自己的解释器路径):

{
  "mcpServers": {
    "my-kb-bridge": {
      "type": "stdio",
      "command": "<python>",
      "args": ["D:/my_kb/server_bridge.py"],
      "env": {
        "PYTHONUTF8": "1",
        "PYTHONIOENCODING": "utf-8",
        "MY_KB_PERSONA_DIR": "D:\\my_agents_v7\\personas",
        "MY_KB_BRIDGE_DEFAULT_PERSONA": "tutor",
        "MY_KB_ROOT": "D:\\kb_root"
      }
    }
  }
}
  • MY_KB_ROOT 必须指向资料根:术语表默认路径与检索期术语扩展都靠它(不设则回退 DB 镜像,且术语表编辑不即时生效)。

  • MY_KB_PERSONA_DIR 指向 my_agents 的人设目录,kb_ask 据此读 ## visible_domains 做限域检索。

  • 本机解释器为 C:\Users\1249840596\.workbuddy\binaries\python\envs\default\Scripts\python.exe (editable 安装 my-kb,含 OCR 依赖);客户端挂载后需重启客户端才生效。

二期:my-kb-bridge(人设可见域编排,只读)

把检索能力按 agent 人设可见域 编排给上层 LLM(与 my-agents 记忆底座联动,server_bridge.py):

  • 角色边界:my-agents 管“记忆 + 人设即文件”;本服务只读消费 my_kb 库,按人设 profile.md## visible_domains 声明限域检索;不写任何数据、不认识 agent 的记忆,纯本地离线。

  • 人设声明(在 my_agents 的 personas/<name>/profile.md 里加可选节):

    ## visible_domains
    
    - gaoshu
    - ds
  • 启动(stdio,单独挂载,与 my-kb / my-agents 并列):

    set MY_KB_PERSONA_DIR=D:\my_agents_v7\personas        # 缺省即此值
    set MY_KB_BRIDGE_DEFAULT_PERSONA=tutor          # 缺省人设(可选)
    python D:\my_kb\server_bridge.py

工具

说明

kb_ask(question, persona="", top_k=5, expand=True)

按人设可见域检索:命中返回带溯源 hits,无命中返回 coverage=false 提示

kb_coverage(persona="")

该人设可见域及各域在库统计(文档/块/词条),对话前探测用

  • 行为约定:domain 只能来自人设声明;未声明 = 知识库不可用(返回明确提示);绝不跨域检索。

OCR 摄取通道(扫描件 PDF)

  • 引擎rapidocr_onnxruntime(PaddleOCR 的 ONNX 移植,CPU 本地推理)。 安装即随包获得模型(“装包=首次获取”),识别全程纯离线、零 API key。

  • 触发:OCR 是显式能力。无文本层 PDF 不带 --ocr 仍报“OCR 不支持”;带 --ocr 逐页识别, 产物与文本层 PDF 同构进入同一 chunks 表,溯源标注 第N页(OCR)(如 第3页(OCR)、跨页 第3-4页(OCR))。

  • 质量取舍:印刷体中文可读性高;数学公式/符号允许识别错误——溯源会指回原 PDF 页码供人工复核。 单页识别失败记日志跳过;整份全败进 ingest 的 failed 清单,不中断整批。

  • “有没有文本层”怎么判core/parsers.text_layer_pages_valid,四重门槛): 文档总字符 ≥ 40、有效正文页 ≥ 1、有效页正文合计 ≥ 30、有效页占比 ≥ 10%。 只管页码戳的 PDF、以及**「扫描件 + 文字封面/目录」**(323 页书只有封面目录带字, 总字符量大但占比 1.5%)都会判为无文本层 → 走 OCR;否则入库的只有目录、正文全丢。 实测真教材占比 34%~99%,门槛留了足够余量。代价:一份已按文本层入库的 PDF 不会自动改判,需 rebuild --ocr 重跑该域。

删除与安全(废弃策略)

  • 默认只增改、不废弃:incremental ingest 永不把缺失文件标为 deprecated。

  • --prune:仅当显式开启时才废弃 本次 source 目录内 扫描缺失的 active 文档 (按 source_path 前缀判定);目录外文档绝不触碰——只 ingest 讲义子目录不会误废弃 板书/习题等其他子目录的文档。废弃前报告给出 预检:…废弃 N 篇 提示。

  • rebuild 语义不变:整 domain 权威重建。

  • --force-ocr:对已入库但内容为废块(PDF 只有页码/页眉戳被误判为文本层)的文档, 即使文件 hash 未变也强制以 OCR 通道重建(溯源标注 第N页(OCR))。

目录约定

D:\kb_root\           资料根(用户原文,不进代码库)
  _glossary\ds.md     术语表(每 domain 一个)
  ds\...              一级子目录即 domain
D:\my_kb\             本仓库
  data\my_kb.sqlite3  索引库(单库+domain 列过滤)
  data\backup\        迁移/手动备份
  data\logs\          日志
  data\gui_config.json Web 控制台的根目录清单(首次启动生成,gitignore)
  core\               解析/切块/摄取/检索核心
  web\                Web 控制台(FastAPI 应用 + 零构建前端)
  serve.py            Web 控制台唯一启动入口(my-kb web 转发到这里)
  tests\              pytest 与回归集

术语表格式

# ds.md
# 以 # 开头为注释;词条 = 扩展词1, 扩展词2, ...
二叉树 = 二叉树, binary tree, 二叉排序树, BST
平衡二叉树 = 平衡二叉树, AVL树, AVL tree, 高度平衡树

检索 query 子串命中“原词”时,自动扩展为“原词 + 扩展词”合并进 FTS MATCH(可用 --no-expand 关闭)。

数据一致性

  • 文档级 SHA-256 整文件哈希判变更;增量更新单文档事务,删除 = deprecated 留档(保留行、不检索)

  • rebuild 整 domain 单事务权威重建;chunks 的一切写路径经 core/fts.py 代码同步 FTS

  • 迁移版本化(PRAGMA user_version),迁移前自动 backup(保留最近 10 份)

回归与测试

python -m pytest tests/ -q

回归集 tests/regression_queries.py 含 22 条概念题,G3 Top-1 命中率 ≥ 80%、P95 < 3s(CI 宽松上限)。

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to query a local knowledge graph built from document collections using hybrid search (BM25 + vector fusion) and entity-relationship extraction. Supports privacy-first, offline operation with tools for semantic search, entity graph exploration, and corpus statistics.
    3
    -
  • F
    license
    A
    quality
    D
    maintenance
    A local-first document retrieval engine that mounts as an MCP tool for agents to index files, search for relevant passages, and let the agent's own LLM answer.
    4
    -
  • A
    license
    A
    quality
    A
    maintenance
    Provides fast, token-efficient search over coding agent documentation (e.g., Claude Code, Cursor) using local SQLite FTS5 indexing, with tools for searching snippets, reading pages, and grepping markdown.
    5
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Provides read-only hybrid RAG search and discovery over a local-first AI knowledge corpus, enabling semantic and keyword search, browse, digest, and status tools.
    4
    PolyForm Noncommercial 1.0.0