PowerInfer 本地文本嵌入实战:使用 embedding 示例生成高维文本向量
2026/9/24 13:53:04 网站建设 项目流程

PowerInfer 本地文本嵌入实战:使用 embedding 示例生成高维文本向量

【免费下载链接】PowerInferHigh-speed Large Language Model Serving for Local Deployment项目地址: https://gitcode.com/gh_mirrors/po/PowerInfer

导读

本文以 examples/embedding 为例,讲解如何在 PowerInfer(llama.cpp 系本地大模型推理框架)中,将一个文本片段转换为高维嵌入向量(embedding vector)。文中既包含开箱即用的 Unix/Windows 命令行示例,也深入 embedding.cpp 源码,剖析从 tokenize、llama_decode 到读取嵌入结果的完整调用链,帮助你在本地部署场景中快速落地文本检索、语义相似度计算与 RAG 向量化等应用。

一、embedding 示例能做什么

embedding 示例演示了使用 llama.cpp 风格接口,为给定文本生成高维嵌入向量(即句向量)。与常规的文本生成不同,它不做自回归续写,而是让模型一次性编码输入文本,并取出模型内部的隐藏层表示作为该文本的向量化结果。输出是一串由空格分隔的浮点数(float),维度由模型的n_embd决定。

这类向量可直接用于:

  • 语义相似度计算(如余弦相似度);
  • 文本检索与重排;
  • RAG(检索增强生成)中的文档向量化;
  • 文本聚类、去重等下游任务。

在 PowerInfer 中,该示例与其他 llama.cpp 生态示例一起通过 examples/CMakeLists.txt 的add_subdirectory(embedding)参与构建。

二、快速开始

使用前请先构建项目并准备一个本地 GGUF 模型,然后将下面的命令中的./path/to/model替换为实际模型路径。

Unix 系系统(Linux、macOS 等)

./embedding -m ./path/to/model --log-disable -p "Hello World!" 2>/dev/null

Windows

embedding.exe -m ./path/to/model --log-disable -p "Hello World!" 2>$null

命令执行后,标准输出(stdout)即为一串空格分隔的浮点数值。2>/dev/null(Windows 下为2>$null)用于把日志、系统信息等诊断输出重定向到 stderr,保证 stdout 中只有纯净的向量数据,方便脚本直接解析。

三、关键命令行参数

embedding 示例通过gpt_params_parse解析参数,因此继承了 llama.cpp 公共参数体系,常用参数如下:

参数含义默认值
-m, --modelGGUF 模型文件路径(必填)
-p, --prompt需要向量化的输入文本无(可配合--random-prompt
--log-disable关闭日志输出(由 common/log.h 处理)关闭状态
--verbose-prompt在 stderr 打印 token 化后的 token 列表,便于调试false
-b, --batch-size单次解码的 token 数(prompt 处理批大小)512,定义于 common/common.h
-c, --context-size上下文窗口大小512,定义于 common/common.h
-t, --threads计算线程数物理核心数
--random-prompt未提供-p时随机生成一个 promptfalse,定义于 common/common.h
--numa启用 NUMA 优化false,定义于 common/common.h

其中--log-disable并非公共参数,而是由日志模块 common/log.h 单独识别并调用log_disable(),因此它不会出现在--help的公共参数列表中,但可以直接使用。

注意:embedding 与文本生成的开关是互斥的。gpt_params中的bool embedding字段(默认false,见 common/common.h)在 common.cpp 中由--embedding参数置位;而在 examples/main/main.cpp 中,当检测到params.embedding为真时,main 示例会提示“please use the 'embedding' tool for embedding calculations”并直接退出,把计算任务交给本示例。

四、源码流程剖析

examples/embedding/embedding.cpp 虽然只有一百余行,却完整展示了 llama.cpp 推理 API 的标准用法,其核心流程如下。

1. 参数解析与初始化

gpt_params params; if (!gpt_params_parse(argc, argv, params)) { return 1; } params.embedding = true; // 显式开启嵌入模式 print_build_info();

无论用户是否传入--embedding,程序都会强制将params.embedding置为true(embedding.cpp),确保后续创建上下文时分配嵌入缓冲区。

若未显式指定随机种子,则用当前时间作为seed(embedding.cpp),并通过std::mt19937初始化随机数生成器;当--random-prompt开启时,调用gpt_random_prompt(rng)生成随机文本(embedding.cpp)。

2. 加载模型与上下文

llama_backend_init(params.numa); std::tie(model, ctx) = llama_init_from_gpt_params(params);

llama_init_from_gpt_params是公共封装,内部会依次完成llama_load_model_from_file加载 GGUF 模型、llama_new_context_with_model创建推理上下文。加载失败时程序报错退出(embedding.cpp)。

创建上下文时,embedding标志的作用会体现在内存分配上:在 llama.cpp 中,if (params.embedding)成立时会执行ctx->embedding.resize(hparams.n_embd),为最终向量预留n_embdfloat的存储空间。该嵌入缓冲区还会参与 llama.cpp 中状态保存/加载的序列化流程,但推理时仅作为输出载体。

随后代码校验上下文窗口:

const int n_ctx_train = llama_n_ctx_train(model); const int n_ctx = llama_n_ctx(ctx); if (n_ctx > n_ctx_train) { /* 警告:模型训练上下文仅为 n_ctx_train */ }

即当用户指定的-c超过模型训练时的上下文长度时,会向 stderr 输出警告(embedding.cpp)。

3. Token 化输入文本

auto embd_inp = ::llama_tokenize(ctx, params.prompt, true);

llama_tokenize使用模型自带的分词器(BPE 或 SentencePiece)将 prompt 转为 token 序列;true表示该文本是“非特殊 token 的完整输入”。若开启--verbose-prompt,会逐 token 打印token id -> 文本片段,便于核对分词结果(embedding.cpp)。

若 token 数超过n_ctx,程序直接报错退出,避免越界(embedding.cpp)。

4. 分块解码

while (!embd_inp.empty()) { int n_tokens = std::min(params.n_batch, (int) embd_inp.size()); if (llama_decode(ctx, llama_batch_get_one(embd_inp.data(), n_tokens, n_past, 0))) { fprintf(stderr, "%s : failed to eval\n", __func__); return 1; } n_past += n_tokens; embd_inp.erase(embd_inp.begin(), embd_inp.begin() + n_tokens); }

这里采用“批处理 + 滑动推进”的方式:每次最多喂入params.n_batch个 token(默认 512,见 common/common.h),通过llama_batch_get_one构造单序列 batch(其签名见 llama.h),调用llama_decode执行前向计算,然后以n_past记录已处理的 token 数,循环直到全部处理完(embedding.cpp)。这种分块机制保证超长文本也能在受限的批大小内完成编码。

5. 读取嵌入向量并输出

const int n_embd = llama_n_embd(model); const auto * embeddings = llama_get_embeddings(ctx); for (int i = 0; i < n_embd; i++) { printf("%f ", embeddings[i]); } printf("\n");

llama_n_embd返回模型隐藏层维度;llama_get_embeddings(声明见 llama.h,返回一维[n_embd]数组)直接返回 llama.cpp 中ctx->embedding.data()的指针。程序随后以%f逐个打印,因此最终输出即为一行空格分隔的浮点数(embedding.cpp)。

6. 收尾

llama_print_timings(ctx); llama_free(ctx); llama_free_model(model); llama_backend_free();

打印推理耗时统计(加载时间、解码 token 数、每 token 耗时等)后,依次释放上下文、模型并关闭后端(embedding.cpp)。

五、底层原理:嵌入向量从哪来

从计算图层面看,模型的第一次变换发生在 llama.cpp:

inpL = ggml_get_rows(ctx, tok_embd, inp_tokens);

即通过ggml_get_rows按 token id 从 token embedding 表中取出对应行,得到输入表示inpL,随后经 Transformer 各层前向传播。本仓库的 PowerInfer 内核会在稀疏算子路径上对这部分计算进行优化(包括基于 GPU/CPU 混合的稀疏推理),但对外暴露的llama_get_embeddingsAPI 语义保持一致,即返回编码完成后累积在ctx->embedding中的最终隐藏状态。

需要留意的是:不同模型对“句向量”的定义不同。部分模型(如 BERT 系)默认取[CLS]token 的表示,部分模型会做 mean pooling。embedding 示例取的是 llama.cpp 内部在嵌入模式下累积的隐藏层结果,具体语义取决于模型在 GGUF 中配置的 pooling 方式。若你的模型需要特定 pooling 策略,请以模型文档或转换脚本(如 convert-hf-to-powerinfer-gguf.py)中的配置为准。

六、构建与集成建议

embedding 示例通过 CMake 构建,其目标定义见 examples/embedding/CMakeLists.txt:

set(TARGET embedding) add_executable(${TARGET} embedding.cpp) install(TARGETS ${TARGET} RUNTIME) target_link_libraries(${TARGET} PRIVATE common llama ${CMAKE_THREAD_LIBS_INIT}) target_compile_features(${TARGET} PRIVATE cxx_std_11)

即生成名为embedding的可执行文件,链接common(参数解析、系统信息等公共库)与llama核心库,并要求 C++11 标准。构建整个项目后,可执行文件通常位于构建目录下的bin/子目录。

实际集成到自己的程序时,可以参照同样的三步 API 模式:

  1. gpt_params_parse(或直接填充gpt_params)配置参数,并置params.embedding = true
  2. llama_init_from_gpt_params加载模型与上下文,llama_tokenize后循环llama_decode
  3. llama_get_embeddings(ctx)拿到n_embd维向量,用于下游相似度计算或向量入库。

七、注意事项

  • 输出纯净性:向量打印在 stdout,日志与统计打印在 stderr;脚本化使用时务必用2>/dev/null2>$null隔离,避免混入噪声。
  • 上下文限制:输入 token 数不得超过n_ctx,超长文本需自行截断或分段;-c不建议超过模型的n_ctx_train,否则会有训练上下文警告。
  • 模型选择:请使用支持嵌入任务(如带[CLS]/pooling 头、或以 text embedding 为目标微调)的模型,并确认其 GGUF 中 embedding 相关配置正确导出。
  • 与生成模式互斥:embedding 计算不产出 token,main示例在--embedding下会被引导到本工具,避免混淆用途。

至此,你已经可以在 PowerInfer 本地环境中完成“文本 → 高维向量”的完整流程:一条命令快速验证,一份 embedding.cpp 源码理解原理,并可将其 API 调用模式直接复用到自己的检索、RAG 或语义分析应用中。

【免费下载链接】PowerInferHigh-speed Large Language Model Serving for Local Deployment项目地址: https://gitcode.com/gh_mirrors/po/PowerInfer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询