Skip to content

Repository files navigation

🧠 知识图谱系统 (Knowledge Graph System)

一个支持多用户的知识图谱系统,整合 Neo4j 图数据库和 ChromaDB 向量数据库,实现文档知识管理、可视化图谱与 RAG 对话。 让散落各处的知识连成一张可探索的网 ✨

⚠️ 安全提醒

🚨 本项目的 .env(根目录与 backend/)包含真实 API 密钥和 JWT 签名密钥。任何 fork、镜像或截图前必须:

  1. 在硅基流动 / Moonshot / 阿里云百炼控制台**轮换(撤销并重新签发)**这些 API 密钥
  2. python -c "import secrets; print(secrets.token_urlsafe(48))" 生成新 JWT_SECRET 并替换
  3. 🙅 永远不要.env 提交到 git(已在 .gitignore 中,但仍请小心处理历史记录)

详见 安全配置 一节。

核心功能

  1. 📚 文档知识库:支持上传 PDF/Word/TXT/MD 格式,自动转换为 Markdown 并按层级切块
  2. 🔍 混合检索:多查询 + 硅基流动 Qwen3-Embedding-8B 向量检索 + BM25 关键词 + 图谱通道 + RRF 融合 + Qwen3-Reranker 重排序 + 父文档扩展再重排(统一管线 services/retriever.py,TTL+LRU 缓存)
  3. 🕸️ 知识图谱可视化:d3 + Vue 3 实现的交互式力导向图谱,支持节点拖拽、实体编辑、合并与删除
  4. 💬 大模型对话:基于 Kimi / 百炼 (qwen3.7-flash) 的 RAG 问答,支持流式 / 非流式、图谱增强 RAG、对比模式、消息反馈、深度思考开关(Qwen 混合思考,推理过程以 event: thinking 帧流式展示)、意图路由(闲聊 / 拒答绕过检索,分类失败回退到 RAG)
  5. 📊 仪表盘与时间线:文档 / 实体 / 标签统计、月度增长、近期活动、实体首现时间线
  6. 🗺️ 文档聚类地图:2D PCA 投影可视化所有文档的语义分布
  7. 🔐 用户隔离:JWT 账号密码认证,SQLite 存储用户数据,Neo4j/ChromaDB 通过 user_id 标签隔离
  8. 🛡️ 健壮性:统一 logging(请求级 X-Request-ID 关联)、请求体大小全局兜底(413)、批量写入(Neo4j UNWIND)、输入校验、4xx 不重试、防 401 重定向循环、API 限流中间件、embedding 缓存自愈(损坏 blob 自动剔除)、BM25 启动预热、卡死文档启动对账(reconcile)、检索结果 TTL+LRU 缓存、向量索引零成本重建脚本、SQLite 增量迁移(schema_version 追踪)、全量备份脚本

技术架构

层级 技术
🎨 前端 Vue 3.5 + Vite 7 + Pinia + Vue Router + d3.js · 学术雅致派双主题(Fraunces + Plus Jakarta Sans + JetBrains Mono)
⚙️ 后端 API FastAPI 0.115 + Python 3.11 + uvicorn
🕸️ 图数据库 Neo4j 5.14 (Docker, APOC 插件)
🧬 向量数据库 ChromaDB 0.4.18 (Docker)
💾 用户数据 SQLite + SQLAlchemy 2.0 + aiosqlite (单文件)
🧩 嵌入模型 硅基流动 Qwen3-Embedding-8B (API)
🎯 重排序 硅基流动 Qwen3-Reranker-8B (API)
🤖 大模型 Kimi API (Moonshot, kimi-k2) / 百炼 qwen3.7-flash (阿里云 DashScope) / 硅基流动 Qwen3-8B
🔑 密码哈希 bcrypt 4.1.3(原生)
📝 日志 Python logging + RotatingFileHandler(统一在 app/logger.py

项目目录结构

D:/NC/
├── docker-compose.yml           # Neo4j + ChromaDB 服务定义
├── .env / .env.example          # 部署环境变量(example 为模板)
├── package.json                 # 根级 npm 脚本(concurrently 一键启动)
├── start-dev.bat / start-dev.sh # Windows / Bash 一键启动脚本
├── backend/
│   ├── .env / .env.example      # 后端实际加载的 .env
│   ├── app/
│   │   ├── api/                 # API 端点
│   │   │   ├── auth.py          # 注册/登录/me
│   │   │   ├── documents.py     # 文档上传/列表/详情/删除/切块/标签/聚类
│   │   │   ├── chat.py          # RAG 对话(流式 + 非流式 + 反馈)
│   │   │   ├── graph.py         # 实体/图谱查询/可视化/编辑/合并
│   │   │   ├── search.py        # 语义检索
│   │   │   ├── progress.py      # 文档处理进度(SSE + 历史)
│   │   │   ├── tags.py          # 用户级标签聚合
│   │   │   ├── timeline.py      # 时间线聚合数据
│   │   │   └── dashboard.py     # 仪表盘汇总
│   │   ├── models/              # Pydantic 数据模型(含字段校验)
│   │   ├── services/            # 核心服务
│   │   │   ├── retriever.py     # 统一检索管线(多查询 + 图谱 + 父文档扩展 + 再重排 + TTL 缓存)
│   │   │   ├── intent.py        # 查询意图分类(fact_retrieval / chitchat / should_reject)
│   │   │   ├── embedding.py     # 硅基流动嵌入(限流 + JSON 缓存)
│   │   │   ├── llm.py           # 百炼 / Kimi / 硅基流动 多 LLM
│   │   │   ├── chunker.py       # Markdown 层级切块(可配 overlap)
│   │   │   ├── entity_extractor.py  # 实体 + 关系提取(LLM 模式)
│   │   │   ├── neo4j_client.py  # Neo4j 封装(含 UNWIND 批量)
│   │   │   ├── chroma_client.py # ChromaDB 封装
│   │   │   ├── bm25.py          # BM25 关键词检索(per-user 索引 + 启动预热)
│   │   │   ├── fusion.py        # RRF / 加权融合
│   │   │   ├── reranker.py      # 硅基流动 Rerank
│   │   │   ├── query_processor.py  # 查询改写 / 变体 / 实体抽取
│   │   │   ├── reconcile.py     # 卡死文档启动对账(标记 failed)
│   │   │   ├── progress_tracker.py  # SSE 进度跟踪
│   │   │   └── doc_status.py    # 文档处理状态机(pending/document_created/indexed/graphed/ready/failed)
│   │   ├── auth/                # JWT 鉴权 + bcrypt 密码哈希 + 限流中间件
│   │   ├── middleware.py        # 纯 ASGI 中间件(请求体限流 + X-Request-ID)
│   │   ├── utils/md_parser.py   # Markdown 解析(markitdown 防御性封装)
│   │   ├── config.py            # 配置管理(含 CORS 白名单 + JWT 占位符拦截)
│   │   ├── database.py          # SQLite 初始化 + 增量迁移(schema_version 追踪)
│   │   ├── logger.py            # 统一 logging 配置(请求 ID 关联)
│   │   └── main.py              # FastAPI 入口(lifespan:预热 / 对账 / 就绪探针)
│   ├── migrations/001_baseline.sql  # 迁移基线(stamp version 1,未来增量迁移按序应用)
│   ├── scripts/rebuild_chroma.py # 向量索引零成本重建(SQLite chunks + embedding 缓存 → Chroma)
│   ├── clean_user_data.py        # 跨 SQLite/Chroma/Neo4j/BM25 清理单个用户数据(破坏性,需确认)
│   └── Dockerfile                # 从仓库根构建:docker build -f backend/Dockerfile .
├── requirements.txt              # Python 依赖清单(backend 与脚本共用,CI 也从根目录安装)
├── docker-compose.yml            # Neo4j + ChromaDB 服务定义
├── frontend/                     # Vue 3 + d3 前端(学术雅致派双主题)
│   ├── src/
│   │   ├── components/
│   │   │   ├── GraphPanel.vue   # 图谱核心面板(d3 力导向)
│   │   │   ├── layout/          # Layout / Sidebar
│   │   │   ├── decor/           # 装饰层(Decor / shapes)
│   │   │   └── ui/              # 通用 UI(Button/Card/Tag/Stat/Switch/...)
│   │   ├── views/
│   │   │   ├── Home.vue                  # 登录 / 注册
│   │   │   ├── DocumentsPage.vue         # 文档列表 + 上传
│   │   │   ├── DocumentDetailPage.vue    # 文档详情(标签 / 实体 / 关联)
│   │   │   ├── ClusterMapPage.vue        # 2D PCA 聚类地图
│   │   │   ├── GraphPage.vue             # 图谱主页(搜索 / 可视化)
│   │   │   ├── EntityDetailPage.vue      # 实体详情页
│   │   │   ├── EntityTimelineAnimationPage.vue  # 实体时间线动画
│   │   │   ├── DashboardPage.vue         # 仪表盘
│   │   │   ├── TimelinePage.vue          # 时间线
│   │   │   ├── ChatPage.vue              # RAG 对话
│   │   │   └── SearchPage.vue            # 语义检索
│   │   ├── composables/
│   │   │   └── useTheme.js       # 亮/暗主题切换 + localStorage 持久化
│   │   ├── api/                  # axios 客户端封装(auth/documents/chat/graph/...)
│   │   ├── router/index.js       # 路由 + 鉴权守卫
│   │   ├── store/auth.js         # Pinia auth store
│   │   ├── utils/                # categorize / timelineAnim / SSE 流式解析 工具
│   │   ├── styles/variables.css  # 学术雅致派设计令牌(墨蓝+琥珀双主题)
│   │   ├── App.vue
│   │   └── main.js
│   ├── index.html
│   ├── package.json
│   └── vite.config.js
├── scripts/                      # 根级脚本
│   ├── run-backend.mjs           # npm run backend 调用(跨平台启动 uvicorn)
│   └── backup.sh                 # 全量备份(SQLite 在线 .backup + Neo4j/Chroma/uploads)
└── data/                         # 数据目录 (gitignore)
    ├── sqlite/                  # SQLite 数据库
    ├── uploads/                 # 上传的原文件
    ├── logs/                    # 应用日志(RotatingFileHandler)
    ├── neo4j/                   # Neo4j 数据卷
    └── chromadb/                # ChromaDB 数据卷

🚀 快速开始

1. 🐳 启动基础设施服务

docker-compose up -d

这将启动:

2. 🔑 配置环境变量(从模板复制,不要直接编辑 .env.example

# 根目录(用于 IDE / 工具)
cp .env.example .env

# 后端实际加载的 .env
cd backend
cp .env.example .env

必填项:

  • SILICON_FLOW_API_KEY — 硅基流动 API 密钥(用于 Embedding + Rerank + 备用 LLM)
  • BAILIAN_API_KEY — 阿里云百炼 API 密钥(用于 LLM)
  • KIMI_API_KEY — Moonshot Kimi API 密钥(备用 LLM)
  • JWT_SECRET生产环境必须python -c "import secrets; print(secrets.token_urlsafe(48))" 生成

可选调整:

  • CORS_ALLOWED_ORIGINS — 逗号分隔的允许来源(默认 http://localhost:5173
  • APP_ENVdevelopment(默认)或 production(生产环境会拒绝默认 JWT_SECRET 启动)
  • UPLOAD_DIR / SQLITE_PATH / LOG_DIR — 数据与日志目录
  • ENABLE_LLM_EXTRACTION / USE_RULE_EXTRACTION — 实体提取策略(默认纯 LLM 模式)
  • ENTITY_BATCH_SIZE — 实体提取批大小(默认 200)

3. 📦 安装后端依赖

# 推荐:使用根目录 .venv(依赖清单在仓库根 requirements.txt)
cd ..
.venv/Scripts/python.exe -m pip install -r requirements.txt
.venv/Scripts/python.exe -m spacy download zh_core_web_sm

4. ▶️ 运行后端服务

cd backend
../.venv/Scripts/python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload

或使用一键启动脚本(Windows / Bash 双版本 / 根级 npm 脚本):

# Windows
start-dev.bat

# Bash (Git Bash / WSL)
./start-dev.sh

# 或:根目录 npm 脚本(需要先 npm install)
npm run dev          # concurrently 同时启动前后端
npm run backend      # 仅后端
npm run frontend     # 仅前端

API 文档地址:http://localhost:8001/docs 健康检查: http://localhost:8001/health

5. 🎨 安装并运行前端

cd frontend
npm install
npm run dev

前端访问地址:http://localhost:5173 Vite 已配置 /api 代理到 http://localhost:8001

🔌 API 接口设计

所有需要鉴权的接口都要求 Authorization: Bearer <jwt> header。SSE 进度接口优先使用 header 鉴权;但由于原生 EventSource 客户端无法设置自定义 header,作为兼容回退也接受 ?token= 查询参数。⚠️ 查询参数形式会把 token 泄露进反向代理访问日志与浏览器历史,请将此类 URL 视为敏感信息(前端 EventSource 即使用此回退方式)。

🔐 认证 /api/auth

  • POST /api/auth/register — 用户注册(用户名 3-50 字符 [A-Za-z0-9_.-]、密码 ≥ 8 字符且必须含字母+数字)
  • POST /api/auth/login — 用户登录(OAuth2 form-data,返回 JWT)
  • GET /api/auth/me — 获取当前用户信息

📄 文档 /api/documents

  • POST /api/documents/upload — 上传文档(multipart/form-data,支持 .pdf/.docx/.doc/.txt/.md/.markdown,≤ 10MB)
  • GET /api/documents — 列出用户文档(分页:?skip=0&limit=100;可选 ?tag=xxx 过滤)
  • GET /api/documents/{id}/detail — 文档详情(metadata + 标签 + 切块统计 + 关键实体 + 关联文档)
  • GET /api/documents/{id}/chunks — 文档切块列表
  • GET /api/documents/cluster-map — 2D PCA 聚类地图(所有文档的语义投影)
  • DELETE /api/documents/{id} — 删除文档(联动清理 SQLite + ChromaDB + Neo4j)
  • GET /api/documents/{id}/tags — 文档标签列表
  • POST /api/documents/{id}/tags — 添加文档标签(幂等,返回最新标签列表)
  • DELETE /api/documents/{id}/tags/{tag:path} — 移除文档标签(返回最新标签列表)

🔍 检索 /api/search

  • POST /api/search — 语义检索(向量 + BM25 + Rerank + 图谱关联)

🕸️ 图谱 /api/graph

  • GET /api/graph/entities?query=xxx — 实体名称模糊搜索
  • POST /api/graph/query — 语义图谱查询(按 query 在向量空间找相关 chunk,再展开图谱)
  • GET /api/graph/visualization — 获取当前用户的全量图谱可视化数据
  • GET /api/graph/entities/{name:path}/detail — 实体详情(实体 + 统计 + 文档 + 关联实体 + 示例 chunk)
  • PATCH /api/graph/entities/{name:path} — 更新实体的类型 / 描述
  • DELETE /api/graph/entities/{name:path} — 删除实体(清理 MENTIONS / RELATES_TO)
  • POST /api/graph/entities/merge — 合并实体({source, target},source 被删除并重新指向 target)

💬 对话 /api/chat

  • POST /api/chat — 发送消息(非流式 RAG 问答,支持 use_graph_rag / compare_mode / enable_thinking;意图路由自动判定是否检索)
  • POST /api/chat/stream — 发送消息(Server-Sent Events 流式)

流式帧顺序:event: sources(参考来源)→ event: thinking(仅当 enable_thinking=true,模型推理过程,可折叠)→ 默认 data: 帧(回答正文 chunk)→ event: done(终止)。 深度思考模式:enable_thinking 透传 Qwen 混合思考参数,模型先流式输出 reasoning_content 再输出正文;对不支持该参数的模型层,HTTP 400 时自动去参重试一次。首字计时锚定到正文首 token,非推理首 token。

  • GET /api/chat/conversations — 获取对话列表
  • GET /api/chat/conversations/{id}/messages — 获取对话历史
  • DELETE /api/chat/conversations/{id} — 删除对话
  • POST /api/chat/messages/{id}/feedback — 提交消息反馈({rating, note?}
  • GET /api/chat/messages/{id}/feedback — 获取消息反馈
  • DELETE /api/chat/messages/{id}/feedback — 删除消息反馈

🏷️ 标签 /api/tags

  • GET /api/tags?q=xxx — 用户级标签聚合(按使用频次倒排,可选模糊搜索)

🕒 时间线 /api/timeline

  • GET /api/timeline — 文档月度分布 + 近期文档 + 实体首现时间线

📊 仪表盘 /api/dashboard

  • GET /api/dashboard/summary — 仪表盘汇总(统计 + 近期活动 + 热门实体 + 热门标签 + 月度增长)

⏳ 进度 /api/progress

  • GET /api/progress/{doc_id} — SSE 流式进度事件(30 秒 keepalive,完成/错误自动关闭)
  • GET /api/progress/{doc_id}/history — 历史进度事件列表

💓 健康检查

  • GET /health — 存活探针(liveness),返回 {"status": "healthy"}
  • GET /health/ready — 就绪探针(readiness),逐个 ping SQLite / ChromaDB / Neo4j,任一核心存储不可用返回 503
  • GET / — 返回 API 元信息

🌊 数据流架构

📤 文档上传流程

PDF/Word/TXT/MD → markitdown → Markdown → 层级解析 → 语义切块
    → 硅基流动 Embedding (Qwen3-Embedding-8B) → ChromaDB 存储
    → Neo4j 实体关系提取 (BM25 索引同步) → SSE 进度推送

🔍 检索对话流程

用户 Query
  ├─ 意图分类 (LLM, ENABLE_INTENT_ROUTING)
  │     ├─ chitchat / should_reject → 跳过检索,模板直接应答
  │     └─ fact_retrieval (默认 / 失败回退) → 进入统一检索管线 retrieve()
  │
  └─ retrieve()(services/retriever.py,结果按 TTL+LRU 缓存)
        1. 并行 LLM 预处理:会话改写 + 多查询变体(+ 图谱实体抽取)
        2. 并行 Embedding(逐文本缓存)
        3. 逐查询 向量 + BM25 召回(multi-query)
        4. 图谱通道作为独立 RRF 列表(GRAPH_RAG_MODE: auto / on / off)
        5. 多列表 RRF 融合(图谱权重 GRAPH_RRF_WEIGHT 可配)
        6. Qwen3-Reranker → seed chunks
        7. 扩展:前后邻居 (Chroma) + 父文档同节兄弟 (SQLite),去重
        8. 扩展集再重排(按 relevance 排序,不驱逐邻居)
        9. 实体 / 关系富化 (Neo4j)
        → 构建 Prompt → Kimi / 百炼 LLM → 流式返回结果
        ├─ enable_thinking=true:  先流式 reasoning_content (event: thinking)
        └─ 默认:                  直接流式正文 (data: chunk)

🧬 核心数据模型

📦 Chunk 数据结构

{
    "chunk_id": "uuid",
    "document_id": "doc_uuid",
    "user_id": "user_uuid",
    "content": "文本内容",
    "hierarchy": {
        "level": 2,                    # 标题层级
        "path": ["标题1", "标题1.1"],    # 层级路径
        "parent_id": "parent_chunk_id"
    },
    "position": {
        "start_line": 10,
        "end_line": 25,
        "prev_chunk_id": "uuid",       # 前一块(用于上下文召回)
        "next_chunk_id": "uuid"        # 后一块
    }
}

🕸️ Neo4j 图谱数据模型

// 节点
(:User {user_id, username, password_hash, created_at})
(:Document {doc_id, title, user_id, file_path, created_at})
(:Chunk {chunk_id, content, embedding_id, user_id, position, hierarchy_path})
(:Entity {name, type, description, user_id})              // 从文本提取

// 关系
(:User)-[:OWNS]->(:Document)
(:Document)-[:CONTAINS]->(:Chunk)
(:Chunk)-[:NEXT]->(:Chunk)                               // 文档顺序
(:Chunk)-[:MENTIONS]->(:Entity)                          // 提及实体
(:Entity)-[:RELATES_TO {relation_type}]->(:Entity)       // 实体关系

🔐 安全配置

状态 备注
🔑 JWT 签名 必须替换 python -c "import secrets; print(secrets.token_urlsafe(48))"
🌐 CORS 来源 白名单 通过 CORS_ALLOWED_ORIGINS 配置,禁用通配符
🔒 密码哈希 bcrypt 72 字节硬截断;不 mutate 调用方入参
🗝️ API 密钥 环境变量 硬编码到代码;.env 已 gitignore
🚦 JWT 占位符 任意环境拦截 get_settings()任何环境(含 development)检测到公开占位符即 RuntimeErrorAPP_ENV 仅为环境标记
🚪 401 处理 拦截器去重 防重入 + 派发 auth:logout 事件
📡 进度 SSE Authorization header 优先 EventSource 回退接受 ?token=(会进代理日志,视为敏感 URL)
💾 嵌入缓存 JSON 序列化 取代 pickle(防反序列化漏洞);损坏 blob 自愈剔除
🚦 API 限流 中间件 app/auth/rate_limit.py 对认证接口限流,防暴力枚举
📦 请求体大小 全局兜底 RequestBodyLimitMiddlewareMAX_REQUEST_BODY 在消费 body 前拒绝超大请求(413);上传端点另按 MAX_FILE_SIZE 流式校验
🆔 请求追踪 correlation id RequestIDMiddleware 为每个请求打 X-Request-ID,回写响应头并注入日志
✅ 注册校验 强校验 用户名 [A-Za-z0-9_.-]、密码 ≥ 8 字符含字母+数字
👥 Neo4j 删除 跨用户隔离 delete_document step 4 强制 user_id 过滤
⚡ 批量写入 UNWIND 实体/关系/MENTIONS 由 N 次往返降为 1 次

⚙️ 配置说明

🛠️ 环境变量

变量名 说明 默认值 必填
APP_ENV 运行环境 development
NEO4J_URI Neo4j 连接地址 bolt://localhost:7687
NEO4J_USER Neo4j 用户名 neo4j
NEO4J_PASSWORD Neo4j 密码 12345678
CHROMA_HOST / CHROMA_PORT ChromaDB 主机端口 localhost / 8000
SQLITE_PATH SQLite 数据库路径 ./data/sqlite/app.db
SILICON_FLOW_API_KEY 硅基流动 API 密钥(Embedding + Rerank + 备用 LLM) -
SILICON_FLOW_BASE_URL 硅基流动 base URL https://api.siliconflow.cn/v1
KIMI_API_KEY Moonshot Kimi 密钥(备用 LLM) -
KIMI_BASE_URL Moonshot base URL https://api.moonshot.cn/v1
BAILIAN_API_KEY 阿里云百炼 LLM 密钥 -
BAILIAN_BASE_URL 百炼 base URL https://dashscope.aliyuncs.com/compatible-mode/v1
BAILIAN_MODEL 百炼模型 qwen3.7-flash
LLM_MODEL_KIMI Kimi 模型 kimi-k2-0905-preview
LLM_MODEL_SILICON 硅基流动模型 Qwen/Qwen3-8B-Instruct
JWT_SECRET JWT 签名密钥 占位符(生产必须替换)
JWT_ALGORITHM JWT 算法 HS256
ACCESS_TOKEN_EXPIRE_MINUTES Token 有效期(分钟) 60
UPLOAD_DIR 上传文件目录 ./data/uploads
MAX_FILE_SIZE 最大文件大小(字节) 10485760(10MB)
EMBEDDING_MODEL 嵌入模型名 Qwen/Qwen3-Embedding-8B
EMBEDDING_DIM 嵌入维度 1024
RERANK_MODEL Rerank 模型 Qwen/Qwen3-Reranker-8B
CORS_ALLOWED_ORIGINS 允许的 CORS 来源(逗号分隔) localhost 开发地址
MAX_REQUEST_BODY 全局请求体大小上限(字节) 15728640(15MB)
ENABLE_INTENT_ROUTING 启用查询意图路由(闲聊/拒答绕过检索) True
INTENT_CLASSIFY_TIMEOUT 意图分类超时(秒) 3.0
GRAPH_RAG_MODE 图谱 RAG 模式(auto/on/off) auto
MULTI_QUERY_NUM_VARIANTS 多查询变体数 3
QUERY_REWRITE_MIN_LEN 触发查询改写的最短长度(字符) 20
RERANK_RECALL_K 每路召回送入 RRF/重排的候选数 25
GRAPH_RRF_WEIGHT 图谱通道 RRF 权重 1.0
ENABLE_EXPANSION_RERERANK 扩展集再重排 True
RETRIEVAL_CACHE_TTL 检索结果缓存 TTL(秒) 300
BM25_PREWARM 启动预热 per-user BM25 索引 True
PARENT_SECTION_MAX_CHARS 父文档扩展最大字符数 2000
PARENT_SECTION_SIBLING_LIMIT 父文档扩展兄弟块上限 4
CONVERSATIONAL_REWRITE_HISTORY_TURNS 会话改写参考的历史轮数 4
CHUNK_OVERLAP 切块重叠字符数(仅影响新上传) 50
ENABLE_LLM_EXTRACTION 启用 LLM 实体提取 True
USE_RULE_EXTRACTION 同时使用规则提取 False
ENTITY_BATCH_SIZE 实体提取批大小 200
ENTITY_EXTRACTION_DELAY 实体提取批间延迟(秒) 0
LLM_EXTRACTION_CONCURRENCY 实体提取并发上限 20
LLM_EXTRACT_MAX_TOKENS 实体提取 max_tokens 1024
LOG_DIR / LOG_LEVEL 日志目录与级别 ./data/logs / INFO

🧭 前端路由总览

路径 页面 说明
/login Home.vue 登录 / 注册
/documents DocumentsPage.vue 文档列表与上传
/documents/:id DocumentDetailPage.vue 文档详情
/documents/map ClusterMapPage.vue 2D PCA 聚类地图
/graph GraphPage.vue 图谱主页(搜索 + 可视化)
/graph/timeline-animation EntityTimelineAnimationPage.vue 实体时间线动画
/entities/:name EntityDetailPage.vue 实体详情
/dashboard DashboardPage.vue 仪表盘
/timeline TimelinePage.vue 时间线
/chat ChatPage.vue RAG 对话
/search SearchPage.vue 语义检索

/login 外所有路由均需要登录,由 router/index.jsbeforeEach 守卫统一拦截。

🛠️ 开发指南

📋 环境要求

  • Python 3.11+
  • Node.js 18+
  • Docker & Docker Compose

🧪 测试

# 冒烟测试(无需 Neo4j/ChromaDB)
cd backend
../.venv/Scripts/python.exe -c "
from app.main import app
from fastapi.testclient import TestClient
c = TestClient(app)
assert c.get('/health').status_code == 200
print('OK')
"

# 集成测试(需启动 Docker 服务)
docker-compose up -d
../.venv/Scripts/python.exe -m pytest backend/tests

单元测试无需真实密钥:conftest.pysetdefault 一个临时 JWT_SECRET(CI 中也显式注入),JWT 占位符拦截不会阻断测试。

✅ 持续集成(CI)

.github/workflows/ci.yml 在 push 到 main/master 及 PR 时自动运行 backendpytest tests/ -q(Python 3.11)。无需真实密钥——JWT_SECRETAPP_ENV=test 由 workflow 注入。

🗃️ 数据库迁移

表结构由 database.init_dbCREATE TABLE IF NOT EXISTS 创建;其后 _run_migrationsbackend/migrations/NNN_*.sql 文件名序号顺序应用,进度记录在 schema_version 表。001_baseline.sql 仅 stamp 版本 1(无结构变更),新增增量迁移直接加 002_*.sql 即可。

🗄️ 备份

# 全量备份(SQLite 在线 .backup + Neo4j/Chroma/uploads 打包)
# 默认数据根是 backend/data(应用的所有启动方式 CWD=backend,相对路径
# ./data/... 实际落在 backend/data/),备份产物在 backend/data/backups/
./scripts/backup.sh
# 自定义路径:DATA_DIR=/var/lib/kg OUT_DIR=/tmp ./scripts/backup.sh
# 注意:脚本会拒绝备份缺失或 0 字节的 SQLite 文件(历史上曾静默备份空库)

🧹 清理单个用户数据(运维,破坏性)

# 从仓库根或 backend/ 运行均可(SQLite 路径自动锚定到 backend/data)
cd backend
../.venv/Scripts/python.exe clean_user_data.py 3 --dry-run   # 预览
../.venv/Scripts/python.exe clean_user_data.py 3 --yes       # 真删
# 若应用正在运行,清理后需重启以清空内存中的检索/聚类缓存

♻️ 向量索引重建(运维)

当 Chroma 向量丢失(容器重建 / 误删 / 迁移)但 SQLite 的 chunks 表与 embedding_cache 仍在时,可零 API 成本回灌:

cd backend
../.venv/Scripts/python.exe scripts/rebuild_chroma.py
# 输出示例:
# [info] chunks with cached embedding: 54
# [info] upserted batch 1: 54/54
# [done] upserted 54 chunks; collection now holds 54 vectors

🐳 Docker 部署

# 构建并运行基础设施(Neo4j + ChromaDB;后端本身不在此 compose 内)
docker-compose up -d

# 单独构建后端镜像 —— 必须从仓库根构建(requirements.txt 在根、app 在 backend/)
docker build -f backend/Dockerfile -t kg-backend .
docker run -p 8001:8001 --env-file backend/.env kg-backend

📦 关键依赖版本

# backend
fastapi==0.115.0
uvicorn==0.32.0
python-jose[cryptography]==3.3.0
bcrypt==4.1.3
python-multipart==0.0.17
neo4j==6.1.0
chromadb==0.4.18
numpy==1.26.4
httpx==0.27.0
aiofiles==24.1.0
markitdown==0.0.1a3
markdown-it-py==3.0.0
jieba==0.42.1
spacy==3.7.5
rank-bm25==0.2.2
python-dotenv==1.0.0
pydantic==2.9.2
pydantic-settings==2.6.0
sqlalchemy==2.0.36
aiosqlite==0.20.0

# dev / test only
pytest==8.3.3
pytest-asyncio==0.24.0
# frontend
vue ^3.5.24
vue-router ^4.6.3
pinia ^2.3.1
d3 ^7.9.0
axios ^1.7.9
@tanstack/vue-virtual ^3.13.28
vite ^7.2.4

注意:原 passlib[bcrypt]==1.7.4 已移除,改为原生 bcrypt==4.1.3(passlib 与新版 bcrypt 存在兼容问题;且 chromadb 0.4.18 依赖 bcrypt>=4.0.1,钉 3.x 会让全新环境的 pip 解析直接失败——CI 曾因此一直红)。app/auth/security.py 在哈希前主动截断 72 字节、验证时捕获 ValueError,兼容 4.x 行为;存量 $2b$ 哈希可直接验证。

📌 注意事项

  1. 🗝️ API 密钥保护.env 中的密钥若已泄露,立即在控制台轮换
  2. 🔑 JWT_SECRET任意环境检测到公开占位符即拒绝启动(不限于 production);用 python -c "import secrets; print(secrets.token_urlsafe(48))" 生成
  3. 硅基流动限速:嵌入服务实现了批量处理、异步队列和并发控制(Semaphore=5)
  4. 🧮 NumPy 版本:必须使用 NumPy 1.x(<2.0)以保证 ChromaDB 兼容性
  5. 🧬 ChromaDB 版本:客户端和服务端必须都使用 0.4.18 版本
  6. 🐳 Docker 内存:Neo4j 需要充足内存,建议 4GB+
  7. 🛡️ markitdown 防御utils/md_parser.py 兼容新旧 API(text_content / markdown / title),失败时回退到 txt 解析
  8. 🧩 Neo4j APOC:docker-compose 启用了 APOC 插件,UNWIND 批量写入依赖其函数
  9. ⚠️ 实体合并POST /api/graph/entities/merge 会硬删 source 并将所有引用指向 target,操作不可逆
  10. 🔧 Chroma entrypoint 绕过docker-compose.yml 覆盖了 chromadb 0.4.18 镜像 entrypoint——原 entrypoint 每次启动 pip install --force-reinstall chroma-hnswlib,新版会拉入 numpy 2.x 导致 np.float_ 崩溃。改为直接跑 uvicorn,沿用镜像内可用的 hnswlib
  11. ♻️ 向量索引重建:若 Chroma 向量丢失(容器重建/误删/迁移),运行 backend/scripts/rebuild_chroma.py 可从 SQLite chunks + embedding_cache(md5-keyed)零 API 成本回灌,复用 get_chroma_client 保证集合名/cosine/upsert 与摄入路径一致

📜 许可证

MIT

About

一个支持多用户的知识图谱系统,整合 Neo4j 图数据库和 ChromaDB 向量数据库,实现文档知识管理、可视化检索和 RAG 智能问答。

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages