Rust高性能LLM推理库llama-cpp-2的使用,支持高效本地运行大语言模型并优化GPU加速
Rust高性能LLM推理库llama-cpp-2的使用
llama-cpp-2是一个Rust语言对llama.cpp库的封装,支持高效在本地运行大语言模型并优化GPU加速。它是utilityai项目中用于支持所有LLM的核心部分。
基本信息
这个库与llama.cpp紧密耦合,并尽可能模仿其API,同时保持安全性以便更新。
依赖要求
使用bindgen来构建与llama.cpp的绑定,因此需要在系统上安装clang。如果这有问题,可以创建issue讨论包含绑定的可能性。
免责声明
这个crate不安全。存在滥用llama.cpp提供的API创建未定义行为(UB)的方法,如果发现任何问题请创建issue。不要在对UB不可接受的任务中使用此代码。
这不是一个简单的库。理想情况下,应该在这个crate之上编写一个良好的抽象层来提供符合人体工学的API - 这个crate相对于原始绑定的优势是安全性(并不多)而不是其他。
安装
在项目目录中运行以下Cargo命令:
cargo add llama-cpp-2
或在Cargo.toml中添加:
llama-cpp-2 = "0.1.113"
示例代码
以下是一个基本使用示例:
use llama_cpp_2::{LlamaModel, LlamaContext, LlamaParams};
fn main() {
// 初始化模型参数
let params = LlamaParams {
model_path: "path/to/model.bin".to_string(),
n_ctx: 2048, // 上下文长度
n_threads: 4, // 使用的线程数
use_gpu: true, // 启用GPU加速
..Default::default()
};
// 加载模型
let model = LlamaModel::load_from_file(¶ms.model_path).expect("Failed to load model");
// 创建推理上下文
let mut ctx = LlamaContext::new(&model, params).expect("Failed to create context");
// 准备输入
let prompt = "Rust is a programming language that";
// 运行推理
let output = ctx.generate(prompt, 100).expect("Generation failed");
println!("Generated text: {}", output);
}
完整示例代码
use llama_cpp_2::{LlamaModel, LlamaContext, LlamaParams};
use std::path::PathBuf;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 设置模型路径 - 请替换为实际的模型路径
let model_path = PathBuf::from("path/to/model.bin");
// 初始化模型参数
let params = LlamaParams {
model_path: model_path.to_str().unwrap().to_string(),
n_ctx: 2048, // 上下文token数量
n_threads: 8, // 使用CPU线程数
use_gpu: true, // 启用GPU加速
n_gpu_layers: 20, // 使用GPU的层数
seed: 1234, // 随机种子
..Default::default()
};
// 加载模型
let model = LlamaModel::load_from_file(¶ms.model_path)
.expect("Failed to load model");
// 创建推理上下文
let mut ctx = LlamaContext::new(&model, params)
.expect("Failed to create context");
// 准备输入文本
let prompt = "Rust is a programming language that";
println!("Starting generation with prompt: {}", prompt);
// 运行推理,生成100个token
let output = ctx.generate(prompt, 100)
.expect("Generation failed");
println!("\nGenerated text:\n{}", output);
// 高级用法示例:交互式生成
println!("\nStarting interactive generation...");
let mut interactive_ctx = ctx; // 复用之前的context
let mut input = String::new();
loop {
println!("\nEnter your prompt (or 'quit' to exit):");
std::io::stdin().read_line(&mut input)?;
input = input.trim().to_string();
if input == "quit" {
break;
}
let generated = interactive_ctx.generate(&input, 50)
.expect("Interactive generation failed");
println!("Response:\n{}", generated);
input.clear(); // 清空输入缓冲区
}
Ok(())
}
贡献指南
欢迎贡献。请在开始非平凡的PR工作之前创建issue。
许可证
MIT OR Apache-2.0
Rust高性能LLM推理库llama-cpp-2使用指南
简介
llama-cpp-2是一个Rust语言实现的高性能大语言模型(LLM)推理库,支持在本地高效运行各种大语言模型。该库特别优化了GPU加速能力,让开发者能够在普通硬件上运行大型语言模型。
主要特性
- 纯Rust实现,安全高效
- 支持多种量化模型格式
- 优化的GPU加速支持
- 低内存占用
- 跨平台支持(Windows/Linux/macOS)
安装方法
在Cargo.toml中添加依赖:
[dependencies]
llama-cpp-2 = "0.1" # 请使用最新版本号
或者直接运行:
cargo add llama-cpp-2
基本使用方法
1. 加载模型
use llama_cpp_2::{
Model, ModelParams,
Context, ContextParams
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 设置模型参数
let model_params = ModelParams {
n_gpu_layers: 20, // 使用20层GPU加速
..Default::default()
};
// 加载模型文件
let model = Model::load_from_file(
"path/to/your/model.bin",
model_params
)?;
// 创建上下文
let ctx_params = ContextParams::default();
let mut ctx = model.create_context(ctx_params)?;
Ok(())
}
2. 运行推理
// 接上面的代码
// 准备输入
let prompt = "Rust是一种";
let tokens = model.tokenize(prompt, true)?;
// 开始推理
ctx.eval(&tokens, tokens.len(), 0)?;
// 获取输出
let n_vocab = model.n_vocab() as i32;
let logits = ctx.get_logits();
let next_token = logits
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
.map(|(idx, _)| idx)
.unwrap();
// 将token转换回文本
let next_word = model.detokenize(&[next_token as i32])?;
println!("下一个词: {}", next_word);
3. 完整文本生成示例
use llama_cpp_2::{Model, ModelParams};
fn generate_text(model_path: &str, prompt: &str, max_tokens: usize) {
let model = Model::load_from_file(
model_path,
ModelParams {
n_gpu_layers: 20,
..Default::default()
}
).unwrap();
let mut ctx = model.create_context(Default::default()).unwrap();
let tokens = model.tokenize(prompt, true).unwrap();
ctx.eval(&tokens, tokens.len(), 0).unwrap();
let mut output = prompt.to_string();
for _ in 0::max_tokens {
let logits = ctx.get_logits();
let next_token = logits
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
.map(|(idx, _)| idx)
.unwrap();
let word = model.detokenize(&[next_token as i32]).unwrap();
output.push_str(&word);
ctx.eval(&[next_token as i32], 1, 0).unwrap();
}
println!("生成结果: {}", output);
}
高级功能
1. 使用GPU加速
let model_params = ModelParams {
n_gpu_layers: 40, // 增加GPU加速层数
main_gpu: 0, // 使用第一个GPU
tensor_split: None, // 不使用多GPU分片
..Default::default()
};
2. 控制生成参数
use llama_cpp_2::SamplingParams;
let sampling_params = SamplingParams {
temperature: 0.7, // 控制随机性
top_p: 0.9, // 核采样
repeat_penalty: 1.1,// 重复惩罚
..Default::default()
};
ctx.set_sampling_params(sampling_params);
3. 流式输出
use std::io::{self, Write};
fn stream_output(model: &Model, ctx: &mut Context, max_tokens: usize) {
for _ in 0..max_tokens {
let logits = ctx.get_logits();
let next_token = /* 选择token的逻辑 */;
let word = model.detokenize(&[next_token]).unwrap();
print!("{}", word);
io::stdout().flush().unwrap();
ctx.eval(&[next_token], 1, 0).unwrap();
}
}
完整示例代码
use llama_cpp_2::{Model, ModelParams, SamplingParams};
use std::io::{self, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 加载模型
let model = Model::load_from_file(
"path/to/model.bin",
ModelParams {
n_gpu_layers: 20,
..Default::default()
}
)?;
// 2. 创建上下文
let mut ctx = model.create_context(Default::default())?;
// 3. 设置采样参数
ctx.set_sampling_params(SamplingParams {
temperature: 0.7,
top_p: 0.9,
..Default::default()
});
// 4. 准备输入
let prompt = "Rust是一种";
let tokens = model.tokenize(prompt, true)?;
// 5. 运行初始推理
ctx.eval(&tokens, tokens.len(), 0)?;
// 6. 流式生成输出
print!("{}", prompt);
io::stdout().flush()?;
for _ in 0..100 { // 生成100个token
let logits = ctx.get_logits();
let next_token = logits
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
.map(|(idx, _)| idx)
.unwrap();
let word = model.detokenize(&[next_token as i32])?;
print!("{}", word);
io::stdout().flush()?;
ctx.eval(&[next_token as i32], 1, 0)?;
}
println!();
Ok(())
}
性能优化建议
- 使用量化模型(如GGUF格式)减少内存占用
- 根据GPU显存大小调整
n_gpu_layers
参数 - 适当增加上下文窗口大小(
n_ctx
)但注意内存消耗 - 批处理推理请求以提高吞吐量
常见问题
-
模型从哪里获取?
- 可以从HuggingFace等平台下载兼容的GGML或GGUF格式模型
-
如何选择GPU层数?
- 从较小值开始测试,逐步增加直到显存占满
-
内存不足怎么办?
- 使用量化程度更高的模型(如4-bit量化)
- 减少上下文窗口大小
-
支持哪些硬件加速?
- 支持CUDA(NVIDIA GPU)和Metal(Apple GPU)
- 也支持纯CPU推理
llama-cpp-2为Rust开发者提供了高效运行大语言模型的能力,结合Rust的安全性和性能优势,是本地AI应用的理想选择。