大语言模型实战:FastAPI+RAG智能问答系统构建
文档智能问答已成为大模型落地实施中的高频场景。无论是搭建企业知识库、解析产品手册,还是从研究报告里快速定位答案,传统的关键词搜索在精度和效率上都难以满足需求。RAG(检索增强生成)因此成为业界公认的主流方案。
实践中,许多团队卡在“如何将RAG封装成可调用的API”这一环节。一个能跑的原型演示与一套可集成上线的服务之间,藏着大量工程细节。本文完整梳理如何借助FastAPI构建RAG系统——从核心原理到代码实现,再到HTTP状态码在工程中的实际意义,一次性讲透。
理解REST API
先对齐一个基础概念。REST API是客户端与服务器之间通信的接口标准,全称Representational State Transfer API。客户端向特定API端点发起HTTP请求,服务器处理后返回结果。本文后续会用到几种核心HTTP方法。
检索增强生成与FastAPI:为何是最佳搭档?
动手前,有必要把两个核心组件拆开来看。
什么是RAG?
RAG的本质是为大语言模型配备“开卷考试”的能力。面对问题,模型先快速翻查资料(检索相关文档片段),再结合资料与自身理解,整合出精准回答。
RAG的核心架构只有两部分:
- 检索器:根据用户问题,从文档库中迅速匹配最相关的信息片段。
- 生成器:大语言模型本身,将检索到的片段作为上下文,结合问题输出最终答案。
这套方案有效解决了大模型知识截止、容易产生幻觉等痛点,是当前连接通用大模型与私有数据的最优路径。
为何选FastAPI?
FastAPI是近两年Python Web框架中的黑马,专为构建API而生。它在RAG项目中的优势只需几条:
- 自动生成交互式文档:代码写完,Swagger UI自动生成,浏览器中可直接测试接口,省去额外前端开发。
- 基于Python类型提示:配合Pydantic模型,请求体验证与序列化自动完成,模板代码大幅减少。
- 原生异步支持:天然适配文件读取、网络调用这类I/O密集型操作。
- 性能扎实:底层基于Starlette与Pydantic,性能不输Node.js和Go。
将RAG与FastAPI组合,等于快速把智能文档问答系统封装成可集成调用的API服务。
项目实战:打造文档智能问答API
接下来进入核心环节——代码实现。目标是创建两个API端点:
/ingest:接收用户上传的PDF或TXT文档,分块、向量化后存入FAISS索引。/query:接收用户提问,检索相关文档块,再调用大语言模型生成答案。
环境准备与依赖安装
开始前,需要准备这些:
- 获取OpenAI API密钥,在项目根目录创建
.env文件,写入:
OPENAI_API_KEY=你的密钥
- 创建并激活Python虚拟环境,安装依赖库。
requirements.txt内容如下(版本号已做兼容性调整):
fastapi
uvicorn[standard]
python-multipart
langchain
langchain-community
langchain-openai
faiss-cpu
openai
pypdf
python-dotenv
运行pip install -r requirements.txt一键安装即可。
核心模块:rag_pipeline.py
这个脚本封装了RAG的所有核心逻辑:文档加载、文本分块、向量存储、检索与生成。代码模块化后,维护和调用都更加方便。
# 全局向量存储对象,用于跨请求共享
vector_store: FAISS | None = None
embeddings = OpenAIEmbeddings(model=EMBEDDING_MODEL_NAME)
def _load_vector_store() -> FAISS | None:
"""从本地磁盘加载已存在的FAISS索引。"""
global vector_store
if vector_store is None and os.path.exists(VECTOR_STORE_PATH):
vector_store = FAISS.load_local(
VECTOR_STORE_PATH,
embeddings,
allow_dangerous_deserialization=True
)
return vector_store
def process_document(file_path: str, display_filename: str = "") -> int:
"""
处理上传的文档:加载、分块、向量化并存入FAISS。
返回被索引的文本块数量。
"""
global vector_store
# 1. 根据文件扩展名选择加载器
if file_path.endswith(".pdf"):
loader = PyPDFLoader(file_path)
else:
loader = TextLoader(file_path)
documents = loader.load()
# 为所有文档块添加来源文件名
source_name = display_filename or os.path.basename(file_path)
for doc in documents:
doc.metadata["source"] = source_name
# 2. 文本分块
splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE,
chunk_overlap=CHUNK_OVERLAP,
separators=["nn", "n", ".", " ", ""]
)
chunks = splitter.split_documents(documents)
# 代码中省略了部分错误处理和细节优化。
API服务:main.py
接着用FastAPI把上述功能暴露为RESTful API。
import os
import tempfile
from fastapi import FastAPI, UploadFile, File, HTTPException
from pydantic import BaseModel
from rag_pipeline import process_document, query_rag
app = FastAPI(
title="文档智能问答API",
description="上传文档并进行检索增强生成式问答",
version="1.0.0"
)
# 允许的文件类型
ALLOWED_FILE_TYPES = {
"application/pdf": ".pdf",
"text/plain": ".txt",
}
class QueryRequest(BaseModel):
question: str
top_k: int = 4
class QueryResponse(BaseModel):
answer: str
sources: list[str]
@app.get("/health", tags=["系统状态"])
async def health_check():
"""健康检查端点,用于确认服务是否运行。"""
return {"status": "running"}
@app.post("/ingest", tags=["文档处理"])
async def ingest_document(file: UploadFile = File(...)):
"""
上传文档(.txt 或 .pdf),系统将自动进行分块、向量化并存储。
"""
if file.content_type not in ALLOWED_FILE_TYPES:
# 代码中省略了更复杂的验证逻辑和自定义异常处理。
启动服务只需在终端执行:
uvicorn main:app --reload
访问 http://127.0.0.1:8000/docs,就能看到自动生成的Swagger UI界面,所有API都可以在这里测试。
- *
DeepSeek、LangGraph和Python融合LSTM、RF、XGBoost、LR多模型预测NFLX股票涨跌|附完整代码数据
原文链接:https://tecdat.cn/?p=44060
- *
测试与验证
文档上传与索引(/ingest)
在Swagger UI中点击/ingest端点,上传一个PDF文件试试。
点击“Execute”后,如果成功,会看到如下响应,表示文档已被成功分块并索引。
此时项目目录下会生成faiss_index文件夹,里面包含向量索引文件。即使服务重启,数据也不会丢失。
智能问答(/query)
接下来测试/query端点。输入一个问题,比如“机器学习有哪些应用?”,设置top_k=4。
点击Execute后,系统会返回答案以及答案所依据的文档来源。
可以清楚地看到,答案基于上传文档的内容生成,并且指明了来源,提升了可信度。
深入理解HTTP状态码:API的通用语言
开发API时,合理使用HTTP状态码是基本功。它们用简洁的状态码向客户端传达了请求的处理结果,我们的系统也遵循了这一规范。
- 2xx 成功:如
200 OK,表示请求成功。/health、/ingest和/query在正常处理时都会返回200。 - 4xx 客户端错误:问题出在客户端发送的请求。比如:
400 Bad Request:上传了不支持的文件类型,或问题为空时,API会返回这个状态码。422 Unprocessable Entity:请求体不符合Pydantic模型定义时,FastAPI会自动返回此状态码。
- 5xx 服务器错误:服务器端在处理请求时发生意外。比如FAISS或OpenAI调用失败,API会捕获异常并返回
500 Internal Server Error。
正确使用状态码,能让API更加健壮和易用。
总结与展望
至此,我们基于FastAPI构建并部署了一个完整的RAG系统。它能够接收并索引PDF或TXT文档,根据用户提问从文档中检索相关信息,再利用大语言模型生成精准答案。
这个项目展示了RAG技术的落地过程,也体现了FastAPI在构建AI服务时的高效与便捷。可以将其应用于企业知识库问答、智能客服、研究报告分析等多种场景。
如果继续往下走,有几个优化方向值得关注:
- 检索策略优化:除了简单的相似度搜索,可以尝试MMR(最大边际相关性)检索,平衡结果的相关性与多样性。
- 分块策略优化:根据文档类型和语言,调整分块大小和重叠部分,或者采用语义分块。
- 多路召回:结合关键字检索(如BM25)与向量检索,提高召回率。
- 前端界面:为API开发一个简单的聊天界面,提升用户体验。
鼓励动手实践,也期待在实际应用中看到更多的改进与落地。