【大模型RAG生成式AI开发实战】《大模型RAG生成式AI开发实战》_74.[第8章 Chroma与开源模型] Llama模型部署:本地运行大语言模型

不需要OpenAI API,不需要天价云端显卡,一台普通电脑就能跑起大模型!本文手把手教你把Llama家族的大模型搬回本地,再用Chroma给它装上“外接大脑”,从零打造完全私有化、零 token 消耗的 RAG 应用。读完这篇,你会发现:原来本地部署大模型,远没有传说中那么可怕!
文章目录
- 环境准备与硬件评估
- 模型选择与下载
- 推理框架选型部署
- Chroma向量数据库本地搭建
- RAG流程打通
- 完整项目代码实战
- 性能调优与问题排查
- 写在最后
嗨,大家好呀,我是你的老朋友精通代码大仙。接下来我们一起学习 《大模型RAG生成式AI开发实战》74.[第8章 Chroma与开源模型] Llama模型部署:本地运行大语言模型。
“不是OpenAI用不起,而是本地Llama更有性价比。”这句话最近在大模型圈子里特别火。但你真动手去折腾的时候,是不是发现事情远没有喊口号那么简单?看着别人在本地跟大模型聊得火热,还能接上自己的文档搞私有知识库,你兴冲冲打开搜索引擎,却被满屏的GGUF、量化、CUDA、Ollama、Chroma这些词儿砸得头晕眼花。好不容易装了个软件,模型一下载,电脑风扇狂转,直接蓝屏给你看。别慌,这太正常了。今天这篇,就是专门给你这类新手准备的“避坑指南+实操手册”。本地运行Llama,再搭上Chroma做RAG,这件事本身不难,难的是每一步都有人在你耳边提醒:这个坑别踩,那条路更近。
环境准备与硬件评估
本地跑Llama,第一件事不是急着下模型,而是先认清你的“家底”。我见过太多新手,一上来就要挑战Llama-3-70B,结果自己的电脑只有16G内存,没有独立显卡,后台挂着微信和浏览器,双击运行后整个人卡到怀疑人生,还以为中了病毒。
这就是最大的误区:以为“本地部署”对硬件没有门槛。
有个读者跟我吐槽,说他在一台八年前的笔记本上折腾了整整两天,按教程一步一步来,到最后一步模型加载时,系统直接OOM,进程被杀死。他愤怒地留言:“这教程是不是假的?”我一看他的配置:8G内存,核显,机械硬盘。这不是教程的问题,是硬件确实触及了物理天花板。
那到底什么配置能玩呢?我给你画个像,心里就有底了。
纯CPU方案,如果你内存有16G,可以跑7B模型的Q4_K_M量化版本。速度大概每秒几个token,能接受。如果你有32G内存,体验会好很多,还能尝试13B的模型。如果你有一张GTX 1060 6G或者RTX 3060 12G这样的显卡,那恭喜你,7B甚至8B的模型可以部分或者全部放到GPU里跑,速度立马从“龟爬”变“人走”。显卡显存是最硬的指标,一张RTX 4060 Ti 16G在这个场景下性价比极高,13B模型能稳稳地塞进显存。至于70B?别想了,那是4090甚至双卡玩家的玩具,新手现阶段完全不需要碰。
操作系统上,Windows不是不能玩,但WSL2(Windows Subsystem for Linux)会让你少掉一半的头发。因为很多推理工具的原生环境就是Linux,在WSL2里跑,安装依赖、编译、路径处理都更顺滑。Mac用户反而幸福一点,尤其是Apple Silicon的Mac,llama.cpp对Metal后端支持得很好,内存统一架构让核显也能分担不少压力。
驱动方面,N卡用户请务必确保你的CUDA驱动是较新的版本,但不用一上来就装庞大的CUDA Toolkit。很多推理框架现在自带了运行时,驱动够新就行。
知己才能知彼,看清自己的硬件边界,选模型时才不会好高骛远。别一上来就想炼丹,先把灶搭稳了。
模型选择与下载
环境心里有数了,接下来面对第二个灵魂拷问:HuggingFace上搜Llama,跳出来几百个结果,到底下哪个?
新手最容易在这里翻车。他们一头扎进meta-llama的官方仓库,下载了Meta-Llama-3-8B-Instruct的原始PyTorch权重。几十G的文件,下了一整天,结果发现这玩意儿需要transformers库、PyTorch、正确的CUDA版本,还要写加载代码,最关键的是,原始FP16格式的8B模型需要16G以上显存才能顺利推理。他看着自己12G显存的3060,陷入了沉思。
这就是典型的格式选错。对于本地部署,特别是想快速跑起来的新手,你几乎只需要认准一个名词:GGUF。
GGUF是llama.cpp项目推出的一种二进制格式,专为本地推理优化。它把模型权重和超参数打包在一起,支持多种量化方案。所谓量化,就是把模型里原本32位或者16位的浮点数,压缩成更低精度的整数来存储和计算。精度损失肯定有,但好的量化方案能让7B模型在4bit精度下只占用4到5G的显存,而且回答质量损失你几乎感知不到。
去哪下?TheBloke这个账号在HuggingFace上做了海量的GGUF量化模型,虽然最近社区也有很多新的优秀量化发布者,但认准Q4_K_M这个后缀,基本不会踩雷。Q4代表4-bit量化,K代表K-quant这种混合精度策略,M是medium,在体积和质量之间取了一个非常甜的平衡点。如果你想质量再好一点,硬盘也宽裕,Q5_K_M或者Q6_K也是极好的选择。
另外,Llama 2和Llama 3怎么选?我的建议是,除非你的设备特别老旧或者需要某个Llama 2特有的微调版本,否则直接上Llama 3。同参数规模下,Llama 3的训练数据更新、词表更大、指令遵循能力明显更强,尤其是对中文的支持,虽然本质还是英文模型,但比Llama 2那种“一个汉字切分成好几个token”的情况要好太多了。
如果你用的是Ollama,那这件事会被简化到极致。你甚至不需要打开浏览器下载,后面我会讲到,一行命令 ollama pull llama3 就搞定了。但如果你手动下载GGUF,记得看清楚文件名里的参数规模和量化级别,别下成了70B还纳闷为什么文件有40G。
选对了格式和量化级别,一次下载,终身受用。格式选错,就是一整天的无效劳动。
推理框架选型部署
模型文件躺在硬盘里了,接下来你需要一个“发动机”来加载它、推理它。这个环节新手最容易陷入选择困难症:Ollama、llama.cpp、text-generation-webui、LM Studio、koboldcpp……工具太多,反而不知道点哪个。
我的建议非常直接:先用Ollama跑起来,再去考虑别的。
为什么?因为Ollama把最麻烦的环节全包起来了。你不需要手动编译C++代码,不需要手动指定模型路径,不需要处理依赖地狱。Windows、macOS、Linux都支持,一条命令安装,一条命令运行。
但坑在哪里呢?坑在于Ollama封装得太好,导致你想改点参数的时候找不到门。
很多人装完Ollama,运行 ollama run llama3,进入交互界面聊了几句,觉得默认回答太短、太死板,想改system prompt,想调temperature,却在命令行里瞎琢磨。还有人发现Ollama默认只监听本机,想给局域网里的其他设备用,却不知道在哪开远程访问。
正确的姿势是这样的。Ollama的核心配置在Modelfile里。你可以基于官方镜像创建自己的定制版本:
FROM llama3
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
SYSTEM """你是一个严谨的技术助手,回答要简洁,不要胡编乱造。遇到不确定的问题,请直接说明。"""
保存为Modelfile后,执行 ollama create my-llama3 -f Modelfile,然后 ollama run my-llama3。这样你的自定义参数就生效了。temperature控制回答的随机性,num_ctx控制上下文窗口长度,SYSTEM定义系统角色,这些都是调优的基础。
如果你想把它当成API服务给Python调用,直接保持Ollama在后台运行 ollama serve,默认端口11434。测试一下:
import requests
def ask_ollama(prompt):
res = requests.post(
"http://localhost:11434/api/generate",
json={
"model": "llama3",
"prompt": prompt,
"stream": False
}
)
return res.json()["response"]
print(ask_ollama("请解释什么是RAG?"))
如果你是个爱折腾的人,llama.cpp会给你更大的控制权。克隆代码后,make编译,然后用 ./server -m 模型路径.gguf -c 4096 --host 0.0.0.0 --port 8080 启动服务。llama.cpp的好处是你可以精确控制 -ngl(n_gpu_layers)来指定多少层放到GPU上,这对显存吃紧的用户特别重要。
但对新手来说,记住这个顺序:先Ollama跑通,再按需深入。工具是为你服务的,别反过来被工具折腾。
Chroma向量数据库本地搭建
有了能跑的大模型,下一步就是给Llama装上“外接大脑”——Chroma。没有向量数据库,你的RAG就是无源之水。大模型只能依赖它那点儿训练时的记忆,遇到你的私有文档,只能靠瞎编。
但Chroma的坑,新手一踩一个准。
最大的误区是以为Chroma只是个内存里的临时变量。很多人跟着某篇教程,写了个 import chromadb; client = chromadb.Client(),跑通了,很开心,关了电脑。第二天打开,昨天辛辛苦苦入库的几百篇文档全没了,检索出来一片空白。他愣在屏幕前:“我的数据呢?”
数据飞了,因为你用的是默认的 Client(),它是纯内存的,进程结束就灰飞烟灭。本地部署要的是私有化、持久化,数据必须落盘。
正确的打开方式是 PersistentClient:
import chromadb
client = chromadb.PersistentClient(path="./my_chroma_db")
collection = client.get_or_create_collection(name="rag_docs")
# 添加文档
collection.add(
ids=["doc1", "doc2"],
documents=["这是第一段内容", "这是第二段内容"],
metadatas=[{"source": "file1.pdf"}, {"source": "file2.txt"}]
)
指定一个本地路径,比如 ./my_chroma_db,Chroma会把所有的向量索引和元数据都存到这个目录里。下次运行代码,只要路径不变,数据就在。
另一个坑是版本和依赖。直接 pip install chromadb 通常没问题,但如果你在Windows原生环境下装,偶尔会遇到hnswlib编译失败的报错。所以前面我推荐WSL2,Linux环境下这些C++扩展的编译会顺畅很多。
还有人会问:Chroma不是还有个服务端模式吗?是的,但本地单机开发,你根本不需要去折腾 docker run chroma 或者手动起后台服务。一个 PersistentClient 足够你用到项目上线前。等服务端真正必要的时候,说明你已经有能力去区分Client、PersistentClient和HttpClient的区别了。
数据在自己手里,Chroma在本地跑,这才是真·私有化的RAG。
RAG流程打通
好,Llama能跑了,Chroma也能存数据了,现在要把它们串起来。这就是RAG的核心链路:加载文档、切分文档、向量化、存入Chroma、检索、送进Llama生成答案。
这一步的坑,那是相当密集。
第一个坑,是文档不切分。我见过有人直接把一本十万字的PDF整本转换成字符串,然后调用embedding模型编码。结果呢?要么超出embedding模型的最大输入长度,被无情截断,只编码了前几页;要么即使编码成功,检索的时候整本书作为一个向量,根本定位不到具体章节。检索出来的“最相关文档”就是整本书,这还有什么意义?
第二个坑,是切分得太碎。有人用了切分工具,但把chunk_size设成了100,overlap设成0。一个完整的句子被拦腰截断,前一句的主语在后一句里变成了代词,语义完全断裂。检索出来的片段像拼图碎片,Llama看了直摇头。
第三个坑,是embedding模型选错或者选太大。有人在本地跑Llama,结果embedding却去调OpenAI的API,这不是脱裤子放屁吗?本地化的灵魂是全部本地。还有人下载了一个2G多的大embedding模型,自己的电脑跑一个7B Llama已经气喘吁吁,再塞一个大embedding,直接double kill。
正确的流水线应该是这样的:
加载与切分。如果你用LangChain(虽然它有点重,但确实适合教学),代码很直观:
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
loader = PyPDFLoader("你的文档.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = splitter.split_documents(docs)
chunk_size 512是一个对7B/8B模型非常友好的尺寸。overlap 50能保证切分处有足够的语义衔接。separators按优先级排列,优先在段落处切,其次句子,尽量避免切断语义单元。
向量化。本地embedding,我推荐两条路。如果你有Ollama,最简单:
from langchain_community.embeddings import OllamaEmbeddings
embeddings = OllamaEmbeddings(model="nomic-embed-text")
nomic-embed-text是一个轻量级但效果很不错的嵌入模型,Ollama直接能拉。或者用HuggingFace的本地小模型,比如BAAI/bge-small系列,对中文支持也很棒:
from langchain_community.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-small-zh-v1.5"
)
入库与检索。LangChain对Chroma的封装很贴心:
from langchain_community.vectorstores import Chroma
db = Chroma.from_documents(
chunks,
embeddings,
persist_directory="./chroma_db",
collection_name="my_rag"
)
retriever = db.as_retriever(search_kwargs={"k": 3})
docs = retriever.get_relevant_documents("这里填你的问题")
k=3表示检索最相关的3段文本。这个k值不是越大越好,太大容易引入噪声,太小可能信息不足。3到5段,对大多数7B/8B模型的上下文窗口来说,是黄金区间。
RAG的精髓就是“先找后答”。Llama只负责根据你给的上下文来组织语言,而找上下文这件事,交给Chroma和embedding。分工明确,才能减少胡说八道。
完整项目代码实战
散件都齐了,现在组装成一辆能跑的车。很多新手卡在“我知道每一步是干嘛的,但合到一块就跑不通”。要么prompt拼得稀烂,Llama看不懂;要么不会调API,只能看着黑框框发呆。
下面给你一个完整的、能直接跑的Python代码骨架。它的逻辑是:接收问题 → Chroma检索 → 拼接Prompt → 调用本地Llama → 流式输出。
import requests
import chromadb
from langchain_community.embeddings import OllamaEmbeddings
# 1. 初始化Chroma和Embedding
embeddings = OllamaEmbeddings(model="nomic-embed-text")
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(name="rag_docs")
# 2. 检索函数
def retrieve_context(query, top_k=3):
query_embed = embeddings.embed_query(query)
results = collection.query(
query_embeddings=[query_embed],
n_results=top_k
)
docs = results["documents"][0]
return "\n\n".join([f"[参考内容 {i+1}] {d}" for i, d in enumerate(docs)])
# 3. 构建Prompt
def build_prompt(query, context):
system = "你是一个基于本地知识库回答问题的AI助手。请严格根据下面的参考内容回答,如果参考内容不足,请明确说明。"
user = f"参考内容:\n{context}\n\n用户问题:{query}\n\n请回答:"
return f"{system}\n\n{user}"
# 4. 流式调用本地Llama
def stream_ask(prompt):
url = "http://localhost:11434/api/generate"
payload = {
"model": "llama3",
"prompt": prompt,
"stream": True,
"options": {"temperature": 0.7}
}
with requests.post(url, json=payload, stream=True) as r:
for line in r.iter_lines():
if line:
import json
data = json.loads(line)
print(data.get("response", ""), end="", flush=True)
print()
# 5. 主流程
if __name__ == "__main__":
query = input("请输入你的问题:")
context = retrieve_context(query)
full_prompt = build_prompt(query, context)
print("\n正在思考...\n")
stream_ask(full_prompt)
这段代码里,我刻意做了几个对新手非常友好的设计。
一是检索结果格式化。每段检索内容前面加了 [参考内容 N] 的标记。别小看这个标记,它能让Llama明确区分“参考资料”和“用户问题”,减少模型把参考内容当成新问题去回答的概率。
二是system prompt里加了约束:“如果参考内容不足,请明确说明。” 这能强制Llama不要脱离上下文瞎编。7B/8B的小模型自制力比较差,你必须在prompt里把规矩立死。
三是流式输出。本地模型生成速度本来就不如云端API,如果等全部生成完再一次性打印,用户会觉得卡死了。stream=True配合 iter_lines,让用户看到字一个一个蹦出来,体验会好很多。
四是embedding和生成完全本地。Ollama跑llama3,Ollama跑nomic-embed-text,Chroma存本地,全程没有一根网线去访问外部大模型API。这才是真正的私有化RAG。
如果你不用LangChain,也可以直接用 chromadb 原生的 collection.query,手动传入embedding向量,就像我上面代码里写的那样。LangChain是糖衣,理解了底层逻辑,裸写也完全没问题。
看图说话,整个流程就是这样一条直线。每一步都踩实了,项目就跑起来了。
性能调优与问题排查
代码能跑,只是拿到了60分。要想跑得爽、答得准,还得会调优。本地部署最大的特点就是“千人千面”,每个人的显卡、内存、系统都不一样,照搬配置往往水土不服。
最普遍的痛点是速度慢。很多人第一次跑7B模型,发现速度只有每秒1到2个token,甚至完全在CPU上跑,GPU风扇都不带转的。这通常是因为推理框架没有把模型层放到显卡上。
如果你用Ollama,虽然它号称自动分配,但有时候判断过于保守。你可以通过Modelfile强制它尽量多用GPU:
FROM llama3
PARAMETER num_gpu 999
PARAMETER num_ctx 4096
num_gpu 999是一个“作弊码”,实际意义是“能放多少层就放多少层”,让Ollama自己铺满显存。num_ctx 4096把上下文窗口拉到4096,这对读长文档很关键,但注意,上下文越长,显存占用越高,需要你自己在速度和长度之间找平衡。
如果你用llama.cpp,控制就更直接了:
./server -m llama3-8b.Q4_K_M.gguf -ngl 35 -c 4096
-ngl 35 代表把35层放到GPU上。8B模型总共大概32到40层,你拉满就行。如果显存不够,它会报错,你再酌情减。
第二个痛点是回答质量差,模型总是答非所问,或者过于简短。这时候你要调的是生成参数。除了前面提到的temperature,还有 repeat_penalty(重复惩罚,建议1.1到1.2),以及 top_p(核采样,建议0.9)。这些参数在Ollama的Modelfile里都能设。如果模型还是发呆,检查一下你的prompt是不是太长太乱,导致模型把算力都浪费在理解格式上了。
第三个痛点是中文乱码或者中英混杂。Llama 3的原生中文版不行,对中文的支持是通过训练数据里的少量中文学会的。如果你主要做中文RAG,强烈建议在Ollama里拉取社区针对中文微调过的Llama 3版本,比如搜一下“llama3-chinese”相关的模型。或者,如果你愿意跳出Llama家族,同参数的Qwen2、Yi、ChatGLM对中文友好得多。Llama是通用标杆,但没必要死磕。
第四个痛点是Chroma检索不到内容。你明明入库了,query却返回空。这时候检查三件事:第一,embedding模型是不是和入库时用的是同一个?换模型后必须重新入库,因为向量空间变了。第二,query本身是不是太短、太抽象?试试用更具体的句子。第三,similarity阈值是不是太高了?可以先不做阈值过滤,看看top_k结果长什么样。
本地部署就像自己装机,没有客服帮你一键优化,但每一次调参带来的性能提升,都会让你对这套系统的掌控感强上一分。别怕报错,报错是你在和模型对话。
写在最后
写到这里,我们不妨回头看看。从最开始的硬件评估,到选对GGUF模型,再到Ollama一键启动Llama,接着把Chroma稳稳地搭在本地,最后把文档切分、向量化、检索、生成的整条RAG链路用Python串起来——你会发现,所谓“本地大模型部署”,并不是什么云端玄学,而是一步一个脚印的工程活。
每一个坑,我都曾经踩过;每一次报错,我也都对着黑屏抓狂过。但正是这些折腾,让我真正理解了大模型不是遥不可及的API调用,而是可以摸得着、调得动、管得住的本地程序。当你第一次在自己的电脑上,看到自己私有文档里的内容被Llama准确引用、流畅总结的时候,那种成就感,远比直接调用ChatGPT来得踏实。
编程之路不易,但每一步成长都算数。保持好奇,持续动手,别怕报错信息里的红字,那其实是系统在教你下一课。本地Llama只是起点,RAG也只是大模型应用的冰山一角。把这套基础打牢了,后面Agent、微调、多模态,你都会有底气去挑战。
加油,下一次,期待听到你跑通自己第一个本地大模型应用的好消息。
关注私信备注:“资料代找获取”,全网计算机学习资料代找:例如:
《课程:2026 年多模态大模型实战训练营》
《课程:AI 大模型工程师系统课程 (22 章完整版 持续更新)》
《课程:AI 大模型系统实战课第四期 (2026 年开课 持续更新)》
《课程:2026 年 AGI 大模型系统课 23 期》
《课程:2026 年 AGI 大模型系统课 21 期》
《课程:AI 大模型实战课 8 期 (2026 年 2 月最新完结版)》
《课程:AI 大模型系统实战课三期》
《课程:AI 大模型系统课程 (2026 年 2 月开课 持续更新)》
《课程:AI 大模型全阶课程 (2025 年 12 月开课 2026 年 6 月结课)》
《课程:AI 大模型工程师全阶课程 (2025 年 10 月开课 2026 年 4 月结课)》
《课程:2026 年最新大模型 Agent 开发系统课 (持续更新)》
《课程:LLM 多模态视觉大模型系统课》
《课程:大模型 AI 应用开发企业级项目实战课 (2026 年 1 月开课)》
《课程:大模型智能体线上速成班 V2.0》
《课程:Java+AI 大模型智能应用开发全阶课》
《课程:Python+AI 大模型实战视频教程》
《书籍:软件工程 3.0: 大模型驱动的研发新范式.pdf》
《课程:人工智能大模型系统课 (2026 年 1 月底完结版)》
《课程:AI 大模型零基础到商业实战全栈课第五期》
《课程:Vue3.5+Electron + 大模型跨平台 AI 桌面聊天应用实战 (2025)》
《课程:AI 大模型实战训练营 从入门到实战轻松上手》
《课程:2026 年 AI 大模型 RAG 与 Agent 智能体项目实战开发课》
《课程:大模型训练营配套补充资料》
更多推荐



所有评论(0)