Skip to content

Repository files navigation

知蔓 — 知识挖掘应用

基于「交互式生成 + 实时检索」的轻量级知识图谱探索工具:输入关键词生成根节点与概念解释,点击节点沿不同方向扩展,通过 SSE 流式实时展示检索与 LLM 生成过程,逐步生长出个人知识图谱。


当前状态

  • 里程碑:M0–M6 已完成(项目启动 → UI 骨架 → 静态交互 → 后端基座 → 扩展引擎 → 端到端联调 → 测试优化),M7「上线部署」未开始。详细规划见 plan.md
  • 已实现功能
    • 用户注册 / 登录(JWT)
    • 关键词创建图谱、多图谱列表与切换、重命名、删除
    • 节点扩展(自动 / 子概念 / 相关应用;扩展数量由 LLM 在 2–5 之间智能决定),SSE 流式推送进度与 LLM 增量输出
    • 在右侧「定义/要点」中选中文字 →「帮我解释」:LLM 分析该段应展开几个概念并复用扩展流水线生成解释性子节点
    • 概念解释(定义 + 要点 + 来源 + 可信度),检索结果事实校验
    • 图谱画布:缩放、平移、节点拖拽、小地图、选择/平移工具切换、画布全屏(隐藏两侧栏)、重排居中
    • 节点删除(级联 / 重挂子树)、扩展撤销(快照回滚)
    • 图谱内搜索定位(左侧「搜索」/ Ctrl+F 弹窗,命中后画布居中到节点)
    • 导出 JSON / Markdown / SVG / PNG
  • 近期改进:检索切换到 Serper(Google Search),429/5xx 自动重试 + 并发限流;扩展数量与「帮我解释」均由 LLM 决定;安全与正确性加固(事务原子化、JWT 启动校验、SSE 走 fetch+Authorization 头、节点按 id 着色);精简 UI(移除笔记/收藏/合集/状态/标签/专注模式/设置,新增全屏、选择/平移、搜索、选中解释)。
  • 测试:后端 29 个单元测试通过,前端 19 个测试通过(另有需数据库的集成测试)。

项目结构

FernGrow/
├── knowledge-graph-frontend/   # React 19 + TypeScript + Vite + Tailwind CSS v4
│   └── src/
│       ├── pages/              # LandingPage / Login / Register / GraphExplorer
│       ├── components/         # layout(三栏)、graph(画布/扩展)、modals、ui
│       ├── stores/             # Zustand:authStore / graphStore / uiStore
│       ├── services/           # axios API 客户端、llmStream(SSE 消费)
│       └── utils/              # 径向布局、导出、streamExtract(流式 JSON 解析)
├── knowledge-graph-backend/    # Python 3.12 + FastAPI + uv
│   └── app/
│       ├── api/v1/             # auth / graphs / nodes 路由
│       ├── core/               # 配置、JWT、鉴权依赖、异常
│       ├── db/                 # SQLAlchemy 引擎与 Repository 层
│       ├── models/             # users / graphs / nodes / edges / snapshots / llm_cache
│       ├── services/           # 图谱、扩展引擎、导出、缓存、Prompt
│       └── external/           # LLM 客户端、Serper 检索、SSE 发布器
├── prd.md                      # 产品需求文档
├── ui.md                       # UI 设计描述
├── design.md                   # 系统架构设计
├── plan.md                     # 项目开发进度规划
├── api-contract.md             # 前后端接口协议
├── docker-compose.yml          # 全栈 Docker 编排
└── .env.example                # 环境变量模板

技术栈

  • 前端:React 19 + TypeScript + Vite 8 + Tailwind CSS v4 + Zustand + axios + 原生 EventSource(SSE)+ Lucide Icons;测试用 Vitest,lint 用 oxlint
  • 后端:Python 3.12 + FastAPI + SQLAlchemy 2.0(async)+ PostgreSQL + Redis(LLM 概念两级缓存:Redis 优先、PG 表降级)+ Alembic 迁移;依赖管理用 uv
  • 外部服务:Serper(Google Search)检索 API + OpenAI 兼容格式的国产 LLM(支持流式输出;无密钥时自动进入 mock 模式,方便本地开发)
  • 部署:Docker + Docker Compose + Nginx(含 SSE 透传配置)

快速开始

1. 环境准备

  • Node.js 20+
  • uv(Python 包管理器)
  • Docker(用于数据库 / 缓存,或完整部署)

2. 启动数据库与缓存(Docker)

docker run -d --name kg-db \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=password \
  -e POSTGRES_DB=kgdb \
  -p 5432:5432 \
  -v $(pwd)/knowledge-graph-backend/init.sql:/docker-entrypoint-initdb.d/init.sql:ro \
  postgres:16-alpine

docker run -d --name kg-redis -p 6379:6379 redis:7-alpine

3. 配置环境变量

cp .env.example .env
# 编辑 .env:JWT_SECRET 必须改成一个随机字符串(占位符会被启动校验拒绝)
# SERPER_API_KEY / LLM_API_KEY 不填时,检索与 LLM 自动进入 mock 模式

4. 启动后端

cd knowledge-graph-backend
uv sync
uv run dev        # 等价于 uvicorn app.main:app --reload --port 8000

交互式 API 文档:http://localhost:8000/docs

5. 启动前端

cd knowledge-graph-frontend
npm install
npm run dev       # 端口 5173,/api 自动代理到 localhost:8000

访问 http://localhost:5173


数据库迁移

cd knowledge-graph-backend
uv run alembic upgrade head                 # 应用到最新
uv run alembic revision --autogenerate -m "..."   # 模型变更后生成新迁移

测试

# 后端:单元测试(全部 mock,无需外部服务)
cd knowledge-graph-backend && uv run pytest -m unit

# 后端:集成测试(需要可连接的 PostgreSQL,连不上自动 skip)
uv run pytest -m integration

# 前端
cd knowledge-graph-frontend && npm test

部署到服务器(腾讯云 + 自有域名)

以「腾讯云香港 Ubuntu 24.04 + Godaddy 域名 geekbit.org,绑定子域 ferngrow.geekbit.org」为例。 架构:Docker Compose 跑 前端(Nginx, 仅 127.0.0.1:$FRONTEND_PORT) + 后端(127.0.0.1:$BACKEND_PORT) + Postgres + Redis;宿主机 Nginx 做 HTTPS 反代到 FRONTEND_PORT(默认 28080),certbot 申请并续期证书。对外只开放 80/443。

0. 前置

  • 一台腾讯云服务器(Ubuntu 24.04),记下公网 IP。
  • Godaddy 上的域名 geekbit.org,DNS 管理权限。

1. DNS:在 Godaddy 添加 A 记录

Godaddy 域名管理 → DNS Records:

  • 类型 A,名称 ferngrow(即 ferngrow.geekbit.org),值填服务器公网 IP,TTL 默认。
  • 生效后用 dig ferngrow.geekbit.org +short 验证返回你的 IP。

2. 腾讯云安全组:放行 80 / 443

腾讯云控制台 → 云服务器 → 安全组 → 入站规则,放行 TCP 80、443(以及 SSH 22)。

必做:腾讯云默认安全组通常只开 22;仅在服务器内 ufw 放行不够,必须在控制台改安全组。

3. 服务器安装 Docker

SSH 登录后:

sudo apt update && sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
docker --version && docker compose version     # 验证
sudo usermod -aG docker $USER                  # 把当前用户加入 docker 组

⚠️ usermod 需要重新登录才生效。加完组后必须 exit 重新 SSH 登录(或在当前 shell 执行 newgrp docker),否则第 5 步 docker compose ... 会报 permission denied ... docker.sock。临时绕过可在命令前加 sudo

4. 拉取代码并配置 .env

git clone <你的仓库地址> FernGrow && cd FernGrow
cp .env.example .env

编辑 .env(生产值):

  • DEBUG=false
  • JWT_SECRET=<openssl rand -hex 32 生成的随机串>(必须改,占位符会被启动校验拒绝)
  • SERPER_API_KEY=<你的 Serper key>
  • LLM_API_KEY / LLM_BASE_URL / LLM_MODEL:填你的 LLM 配置
  • CORS_ORIGINS=["https://ferngrow.geekbit.org"]
  • DATABASE_URL / REDIS_URL:保持 .env.example 即可(compose 会用容器网络地址覆盖)

5. 启动全栈

docker compose up --build -d
docker compose ps                  # 4 个服务都应为 Up
docker compose logs -f backend     # 含 alembic upgrade head 自动建表
  • 后端容器启动时自动 alembic upgrade head
  • 前端 Nginx 托管静态资源并把 /api 反代到后端(已配 SSE 透传)。
  • 此时前端仅在 127.0.0.1:28080(即 $FRONTEND_PORT,可在 .env 改),尚未对外。

6. 宿主机 Nginx + HTTPS(certbot)

sudo apt install -y nginx certbot python3-certbot-nginx

新建 /etc/nginx/sites-available/ferngrow.conf

server {
    listen 80;
    server_name ferngrow.geekbit.org;
    client_max_body_size 20m;

    location / {
        proxy_pass http://127.0.0.1:28080;   # = FRONTEND_PORT(在 .env 里设置)
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # SSE:关闭缓冲 + 加长超时,避免流式扩展被 Nginx 截断
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

启用并申请证书(自动加 443 配置 + 80→443 跳转):

sudo ln -s /etc/nginx/sites-available/ferngrow.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d ferngrow.geekbit.org

7. 本机防火墙

sudo ufw allow 22/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
sudo ufw enable

8. 验证

浏览器打开 https://ferngrow.geekbit.org → 注册登录 → 建图谱并扩展节点;SSE 应正常流式输出。 查日志:docker compose logs -f backend / sudo tail -f /var/log/nginx/error.log

9. 后续更新与续期

cd FernGrow && git pull && docker compose up --build -d     # 重建并滚动更新
sudo certbot renew --dry-run                                # 验证证书自动续期(certbot 已装 systemd timer)

备注

  • 容器均绑在 127.0.0.1(前端 FRONTEND_PORT、后端 BACKEND_PORT,默认 28080 / 28000),对外只经宿主机 Nginx 的 80/443;Postgres/Redis 不暴露端口。多项目服务器端口冲突时:在 .envFRONTEND_PORT / BACKEND_PORT(用 sudo ss -ltnp | grep :端口号 确认空闲),并同步把 Nginx 的 proxy_pass 端口改成新的 FRONTEND_PORT,然后 docker compose up -d
  • .env 含密钥,勿提交(已在 .gitignore)。
  • 香港服务器访问 Serper / LLM 外网通常无碍;若用内地服务器需确认出网。

接口文档

详见 api-contract.md

核心接口(均挂在 /api/v1 下):

  • POST /auth/registerPOST /auth/loginGET /auth/me
  • POST /graphsGET /graphsGET /graphs/{id}PUT /graphs/{id}DELETE /graphs/{id}
  • POST /graphs/{id}/export(JSON / Markdown / SVG / PNG)
  • GET /nodes/{id}/expand —— SSE 流式扩展(事件:progress / node_start / node_chunk / node_complete / edge_create / complete / error
  • POST /nodes/{id}/explain —— 选中文字「帮我解释」,SSE 扩展(复用扩展流水线)
  • DELETE /nodes/{id}POST /nodes/{id}/undo

About

知蔓 — 知识挖掘应用

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages