纯本地知识库:全文检索 + 知识图谱,不依赖任何大模型,断网可跑。
技术栈:SQLite FTS5 + jieba + BM25 + 自建知识图谱 + Flask + 本地 ECharts
| 能力 | 说明 |
|---|---|
| 关键词搜索 | BM25 相关性排序,jieba 搜索引擎模式分词 |
| 关键词高亮 | 命中词黄色 <mark> 高亮,大小写不敏感 |
| 定位出处 | 文件路径 + 章节路径 + 段落号/行号,点击查看原文上下文 |
| 多格式 | Word .docx / .doc、PDF、Excel .xlsx / .xls、TXT、Markdown |
| 来源过滤 | Word / PDF / Excel / TXT·MD |
| 命中实体 | 搜索结果顶部显示命中的图谱实体 chips,点击直达图谱 |
| 能力 | 说明 |
|---|---|
| L0 结构层 | 目录 → 文档 → 章节 的层级树 |
| L1 实体层 | 人物 / 系统 / 术语抽取,段落级共现关系 |
| 两种视图 | 列表视图(默认,每页 10 条)/ 图视图(力导向、缩放拖拽、点节点看详情) |
| 最短路径 | 任意两实体间 1–6 跳无向路径,显示每段谓词 |
| 别名合并 | 按 data/kg_alias.json 收敛重复实体(如「所述对账系统」→「对账系统」),也支持详情面板手动合并 |
| 重建图谱 | 从现有索引重建,不重新解析文件 |
| 能力 | 说明 |
|---|---|
| 增量同步 | 扫描目录,MD5 变化才重新索引;prune 清理已删除文件 |
| 索引文件 / 目录 | 唯一入口:填本机单个文件或目录的路径,服务端直接扫描(不上传、不复制文件);索引的是文件在本机的真实路径(可「📁 在系统中打开」),后续「🔄 同步」按已索引文档所在目录持续增量更新(无需在 config.yaml 手工配置扫描目录) |
| 单文件索引 | 只索引这一个文件:同步时也不会把它所在目录的其它文件拉进来 |
| 同步保护 | 库里没有任何本机文件/目录的文档,或路径不可达(如移动硬盘未接)时跳过同步,不会把索引误判为"已删除" |
| 文件管理 | 列表查看 / 原文弹窗 / 单条或批量移除 / 打开所在目录(只清索引与图谱,永不删除磁盘原文件) |
| 清空文档 | 🧹 清空文档:一次清掉全部索引与图谱,二次确认(第二次须输入「清空」二字),不删除磁盘原文件 |
文档总数、片段总数、来源分布一眼看清,下方是最近索引的文件。
关键词 → BM25 排序;顶部 🕸 命中实体 chips 可直达图谱,命中词黄色高亮,卡片带来源标签与章节定位。
工具栏显示实体 / 关系 / 提及统计与类型图例;力导向布局支持滚轮缩放、拖拽节点、点节点看详情(提及片段 / 共现实体 / 别名 / 最短路径)。
表格展示来源、片段数、索引时间与文件真实路径,支持勾选批量移除、原文弹窗、打开所在目录。
填写本机单个文件或目录的绝对路径 → 「🚀 开始索引」,服务端扫描(不上传、不复制文件),带进度条与逐条结果。
knowseek/
├── app/
│ ├── __init__.py # 包初始化
│ ├── parser.py # 文档解析(Word/PDF/Excel/TXT/MD → chunks)
│ ├── indexer.py # SQLite FTS5 索引 + 搜索 + 统计
│ ├── sync.py # 增量同步(扫描目录 → MD5 对比 → 索引)
│ ├── kg.py # 知识图谱(结构树 / 实体抽取 / 别名合并 / 最短路径)
│ ├── runtime.py # 运行路径(源码 / exe 便携目录)
│ └── server.py # Flask 服务 + 全部前端界面(单文件模板)
├── data/
│ ├── knowseek.db # SQLite 数据库(唯一数据源,首次运行自动创建)
│ ├── kg_terms.txt # 图谱领域词典(空模板,按需填词)
│ ├── kg_stopwords.txt # 实体噪声词表(内置通用停用词,文件缺失也能跑)
│ └── kg_alias.json # 实体别名表(随仓库提供:通用缩写/别称词典,可自行增删)
├── images/ # README 界面截图
│ ├── dashboard.png # 仪表盘
│ ├── search.png # 搜索
│ ├── kg.png # 知识图谱(图视图)
│ ├── files.png # 文件列表
│ └── upload.png # 索引文件
├── static/
│ └── echarts.min.js # 离线内置 ECharts(不走 CDN)
├── logs/
│ └── knowseek.log # 运行日志
├── config.yaml # 配置文件
├── requirements.txt # Python 依赖
├── knowseek.spec # PyInstaller 打包配置
├── build_exe.py # Windows exe 构建脚本
└── run.py # 启动入口
需要 Python 3.9–3.12(Flask 3.x 已不支持更老的版本)。
首次使用先安装依赖(只需一次):
& python -m pip install -r requirements.txt启动(默认后台运行):
& python run.py启动器会先结束占用端口的旧实例,再启动服务;浏览器会自动打开 **http://127.0.0.1:9876**,启动器进程约 5 秒后退出,服务继续在后台运行。
停止后台服务:
& python run.py --stop需要查看日志或使用 Ctrl+C 时,改为前台运行:
& python run.py --foreground路径请替换为本机 Python 3.9–3.12 的实际位置;本机默认
python若是 3.7(例如旧版 Anaconda),不要使用。 也可以打包 exe 后直接运行KnowSeek.exe,无需 Python。
需要 Python 3.9–3.12(Flask 3.x 已不支持更老的版本)。
pip install -r requirements.txt国内网络建议清华镜像:
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
编辑 config.yaml:
# 支持的文件扩展名(.doc 走 Word COM,仅 Windows;.xlsx 用 openpyxl,.xls 用 xlrd)
extensions:
- ".docx"
- ".doc"
- ".txt"
- ".md"
- ".pdf"
- ".xlsx"
- ".xls"
max_results: 50 # 搜索 / 文件列表每页条数上限(前端默认每页 10 条)
port: 9876 # 服务端口
# 自定义词典(可选,一行一个词)
# custom_dict: "data/custom_dict.txt"
# 知识图谱
kg:
term_dict: "data/kg_terms.txt" # 领域词典:词 [词频] [词性]
stopwords: "data/kg_stopwords.txt" # 噪声词:不会抽成实体
alias_file: "data/kg_alias.json" # 别名表:{"规范名": ["别名", ...]},随仓库提供,可直接改
min_doc: 2 # 重建时清理低频实体:出现文档数 < 该值
min_mention: 3 # 且 提及数 < 该值
topk_edges: 10 # 每个节点保留的共现边上限python run.py浏览器访问 **http://127.0.0.1:9876**。macOS / Linux 默认前台运行,按 Ctrl+C 停止;Windows 默认后台运行,启动器约 5 秒后退出,可用 python run.py --stop 停止。
项目不再提供 .bat 脚本,统一使用命令或 exe:
| 场景 | 命令 |
|---|---|
| 默认后台启动(5 秒后关闭窗口) | python run.py / KnowSeek.exe |
前台运行(保留窗口,Ctrl+C 停止) |
python run.py --foreground / KnowSeek.exe --foreground |
| 停止后台服务 | python run.py --stop / KnowSeek.exe --stop |
| 不自动打开浏览器 | 追加 --no-browser |
启动前会自动结束占用当前端口的旧实例,无需手动处理端口。
& python build_exe.py产物在 dist\KnowSeek\KnowSeek.exe,采用 onedir 模式:
KnowSeek.exe和_internal\必须放在同一目录,不能只拷 execonfig.yaml、data\、logs\位于 exe 同目录,便于备份和迁移- 首次启动会从
_internal复制默认配置与词典;当前索引库在首次构建时复制,后续重建保留dist中的数据 - 直接双击
KnowSeek.exe会先清理旧端口,再后台启动并自动打开浏览器;启动器窗口 5 秒后自动关闭,服务继续运行 - 停止后台服务用
KnowSeek.exe --stop;调试时用--foreground保留控制台,--no-browser可关闭浏览器 - 目标机器不需要安装 Python;
.doc解析仍需要本机安装 Microsoft Word
Tab 顺序:📊 仪表盘 › 🔍 搜索 › 🕸 知识图谱 › 📁 文件列表 › 📄 索引文件
- 文档总数、片段总数、各来源分类数量
- 点击来源卡片跳转到搜索并自动筛选该类型
- 最近索引文件列表
- 关键词 → BM25 排序返回结果
- 结果顶部:🕸 命中实体 chips(带命中次数,点击直达图谱该实体)
- 结果卡片:来源标签、文件名、高亮内容、章节定位、BM25 分数、
🕸 图谱直达 - 点击卡片 → 原文弹窗(目标段黄底高亮,前后各 2 段灰色上下文)
- 来源过滤 + 重置按钮 + 分页(每页 10 条)
- 默认列表视图(每页 10 条),工具栏可切到图视图
- 图视图:力导向布局,滚轮缩放、拖拽节点、点击节点看详情(提及片段 / 共现实体 / 别名 / 最短路径)
- 工具栏:类型筛选、Top 60/120、关键词搜索、
🛠 重建图谱、🔀 应用别名 - 路径查询:
🔗 设为起点+🎯 设为终点→🧭 计算最短路径
- 已索引文件(文件名、来源、片段数、索引时间、路径)
- 全选/取消全选、单行勾选高亮、批量移除(都只清索引与图谱,磁盘原文件保留)
🧹 清空文档:第一次弹窗告知范围 → 第二次弹窗须输入「清空」二字- 点击文件名 → 原文弹窗;分页(每页 10 条)
- 路径列显示文件在本机的真实路径;过长时中间省略为「开头...结尾」,鼠标悬浮跑马灯展示完整路径,📋 按钮可复制完整路径
- 填写本机单个文件或目录的绝对路径(回车即可索引)→ 「🚀 开始索引」
- 支持
.docx.doc.pdf.xlsx.xls.txt.md(页面会列出当前config.yaml里生效的格式) .doc解析走 Word COM:需 Windows + 本机装有 Word +pywin32;未装 Word 时该文件显示为 ❌- 进度条 + 逐条结果(✅ 新增 / 🔄 更新 / ⏩ 未变更 / ❌ 失败),可随时「⛔ 终止」
- 服务端直接扫描,不上传、不复制文件,原文件始终留在本机
- 单文件索引只针对该文件,后续同步不会牵连同目录的其它文件
┌───────────────┐ ┌────────────────┐ ┌──────────────────────┐
│ 文档解析 │ ──→ │ jieba 分词 │ ──→ │ SQLite FTS5 │
│ docx/doc/pdf │ │ 搜索引擎模式 │ │ BM25 + UNINDEXED 原文│
│ xlsx/txt/md │ └────────────────┘ └──────────┬───────────┘
└───────────────┘ │
│ SQL
┌───────────────┐ │
│ 增量同步 │ ←── MD5 对比 ───────────────────────────┘
└───────────────┘ │
│ chunks
┌───────────────┐ ┌───────────▼───────────┐
│ 知识图谱 │ ── 结构树 + 实体共现 ───→ │ kg_* 表(同库) │
│ jieba posseg │ │ 实体 / 关系 / 提及 │
└───────────────┘ └───────────┬───────────┘
│
┌──────────────▼─────────────┐
│ Flask API + Web UI │
│ 搜索 / 图谱 / 文件管理 │
└────────────────────────────┘
| 格式 | 解析方式 | 切块策略 | 定位信息 |
|---|---|---|---|
.docx |
python-docx 按段落 | 每段落 = 1 chunk | 文件路径 + Heading 路径 + 段落序号 |
.doc |
pywin32 调 Word COM 转换(仅 Windows) | 同 .docx |
同 .docx |
.pdf |
pdfplumber 按页 | 每页 = 1 chunk | 文件路径 + "第 N 页" + 页号 |
.xlsx |
openpyxl 按 Sheet | 每行 = 1 chunk | 文件路径 + Sheet 名 + 行号 |
.xls |
xlrd 按 Sheet(Excel 97-2003) | 每行 = 1 chunk | 文件路径 + Sheet 名 + 行号 |
.txt / .md |
逐行读取,按空行分段;Markdown 按标题分段 | 连续非空行为 1 chunk | 文件路径 + 行号 + 最近标题 |
- 关键词 → jieba
cut_for_search分词 - 构建 FTS5 MATCH 表达式(AND 语义)
- SQLite
bm25()排序 - Python 层高亮(
file_path同样参与显示) - 按结果片段反查
kg_mentions,聚出命中实体一并返回 - 点击结果 → 按
file_path + para_index取目标 chunk + 前后各 2 段(毫秒级)
- L0 结构层:目录链 → 文档节点 → 章节树(
contains边) - 实体挂载:实体通过
mentions边挂到所在章节/文档,保证图谱连通 - L1 实体层:自定义词典 + jieba 词性标注抽取 人物 / 系统 / 术语,段落内共现建
related_to边(权重累加,按topk_edges裁剪) - 降噪:别名映射 + 句首粘连词剥离(
所述 / 一种 / 通过 …)+ 噪声词表
data/knowseek.db是唯一数据源(索引 + 图谱都在里面)。备份/迁移拷贝这一个文件即可;建议先停止服务再拷贝。启用 WAL 后运行期间可能同时存在knowseek.db-wal/knowseek.db-shm,服务停止时会自动合并,若仍在运行中备份请把这三个文件一起拷贝。- 只索引本机文件 / 目录:不上传、不复制文件,库里记的是文件在本机的真实路径,列表里可「📁 在系统中打开」;原文件始终在磁盘,改动后点同步按 MD5 重新解析。
- 全量同步(
prune)会清理"扫描不到的文档";早期版本上传产生的upload://记录(若有)会被跳过,不会误删。 - 知寻不会删除磁盘上的任何原文件:单条移除 / 批量移除 /
🧹 清空文档清的都是数据库(documents/chunks_fts/kg_*),原文件始终留在磁盘上;要真正删文件请用系统文件管理器(列表里有「📁 在系统中打开」)。 🧹 清空文档后库里不再有文档,「⚡ 同步索引」的扫描目录(由已索引文档路径反推)也随之为空,不会把旧目录重新索引回来。- 首次使用 / 全新 clone 时的
data/状态:knowseek.db— 不存在,首次运行自动建表生成kg_terms.txt— 空模板(只有注释),按需填领域词kg_stopwords.txt— 通用停用词,可留;删掉也能跑(代码内置_STOP/_EN_STOP兜底)kg_alias.json— 随仓库提供,内置 AI/数据、中间件、开发框架、厂商等通用别名;使用过程中发现重复实体继续往里加即可(涉及业务实体名时,建议另存kg_alias.local.json并忽略)
| 依赖 | 用途 |
|---|---|
| jieba | 中文分词 + 词性标注 |
| python-docx | Word .docx 解析 |
| pdfplumber | PDF 解析 |
| openpyxl | Excel .xlsx 解析 |
| xlrd | Excel 97-2003 .xls 解析 |
| flask | Web 服务 |
| PyYAML | 配置文件解析 |
| pywin32 | .doc 解析(仅 Windows) |
pdfplumber会附带Pillow/pypdfium2,它们只用于把 PDF 页面渲染成图片;知寻只提取文本,打包 exe 时会排除这两个依赖。若只提取文本,可在本机环境移除它们,pip check的对应提示可忽略;重新执行pip install -r requirements.txt会恢复。
新项目启动后
data/knowseek.db是空的(0 文档 / 0 片段),下表为参考量级,实际会随文档数量、篇幅、格式和机器配置浮动;自己库里的真实数字看「📊 仪表盘」。
| 指标 | 参考值 |
|---|---|
| 首次索引速度 | 约 100–400 篇/分钟(实测:32 KB 的 .docx ≈ 0.14 s/篇,800 KB 的 .pdf ≈ 0.8 s/篇) |
| 增量同步 | 只重新解析 MD5 变化过的文件,通常秒级完成 |
| 搜索响应 | 1 万篇以内 < 1 秒(分词 + FTS5 + BM25 + 高亮) |
| 原文查看 | < 100 ms(直接查 SQLite,不重新解析文件) |
| 图谱重建 | 数百篇文档约 10–60 秒(读库重建,同样不重新解析文件) |
| 内存占用 | 常驻 < 100 MB(PDF 解析瞬间会高一些) |
| 适用规模 | 1 万篇文档以内 |
图谱越用越准:往 data/kg_terms.txt 加领域词、往 kg_stopwords.txt 加噪声词、往 kg_alias.json 加别名,然后 🔀 应用别名 或 🛠 重建图谱 即可生效。
- 搜索页的来源过滤器里预留了 飞书 / 语雀 / Jenkins 标签,但对应 Connector 尚未接入,当前实际数据源只有本地文件。
- 图谱为自建实现(非 GraphRAG),全程离线、不接入任何大模型,也没有任何联网调用。




