搭建一套完整的大模型应用系统并不是单纯把模型权重下载下来跑通推理这么简单。从底层算力适配、模型加载推理,到上层业务接口和知识库联动,每一个环节都有具体的技术选型与坑点。下面我们以一个最小可行系统为目标,逐步拆解从零到一的搭建过程。

一、基础环境准备与模型本地化推理
在正式动手前,需要明确硬件与软件栈的匹配关系。如果手头是一张消费级显卡(例如 24G 显存的 RTX 3090/4090),那么可以承载 7B 到 13B 级别模型的 4bit 或 8bit 量化版本;如果是纯 CPU 环境,则只能运行更小参数量模型或使用高性能推理引擎做限流响应。软件层面推荐 Python 3.10 搭配 PyTorch 2.x,并安装 transformers 与 accelerate 库来管理设备映射。
以 ChatGLM3-6B 的量化版本为例,使用如下代码即可在单卡上启动本地推理。这里采用 load_in_4bit 参数降低显存占用,使 6B 模型在 8G 显存下也能运行。
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_path = "THUDM/chatglm3-6b"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
model_path,
trust_remote_code=True,
load_in_4bit=True,
device_map="auto"
)
query = "请用一句话解释什么是向量数据库"
inputs = tokenizer(query, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=100)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
上述方案的优势是落地极快,半小时内就能在本地对话。但缺点同样明显:模型本身不具备你的私有业务知识,所有回答都来自训练语料,遇到内部文档、 proprietary 规则就会胡说。因此基础推理只是第一步,必须叠加知识注入能力。
另一个容易忽视的点是推理服务的并发。直接用脚本跑 generate 只能串行处理请求,真实业务需要借助文本生成推理框架(如 vLLM、TGI)来提升吞吐。它们通过 PagedAttention 等机制把显存切片复用,同等显卡下并发量可提升三到五倍,这是生产化时不得不考虑的工程细节。
二、引入向量数据库实现检索增强生成
检索增强生成(RAG)是当前性价比最高的私有知识接入方案。其核心原理是:把文档切分成片段,用嵌入模型转成向量,存入向量数据库;用户提问时先把问题转向量,检索最相近的片段,再把这些片段作为上下文送给大模型生成答案。相比全量微调,RAG 不需要改模型权重,当天就能生效,且知识可随时增删。
下面以 Chroma 这一轻量向量库为例,展示如何把一段产品手册写入并建立检索。注意嵌入模型选用多语言模型以保证中文效果。
import chromadb
from chromadb.utils import embedding_functions
client = chromadb.Client()
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="shibing624/text2vec-base-chinese"
)
collection = client.create_collection("manual", embedding_function=embedding_fn)
docs = [
"退货政策:商品购买七日内未拆封可申请全额退款",
"会员等级:消费满一千元自动升级为黄金会员"
]
collection.add(documents=docs, ids=["d1", "d2"])
result = collection.query(query_texts=["怎么退钱"], n_results=1)
print(result["documents"])
拿到检索结果后,将其拼进 prompt 模板再调用第一节的模型,就能得到基于手册的准确回答。这种方式的突出优点是知识边界清晰,不会产生模型权重污染,且合规审计时可以直接追溯答案来自哪条文档。对于中小团队,用 Chroma 或 Milvus 的单机版已完全够用。
当然 RAG 也有局限,比如对需要跨文档推理的问题效果一般,且切分策略直接影响召回率。实践中建议把长文档按语义而不是固定字数切分,并为每个片段补充标题上下文,可显著降低答非所问的概率。
三、封装接口层与系统联调上线
当模型与知识库各自就绪后,需要用接口层把它们粘起来,对外提供统一服务。最朴素的做法是用 FastAPI 写一个 HTTP 接口,内部先查向量库,再调模型,最后返回答案。这样前端、小程序或内部系统都可以通过 POST 请求接入,不必关心底层推理细节。
以下代码演示了一个最小服务:接收问题,检索知识,拼装提示词,调用本地模型并返回。注意这里用 torch.inference_mode 减少中间变量占用。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Ask(BaseModel):
question: str
@app.post("/chat")
def chat(req: Ask):
hits = collection.query(query_texts=[req.question], n_results=2)
context = "n".join(hits["documents"][0])
prompt = f"参考内容:{context}n问题:{req.question}n请回答:"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
with torch.inference_mode():
out = model.generate(**inputs, max_new_tokens=200)
return {"answer": tokenizer.decode(out[0], skip_special_tokens=True)}
联调阶段要重点压测两件事:一是向量检索延迟,通常本地库在毫秒级,可接受;二是模型生成延迟,7B 模型在单卡上生成百字大约需要两三秒,若业务要求更低延迟,就要上推理加速框架或换更小模型。系统上线后还应保留日志,记录每次问题的检索片段与最终回答,方便后续优化切分策略和 prompt 模板。
整体来看,从零到一搭建大模型系统并不神秘:本地推理解决“能说话”,向量数据库解决“说对话”,接口层解决“接得进业务”。三者串联后,一个能服务真实场景的轻量大模型应用就完成了,后续可逐步加入缓存、鉴权与监控,演化为更完备的平台。