PythonAI算法
Llama.cpp Python 绑定与 API 使用详解
Llama.cpp 是一个高效的 C++ 实现,用于在 CPU 上运行 Meta 的 LLaMA 模型,支持多种架构和量化格式。其 Python 绑定 API,涵盖模型加载、文本生成、聊天对话、嵌入生成及服务器模式等核心功能。内容包含初始化参数配置、采样策略、性能优化及与 LangChain、Gradio 等库的集成示例,旨在帮助开发者快速上手本地大模型部署与应用开发。

Llama.cpp 是一个高效的 C++ 实现,用于在 CPU 上运行 Meta 的 LLaMA 模型,支持多种架构和量化格式。其 Python 绑定 API,涵盖模型加载、文本生成、聊天对话、嵌入生成及服务器模式等核心功能。内容包含初始化参数配置、采样策略、性能优化及与 LangChain、Gradio 等库的集成示例,旨在帮助开发者快速上手本地大模型部署与应用开发。

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 等 |
# 安装 Python 绑定
pip install llama-cpp-python
# 可选:带 GPU 支持的版本
pip install llama-cpp-python[server]
| 类/方法 | 功能 | 参数说明 | 示例 |
|---|---|---|---|
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") |
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 # 显示详细信息
)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
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 | 显示加载信息 |
# 使用 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
)
# 基本生成
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:"]
)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
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 | 是否回显输入 |
# 流式生成
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)
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"])
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"])
def chat_with_llama(llm, messages):
"""多轮对话函数"""
while True:
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)
# 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 """
# 生成单个文本嵌入
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)} 个嵌入向量")
import numpy as np
from numpy.linalg import norm
def cosine_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}")
# 使用不同采样策略
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 学习率
)
# 使用 grammar 约束生成
grammar = """ root ::= (statement ". ")*
statement ::= "I" verb object
verb ::= " love" | " hate"
object ::= " cats" | " dogs"
"""
# 注意:当前版本可能需要通过不同方式应用 grammar
# 通常通过 GGML 格式的 grammar 文件
# 获取生成的对数概率
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 in zip(logprobs["tokens"], logprobs["token_logprobs"]):
prob = np.exp(logprob)
print(f" {token}: {prob:.4f}")
# 获取模型上下文大小
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}")
# 编码文本
text = "Hello, world!"
tokens = llm.tokenize(text.encode())
print(f"文本 '{text}' 的 tokens: {tokens}")
# 解码 tokens
decoded_text = llm.detokenize(tokens)
print(f"解码后的文本:{decoded_text}")
# 计算 token 数
def count_tokens(text):
tokens = llm.tokenize(text.encode())
return len(tokens)
text = "这是一个测试句子。"
token_count = count_tokens(text)
print(f"文本 token 数:{token_count}")
# 启动服务器(使用命令行)
# 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)
| 端点 | 方法 | 功能 | 请求示例 |
|---|---|---|---|
/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 | 模型信息 | 无参数 |
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"])
# 批处理生成
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")
# 内存优化配置
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()
# 不同量化级别的模型
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]}")
class DocumentQA:
def __init__(self, model_path):
self.llm = Llama(
model_path=model_path,
n_ctx=4096,
n_threads=8,
verbose=False
)
def answer_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}")
class CodeGenerator:
def __init__(self, model_path):
self.llm = Llama(
model_path=model_path,
n_ctx=2048,
n_threads=8,
verbose=False
)
def generate_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)
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" in str(e).lower():
print("内存不足,尝试减小上下文大小")
llm = Llama(
model_path="./models/model.bin",
n_ctx=1024 # 减小上下文
)
import time
def benchmark_generation(llm, prompt, iterations=5):
"""性能基准测试"""
times = []
for i in range(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}秒,{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")
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)
import gradio as gr
def generate_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)
| 实践类别 | 建议 | 理由 |
|---|---|---|
| 模型选择 | 使用 4-bit 量化模型 | 平衡速度和精度 |
| 上下文大小 | 根据需求设置,不要过大 | 减少内存使用 |
| 批处理 | 设置合适的 n_batch 值 | 提高 CPU 利用率 |
| 温度设置 | 根据任务调整温度 | 创造性任务用高温,精确任务用低温 |
| 线程数 | 设置为物理核心数 | 充分利用 CPU |
| 内存管理 | 使用 use_mmap=True | 减少内存占用 |
| 错误处理 | 总是包含异常处理 | 提高稳定性 |
| 性能监控 | 定期基准测试 | 优化参数设置 |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online