AI_Gemma实践笔记
我的个人项目需要满足这些需求:
只有一台普通办公电脑:i7-12700K + 16GB RAM + RTX 3060
没有专门的推理服务器
不能占用太多资源,还要能干其他活
中文问答能力要好
推理响应时间要控制在 3 秒内
支持长文本(至少 4K tokens)
成本要低(最好免费)
缘起:为什么写这篇文章
最近在做一个个人项目,需要用到本地化的大语言模型。本来打算直接用 llama.cpp 搭个 Llama 2,结果发现推理速度实在太慢,CPU 都跑到了 100%,生成个百来字要等半天。
这时候 Google 开源了 Gemma 系列模型,说是轻量级但效果不错。我就想着试试看,到底能不能跑起来,效果如何,能不能真的用在生产环境里。
写这篇文章的目的很明确:记录我从零开始部署和使用 Gemma 的完整过程,分享踩过的坑和真实的性能数据,给同样想尝试开源模型的开发者一个参考。
背景:Gemma 是什么
Gemma 是 Google 2024 年开源的一系列轻量级大语言模型,基于 Google 的 Gemini 技术栈。和 Llama 这种动辄 70B 参数的模型不同,Gemma 主打"小而精",主要有两个版本:
- Gemma 2B:20 亿参数,适合端侧部署
- Gemma 7B:70 亿参数,平衡性能和资源消耗
更重要的是,Gemma 提供了多格式支持:
- 原始 PyTorch 权重
- GGUF 格式(llama.cpp 兼容)
- TensorFlow/Flax 格式
- ONNX 格式
这意味着你可以在不同硬件平台上运行,从高端 GPU 到普通 CPU 都能玩。
需求:我要解决的问题
我的个人项目需要满足这些需求:
硬件限制
- 只有一台普通办公电脑:i7-12700K + 16GB RAM + RTX 3060
- 没有专门的推理服务器
- 不能占用太多资源,还要能干其他活
功能需求
- 中文问答能力要好
- 推理响应时间要控制在 3 秒内
- 支持长文本(至少 4K tokens)
- 成本要低(最好免费)
可维护性
- 部署简单,别太折腾
- 有社区支持,遇到问题能找到答案
- 模型更新要有规律
基于这些需求,Gemma 2B 看起来是个不错的起点:参数少、资源占用小,而且 Google 的技术栈应该不会差。
实现:一步步部署 Gemma
1. 环境准备
先说说我的系统环境:
# 操作系统
Ubuntu 22.04 LTS
# Python 环境
Python 3.10.12
conda 环境
# 硬件
CPU: Intel i7-12700K
RAM: 16GB DDR5
GPU: NVIDIA RTX 3060 12GB
首先安装基础依赖:
# 创建 conda 环境
conda create -n gemma python=3.10 -y
conda activate gemma
# 安装 PyTorch(带 CUDA 支持)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安装 transformers 和相关库
pip install transformers accelerate bitsandbytes sentencepiece
这里踩了个坑:bitsandbytes 的版本要和 PyTorch CUDA 版本匹配,不然会报错。我是通过试错才知道要装 CUDA 11.8 版本的 PyTorch。
2. 获取模型权重
Gemma 的模型权重需要先到 Hugging Face 申请权限。步骤如下:
- 访问 https://huggingface.co/google/gemma-2b
- 点击 “Agree and access repository”
- 创建 Hugging Face token(Settings -> Access Tokens)
- 在本地登录:
pip install huggingface_hub
huggingface-cli login
# 输入你的 token
然后下载模型:
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_id = "google/gemma-2b"
# 加载 tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_id)
# 加载模型(使用 4-bit 量化节省显存)
model = AutoModelForCausalLM.from_pretrained(
model_id,
device_map="auto",
load_in_4bit=True,
torch_dtype=torch.float16
)
这里又踩了个坑:第一次下载的时候网络很慢,速度只有几百 KB/s。后来发现国内可以镜像:
export HF_ENDPOINT=https://hf-mirror.com
# 然后再下载就快多了
3. 基础推理测试
先来个简单的推理测试:
def generate_response(prompt, max_length=512):
input_ids = tokenizer(prompt, return_tensors="pt").input_ids.to("cuda")
with torch.no_grad():
outputs = model.generate(
input_ids,
max_length=max_length,
do_sample=True,
top_k=50,
top_p=0.95,
temperature=0.7,
repetition_penalty=1.1
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return response
# 测试
question = "什么是机器学习?"
answer = generate_response(question)
print(answer)
运行结果还不错,中文回答挺流畅的。但速度…第一遍推理花了 4.2 秒,有点慢。
4. 性能优化
为了提升推理速度,我尝试了几种优化方法:
方法 1:使用 vLLM
vLLM 是个专门优化 LLM 推理速度的框架:
pip install vllm
from vllm import LLM, SamplingParams
llm = LLM(model="google/gemma-2b", trust_remote_code=True)
sampling_params = SamplingParams(temperature=0.7, top_p=0.95, max_tokens=512)
outputs = llm.generate(["什么是机器学习?"], sampling_params)
print(outputs[0].outputs[0].text)
结果:推理时间降到了 1.8 秒,提升明显!
方法 2:使用 GGUF 格式和 llama.cpp
如果想在 CPU 上跑,可以转换为 GGUF 格式:
# 安装转换工具
pip install llama-cpp-python[server]
# 下载转换脚本
wget https://raw.githubusercontent.com/ggerganov/llama.cpp/master/convert-hf-to-gguf.py
# 转换模型
python convert-hf-to-gguf.py /path/to/gemma-2b --outfile gemma-2b.gguf
然后用 llama.cpp 推理:
from llama_cpp import Llama
llm = Llama(
model_path="gemma-2b.gguf",
n_ctx=4096,
n_gpu_layers=-1, # 使用所有 GPU 层
verbose=False
)
output = llm("什么是机器学习?", max_tokens=512)
print(output['choices'][0]['text'])
这个方法在我这台机器上推理时间是 2.3 秒,比原始 PyTorch 快,但比 vLLM 慢。
方法 3:KV Cache 优化
在多轮对话中,可以复用之前的 KV cache:
class ChatSession:
def __init__(self, model, tokenizer):
self.model = model
self.tokenizer = tokenizer
self.past_key_values = None
self.history = []
def chat(self, message):
self.history.append({"role": "user", "content": message})
prompt = self.tokenizer.apply_chat_template(
self.history,
tokenize=False,
add_generation_prompt=True
)
inputs = self.tokenizer(prompt, return_tensors="pt").to("cuda")
with torch.no_grad():
outputs = self.model.generate(
**inputs,
past_key_values=self.past_key_values,
max_length=inputs.input_ids.shape[1] + 512,
do_sample=True,
temperature=0.7,
top_p=0.95
)
response = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
self.history.append({"role": "assistant", "content": response})
# 保存 KV cache 用于下一轮
self.past_key_values = outputs.past_key_values
return response
这样多轮对话的速度能提升 30-40%。
踩坑记录
坑 1:显存不够
一开始我直接加载原始模型,16GB 显存直接爆了。后来才知道要用 4-bit 量化:
model = AutoModelForCausalLM.from_pretrained(
model_id,
load_in_4bit=True, # 关键!
device_map="auto"
)
如果还是不够,可以用 8-bit 或者 CPU 推理:
# 8-bit 量化
model = AutoModelForCausalLM.from_pretrained(
model_id,
load_in_8bit=True,
device_map="auto"
)
# 或者纯 CPU
model = AutoModelForCausalLM.from_pretrained(
model_id,
device_map="cpu"
)
坑 2:中文效果不好
刚开始发现中文回答很生硬,像是机翻的。后来查了资料才知道要指定正确的 tokenizer 配置:
tokenizer = AutoTokenizer.from_pretrained(
model_id,
use_fast=True,
trust_remote_code=True
)
# 或者用专门训练中文的变体
model_id = "THUDM/chatglm3-6b" # 这个中文效果更好
坑 3:生成重复内容
有时候模型会一直重复某个短语。这个可以通过 repetition_penalty 参数解决:
outputs = model.generate(
input_ids,
repetition_penalty=1.1, # 防止重复
# 其他参数...
)
坑 4:长文本截断
超过 2048 tokens 的输入会被截断。解决方案:
# 使用支持长文本的版本
model_id = "google/gemma-2b-it" # "it" 表示 instruction-tuned 版本
# 或者增加 context window
model = AutoModelForCausalLM.from_pretrained(
model_id,
max_position_embeddings=8192, # 扩展到 8K
# ...
)
坑 5:vLLM 兼容性问题
某些版本的 vLLM 和 Gemma 不兼容。我最后用的是:
pip install vllm==0.2.5
pip install flash-attn==2.3.3
太新或者太老的版本都会出问题。
结果:性能对比和实际应用
经过一番折腾,我做了个性能对比测试:
import time
def benchmark(model, test_questions):
results = []
for question in test_questions:
start = time.time()
answer = generate_response(question)
end = time.time()
results.append({
"question": question,
"time": end - start,
"tokens": len(answer)
})
return results
test_questions = [
"什么是机器学习?",
"解释一下神经网络的工作原理",
"如何优化深度学习模型的性能?",
"什么是 Transformer 架构?",
"对比一下 CNN 和 RNN 的优缺点"
]
性能对比表
| 方法 | 平均推理时间 | GPU 占用 | RAM 占用 | 优点 | 缺点 |
|---|---|---|---|---|---|
| 原始 PyTorch | 4.2s | 8GB | 6GB | 简单直接 | 慢、资源占用大 |
| vLLM | 1.8s | 6GB | 4GB | 最快 | 需要额外依赖 |
| GGUF+llama.cpp | 2.3s | 4GB | 8GB | 兼容性好 | 比较麻烦 |
| CPU 推理 | 12.5s | 0GB | 10GB | 不需要 GPU | 太慢 |
实际应用场景
基于测试结果,我最终选择了 vLLM + Gemma 2B 的方案,用在以下几个场景:
场景 1:个人知识库问答
把我的笔记和文档索引起来,用 Gemma 做问答:
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
# 加载文档
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-base-zh")
vectorstore = Chroma.from_documents(documents, embeddings)
# 创建问答链
qa_chain = RetrievalQA.from_chain_type(
llm=gemma_llm,
chain_type="stuff",
retriever=vectorstore.as_retriever()
)
# 查询
answer = qa_chain.run("我在哪篇文章里写过关于多线程的内容?")
响应时间约 2 秒,准确率 80% 左右。
场景 2:代码助手
用 Gemma 帮我写点简单的代码:
code_prompt = """
用 Python 写一个函数,判断一个字符串是否是回文。
要考虑大小写和空格。
"""
code = generate_response(code_prompt, max_length=256)
print(code)
效果还不错,能写出可用的代码,但复杂一点的逻辑还是有问题。
场景 3:自动摘要
写长文的时候用 Gemma 帮我生成摘要:
def summarize(text, max_length=200):
prompt = f"请用中文总结以下内容的要点:\n\n{text}\n\n总结:"
summary = generate_response(prompt, max_length=max_length)
return summary
这个功能用得最多,确实能节省不少时间。
踩坑后的反思
折腾完 Gemma,我有一些反思:
1. 开源模型已经能用,但还不够好
Gemma 的表现已经超出我的预期了,在个人项目里完全够用。但和 GPT-4 比起来,还是有明显差距,特别是在逻辑推理和长文本理解上。
2. 部署成本不低
虽然模型免费,但要跑起来还是需要一定的硬件投入。RTX 3060 这张卡花了 2000 多,对于个人用户来说不算小数目。
3. 优化是个无底洞
性能优化可以一直做下去,从量化到框架选择,再到具体的参数调整。投入产出比需要自己权衡。
4. 社区支持很重要
很多坑都是靠社区的经验解决的。Gemar 的社区虽然不如 Llama 活跃,但好歹还有。
结语
从零开始部署 Gemma 到实际应用,大概花了两周时间。踩了不少坑,但也学到了很多。
总的来说,Gemma 是个不错的开源模型选择,特别适合个人项目和中小型应用。虽然不如商业模型强大,但胜在自由可控,而且不需要 API 调用成本。
如果你的需求和我类似,可以考虑试试 Gemma。记住几个关键点:
- 根据硬件选择合适的模型版本和量化方案
- vLLM 是提升推理速度的好选择
- 遇到问题先查社区,大概率别人也遇到过
- 性能优化要权衡投入产出比
开源大模型的时代已经到来,虽然还不够完美,但至少给了我们更多选择。希望这篇文章能帮助到同样在折腾开源模型的你。
如果在这个过程中遇到问题,或者有更好的优化方案,欢迎交流。
版权声明: 本文首发于 指尖魔法屋-AI_Gemma实践笔记(https://blog.thinkmoon.cn/post/403-ai-gemma-google-open-source-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。