从零构建 AI 学术论文助手(一):架构设计与技术选型
系列文章:用 FastAPI + RAG + 多模型路由,独立开发一个可商用的学术 PDF 知识库 SaaS 平台 DocMind。
一、为什么做这个项目
读研期间最痛苦的事情之一:桌面上堆了几十篇 PDF,想找某个知识点,只能靠 Ctrl+F 关键词搜索,看到一半又跳到另一篇,上下文完全割裂。
市面上有 ChatPDF、Elicit 这类工具,但:
- ChatPDF:免费版只能传一篇,不支持跨文献对比
- Elicit:主要做文献发现,不做深度问答
- Notion AI:导入 PDF 体验很差
- 本地部署方案(Ollama + AnythingLLM):配置复杂,非技术用户用不了
决定自己做一个:上传论文 → 自动解析章节 → AI 问答 + 精读 + 写综述 + 降率,一站搞定。
二、最终实现的功能模块
经过迭代,DocMind 最终实现了 6 个核心模块:
| 模块 | 功能 |
|---|---|
| 📁 文档库 | PDF 上传、管理、批量删除 |
| 💬 知识库问答 | 多文献 RAG 问答,支持章节定向检索 |
| 📖 PDF 精读对话 | 三栏布局:目录 + PDF 原文 + AI 对话,支持框选截图分析 |
| 📝 文献综述 | 多文献一键生成综述 |
| ✍️ 论文撰写 | 按章节框架 AI 辅助写作 |
| ✂️ 降率工具 | 英文降 AI 率 / 降重复率,分块流式处理 |
附加功能:引用格式导出(10+ 种格式)、联网检索增强。
三、整体架构
┌─────────────────────────────────────────────────────┐ │ 用户浏览器 │ │ index.html(落地页)+ app.html(SPA) │ └──────────────────────┬──────────────────────────────┘ │ HTTPS / SSE ┌──────────────────────▼──────────────────────────────┐ │ FastAPI 后端(Railway) │ │ │ │ routers/ │ │ ├── auth.py 注册/登录/JWT │ │ ├── upload.py PDF上传 + 异步处理入库 │ │ ├── query.py RAG问答 / 综述 / 撰写 / 引用 │ │ ├── reduce.py 英文降率 │ │ └── vision.py 图像分析(Gemini) │ │ │ │ services/ │ │ ├── pdf_processor.py PyMuPDF章节解析 │ │ ├── embedder.py Jina AI向量化 + Chroma存储 │ │ └── retriever.py RAG检索 + LLM调用 │ └─────┬────────────────┬───────────────────────────────┘ │ │ ▼ ▼ Supabase Chroma DB PostgreSQL (Railway 本地卷) 用户/文档元数据 向量索引 │ └──── 调用外部 API ────┐ ▼ ┌─────────────────┐ │ LLM / Embedding │ │ DeepSeek v4 │(主力问答) │ Groq Llama 3 │(限流降级) │ Gemini 2.5 Flash│(视觉分析) │ Jina AI │(向量化) └─────────────────┘四、关键技术选型理由
4.1 为什么不用 LangChain
LangChain 是 RAG 场景的常见选择,但我最终没有用,原因:
- 过度抽象:LangChain 把检索、提示、输出解析全包了,出了问题很难定位是哪一层的锅
- 升级频繁:0.1 → 0.2 → 0.3 接口变化很大,文档跟不上
- 我的场景简单:RAG 核心逻辑不过 200 行,自己写反而清晰
最终选择:直接用openaiSDK + 自写检索逻辑,所有 LLM 调用一目了然。
4.2 向量库:Chroma 而非 Pinecone / Weaviate
| Chroma | Pinecone | Weaviate | |
|---|---|---|---|
| 部署 | 本地/嵌入 | 云服务 | 自托管/云 |
| 免费 | 完全免费 | 有免费额度 | 开源免费 |
| Railway 适配 | ✅ 直接挂卷 | ✅ 但需联网 | ⚠️ 较重 |
| 中文支持 | ✅ | ✅ | ✅ |
选 Chroma 的关键原因:可以直接挂 Railway 持久卷,零额外费用,嵌入式运行无需独立服务。
⚠️ 注意:Railway 免费套餐文件系统是临时的,每次重启数据清空。需要升级到有持久卷的套餐或迁移到 Supabase pgvector。
4.3 Embedding:Jina AI 而非 OpenAI
- OpenAI
text-embedding-3-small:$0.02/1M token,但对中英混合文本效果一般 - Jina AI
jina-embeddings-v3:免费额度 100万 token/月,中英双语语义对齐好
对学术场景特别有价值:用中文提问「注意力机制」能命中英文文本中的「Attention」,不需要额外翻译。
4.4 LLM 路由:DeepSeek 主力 + Groq 降级
DeepSeek v4-flash 性价比极高(官方定价约 $0.07/1M 输入 token),但 Groq 免费版每日有 Token 上限(约 14400 token/分钟)。
解决方案:设计MODEL_ROUTES+MODEL_FALLBACK双表路由,遇到 429 自动切换,对用户完全透明。具体实现见第三篇。
4.5 部署平台:Railway 而非 Vercel
- Vercel:适合 Node.js/Next.js,Python 支持通过 Serverless Functions,有执行时间限制(10s),PDF 处理会超时
- Railway:完整 Linux 环境,可以跑任意 Python 进程,支持后台线程,持久卷,Dockerfile 部署
五、数据库设计
使用 Supabase PostgreSQL,核心表:
-- 用户表 CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email TEXT UNIQUE NOT NULL, password TEXT NOT NULL, -- SHA256 + salt plan TEXT DEFAULT 'free', -- free / pro pdf_count INTEGER DEFAULT 0, query_today INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT now() ); -- 文档表 CREATE TABLE documents ( id UUID PRIMARY KEY, user_id UUID REFERENCES users(id), filename TEXT, -- 服务器存储名(uuid.pdf) original_name TEXT, -- 用户上传的原始文件名 size_bytes INTEGER, page_count INTEGER, chunk_count INTEGER, status TEXT DEFAULT 'pending', -- pending/processing/ready/error error_msg TEXT, created_at TIMESTAMP DEFAULT now() );向量块单独存在 PostgreSQL(doc_chunks表,通过 pgvector 扩展),或 Chroma 本地库。
六、项目目录结构
kb_project/ ├── main.py # FastAPI 入口,挂载路由 ├── config.py # 所有配置:API Key、模型路由、分块参数 ├── requirements.txt │ ├── db/ │ └── database.py # SQLAlchemy 模型 + 连接池 │ ├── routers/ │ ├── auth.py # 注册/登录/JWT 验证 │ ├── upload.py # PDF 上传 + 文件下载接口 │ ├── query.py # 问答/综述/撰写/引用 │ ├── reduce.py # 英文降率 │ └── vision.py # 图像分析 │ ├── services/ │ ├── pdf_processor.py # PDF 解析 → chunks │ ├── embedder.py # 向量化 + Chroma 存取 │ └── retriever.py # RAG 检索 + LLM 调用 │ ├── uploads/ # 上传的 PDF 文件 └── frontend/ ├── index.html # 落地页 └── app.html # 工作台 SPA(单文件,约3000行)七、开发与部署流程
# 本地开发 pip install -r requirements.txt uvicorn main:app --reload --port 8000 # Railway 部署(Dockerfile) FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]Railway 环境变量(不写死在代码里):
GROQ_API_KEY=... DEEPSEEK_API_KEY=... GEMINI_API_KEY=... JINA_API_KEY=... DATABASE_URL=postgresql://...@...supabase.co:5432/postgres SECRET_KEY=your-jwt-secret八、小结
本篇覆盖了 DocMind 的整体架构与核心选型。关键决策回顾:
- 不用 LangChain,自写 RAG 逻辑更可控
- Chroma做向量库,Railway 本地挂卷
- Jina AI做 Embedding,中英双语对齐
- DeepSeek 主力 + Groq 降级,兼顾成本与稳定性
- 单文件 SPA 前端,零构建步骤,Railway 直接静态服务
下一篇:PDF 解析与 RAG 检索核心实现——如何让 AI 真正读懂论文章节结构。
