Python 本地 AI 问答系统搭建:环境配置与 RAG 实践
介绍如何使用 Python 从零搭建本地 AI 问答系统。内容包括虚拟环境隔离、PyTorch 版本对齐、Ollama 模型管理、基于 LangChain 和 FAISS 的 RAG 流程实现、显存优化策略及 Gradio Web 界面搭建。旨在帮助开发者规避常见环境陷阱,构建私有知识库问答应用。

介绍如何使用 Python 从零搭建本地 AI 问答系统。内容包括虚拟环境隔离、PyTorch 版本对齐、Ollama 模型管理、基于 LangChain 和 FAISS 的 RAG 流程实现、显存优化策略及 Gradio Web 界面搭建。旨在帮助开发者规避常见环境陷阱,构建私有知识库问答应用。

想在本地跑一个 AI 问答系统?听起来很酷,但现实往往是这样的:
'为什么我的 CUDA 版本和 PyTorch 不兼容?' '为什么
pip install装了半天,运行时还是报ModuleNotFoundError?' '为什么模型加载到一半内存就爆了?'
这些问题,90% 的新手都踩过。本文将带你从零搭建一个本地 AI 问答系统,并系统性地帮你绕开那些'经典陷阱'。
在动手之前,先看清楚我们要搭建的是什么:
整个系统分为三层:
流程简述:用户输入 -> 文本预处理 -> (向量数据库检索) -> 构建 Prompt -> 本地 LLM 推理 -> 后处理 & 输出。
根据社区反馈,新手遇到的问题主要集中在以下几类:
接下来,我们按照这个优先级,逐一击破。
❌ 新手常见错误:
pip install torch transformers langchain # 直接装到全局
✅ 正确做法:用 venv 或 conda 隔离环境
# 方式一:使用 venv(推荐,Python 内置)
python -m venv ai-qa-env
source ai-qa-env/bin/activate # Linux/macOS
ai-qa-env\Scripts\activate # Windows
# 方式二:使用 conda
conda create -n ai-qa python=3.11
conda activate ai-qa
💡 为什么要隔离? 不同项目依赖不同版本的库,全局安装会导致版本冲突,出了问题极难排查。
这是 最高频的踩坑点。PyTorch 的安装命令取决于你的 CUDA 版本,不能无脑 pip install torch。
第一步:查看你的 CUDA 版本
nvidia-smi # 查看 GPU 驱动支持的最高 CUDA 版本
nvcc --version # 查看已安装的 CUDA Toolkit 版本
第二步:去官网生成对应命令
# CUDA 12.1 对应的安装命令示例
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# 没有 GPU,只用 CPU
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
第三步:验证安装是否成功
import torch
print(f"PyTorch 版本:{torch.__version__}")
print(f"CUDA 是否可用:{torch.cuda.is_available()}")
print(f"GPU 数量:{torch.cuda.device_count()}")
if torch.cuda.is_available():
print(f"当前 GPU: {torch.cuda.get_device_name(0)}")
print(f"显存总量:{torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB")
# 生成当前环境的依赖快照
pip freeze > requirements.txt
# 在新环境中还原
pip install -r requirements.txt
推荐的 requirements.txt 示例:
torch==2.2.0
transformers==4.38.0
langchain==0.1.9
langchain-community==0.0.24
faiss-cpu==1.7.4
sentence-transformers==2.5.1
ollama==0.1.7
gradio==4.19.2
Ollama 是目前最省心的本地模型管理工具,一行命令搞定下载和运行:
# 安装 Ollama(macOS/Linux)
curl -fsSL https://ollama.com/install.sh | sh
# 下载并运行模型
ollama pull llama3.2 # Meta Llama 3.2 (3B)
ollama pull qwen2.5:7b # 阿里通义千问 2.5 (7B)
ollama pull deepseek-r1:7b # DeepSeek R1 (7B)
# 验证模型列表
ollama list
import ollama
def ask_local_llm(question: str, model: str = "qwen2.5:7b") -> str:
"""
调用本地 Ollama 模型进行问答
Args:
question: 用户问题
model: 模型名称
Returns:
模型回答
"""
response = ollama.chat(
model=model,
messages=[{"role": "system", "content": "你是一个专业的 AI 助手,请用中文简洁准确地回答问题。"},
{"role": "user", "content": question}]
)
return response["message"]["content"]
# 测试
if __name__ == "__main__":
answer = ask_local_llm("Python 中的 GIL 是什么?")
print(answer)
RAG(Retrieval-Augmented Generation)是让 AI 能回答你私有文档问题的核心技术。
离线阶段(一次性):
在线阶段(每次查询):
"""
本地 RAG 问答系统
依赖:pip install langchain langchain-community faiss-cpu sentence-transformers ollama
"""
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.document_loaders import TextLoader, DirectoryLoader
from langchain.chains import RetrievalQA
from langchain_community.llms import Ollama
import os
class LocalRAGSystem:
"""本地 RAG 问答系统"""
def __init__(self, docs_dir: str = "./docs", model_name: str = "qwen2.5:7b",
embedding_model: str = "BAAI/bge-small-zh-v1.5",
chunk_size: int = 500, chunk_overlap: int = 50):
self.docs_dir = docs_dir
self.model_name = model_name
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
print("🔧 初始化 Embedding 模型...")
# 使用本地 Embedding 模型,避免调用外部 API
self.embeddings = HuggingFaceEmbeddings(
model_name=embedding_model,
model_kwargs={"device": "cpu"}, # 改为 "cuda" 可用 GPU 加速
encode_kwargs={"normalize_embeddings": True}
)
.vectorstore =
.qa_chain =
():
()
loader = DirectoryLoader(
.docs_dir, glob=, loader_cls=TextLoader,
loader_kwargs={: }
)
documents = loader.load()
()
splitter = RecursiveCharacterTextSplitter(
chunk_size=.chunk_size, chunk_overlap=.chunk_overlap,
separators=[, , , , , ]
)
chunks = splitter.split_documents(documents)
()
()
.vectorstore = FAISS.from_documents(chunks, .embeddings)
()
.vectorstore.save_local()
()
():
os.path.exists():
()
.vectorstore = FAISS.load_local(
, .embeddings, allow_dangerous_deserialization=
)
()
:
()
():
.vectorstore :
ValueError()
()
llm = Ollama(model=.model_name, temperature=)
retriever = .vectorstore.as_retriever(
search_type=, search_kwargs={: }
)
.qa_chain = RetrievalQA.from_chain_type(
llm=llm, chain_type=, retriever=retriever, return_source_documents=
)
()
() -> :
.qa_chain :
ValueError()
result = .qa_chain.invoke({: question})
{
: result[],
: [doc.metadata.get(, ) doc result[]]
}
__name__ == :
rag = LocalRAGSystem(docs_dir=, model_name=)
rag.load_and_index()
rag.build_qa_chain()
:
question = ().strip()
question.lower() == :
result = rag.ask(question)
()
()
不同规模模型的显存需求(FP16 精度):
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
# 4-bit 量化配置(显存减少约 75%)
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
)
model_id = "Qwen/Qwen2.5-7B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id, quantization_config=quantization_config, device_map="auto" # 自动分配到 GPU/CPU
)
print(f"模型加载完成,占用显存:{torch.cuda.memory_allocated()/1024**3:.2f} GB")
import ollama
def stream_answer(question: str, model: str = "qwen2.5:7b"):
"""流式输出,边生成边显示"""
print("💬 ", end="", flush=True)
for chunk in ollama.chat(
model=model,
messages=[{"role": "user", "content": question}],
stream=True # 开启流式输出
):
content = chunk["message"]["content"]
print(content, end="", flush=True)
print()
stream_answer("用一句话解释什么是 Transformer 架构")
用 Gradio 5 分钟搭一个好看的 Web 界面:
import gradio as gr
from local_rag import LocalRAGSystem # 引用上面的代码
# 初始化 RAG 系统
rag = LocalRAGSystem()
rag.load_existing_index()
rag.build_qa_chain()
def chat(message: str, history: list) -> str:
"""Gradio 聊天回调函数"""
if not message.strip():
return "请输入问题"
result = rag.ask(message)
answer = result["answer"]
sources = result["sources"]
if sources:
answer += f"\n\n---\n📎 **参考来源**: {', '.join(set(sources))}"
return answer
# 创建 Gradio 界面
demo = gr.ChatInterface(
fn=chat, title="🤖 本地 AI 问答系统",
description="基于本地 LLM + RAG 的私有知识库问答",
examples=["这个系统是如何工作的?", "请总结一下主要内容"],
theme=gr.themes.Soft()
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860, share=False) # 改为 True 可生成公网链接
运行后访问 http://localhost:7860 即可使用。
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
CUDA out of memory | 显存不足 | 使用量化模型或减小 batch_size |
ModuleNotFoundError: No module named 'torch' | 虚拟环境未激活 | 激活对应的 venv/conda 环境 |
RuntimeError: CUDA error: no kernel image is available | PyTorch 与 CUDA 版本不匹配 | 重新安装对应 CUDA 版本的 PyTorch |
ConnectionRefusedError: [Errno 111] | Ollama 服务未启动 | 运行 ollama serve |
OSError: [Errno 28] No space left on device | 磁盘空间不足 | 清理磁盘或更换存储路径 |
ValueError: Tokenizer class ... not found | transformers 版本过低 | pip install -U transformers |
huggingface_hub.utils._errors.EntryNotFoundError | 模型名称错误或网络问题 | 检查模型 ID 或使用镜像源 |
# 设置 HuggingFace 镜像(国内访问加速)
export HF_ENDPOINT=https://hf-mirror.com
# pip 使用清华镜像
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers
# conda 使用清华镜像
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
# 在代码中指定镜像
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
from transformers import AutoTokenizer
# 之后的下载会自动走镜像
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
🎉 系统就绪!

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online