从零构建 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 场景的常见选择,但我最终没有用,原因:

  1. 过度抽象:LangChain 把检索、提示、输出解析全包了,出了问题很难定位是哪一层的锅
  2. 升级频繁:0.1 → 0.2 → 0.3 接口变化很大,文档跟不上
  3. 我的场景简单:RAG 核心逻辑不过 200 行,自己写反而清晰

最终选择:直接用openaiSDK + 自写检索逻辑,所有 LLM 调用一目了然。

4.2 向量库:Chroma 而非 Pinecone / Weaviate

ChromaPineconeWeaviate
部署本地/嵌入云服务自托管/云
免费完全免费有免费额度开源免费
Railway 适配✅ 直接挂卷✅ 但需联网⚠️ 较重
中文支持

选 Chroma 的关键原因:可以直接挂 Railway 持久卷,零额外费用,嵌入式运行无需独立服务

⚠️ 注意:Railway 免费套餐文件系统是临时的,每次重启数据清空。需要升级到有持久卷的套餐或迁移到 Supabase pgvector。

4.3 Embedding:Jina AI 而非 OpenAI

  • OpenAItext-embedding-3-small:$0.02/1M token,但对中英混合文本效果一般
  • Jina AIjina-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 真正读懂论文章节结构。