Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Neroxsh/fastapi-rag-service

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

本项目依托 FastAPI 构建后端服务,通过 LangChain 实现 RAG 全流程编排,结合通义千问 Embedding 与 LLM 能力、PostgreSQL 向量数据库,对外暴露接口完成知识库管理与检索增强问答。


FastAPI RAG Service (基于 LangChain & Qwen & PGVector)

一个基于检索增强生成(Retrieval-Augmented Generation, RAG)技术的智能问答后端服务。使用 FastAPI 构建接口,LangChain 编排流程,通义千问(Qwen)提供 Embedding 和 LLM 能力,PostgreSQL + pgvector 作为向量数据库。

📚 目录


项目简介

本项目是一个完整的 RAG 后端服务,旨在解决大模型的“知识时效性”和“私有知识库问答”问题。

核心能力

  1. 知识库管理:通过 /add 接口将文本切分、向量化后存入 PostgreSQL。
  2. 智能问答:通过 /query 接口,基于已添加的私有知识库进行精准检索并生成回答。
  3. 防幻觉 (Hallucination):通过 Prompt 工程严格约束 LLM 仅使用检索到的上下文回答,未知问题明确告知“未找到相关内容”。

应用场景

  • 毕业设计智能问答系统
  • 企业内部文档知识库
  • 个人笔记智能助手

功能特性

  • RESTful API:基于 FastAPI,自动生成交互式文档 (/docs)。
  • 文本切分 (Chunking):使用 RecursiveCharacterTextSplitter,支持自定义 chunk 大小与重叠。
  • 向量存储:集成 PostgreSQL + pgvector,开源、稳定、可扩展。
  • 检索增强生成:LangChain RetrievalQA 链,实现“检索 -> 组装 Prompt -> LLM 生成”全流程。
  • 配置分离:使用 python-dotenv 管理 API Key 等敏感信息。

技术栈详解

层级 技术选型 版本 作用
Web 框架 FastAPI 0.115.0 构建高性能 API 接口,提供自动文档。
ASGI 服务器 Uvicorn 0.32.0 运行 FastAPI 应用。
RAG 编排框架 LangChain 0.3.4 串联文本切分、向量化、检索、LLM 调用。
向量数据库 PostgreSQL + pgvector 14 存储文本片段及其向量,执行相似度搜索。
数据库驱动 psycopg2-binary 2.9.10 Python 连接 PostgreSQL 的驱动。
Embedding 模型 通义千问 Embedding-v3 - 阿里云提供,将文本转化为 1536 维向量。
大语言模型 通义千问 Qwen-Max - 阿里云提供,基于上下文生成最终回答。
配置管理 python-dotenv 1.0.1 环境变量管理。
数据校验 Pydantic 2.9.2 API 请求/响应的数据结构定义与校验。

系统架构

逻辑架构图

graph TD
    User[用户/前端] -->|POST /add| FastAPI[FastAPI 接口层]
    User -->|POST /query| FastAPI
    
    subgraph "业务逻辑层 (app/services)"
        FastAPI -->|文本| Chunk[文本切分<br/>TextSplitter]
        FastAPI -->|问题| Retrieve[向量检索<br/>Similarity Search]
        
        Chunk --> Embedding[向量化<br/>Qwen-Embedding]
        Retrieve --> Embedding
        Retrieve --> Prompt[Prompt 组装<br/>Context + Question]
        Prompt --> LLM[大模型生成<br/>Qwen-LLM]
    end
    
    subgraph "数据存储层 (PostgreSQL)"
        Embedding -->|存储| PG[(langchain_pg_embedding<br/>文本 + 向量)]
        Retrieve -->|相似度搜索 <=>| PG
    end
Loading

数据流向

  1. Add (写入)用户文本 -> 切分 (Chunk) -> 向量化 (Embedding) -> 存入 PostgreSQL
  2. Query (查询)用户问题 -> 向量化 -> 相似度检索 (Top K) -> 组装上下文 -> 送入 LLM -> 返回答案

目录结构

项目采用经典的后端分层架构,实现了接口层、业务逻辑层、数据层的解耦。

fastapi-rag-service/
├── app/
│   ├── __init__.py
│   ├── api/
│   │   ├── __init__.py
│   │   └── routes.py          # [接口层] URL 路由定义,仅负责接收和返回
│   ├── core/
│   │   ├── __init__.py
│   │   ├── config.py          # [配置中心] 读取 .env,全局单例
│   │   └── database.py        # [数据库连接] 初始化 PGVector 和 Embedding
│   ├── schemas/
│   │   ├── __init__.py
│   │   └── schemas.py         # [数据模型] Pydantic 模型,定义 API 入参/出参
│   └── services/
│       ├── __init__.py
│       └── rag_service.py     # [业务逻辑层] RAG 核心算法实现
├── .env                        # 环境变量 (需自行创建,不上传 Git)
├── .gitignore
├── requirements.txt            # Python 依赖列表
├── main.py                     # [入口文件] FastAPI 应用初始化
└── README.md                   # 项目文档 (本文件)

快速开始

1. 环境准备

确保你已安装以下环境:

  • Python 3.9+
  • PostgreSQL 12+ (需安装 pgvector 扩展)
  • Docker (可选,用于快速启动 PostgreSQL)

2. 克隆项目

git clone <your-repo-url>
cd fastapi-rag-service

3. 配置环境变量

在根目录创建 .env 文件,填入以下内容:

# 阿里云 API Key (获取地址: https://bailian.console.aliyun.com/)
DASHSCOPE_API_KEY=sk-你的APIKey

# PostgreSQL 数据库连接串
# 格式: postgresql://用户名:密码@主机:端口/数据库名
DATABASE_URL=postgresql://postgres:你的密码@localhost:5432/my_vector_db

# 模型配置
EMBEDDING_MODEL=text-embedding-v3
LLM_MODEL=qwen-max

4. 安装依赖

conda create -n py39 python=3.9
conda activate py39
pip install -r requirements.txt

5. 初始化数据库 (Docker 示例)

如果你使用 Docker 启动 PostgreSQL:

# 拉取并运行带 pgvector 的 PostgreSQL
docker run -d \
  --name pgvector-14 \
  -e POSTGRES_PASSWORD=你的密码 \
  -e POSTGRES_DB=my_vector_db \
  -p 5432:5432 \
  pgvector/pgvector:pg14

# 进入容器并创建扩展
docker exec -it pgvector-14 psql -U postgres -d my_vector_db
# 在 psql 中执行:
# CREATE EXTENSION IF NOT EXISTS vector;
# \q

6. 启动服务

uvicorn main:app --reload

7. 测试接口

打开浏览器访问:http://127.0.0.1:8000/docs

你将看到 FastAPI 自动生成的交互式文档,可以直接在页面上测试 /add/query 接口。


核心流程原理解析

流程一:添加知识库 (/add)

文件位置app/services/rag_service.py -> add_document_to_kb()

  1. 文本切分:使用 RecursiveCharacterTextSplitter 将长文本切分为固定大小的片段 (Chunks)。
    • 参数chunk_size=500, chunk_overlap=50
    • 目的:解决 Embedding 模型输入长度限制,提高检索精度。
  2. 向量化与存储:调用 vector_store.add_documents()
    • LangChain 自动调用 Qwen-Embedding 将每个 Chunk 转化为向量。
    • 原文 (Content) + 向量 (Vector) + 元数据 (Metadata) 批量写入 PostgreSQL。

流程二:检索问答 (/query)

文件位置app/services/rag_service.py -> query_knowledge_base()

  1. 初始化 LLM:加载 qwen-max,设置 temperature=0.1 以保证输出严谨。
  2. Prompt 工程
    • 核心指令:“仅使用以下上下文回答用户的问题。如果上下文中没有答案,请明确说明‘知识库中未找到相关内容’。”
    • 作用:防止 LLM 幻觉 (Hallucination)。
  3. 构建检索链:使用 RetrievalQA.from_chain_type
    • search_kwargs={"k": 3}:召回相似度最高的 3 个文本片段。
  4. 执行逻辑
    1. 用户问题向量化。
    2. 在 PostgreSQL 中执行余弦相似度搜索 (<=> 运算符)。
    3. 拼接召回片段作为 Context。
    4. 将 Context + Question 送入 LLM。
    5. 返回 LLM 生成的答案及参考来源。

API 接口文档

1. 添加知识 (Add Document)

  • URL: POST /api/v1/add
  • Content-Type: application/json
  • Request Body:
{
  "content": "桂林电子科技大学,简称桂电,坐落于广西桂林市...",
  "source": "桂电官方介绍"
}
  • Response (200):
{
  "status": "success",
  "message": "成功添加 3 个文本片段"
}

2. 检索问答 (Query Knowledge Base)

  • URL: POST /api/v1/query
  • Content-Type: application/json
  • Request Body:
{
  "query": "桂林电子科技大学的计算机学科评估结果是什么?"
}
  • Response (200):
{
  "answer": "桂林电子科技大学的计算机科学与技术学科在第四轮学科评估中获评B-。",
  "sources": [
    "桂电的计算机科学与技术学科是国家级特色专业,在第四轮学科评估中获评B-...",
    "..."
  ]
}

数据库设计

LangChain 会在首次启动时自动创建以下两张表,无需手动执行 SQL。

表 1: langchain_pg_collection (集合管理)

用于管理不同的知识库集合。

字段 类型 说明
uuid UUID 主键,集合唯一ID
name VARCHAR 集合名称 (如: knowledge_base)
cmetadata JSONB 自定义元数据

表 2: langchain_pg_embedding (核心数据表)

存储文本片段、向量及元数据。

字段 类型 说明
uuid UUID 主键,本条数据唯一ID
collection_id UUID 外键,关联集合表
embedding vector(1536) 核心:Qwen-Embedding 生成的向量
document TEXT 原文片段 (Chunk)
cmetadata JSONB 元数据 (如: {"source": "..."})

常见问题 (FAQ)

Q1: 启动报错 ModuleNotFoundError: No module named 'pgvector'

A: 缺少 Python 客户端包。运行 pip install pgvector 即可。

Q2: 为什么我没写 SQL 项目也能跑?

A: LangChain 的 PGVector 类封装了所有底层 SQL 操作(建表、插入、相似度查询)。它会在初始化时自动建表,在调用方法时自动生成并执行 SQL。

Q3: 如何查看 LangChain 执行了哪些 SQL?

A: 在 app/core/database.py 开头添加 SQLAlchemy 日志配置:

import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

未来优化方向

  1. 迁移到新包:将 langchain_community.vectorstores.PGVector 迁移到官方新包 langchain-postgres (使用 PGVectorStore)。
  2. 文档解析:支持 PDF、Word 等文件的自动解析与上传 (使用 PyPDF2 或 LangChain Document Loaders)。
  3. 混合检索:结合关键词检索 (BM25) 和向量检索,提升召回率。
  4. 日志系统:引入 logging 模块,记录 Query 全链路日志。
  5. 前端界面:开发简单的 Web UI (如 Gradio/Streamlit/Vue) 用于演示。

一、宏观架构总览

你的项目是一个标准的检索增强生成(Retrieval-Augmented Generation, RAG)系统,采用经典的分层架构设计

1. 系统架构图(逻辑视图)

graph TD
    User[用户/前端] -->|HTTP请求| FastAPI[FastAPI 接口层]
    
    subgraph "业务逻辑层"
        FastAPI -->|add| Chunk[文本切分模块]
        FastAPI -->|query| Retrieve[向量检索模块]
        
        Chunk --> Embedding[向量化模块 Qwen-Embedding]
        Retrieve --> Embedding
        Retrieve --> Prompt[Prompt 组装模块]
        Prompt --> LLM[大模型 Qwen-LLM]
    end
    
    subgraph "数据存储层"
        Embedding -->|存储向量/文本| PG[(PostgreSQL + pgvector)]
        Retrieve -->|相似度搜索| PG
    end
Loading

2. 数据流向

  • Add(写入)流程:用户文本 $\to$ 切分 $\to$ 向量化 $\to$ 存入 PostgreSQL
  • Query(查询)流程:用户问题 $\to$ 向量化 $\to$ 向量检索 $\to$ 组装上下文 $\to$ 送入 LLM $\to$ 返回答案

二、技术栈深度解析

我们来逐一分析为什么选这些技术,以及它们在项目中的具体角色:

层级 技术选型 版本 核心作用 & 选型理由
Web框架 FastAPI 0.115.0 提供 RESTful API 接口。
理由:自动生成交互式文档 (/docs),非常适合毕设演示和调试;异步支持好;Python 生态完善。
ASGI 服务器 Uvicorn 0.32.0 运行 FastAPI 应用。
理由:FastAPI 官方推荐,性能优异。
RAG 编排 LangChain 0.3.4 串联整个 RAG 流程的“胶水”。
理由:内置文本切分器、向量数据库集成、LLM Chain,避免重复造轮子,快速搭建原型。
向量数据库 PostgreSQL + pgvector PG 14 存储原文和向量,并执行相似度搜索。
理由:你已熟悉 Docker 部署;开源免费;是目前业界最主流的向量存储方案之一。
数据库驱动 psycopg2-binary 2.9.10 Python 连接 PostgreSQL 的驱动。
Embedding 模型 Qwen-Embedding-v3 - 将文本转化为向量。
理由:阿里云提供,API 稳定,中文效果好。
LLM 模型 Qwen-Max - 理解上下文并生成最终回答。
理由:能力强,适合作为毕设的生成底座。
配置管理 python-dotenv 1.0.1 管理 API Key、数据库密码等敏感信息。
理由:安全(不把密码写死在代码里),符合开发规范。
数据校验 Pydantic 2.9.2 定义接口请求/响应的数据结构。
理由:FastAPI 原生集成,自动做数据类型校验。

三、目录结构与职责划分

你的项目采用了经典的后端分层架构,职责清晰,耦合度低。

my_rag_project/
├── app/
│   ├── api/
│   │   └── routes.py          # [接口层] 定义 URL 路由,只负责接收请求和返回响应,不写业务逻辑
│   ├── core/
│   │   ├── config.py          # [配置中心] 读取 .env 文件,全局单例配置
│   │   └── database.py        # [数据库连接] 初始化 PGVector 和 Embedding 模型
│   ├── schemas/
│   │   └── schemas.py         # [数据模型] 定义 Pydantic 模型(接口入参/出参长什么样)
│   └── services/
│       └── rag_service.py     # [业务逻辑层] RAG 的核心算法都在这里
├── .env                        # 环境变量(不上传 Git)
├── requirements.txt            # 依赖包列表
└── main.py                     # [入口文件] 初始化 FastAPI 应用,注册路由

分层的好处(毕设答辩可讲)

  1. 单一职责:每个文件只做一件事。
  2. 易维护:比如以后想换数据库,只需要改 database.py,不用动 routes.py
  3. 易测试:可以单独测试 rag_service.py 里的函数。

四、核心流程深度拆解

流程一:Add Document(添加知识库)

文件位置app/services/rag_service.py -> add_document_to_kb()

详细步骤:

  1. 接收输入:拿到用户传来的长文本 content
  2. 文本切分 (Chunking)
    • 工具RecursiveCharacterTextSplitter
    • 参数chunk_size=500(每段最多500字符),chunk_overlap=50(段与段之间重叠50字符)。
    • 为什么要切分?:LLM 和 Embedding 模型都有输入长度限制;切分后检索更精准。
    • 为什么要重叠?:防止语义在切分处被割裂。
  3. 向量化与存储
    • 调用 vector_store.add_documents(chunks)
    • 内部发生了什么?
      1. LangChain 自动遍历每个 Chunk。
      2. 调用 DashScopeEmbeddings (Qwen) 将文本变成向量(数组)。
      3. 原文 (Content) + 向量 (Vector) + 元数据 (Metadata) 一起写入 PostgreSQL。

流程二:Query Knowledge Base(检索问答)

文件位置app/services/rag_service.py -> query_knowledge_base()

详细步骤:

  1. 初始化 LLM
    • 模型:qwen-max
    • temperature=0.1:温度设得很低,让模型输出更严谨、更少发散。
  2. 构建 Prompt 模板
    • 核心指令:“仅使用以下上下文回答...如果没有请说明...”
    • 作用:这是 RAG 的“灵魂”,强制 LLM 只使用检索到的内容,禁止编造(Hallucination)
  3. 构建检索链 (RetrievalQA)
    • chain_type="stuff":最简单的策略,把检索到的文档直接“塞进” Prompt 里。
    • search_kwargs={"k": 3}:召回最相关的 3 个文本片段。
  4. 执行查询(内部黑箱)
    1. 问题向量化:把用户的 query 发给 Qwen-Embedding,得到问题向量。
    2. 相似度搜索:拿着问题向量去 PostgreSQL 里算距离(余弦相似度),找出最接近的 3 个文本。
    3. 组装上下文:把这 3 个文本拼在一起,作为 {context}
    4. 调用 LLM:把 {context}{question} 填入 Prompt,发给 Qwen-Max。
    5. 返回结果:拿到 LLM 的回答,连同参考的原文片段一起返回给用户。

五、关键代码文件精读

1. app/core/database.py(数据库核心)

这是项目的基石,我们在这里初始化了 LangChain 的 PGVector 对象。

  • 注意:你现在看到的 PGVector 来自 langchain_community,虽然有警告,但目前是稳定可用的。
  • 它做了什么?:它自动帮你在数据库里创建了两张表(见下文数据库设计),并封装了 add_documentssimilarity_search 方法。

2. app/schemas/schemas.py(数据契约)

这里定义了接口的“输入输出格式”。

  • AddDocumentRequest:规定了加知识必须传 content,可选传 source
  • QueryResponse:规定了返回必须包含 answer(回答)和 sources(参考来源),这在毕设演示中非常重要,能证明你的系统确实是“基于知识库”在回答。

六、数据库设计(LangChain 自动生成)

虽然你没写 SQL,但 LangChain 已经在 my_vector_db 里自动建好了表。理解这两张表对后续优化很重要。

表 1:langchain_pg_collection(集合表)

字段 类型 说明
uuid UUID 集合的唯一ID
name VARCHAR 集合名称,即代码里的 knowledge_base
cmetadata JSON 自定义元数据

表 2:langchain_pg_embedding(向量数据表)(核心表)

这是真正存数据的地方。

字段 类型 说明
uuid UUID 本条数据的唯一ID
collection_id UUID 外键,关联到 langchain_pg_collection
embedding vector 重点:存储 Qwen-Embedding 生成的向量数组
document VARCHAR 存储原文片段 (Chunk)
cmetadata JSON 存储元数据(比如 {"source": "桂电介绍"}

七、当前项目的“待优化点”与“毕设加分项”

目前的项目是一个MVP(最小可行性产品)。为了让毕设更出彩,你可以考虑以下优化方向(按优先级排序):

1. 解决代码警告(立即可做)

  • 警告内容PGVector is pending deprecation. Please swap to langchain_postgres.
  • 解决方案:将 langchain_community.vectorstores.PGVector 迁移到新的官方包 langchain-postgres
  • 迁移收益:消除警告,使用性能更好的 PGVectorStore,代码更规范。

2. 增加文档解析功能(实用加分)

目前 add 接口只能传纯文本。

  • 优化:引入 PyPDF2LangChain Document Loaders,让接口支持上传 PDF/Word/TXT 文件。
  • 效果:用户直接上传毕业论文,系统就能自动解析并回答,演示效果非常好。

3. 增加日志系统(专业加分)

  • 现状:只有 Uvicorn 的访问日志。
  • 优化:引入 Python 标准库 logging,记录每一次 Query 的:
    • 用户输入的问题
    • 检索到了哪些片段
    • LLM 最终返回了什么
    • 耗时多久
  • 收益:方便调试;答辩时可以展示后台运行逻辑。

4. 前端界面(展示加分)

  • 现状:只有 API 文档页面。
  • 优化:写一个简单的 HTML 页面(或用 Gradio/Streamlit),有一个输入框和一个对话窗口。
  • 收益:答辩时演示非常直观,看起来像一个完整的产品。

八、总结

你的这个 RAG 项目,麻雀虽小,五脏俱全

  1. 技术栈主流:覆盖了 FastAPI、LangChain、向量数据库等当前 AI 后端开发的核心技术。
  2. 流程完整:从数据摄入到检索生成,形成了闭环。
  3. 扩展性强:分层架构使得后续加功能(如文件上传、用户管理)很方便。

这作为一个本科毕业设计的基础项目,是完全合格且有亮点的。

About

本项目依托 FastAPI 构建后端服务,通过 LangChain 实现 RAG 全流程编排,结合通义千问 Embedding 与 LLM 能力、PostgreSQL 向量数据库,对外暴露接口完成知识库管理与检索增强问答。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 83.6%
  • Shell 16.4%