Llama.cpp
1. Llama.cpp 概述
Llama.cpp 是一个高效的 C++ 实现,用于在 CPU 上运行 Meta 的 LLaMA 模型,支持多种架构和量化格式。
主要特性
| 特性 | 说明 |
|---|
| 纯CPU推理 | 无需GPU,在CPU上高效运行 |
| 多种量化 | 支持4bit、5bit、8bit量化 |
| 多平台 | Windows/Linux/macOS/iOS/Android |
| 多架构 | ARM NEON, AVX2, AVX512支持 |
| 多种模型 | LLaMA, Alpaca, Vicuna, CodeLLaMA等 |
| 绑定支持 | Python, Go, Rust, Node.js等 |
2. Python 绑定 API
2.1 安装和导入
# 安装Python绑定 pip install llama-cpp-python # 可选:带GPU支持的版本 pip install llama-cpp-python[server]
2.2 核心类和方法
| 类/方法 | 功能 | 参数说明 | 示例 |
|---|
Llama | 主模型类 | 加载和运行模型 | llm = Llama(model_path="./models/7B/ggml-model-q4_0.bin") |
.create_completion() | 生成文本 | 多种生成参数 | llm.create_completion(prompt="Hello") |
.create_chat_completion() | 聊天生成 | 支持对话格式 | llm.create_chat_completion(messages=messages) |
.embed() | 生成嵌入 | 文本向量化 | embeddings = llm.embed("text") |
3. 模型加载和初始化
3.1 基础初始化
from llama_cpp import Llama # 基础加载 llm = Llama( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_ctx=2048,# 上下文长度 n_threads=8,# CPU线程数 n_gpu_layers=0,# 使用GPU的层数(0=仅CPU) verbose=True# 显示详细信息)
3.2 完整初始化参数
| 参数 | 类型 | 默认值 | 说明 |
|---|
model_path | str | 必填 | 模型文件路径 |
n_ctx | int | 512 | 上下文窗口大小 |
n_parts | int | -1 | 模型分片数 |
n_gpu_layers | int | 0 | 使用GPU的层数 |
seed | int | -1 | 随机种子 |
f16_kv | bool | True | 使用半精度键值缓存 |
logits_all | bool | False | 返回所有logits |
vocab_only | bool | False | 仅加载词汇表 |
use_mlock | bool | False | 锁定内存防止交换 |
use_mmap | bool | True | 使用内存映射 |
n_threads | int | None | CPU线程数 |
n_batch | int | 512 | 批处理大小 |
last_n_tokens_size | int | 64 | 重复惩罚窗口 |
verbose | bool | True | 显示加载信息 |
3.3 GPU支持配置
# 使用GPU(如果支持) llm = Llama( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_gpu_layers=35,# 将35层放在GPU上 n_threads=4,# CPU线程数 n_ctx=2048, verbose=True)# Apple Silicon GPU支持(Metal) llm = Llama( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_gpu_layers=1,# 使用Metal GPU n_threads=8, n_ctx=2048, verbose=True)
4. 文本生成 API
4.1 基础文本生成
# 基本生成 output = llm("Once upon a time")print(output["choices"][0]["text"])# 使用create_completion方法 output = llm.create_completion( prompt="What is AI?", max_tokens=100, temperature=0.7, top_p=0.9, stop=["\n","Human:","AI:"])
4.2 生成参数详解
| 参数 | 类型 | 默认值 | 说明 |
|---|
prompt | str | 必填 | 输入提示 |
suffix | str | None | 生成文本后的后缀 |
max_tokens | int | 16 | 最大生成token数 |
temperature | float | 0.8 | 温度(随机性) |
top_p | float | 0.95 | 核采样概率 |
top_k | int | 40 | 仅考虑top-k个token |
frequency_penalty | float | 0.0 | 频率惩罚 |
presence_penalty | float | 0.0 | 存在惩罚 |
repeat_penalty | float | 1.1 | 重复惩罚 |
stop | List[str] | [] | 停止序列 |
stream | bool | False | 流式输出 |
echo | bool | False | 是否回显输入 |
4.3 流式生成
# 流式生成 stream = llm.create_completion( prompt="Write a story about", max_tokens=200, temperature=0.8, stream=True)for output in stream: chunk = output["choices"][0]["text"]print(chunk, end="", flush=True)
4.4 带参数的生成示例
response = llm.create_completion( prompt="解释量子计算的基本原理:", max_tokens=300, temperature=0.7,# 中等创造性 top_p=0.9,# 核采样 top_k=40,# 仅考虑前40个候选 frequency_penalty=0.5,# 减少重复词汇 presence_penalty=0.3,# 鼓励新话题 repeat_penalty=1.1,# 惩罚重复 stop=["\n\n","###"],# 停止符 echo=False# 不包含输入)print(response["choices"][0]["text"])
5. 聊天对话 API
5.1 基础聊天
messages =[{"role":"system","content":"你是一个有用的助手。"},{"role":"user","content":"你好,请介绍一下你自己。"}] response = llm.create_chat_completion( messages=messages, temperature=0.7, max_tokens=200)print(response["choices"][0]["message"]["content"])
5.2 多轮对话
defchat_with_llama(llm, messages):"""多轮对话函数"""whileTrue: user_input =input("\n用户: ")if user_input.lower()=='quit':break messages.append({"role":"user","content": user_input}) response = llm.create_chat_completion( messages=messages, max_tokens=150, temperature=0.7) assistant_reply = response["choices"][0]["message"]["content"]print(f"助手: {assistant_reply}") messages.append({"role":"assistant","content": assistant_reply})return messages # 初始消息 messages =[{"role":"system","content":"你是一个友好的AI助手,用中文回答。"}]# 开始对话 chat_with_llama(llm, messages)
5.3 不同聊天格式
# Alpaca格式 alpaca_prompt ="""Below is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: {instruction} ### Response:"""# Vicuna格式 vicuna_prompt ="""A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions. USER: {prompt} ASSISTANT:"""# ChatML格式 chatml_prompt ="""<|im_start|>system {system_message}<|im_end|> <|im_start|>user {user_message}<|im_end|> <|im_start|>assistant """
6. 嵌入生成 API
6.1 生成文本嵌入
# 生成单个文本嵌入 embedding = llm.embed("This is a sample text.")print(f"嵌入维度: {len(embedding)}")print(f"嵌入向量: {embedding[:5]}...")# 显示前5个维度# 批量生成嵌入 texts =["人工智能是计算机科学的一个分支","机器学习是AI的子领域","深度学习使用神经网络"] embeddings =[]for text in texts: emb = llm.embed(text) embeddings.append(emb)print(f"生成了 {len(embeddings)} 个嵌入向量")
6.2 计算相似度
import numpy as np from numpy.linalg import norm defcosine_similarity(vec1, vec2):"""计算余弦相似度"""return np.dot(vec1, vec2)/(norm(vec1)* norm(vec2))# 生成嵌入 emb1 = llm.embed("猫是一种动物") emb2 = llm.embed("狗是一种宠物") emb3 = llm.embed("Python是一种编程语言")# 计算相似度 sim_cat_dog = cosine_similarity(emb1, emb2) sim_cat_python = cosine_similarity(emb1, emb3)print(f"猫-狗相似度: {sim_cat_dog:.4f}")print(f"猫-Python相似度: {sim_cat_python:.4f}")
7. 高级生成控制
7.1 采样策略
# 使用不同采样策略 response = llm.create_completion( prompt="写一首关于春天的诗:", max_tokens=100, temperature=0.8,# 高温度 = 更多随机性# temperature=0.2, # 低温度 = 更确定 top_p=0.9,# 核采样 top_k=50,# top-k采样 repeat_penalty=1.2,# 重复惩罚 frequency_penalty=0.5,# 频率惩罚 presence_penalty=0.5,# 存在惩罚 mirostat_mode=2,# Mirostat采样(0=禁用,1=Mirostat,2=Mirostat 2.0) mirostat_tau=5.0,# Mirostat目标困惑度 mirostat_eta=0.1# Mirostat学习率)
7.2 语法约束生成
# 使用grammar约束生成 grammar =""" root ::= (statement ". ")* statement ::= "I" verb object verb ::= " love" | " hate" object ::= " cats" | " dogs" """# 注意:当前版本可能需要通过不同方式应用grammar# 通常通过GGML格式的grammar文件
7.3 对数概率获取
# 获取生成的对数概率 response = llm.create_completion( prompt="The weather is", max_tokens=10, logprobs=10,# 返回前10个候选的logprobs echo=True# 包含输入文本)if"logprobs"in response["choices"][0]: logprobs = response["choices"][0]["logprobs"]print("Top token probabilities:")for token, logprob inzip(logprobs["tokens"], logprobs["token_logprobs"]): prob = np.exp(logprob)print(f" {token}: {prob:.4f}")
8. 模型信息和管理
8.1 获取模型信息
# 获取模型上下文大小print(f"模型上下文大小: {llm.n_ctx()}")# 获取词表大小print(f"词表大小: {llm.n_vocab()}")# 获取模型参数print(f"模型参数: {llm.model.params}")# 获取所有token vocab = llm.tokenize(b"test")print(f"Token IDs: {vocab}")# 解码token token_id =1234 token_text = llm.detokenize([token_id])print(f"Token {token_id} 对应文本: {token_text}")
8.2 Token处理
# 编码文本 text ="Hello, world!" tokens = llm.tokenize(text.encode())print(f"文本 '{text}' 的tokens: {tokens}")# 解码tokens decoded_text = llm.detokenize(tokens)print(f"解码后的文本: {decoded_text}")# 计算token数defcount_tokens(text): tokens = llm.tokenize(text.encode())returnlen(tokens) text ="这是一个测试句子。" token_count = count_tokens(text)print(f"文本token数: {token_count}")
9.服务器模式 API
9.1 启动服务器
# 启动服务器(使用命令行)# python -m llama_cpp.server --model models/7B/ggml-model.bin# 或者从Python启动from llama_cpp.server.app import create_app import uvicorn app = create_app( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_ctx=2048, n_threads=8)# 运行服务器 uvicorn.run(app, host="0.0.0.0", port=8000)
9.2 API端点
| 端点 | 方法 | 功能 | 请求示例 |
|---|
/v1/completions | POST | 文本补全 | {"prompt": "Hello", "max_tokens": 50} |
/v1/chat/completions | POST | 聊天补全 | {"messages": [{"role": "user", "content": "Hi"}]} |
/v1/embeddings | POST | 嵌入生成 | {"input": "text to embed"} |
/v1/models | GET | 模型信息 | 无参数 |
9.3 客户端调用
import requests # 调用本地服务器 response = requests.post("http://localhost:8000/v1/chat/completions", json={"messages":[{"role":"user","content":"你好"}],"temperature":0.7,"max_tokens":100}) result = response.json()print(result["choices"][0]["message"]["content"])
10.性能优化 API
10.1 批处理优化
# 批处理生成 prompts =["解释AI的含义:","什么是机器学习?","深度学习有哪些应用?"]for prompt in prompts: response = llm.create_completion( prompt=prompt, max_tokens=100, temperature=0.7, n_batch=512# 批处理大小)print(f"Q: {prompt}")print(f"A: {response['choices'][0]['text']}\n")
10.2 内存优化
# 内存优化配置 llm = Llama( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_ctx=2048, n_threads=8, n_batch=512, use_mlock=True,# 锁定内存,防止交换 use_mmap=True,# 使用内存映射文件 verbose=True)# 释放内存del llm import gc gc.collect()
10.3 量化模型使用
# 不同量化级别的模型 quantizations ={"q4_0":"4-bit整数量化(最快)","q4_1":"4-bit带尺度量化","q5_0":"5-bit整数量化","q5_1":"5-bit带尺度量化","q8_0":"8-bit整数量化","f16":"半精度浮点数","f32":"全精度浮点数"}# 加载量化模型 model_path ="./models/llama-2-7b-chat.ggmlv3.q4_0.bin" llm = Llama(model_path=model_path, n_ctx=2048)print(f"加载模型: {model_path}")print(f"量化类型: {model_path.split('.')[-2]}")
11. 实际应用示例
11.1 文档问答系统
classDocumentQA:def__init__(self, model_path): self.llm = Llama( model_path=model_path, n_ctx=4096, n_threads=8, verbose=False)defanswer_question(self, context, question): prompt =f"""基于以下文本回答问题。 文本内容: {context} 问题:{question} 答案:""" response = self.llm.create_completion( prompt=prompt, max_tokens=200, temperature=0.3,# 低温度确保准确性 stop=["\n\n"])return response["choices"][0]["text"].strip()# 使用示例 qa_system = DocumentQA("./models/llama-2-7b-chat.ggmlv3.q4_0.bin") context ="Llama.cpp是一个用C++编写的LLaMA模型推理实现,支持CPU上的高效推理..." question ="Llama.cpp是什么?" answer = qa_system.answer_question(context, question)print(f"问题: {question}")print(f"答案: {answer}")
11.2 代码生成助手
classCodeGenerator:def__init__(self, model_path): self.llm = Llama( model_path=model_path, n_ctx=2048, n_threads=8, verbose=False)defgenerate_code(self, description, language="python"): prompt =f"""# {language.capitalize()}代码生成 # 要求:{description} # 代码:""" response = self.llm.create_completion( prompt=prompt, max_tokens=300, temperature=0.5, stop=["# ","\n\n"])return response["choices"][0]["text"]# 使用示例 coder = CodeGenerator("./models/codellama-7b.ggmlv3.q4_0.bin") description ="写一个函数计算斐波那契数列" code = coder.generate_code(description,"python")print(code)
12. 错误处理和调试
12.1 常见错误处理
import traceback try:# 尝试加载模型 llm = Llama( model_path="./models/nonexistent.bin", n_ctx=2048)except FileNotFoundError as e:print(f"模型文件不存在: {e}")# 尝试备用模型 llm = Llama( model_path="./models/backup.bin", n_ctx=2048)except Exception as e:print(f"加载模型时出错: {e}") traceback.print_exc()# 生成时的错误处理try: response = llm.create_completion( prompt="test", max_tokens=100)except RuntimeError as e:if"out of memory"instr(e).lower():print("内存不足,尝试减小上下文大小") llm = Llama( model_path="./models/model.bin", n_ctx=1024# 减小上下文)
12.2 性能监控
import time defbenchmark_generation(llm, prompt, iterations=5):"""性能基准测试""" times =[]for i inrange(iterations): start_time = time.time() response = llm.create_completion( prompt=prompt, max_tokens=100, temperature=0.7) end_time = time.time() generation_time = end_time - start_time times.append(generation_time) tokens_per_second =100/ generation_time print(f"迭代 {i+1}: {generation_time:.2f}秒, "f"{tokens_per_second:.2f} tokens/秒") avg_time =sum(times)/len(times)print(f"\n平均生成时间: {avg_time:.2f}秒")print(f"平均速度: {100/avg_time:.2f} tokens/秒")# 运行基准测试 benchmark_generation(llm,"Once upon a time")
13. 与其他库集成
13.1 与LangChain集成
from langchain.llms import LlamaCpp from langchain.prompts import PromptTemplate from langchain.chains import LLMChain # 创建LlamaCpp实例 llm = LlamaCpp( model_path="./models/llama-2-7b-chat.ggmlv3.q4_0.bin", n_ctx=2048, n_threads=8, temperature=0.7, max_tokens=200, verbose=True)# 创建提示模板 template ="""问题:{question} 回答:""" prompt = PromptTemplate(template=template, input_variables=["question"])# 创建链 llm_chain = LLMChain(prompt=prompt, llm=llm)# 运行 question ="什么是人工智能?" response = llm_chain.run(question)print(response)
13.2 与Gradio集成创建Web界面
import gradio as gr defgenerate_text(prompt, temperature, max_tokens): response = llm.create_completion( prompt=prompt, temperature=temperature, max_tokens=max_tokens )return response["choices"][0]["text"]# 创建界面 iface = gr.Interface( fn=generate_text, inputs=[ gr.Textbox(label="输入提示", lines=3), gr.Slider(0,1, value=0.7, label="温度"), gr.Slider(1,500, value=100, label="最大Token数")], outputs=gr.Textbox(label="生成结果", lines=10), title="Llama.cpp 文本生成器", description="使用Llama.cpp模型生成文本") iface.launch(share=True)
14. 最佳实践总结
| 实践类别 | 建议 | 理由 |
|---|
| 模型选择 | 使用4-bit量化模型 | 平衡速度和精度 |
| 上下文大小 | 根据需求设置,不要过大 | 减少内存使用 |
| 批处理 | 设置合适的n_batch值 | 提高CPU利用率 |
| 温度设置 | 根据任务调整温度 | 创造性任务用高温,精确任务用低温 |
| 线程数 | 设置为物理核心数 | 充分利用CPU |
| 内存管理 | 使用use_mmap=True | 减少内存占用 |
| 错误处理 | 总是包含异常处理 | 提高稳定性 |
| 性能监控 | 定期基准测试 | 优化参数设置 |