LlamaAI本地部署实战专栏第6篇
从"只会聊天的大模型"到"懂你资料的私人AI助手",使用RAG技术构建完全离线知识库问答系统。
一、为什么本地大模型还需要RAG?
在上一篇文章中,我们已经完成:
✅ llama-server部署
✅ OpenAI API兼容接口
✅ Python调用本地模型
现在我们拥有:
用户
↓
本地Llama
↓
生成答案
但是很快会发现一个问题:
我的模型为什么不知道我的PDF、公司文档、项目代码?
例如:
用户:
我们公司的产品架构是什么?
模型:
抱歉,我不知道。
原因:
大模型训练数据:
互联网公开数据
↓
模型训练
↓
固定知识
它并不知道:
- 企业内部文档
- 最新项目资料
- 私人笔记
- 技术文档
二、解决方案:RAG技术
RAG:
全称:
Retrieval Augmented Generation
中文:
检索增强生成
简单理解:
不要重新训练模型。
而是在回答问题之前:
先查资料。
传统LLM:
用户问题
↓
LLM
↓
生成答案
RAG:
用户问题
↓
搜索知识库
↓
找到相关资料
↓
发送给LLM
↓
生成答案
三、RAG整体架构
完整流程:
用户
|
问题
|
Query Embedding
|
向量数据库
|
检索相关文本
|
Prompt组合
|
本地Llama
|
答案
四、RAG核心组成部分
一个完整RAG系统包含:
1. 文档加载
支持:
- Word
- Markdown
- TXT
- 网页
例如:
技术文档.pdf
产品说明.docx
项目README.md
2. 文本切片(Chunk)
为什么需要切片?
假设PDF:
100万字
不能直接:
PDF
↓
LLM
原因:
- 超过上下文限制
- 检索困难
需要拆分:
原文
↓
Chunk1
↓
Chunk2
↓
Chunk3
例如:
chunk_size=1000
chunk_overlap=100
含义:
每段:
1000字符
相邻:
重叠100字符
五、Embedding:让机器理解文本
计算机不能直接理解:
"Transformer是什么"
需要转换:
文本:
Transformer是一种神经网络架构
变成向量:
[
0.123,
0.532,
0.876,
...
]
这个过程:
叫:
Embedding(文本向量化)
六、为什么不用大模型生成Embedding?
因为:
Embedding任务:
只需要:
判断文本语义相似度
例如:
问题:
什么是GPU加速?
知识库:
CUDA可以利用GPU进行并行计算
虽然文字不同:
但是:
语义接近。
七、本地Embedding模型选择
推荐:
中文场景
BGE系列
BAAI 开源的BGE系列是目前中文Embedding任务常用模型。
推荐:
| 模型 | 特点 |
|---|---|
| bge-small-zh | 轻量 |
| bge-base-zh | 效果好 |
| bge-large-zh | 高精度 |
八、向量数据库
Embedding之后:
需要保存:
文本
+
向量
+
来源信息
例如:
{
"text":
"CUDA是一种GPU计算平台",
"vector":
[
0.123,
0.543
]
}
这个数据库:
叫:
向量数据库。
常见方案:
| 数据库 | 特点 |
|---|---|
| FAISS | 本地轻量 |
| Milvus | 企业级 |
| Chroma | 开发方便 |
本文使用:
FAISS
因为:
- 免费
- 本地运行
- 性能高
九、构建第一个离线RAG系统
环境安装:
pip install \
langchain \
faiss-cpu \
sentence-transformers \
pypdf
十、读取PDF文档
安装:
from pypdf import PdfReader
reader = PdfReader(
"document.pdf"
)
text=""
for page in reader.pages:
text += page.extract_text()
得到:
PDF全部文本
十一、文本切片
使用:
RecursiveCharacterTextSplitter
from langchain.text_splitter import (
RecursiveCharacterTextSplitter
)
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100
)
chunks = splitter.split_text(text)
结果:
[
chunk1,
chunk2,
chunk3
]
十二、生成Embedding
加载模型:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer(
"BAAI/bge-small-zh"
)
vectors=model.encode(
chunks
)
结果:
文本
↓
向量矩阵
十三、建立FAISS索引
安装:
pip install faiss-cpu
代码:
import faiss
import numpy as np
dimension=vectors.shape[1]
index=faiss.IndexFlatL2(
dimension
)
index.add(
np.array(vectors)
)
现在:
知识库建立完成。
十四、用户提问检索
用户:
GPU加速是什么?
首先:
问题Embedding:
question_vector=model.encode(
["GPU加速是什么"]
)
搜索:
distance, ids=index.search(
question_vector,
k=3
)
返回:
最相关3个文本。
十五、拼接Prompt给Llama
得到资料:
CUDA是一种GPU计算平台...
GPU可以执行并行计算...
组合:
请根据下面资料回答:
资料:
xxxx
问题:
GPU加速是什么?
发送:
Prompt
↓
llama-server
↓
生成答案
十六、完整RAG流程
最终:
PDF文件
|
文本解析
|
Chunk切片
|
Embedding
|
FAISS
|
用户问题
|
相似搜索
|
Prompt增强
|
llama.cpp
|
答案
十七、RAG和重新训练模型区别
很多人误认为:
想让模型知道我的资料,需要训练。
实际上:
大部分场景:
不需要。
比较:
| 方式 | 成本 | 适合 |
|---|---|---|
| 重新训练 | 极高 | 改变模型能力 |
| 微调 | 中等 | 改变模型风格 |
| RAG | 低 | 增加知识 |
企业知识库:
优先选择:
RAG。
十八、常见问题
1. 为什么RAG回答不准确?
原因:
检索不到正确资料。
优化:
- 增大chunk
- 增加top-k
- 使用reranker
下一篇会详细优化。
2. 为什么PDF读取乱码?
原因:
扫描PDF没有文字层。
解决:
使用OCR:
- PaddleOCR
- Tesseract
3. 为什么速度慢?
瓶颈:
可能在:
- embedding
- 向量搜索
- LLM生成
需要分别优化。
十九、本篇总结
今天完成:
✅ 理解RAG原理
✅ 搭建离线知识库流程
✅ PDF解析
✅ 文本切片
✅ Embedding生成
✅ FAISS向量检索
✅ 对接本地Llama
现在你的AI已经从:
普通聊天机器人
升级为:
懂你资料的私人AI助手
完整架构:
本地文档
↓
RAG系统
↓
llama.cpp Server
↓
本地LLM
↓
AI助手
下一篇预告
《别只用向量搜索:BM25+FAISS打造工业级RAG检索系统》
下一篇将解决RAG最大的痛点:
为什么你的知识库明明有答案,AI却找不到?
内容包括:
- 向量搜索原理
- BM25关键词检索
- 混合检索架构
- RRF融合排序
- Reranker重排序
- 企业级RAG优化方案
让你的本地AI从"能用"进入"可靠"。