Skip to content
simonking-wsPublic

About

纯本地全文检索系统,不依赖任何大模型。输入关键词,秒级定位到文档出处

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

🔍 知寻 KnowSeek

纯本地知识库:全文检索 + 知识图谱,不依赖任何大模型,断网可跑。

技术栈: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                   # 启动入口

🚀 快速开始

方式 A:Windows 本机 Python

需要 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。

方式 B:手动命令行(macOS / Linux / 想用自己的 Python)

需要 Python 3.9–3.12(Flask 3.x 已不支持更老的版本)。

1. 安装依赖

pip install -r requirements.txt

国内网络建议清华镜像:pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 配置

编辑 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                      # 每个节点保留的共现边上限

3. 启动

python run.py

浏览器访问 **http://127.0.0.1:9876**。macOS / Linux 默认前台运行,按 Ctrl+C 停止;Windows 默认后台运行,启动器约 5 秒后退出,可用 python run.py --stop 停止。


🪟 Windows 启动说明

项目不再提供 .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

启动前会自动结束占用当前端口的旧实例,无需手动处理端口。

打包 Windows exe

& python build_exe.py

产物在 dist\KnowSeek\KnowSeek.exe,采用 onedir 模式:

  • KnowSeek.exe 和 _internal\ 必须放在同一目录,不能只拷 exe
  • config.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 文件路径 + 行号 + 最近标题

搜索流程

  1. 关键词 → jieba cut_for_search 分词
  2. 构建 FTS5 MATCH 表达式(AND 语义)
  3. SQLite bm25() 排序
  4. Python 层高亮(file_path 同样参与显示)
  5. 按结果片段反查 kg_mentions,聚出命中实体一并返回
  6. 点击结果 → 按 file_path + para_index 取目标 chunk + 前后各 2 段(毫秒级)

图谱构建

  1. L0 结构层:目录链 → 文档节点 → 章节树(contains 边)
  2. 实体挂载:实体通过 mentions 边挂到所在章节/文档,保证图谱连通
  3. L1 实体层:自定义词典 + jieba 词性标注抽取 人物 / 系统 / 术语,段落内共现建 related_to 边(权重累加,按 topk_edges 裁剪)
  4. 降噪:别名映射 + 句首粘连词剥离(所述 / 一种 / 通过 …)+ 噪声词表

💾 数据存储说明

  • 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),全程离线、不接入任何大模型,也没有任何联网调用。

About

纯本地全文检索系统,不依赖任何大模型。输入关键词,秒级定位到文档出处

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages