# Embedding 模型学习笔记 > 基于 hr-assistant 项目的模型选型实践 --- ## 1. GGUF 是什么 **GGUF** = **G**GML **U**niversal **F**ile **F**ormat 一种专门为大语言模型设计的**压缩文件格式**。 ### 类比理解 | 格式 | 说明 | 类比 | |------|------|------| | 原始模型 (.bin/.safetensors) | 完整的 PyTorch 模型文件 | 未压缩的 ZIP | | **GGUF** | 针对 llama.cpp 优化的量化格式 | 高压缩的 7z/RAR | --- ## 2. GGUF 的优点 - ✅ **体积小** - 量化后只有原模型的 1/4 ~ 1/8 - ✅ **CPU 友好** - 专为 llama.cpp 优化,普通电脑也能流畅运行 - ✅ **加载快** - 内存映射技术,启动速度快 - ✅ **单一文件** - 所有权重 + 配置都在一个 .gguf 文件里 --- ## 3. 量化级别选择 | 格式 | 精度 | 体积 | 适用场景 | |------|------|------|----------| | Q4_0.gguf | 4-bit | 最小 | 资源极度受限,可接受一定精度损失 | | Q8_0.gguf | 8-bit | 中等 | **推荐** - 平衡大小和质量 | | F16.gguf | 16-bit | 较大 | 追求最高精度,不差存储空间 | **实际案例:** - nomic-embed-text-v1.5.Q8_0.gguf - 139MB - hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf - 313MB --- ## 4. GGUF vs 原始模型 | 特性 | 原始模型 | GGUF | |------|----------|------| | **用途** | 训练、微调、研究 | 推理、部署、生产 | | **精度** | 完整精度 (FP32/FP16) | 量化后 (Q4-Q8) | | **体积** | 大 (7B模型约 13GB) | 小 (7B模型约 4GB) | | **运行要求** | 需要 GPU + 大量显存 | CPU 也能流畅跑 | | **生态系统** | PyTorch/Transformers | llama.cpp/Ollama | ### 为什么还有人用原始模型? 1. **需要训练和微调** - GGUF 是"只读"格式,不能训练 2. **追求最高精度** - 量化会损失一些精度 3. **灵活性** - 原始模型可以改架构、换词表 4. **生态兼容** - HuggingFace 生态原生支持 --- ## 5. 实践:模型选型与问题解决 ### 遇到的问题 **问题 1:架构不兼容** unknown model architecture: gemma-embedding - 原有模型:hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf - 原因:llama_cpp 0.3.16 不支持 gemma-embedding 架构 - 解决:更换为 llama_cpp 支持的模型 **问题 2:网络不通** - 无法从 HuggingFace 下载模型 - 解决:使用魔搭镜像 (modelscope.cn) ### 解决方案 Step 1:下载支持的模型 wget -O /root/.node-llama-cpp/models/nomic-embed-text-v1.5.Q8_0.gguf \ "https://modelscope.cn/models/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/master/nomic-embed-text-v1.5.Q8_0.gguf" Step 2:配置模型路径 class EmbeddingGenerator: def __init__( self, model_path: str = "/root/.node-llama-cpp/models/nomic-embed-text-v1.5.Q8_0.gguf", n_ctx: int = 512, n_threads: int = 4 ): Step 3:验证运行 embedder = EmbeddingGenerator() vec = embedder.encode("测试文本") print(f"向量维度: {vec.shape}") # (1, 768) --- ## 6. 常用 Embedding 模型推荐 ### 通用模型 | 模型 | 语言 | 维度 | 特点 | |------|------|------|------| | nomic-embed-text-v1.5 | 多语言 | 768 | 当前使用,llama_cpp 原生支持 | | bge-small-en-v1.5 | 英文 | 384 | 轻量级,速度快 | | bge-base-en-v1.5 | 英文 | 768 | 精度更高 | ### 中文优化模型 | 模型 | 语言 | 维度 | 特点 | |------|------|------|------| | bge-small-zh-v1.5 | 中文 | 512 | 智源出品,中文优化 | | bge-large-zh-v1.5 | 中文 | 1024 | 中文最佳,但体积大 | | bge-m3 | 多语言 | 1024 | 支持 100+ 语言 | --- ## 7. 模型文件存放路径 /root/.node-llama-cpp/models/ ├── hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf # 旧模型(不支持) └── nomic-embed-text-v1.5.Q8_0.gguf # 当前使用 --- ## 8. 核心代码简化版 from typing import List, Union from llama_cpp import Llama import numpy as np class EmbeddingGenerator: def __init__(self, model_path: str, n_ctx: int = 512, n_threads: int = 4): self.model_path = model_path self.n_ctx = n_ctx self.n_threads = n_threads self.embedding_dim = 768 self.llm = Llama( model_path=model_path, n_ctx=n_ctx, n_threads=n_threads, embedding=True, verbose=False, n_gpu_layers=0 ) def encode(self, texts: Union[str, List[str]], normalize: bool = True) -> np.ndarray: if isinstance(texts, str): texts = [texts] embeddings = [] for text in texts: if len(text) > self.n_ctx * 4: text = text[:self.n_ctx * 4] output = self.llm.embed(text) embeddings.append(output) embeddings = np.array(embeddings) if normalize: embeddings = embeddings / np.linalg.norm(embeddings, axis=1, keepdims=True) return embeddings def similarity(self, text1: str, text2: str) -> float: emb1, emb2 = self.encode([text1, text2], normalize=True) return float(np.dot(emb1, emb2)) --- ## 9. 总结 1. GGUF 是部署首选 - 体积小、速度快、CPU 可跑 2. Q8_0 是性价比之选 - 平衡精度和大小 3. 注意架构兼容性 - 不是所有 GGUF 都能被 llama_cpp 加载 4. 中文场景用 BGE - 有网络时推荐 bge-small-zh-v1.5 5. 魔搭镜像可解决下载问题 - 国内访问 HuggingFace 的替代方案 --- 生成时间:2026-03-11 相关项目:hr-assistant