Noticias
Modelos
API
keyboard_arrow_down
Lector
Lea las URL y busque en la web para obtener una base más sólida para su LLM.
Incrustaciones
Integraciones multilingües y multimodales de clase mundial.
reclasificador
Recuperador neuronal de clase mundial para maximizar la relevancia de la búsqueda.
MCP terminalCLIarticlellms.txtsmart_toyAgentesdata_objectEsquemamenu_bookDocumentos



Acceso
login
GGUF Base y Cuantificados
Uso y advertencias
Creación de **vectores modelo** eficiente a través de llama-embedding
Benchmark
Conclusión
Blog de tecnología
agosto 13, 2025

Optimización de GGUF para modelos de Embeddings solo de decodificador

4000 tokens/segundo para un modelo de 向量模型 de 3B parámetros en una GPU L4 es probablemente lo más rápido que conseguirás con llama.cpp. ¿O no?
Han Xiao
Han Xiao • 15 minutos de lectura

Hace dos semanas, publicamos los formatos GGUF de jina-embeddings-v4, un modelo de vectorización universal para la recuperación multimodal multilingüe, con varias versiones cuantificadas. Nuestra motivación era simple: como modelo de 3.75B parámetros, la versión de transformador vainilla de jina-embeddings-v4 no escala bien en nuestras instancias de API de GCP G2 (GPU L4), por lo que queríamos acelerar la inferencia utilizando estas versiones GGUF más pequeñas y rápidas. Durante nuestros experimentos, descubrimos algunos hallazgos interesantes al convertir y ejecutar modelos de vectorización GGUF. Dado que la mayoría de la comunidad de llama.cpp se centra en los LLM, pensamos que sería valioso compartir esto desde la perspectiva de un proveedor de vectorizaciones.

Lo que es particularmente relevante es que los modelos de vectorización actuales son casi idénticos a los LLM; por ejemplo, jina-embeddings-v4 se basa en Qwen2.5-VL-3B-instruct y jina-reranker-m0 se basa en Qwen2-VL-2B. La única diferencia real es la salida: los LLM son generativos, las vectorizaciones y los重排器 son discriminativos. Esto crea oportunidades y desafíos: por un lado, podemos aprovechar la implementación eficiente de llama.cpp (por ejemplo, ubatch_size) para servir modelos de vectorización/重排器; por otro lado, las implementaciones de vectorización de llama.cpp se desarrollaron principalmente para arquitecturas más antiguas de solo codificador (como los modelos basados en RoBERTa) y no se han puesto al día por completo con los modelos modernos de vectorización/重排器 de solo decodificador. Este artículo comparte lo que aprendimos al adaptar los modelos de vectorización modernos para que funcionen con el formato GGUF y las herramientas de llama.cpp, por ejemplo, llama-embedding y llama-serving.

tagGGUF Base y Cuantificados

jina-embeddings-v4 se basa en Qwen2.5-VL-3B-instruct con tres adaptadores LoRA: retrieval (optimizado para tareas de recuperación), text-matching (optimizado para tareas de similitud de oraciones) y code (optimizado para tareas de recuperación de código). También está muy entrenado para la recuperación visual de documentos y la salida multi-vector de estilo de interacción tardía. Así que la idea aquí es aprovechar la implementación de gráfico existente de llama.cpp de Qwen2.5-VL-3B y usar llama-embedding para la inferencia.

Sin embargo, lo primero que notamos fue un comportamiento defectuoso en la implementación de transformador de visión o mmproj en llama.cpp, que produce diferentes vectorizaciones con respecto a la implementación torch de Qwen2.5-VL-3B dada la misma entrada de imagen. Mientras solucionamos este problema en nuestra bifurcación, decidimos excluir la torre de visión de las versiones GGUF por ahora. Puedes encontrar más detalles sobre esta discusión aquí.

Multi-modal embeddings for jinaai/jina-embeddings-v4 · ggml-org llama.cpp · Discussion #14851
Hey folks! I’m working on getting multimodal embeddings working with jina-embeddings-v4 (based on Qwen 2.5 VL) through llama.cpp server. I’ve hit an issue with mtmd inconsistencies and was hoping s…
GitHubggml-org

La salida de vectorización multi-vector tampoco es compatible de forma predeterminada, pero no es un problema tan grande como los transformadores de visión. La salida multi-vector proviene de un MLP entrenado en el último bloque de transformador, por lo que, en el peor de los casos, siempre podemos exportar este MLP por separado a numpy y aplicarlo después de obtener las vectorizaciones a nivel de 词元 de llama.cpp: que es lo que hicimos para jina-reranker-m0-GGUF. Claro, no es muy eficiente, pero funciona sin tener que modificar y recompilar llama.cpp.

0:00
/0:04

Eliminamos el transformador de visión y el proyector multi-vector y obtuvimos tres modelos GGUF base en F16.

Así que, para cumplir plenamente con la implementación de gráfico existente de Qwen2.5-VL-3B de llama.cpp, eliminamos el transformador de visión y el proyector multi-vector en el último bloque de transformador y fusionamos todos los adaptadores LoRA de nuevo en el modelo de lenguaje base. Esto nos dio tres modelos v4 específicos para cada tarea con 3.09B parámetros cada uno, por debajo de los 3.75B parámetros originales del v4:

Repositorio de HuggingFace Tarea
jinaai/jina-embeddings-v4-text-retrieval-GGUF Recuperación de texto
jinaai/jina-embeddings-v4-text-code-GGUF Recuperación de código
jinaai/jina-embeddings-v4-text-matching-GGUF Similitud de oraciones

Luego usamos calibration_data_v5_rc.txt (que se puede encontrar aquí y es recomendado por Unsloth) para calibrar los tres modelos GGUF base y obtuvimos tres archivos imatrix, luego usamos llama-quantize con imatrix para cuantificar los modelos de float16 de la siguiente manera:

# build imatrix
llama-imatrix -m jina-embeddings-v4-text-retrieval-F16.gguf -f calibration_data_v5_rc.txt -ngl 99 --no-ppl -o imatrix-retrieval-512.dat

# quantize
./quantize.sh jina-embeddings-v4-text-retrieval-F16.gguf retrieval-i3 imatrix-retrieval-512.dat jinaai/jina-embeddings-v4-text-retrieval-GGUF

El script quantize.sh se muestra a continuación:

#!/bin/bash

F16_MODEL_FILE="$1"
OUTPUT_DIR="$2"
IMATRIX="$3"
HF_REPO="$4"

FILENAME="$(basename "$F16_MODEL_FILE")"
BASE_NAME="${FILENAME%-F16.gguf}"
BASE_NAME="${BASE_NAME%.gguf}"

mkdir -p "$OUTPUT_DIR"

# Array of quantization types
QUANT_TYPES=("IQ1_S" "IQ1_M" "IQ2_XXS" "IQ2_M" "Q2_K" "IQ4_NL" "IQ4_XS"  "IQ3_XXS" "IQ3_S" "IQ3_M" "IQ3_XS" "Q3_K_M" "Q4_K_M" "Q5_K_S" "Q5_K_M" "Q6_K" "Q8_0")

for quant_type in "${QUANT_TYPES[@]}"; do
    llama-quantize --imatrix "${IMATRIX}" "$F16_MODEL_FILE" "${OUTPUT_DIR}/${BASE_NAME}-${quant_type}.gguf" $quant_type 8
done

Finalmente, subimos todas las cuantificaciones a HuggingFace.

Cuantificación BPW Tamaño del archivo (GB)
IQ1_S 2.04 0.73
IQ1_M 2.19 0.79
IQ2_XXS 2.44 0.88
IQ2_M 2.94 1.06
Q2_K 3.29 1.18
IQ3_XXS 3.31 1.19
IQ3_XS 3.59 1.29
IQ3_S 3.76 1.35
IQ3_M 3.84 1.38
Q3_K_M 4.11 1.48
IQ4_NL 4.72 1.69
IQ4_XS 4.49 1.61
Q4_K_M 4.99 1.79
Q5_K_S 5.61 2.02
Q5_K_M 5.75 2.07
Q6_K 6.56 2.36
Q8_0 8.50 3.05
F16 16.00 5.75
v3 (Transformers) 16.00 1.10
v4 (Transformers) 16.00 7.40

tagUso y advertencias

Ahora podemos usar llama-server y llama-embedding para servir GGUFs para la creación de **vectores modelo**. A diferencia de las bibliotecas de transformers, donde tenemos la flexibilidad de escribir código personalizado de preprocesamiento de entrada, tenemos que manejar esta parte manualmente (a menos que queramos recompilar llama-server y llama-embedding). Específicamente, para obtener resultados que sean totalmente consistentes con el uso de AutoModel.from_pretrained("jinaai/jina-embeddings-v4")..., debe tener mucho cuidado con los prefijos y agregarlos manualmente a las entradas de su modelo GGUF. Aquí hay una tabla de referencia:

Tarea prompt_name en la implementación de Transformer Entrada real al modelo
retrieval query (predeterminado) Query: {original_text}
retrieval passage Passage: {original_text}
text-matching query (predeterminado) Query: {original_text}
text-matching passage Query: {original_text} ⚠️
code query (predeterminado) Query: {original_text}
code passage Passage: {original_text}

Algunos usuarios podrían encontrar sorprendente ⚠️ que prompt_name='passage' se anule a "Query: " cuando se usa text-matching en el AutoModel.from_pretrained("jinaai/jina-embeddings-v4").... original. Pero esto en realidad tiene sentido ya que text-matching es una tarea de similitud de oraciones sin roles de izquierda/derecha: las entradas son simétricas.

tagVía llama-server

Después de instalar llama.cpp, puede ejecutar llama-server para alojar el modelo de **vector modelo** como un servidor HTTP compatible con la API de OpenAI. Por ejemplo, para usar text-matching con F16, puede hacer lo siguiente:

llama-server -hf jinaai/jina-embeddings-v4-text-matching-GGUF:F16 --embedding --pooling mean -ub 8192

--pooling mean es necesario ya que v4 son **vectores modelo** de agrupación media.

Luego envíe la solicitud a través de:

curl -X POST "http://127.0.0.1:8080/v1/embeddings" \
  -H "Content-Type: application/json" \
  -d '{
    "input": [
      "Query: A beautiful sunset over the beach",
      "Query: Un beau coucher de soleil sur la plage",
      "Query: 海滩上美丽的日落",
      "Query: 浜辺に沈む美しい夕日"
    ]
  }'

Cuando use los modelos retrieval y code, agregue Query: o Passage: delante de su entrada, así:

curl -X POST "http://127.0.0.1:8080/v1/embeddings" \
  -H "Content-Type: application/json" \
  -d '{
    "input": [
      "Query: A beautiful sunset over the beach",
      "Query: Un beau coucher de soleil sur la plage",
      "Passage: 海滩上美丽的日落",
      "Passage: 浜辺に沈む美しい夕日"
    ]
  }'

tagVía llama-embedding

Para una verificación rápida de cordura, también puede usar el llama-embedding precompilado para la creación de **vectores modelo** de un solo disparo. No recomendamos usarlo para la creación de **vectores modelo** en masa, ya que tiene algunos problemas de rendimiento que discutiremos en la siguiente sección:

llama-embedding -hf jinaai/jina-embeddings-v4-text-matching-GGUF:F16 --pooling mean -p "Query: jina is awesome" --embd-output-format json  2>/dev/null

Lea la siguiente sección para obtener una creación de **vectores modelo** en masa más eficiente con nuestra compilación de llama-embedding con algunas correcciones y mejoras.

tagResumen de las advertencias

Antes de pasar a una implementación más eficiente, resumamos las advertencias de los modelos GGUF:

  • Debe agregar manualmente Query: o Passage: delante de las entradas de texto.
  • No pueden manejar la entrada de imágenes en este momento porque eliminamos los transformadores de visión del modelo GGUF. Tuvimos que eliminarlos debido a errores en la implementación del transformador de visión/mmproj de Qwen2.5-vl-3b de llama.cpp, que estamos trabajando para solucionar con upstream.
  • No pueden generar **vectores modelo** multivectoriales, ya que no es parte de la implementación del gráfico Qwen2.5-vl-3b de llama.cpp. La solución más fácil sin recompilar llama.cpp es exportar y ejecutar el MLP por separado después de obtener los **vectores modelo** a nivel de **token** estableciendo --pooling none en llama-embedding.
  • v4 se entrena con el aprendizaje de representación de Matryoshka, y la conversión a GGUF conserva esta característica. Si obtiene **vectores modelo** con forma NxD, simplemente puede usar embeddings[:, :truncate_dim] para obtener **vectores modelo** truncados más pequeños. Sin embargo, no todas las dimensiones están entrenadas. Para v4, entrenamos truncate_dim para estos valores específicos: [128, 256, 512, 1024, 2048]. Esto significa que la calidad de embeddings[:, :131] no será una interpolación entre la calidad de embeddings[:, :128] y embeddings[:, :256], sino que será significativamente peor que los **vectores modelo** de 128 dimensiones o 256 dimensiones porque 131 dimensiones no están entrenadas.
  • La fragmentación tardía aún puede funcionar como parte del posprocesamiento después de obtener los **vectores modelo** a nivel de **token** a través de --pooling none. Al igual que lo que hicimos al separar el MLP del gráfico llama.cpp, esto no es súper eficiente, pero no requiere recompilación. Sin embargo, hay otra advertencia: dado que v4 es un modelo causal, la fragmentación tardía ya no será bidireccional: los **vectores modelo** de fragmentos anteriores no contendrán información contextual de los fragmentos posteriores. Recuerde que en v3, cada **vector modelo** de fragmento tenía información de contexto global porque usamos máscaras de atención bidireccionales en los bloques de transformadores. Internamente, discutimos si la causalidad hace que la fragmentación tardía sea obsoleta: algunos argumentan que "el contexto también es causal", lo que significa que un lector procesa el texto de izquierda a derecha, por lo que el contexto necesario para interpretar una oración debe provenir del texto anterior. Otros dicen que restringir la fragmentación tardía para que sea unidireccional bloquea el intercambio de contexto entre fragmentos. De cualquier manera, la efectividad de la fragmentación tardía en v4 sigue siendo cuestionable y necesita más estudio.

tagCreación de **vectores modelo** eficiente a través de llama-embedding

llama-embedding es un wrapper de C++ relativamente simple encima de llama.cpp para la creación de **vectores modelo** de texto con E/S muy limpia: stdin, stdout. Nos estamos centrando en mejorar esto en lugar de llama-server en este momento porque hay toneladas de otros problemas como la cola de red, el equilibrio de carga, la multiinquilinato y la serialización que creemos que están fuera del alcance en este punto. Nuestra pregunta es sencilla: ¿cuánta velocidad podemos obtener de una GPU L4 de 24 GB y cuál es el uso máximo de VRAM para la creación de **vectores modelo** de documentos largos?

¿Pero por qué L4? Principalmente porque GCP ofrece funciones de Cloud Run bastante convenientes encima, y es el tipo de GPU más ampliamente disponible y económico que puede obtener para las API de inferencia sin servidor. GCP ofrece A100 y H100 en Cloud Run a petición, y el equipo de GCP nos propone de vez en cuando usar mejores GPU. Pero nuestra filosofía es simple: si necesitamos A100/H100 para servir un modelo 3B, eso es claramente un problema de habilidad por nuestra parte.

Para algunos antecedentes, en llama.cpp, el tamaño de lote lógico (-b) representa el número máximo de tokens enviados al modelo en una sola llamada de evaluación. Cuando se procesan entradas largas, se dividen en fragmentos hasta este tamaño. El **tamaño de lote físico** (-ub) es el número real de tokens procesados simultáneamente en un pase directo a través del hardware, limitado por la memoria disponible. Las actualizaciones de la caché KV se realizan después de que se completa cada lote físico. La **Ventana de Contexto** (-c) es el límite estricto de cuántos tokens puede "ver" el modelo a la vez; para los modelos v4, esto es 32,000 tokens, lo que representa el alcance máximo de atención del modelo. Todos los tokens deben caber dentro de esta ventana de contexto para mantener una atención coherente en toda la secuencia. La siguiente figura ilustra sus relaciones.

tagNuestras correcciones

GitHub - hanxiao/llama.cpp: Inferencia de LLM en C/C++
Inferencia de LLM en C/C++. Contribuye al desarrollo de hanxiao/llama.cpp creando una cuenta en GitHub.
GitHubhanxiao

En nuestra bifurcación anterior, realizamos varias optimizaciones para que llama-embedding sea más eficiente:

  • Manejo simplificado de lotes: establecimos automáticamente -b igual a -c, lo que hace que este parámetro sea obsoleto. Los usuarios ya no necesitan especificar -b, ya que siempre aprovechamos la longitud completa del contexto del modelo para el procesamiento por lotes lógico.
  • Control de memoria flexible: a diferencia de la implementación original donde -ub se veía obligado a ser igual a -b (ya que asumían que los modelos de Embedding no pueden ser causales), permitimos a los usuarios configurar -ub de forma independiente. Esto brinda un control preciso sobre el uso máximo de VRAM al codificar contextos largos; puede procesar un contexto de 32K con un pequeño lote físico de 512 tokens para permanecer dentro de los límites de VRAM gracias a la implementación de la caché KV. Tenga en cuenta que este cambio solo es correcto para los modelos de Embedding causales como jina-embeddings-v4; para las arquitecturas de solo codificador como v3, esta sería la implementación incorrecta.
  • Agrupación media fija: corregimos el cálculo de la agrupación media para los Embeddings cuando ub < b, que anteriormente estaba roto en la implementación original.

Este cambio facilita mucho el trabajo con modelos de Embedding largos de solo decodificador mientras se administran las limitaciones de memoria de manera efectiva. Ahora los usuarios solo necesitan configurar dos parámetros:

    • -c: La longitud máxima del contexto (cuántos tokens puede procesar el modelo de Embedding)
    • -ub: El tamaño del lote físico (cuántos tokens procesa la GPU a la vez)

Entonces, el código exacto para ejecutar nuestra bifurcación en L4 es el siguiente:

# Compile
git clone https://github.com/hanxiao/llama.cpp.git
cd llama.cpp
cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release -j 8

# Run
INPUT_PREFIX="Query: "  # or "Passage: "

cat big_input.txt | sed "s/^/${INPUT_PREFIX}/" | \
./llama.cpp/build/bin/llama-embedding -f /dev/stdin \
    -hf "jinaai/jina-embeddings-v4-text-retrieval-GGUF:FP16" \
    --pooling mean \
    --no-escape \
    --embd-output-format array \
    --ubatch-size 512 \
    --ctx-size 8192 \
    --flash-attn \
    -ngl 99 \
    > "embeddings.txt" 2> "error.log"

Cada línea en big_input.txt es una oración que se va a incorporar. --no-escape se debe establecer para evitar que \n dentro de la oración se interprete como separadores. --flash-attn y -ngl 99 se deben configurar para obtener el mejor rendimiento en la GPU L4.

tagBenchmark

Queremos comprender las siguientes preguntas a través de la evaluación comparativa:

  • ¿Qué tan buena es nuestra cuantificación en comparación con la v4 Float16 original? ¿En qué punto se degrada tanto que sería mejor usar los Embeddings v3?
  • ¿Qué tan rápido puede ejecutarse cada cuantificación en L4 y cuál es el uso máximo de VRAM?
  • ¿Cómo afectan el tamaño del lote físico -ub y la longitud del contexto -c a la velocidad y al uso máximo de VRAM?

Los conjuntos de datos que utilizamos en la evaluación comparativa son:

Tarea Documentos Consultas Pares relevantes Longitud promedio del documento Longitud máxima del documento Longitud promedio de la consulta
NanoHotpotQA 5,090 50 100 57.3 345 14.9
NanoSciFact 2,919 50 56 205.8 1524 13.5
NanoArguAna 3,635 50 50 164.5 1058 193.0
NanoNFCorpus 2,953 50 2,518 223.3 1460 3.3
NanoFiQA2018 4,598 50 123 159.1 1882 10.2

Utilizamos nuestra compilación personalizada de llama-embedding para la evaluación comparativa.

tagCalidad de las cuantificaciones

La versión cuantificada de mejor rendimiento es IQ3_M (3.84 BPW); las cuantificaciones por debajo de 2 bits funcionan peor que v3, por lo que tiene poco sentido usarlas.

Cuantización NanoHotpotQA NanoFiQA2018 NanoArguAna NanoNFCorpus NanoSciFact
IQ1_S 0.6369 0.3178 0.3798 0.2933 0.5934
IQ1_M 0.6316 0.3313 0.5167 0.3256 0.6114
IQ2_XXS 0.7236 0.4582 0.4584 0.4067 0.7392
IQ2_M 0.7427 0.5869 0.5090 0.4468 0.7880
Q2_K 0.7683 0.5744 0.5168 0.4183 0.7546
IQ3_XXS 0.7780 0.5991 0.4811 0.4267 0.7610
IQ3_XS 0.7727 0.5615 0.5195 0.4439 0.7726
IQ3_S 0.8002 0.5505 0.4886 0.4381 0.7690
IQ3_M 0.8106 0.5387 0.5091 0.4462 0.7760
Q3_K_M 0.7567 0.5267 0.4486 0.4092 0.7775
IQ4_NL 0.7930 0.5598 0.4911 0.4285 0.7794
IQ4_XS 0.7979 0.5627 0.4947 0.4258 0.7789
Q4_K_M 0.8029 0.5569 0.4883 0.4226 0.7877
Q5_K_S 0.7969 0.5581 0.4721 0.4288 0.7842
Q5_K_M 0.7927 0.5601 0.4745 0.4247 0.7873
Q6_K 0.7951 0.5636 0.4822 0.4337 0.7846
Q8_0 0.7938 0.5687 0.4784 0.4335 0.7851
F16 0.7940 0.5610 0.4931 0.4343 0.7963
v3 (Transformers) 0.7393 0.5144 0.4600 0.4068 0.7820
v4 (Transformers) 0.7977 0.5571 0.4844 0.4351 0.7963

tagVelocidad y VRAM

Ahora fijamos el conjunto de datos de referencia a NanoHotpotQA y trazamos todas las cuantizaciones por sus bits por peso frente a la velocidad (medida en tokens por segundo) y el consumo de VRAM. Descubrimos que las versiones GGUF son ligeramente más rápidas que la versión original en FP16 (2023 frente a 1865 tokens/seg). La mayoría de las cuantizaciones se agrupan en torno a 2000-2100 tokens/seg. Con la atención flash habilitada, obtenemos una aceleración de ~77% en todas las cuantizaciones (3000+ frente a 2000+ tokens/seg). Sin embargo, la cuantización con mejor rendimiento Q8_0, con alrededor de 3700 tokens por segundo, sigue estando muy por detrás de la versión v3 original (572M parámetros), que alcanza los 16000 tokens/seg. Las versiones cuantificadas ahorran una considerable VRAM y casi alcanzan el nivel del modelo v3 FP16 con IQ3.

Cuantización BPW Tamaño del archivo (GB) VRAM máxima (GB) Token/s con FA Token/s sin FA
IQ1_S 2.04 0.73 4.04 3625 2050
IQ1_M 2.19 0.79 4.09 3349 1997
IQ2_XXS 2.44 0.88 4.19 3701 2071
IQ2_M 2.94 1.06 4.37 3407 1989
Q2_K 3.29 1.18 4.49 3173 1905
IQ3_XXS 3.31 1.19 4.50 3668 2067
IQ3_XS 3.59 1.29 4.60 3604 2053
IQ3_S 3.76 1.35 4.66 3599 2049
IQ3_M 3.84 1.38 4.69 3603 2053
Q3_K_M 4.11 1.48 4.78 3450 2008
IQ4_NL 4.72 1.69 5.00 3571 2039
IQ4_XS 4.49 1.61 4.92 3585 2046
Q4_K_M 4.99 1.79 5.10 3558 2045
Q5_K_S 5.61 2.02 5.32 3567 2044
Q5_K_M 5.75 2.07 5.38 3528 2034
Q6_K 6.56 2.36 5.66 3334 1981
Q8_0 8.50 3.05 6.36 3767 2101
F16 16.00 5.75 9.70 3399 2023
v3 (Transformers) 16.00 1.10 2.82 16505
v4 (Transformers) 16.00 7.40 14.45 1865

Haz clic para expandir la información del sistema

load_tensors: loading model tensors, this can take a while... (mmap = true)
load_tensors: offloading 36 repeating layers to GPU
load_tensors: offloading output layer to GPU
load_tensors: offloaded 37/37 layers to GPU
load_tensors: CUDA0 model buffer size = 3127.61 MiB
load_tensors: CPU_Mapped model buffer size = 315.30 MiB
...................................................................................
llama_context: constructing llama_context
llama_context: n_seq_max = 1
llama_context: n_ctx = 4096
llama_context: n_ctx_per_seq = 4096
llama_context: n_batch = 4096
llama_context: n_ubatch = 4096
llama_context: causal_attn = 1
llama_context: flash_attn = 1 // 1 for w/ FA in the table; 0 for w/o FA
llama_context: kv_unified = true
llama_context: freq_base = 1000000.0
llama_context: freq_scale = 1
llama_context: n_ctx_per_seq (4096) < n_ctx_train (128000) -- the full capacity of the model will not be utilized
llama_context: CUDA_Host output buffer size = 0.59 MiB
llama_kv_cache_unified: CUDA0 KV buffer size = 144.00 MiB
llama_kv_cache_unified: size = 144.00 MiB ( 4096 cells, 36 layers, 1/1 seqs), K (f16): 72.00 MiB, V (f16): 72.00 MiB
llama_context: CUDA0 compute buffer size = 2470.16 MiB
llama_context: CUDA_Host compute buffer size = 96.17 MiB
llama_context: graph nodes = 1234
llama_context: graph splits = 2
common_init_from_params: added <|endoftext|> logit bias = -inf
common_init_from_params: added <|im_end|> logit bias = -inf
common_init_from_params: added <|fim_pad|> logit bias = -inf
common_init_from_params: added <|repo_name|> logit bias = -inf
common_init_from_params: added <|file_sep|> logit bias = -inf
common_init_from_params: setting dry_penalty_last_n to ctx_size = 4096
common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)

system_info: n_threads = 4 (n_threads_batch = 4) / 8 | CUDA : ARCHS = 890 | USE_GRAPHS = 1 | PEER_MAX_BATCH_SIZE = 128 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VNNI = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
main: n_tokens in batch = 0
main: number of embeddings = 5090

tagTamaño óptimo del lote físico y del contexto

Ahora fijamos el tipo de cuantificación a IQ3_S y examinamos cómo el tamaño del lote físico (-ub) y el tamaño del contexto (-c) afectan a la velocidad y a la VRAM. Los resultados en la GPU L4 muestran que -ub=512 con -c=2048 proporciona la configuración óptima, ofreciendo 4.143 tokens/seg mientras se utilizan 2.025MB de VRAM. La conclusión es intuitiva: cuando se conoce la longitud máxima de un único documento en la entrada, se debe utilizar un tamaño de contexto más pequeño que sea justo el necesario para cubrirlo. Para el tamaño del lote físico, 512 tokens parece ser el punto óptimo en la GPU L4.

Rendimiento de tokens por segundo

ubatch_size ctx_size=64 ctx_size=128 ctx_size=256 ctx_size=512
64 2233 2093 2128 2125
128 N/A 2866 2821 2877
256 N/A N/A 3287 3349
512 N/A N/A N/A 3469
ubatch_size ctx_size=2048 ctx_size=4096 ctx_size=8192 ctx_size=16384
256 3971 3630 3593 2766
512 4143 3797 3758 2852
1024 4059 3742 3707 2822
2048 3957 3631 3603 2762
4096 N/A 3450 3410 2625

Uso máximo de VRAM (MB)

ubatch_size ctx_size=64 ctx_size=128 ctx_size=256 ctx_size=512
64 1691 1689 1689 1697
128 N/A 1729 1727 1737
256 N/A N/A 1803 1811
512 N/A N/A N/A 1963
ubatch_size ctx_size=2048 ctx_size=4096 ctx_size=8192 ctx_size=16384
256 1885 1947 2099 2409
512 2025 2101 2257 2577
1024 2329 2407 2571 2917
2048 2933 3025 3203 3597
4096 N/A 4285 4497 4985

tagConclusión

Para los usuarios de v4 que quieran ejecutar GGUF cuantizado de forma eficiente en GPUs económicas, elijan IQ3_S o IQ3_M con nuestra compilación personalizada de llama-embedding - esto debería darles 4000 tokens/seg en conjuntos de datos regulares (donde la longitud de la frase es <2048 tokens). Para incrustar documentos más largos, aumente el tamaño del contexto -c y controle el tamaño del lote físico -ub para reducir la huella de VRAM. Con nuestra compilación personalizada, puede codificar documentos súper largos (>32K tokens) utilizando sólo 3GB de VRAM configurando -ub a un número pequeño como 1024 - algo que no era posible con la implementación original o los transformadores vainilla.

La búsqueda de la optimización de la velocidad nunca termina. Siempre hay espacio para implementaciones más rápidas y ágiles con mayor rendimiento. 4000 tokens/seg probablemente no sea nuestro límite máximo - hay mucho más trabajo por hacer. Más allá de arreglar la implementación del transformador qwen2.5-vl-3b mmproj/vision en llama.cpp, también estamos explorando optimizaciones más profundas a nivel de llama.graph y KV-cache, mejorando la lógica de procesamiento por lotes de llama-serving y añadiendo opciones de streaming a las APIs de incrustación. Nuestro objetivo es que llama.cpp soporte de forma nativa las incrustaciones multimodales modernas de sólo decodificador para nuestras versiones actuales y futuras de Reranker.

Categorías:
Blog de tecnología
rss_feed

Leer más
marzo 11, 2026 • 7 minutos de lectura
Generación de embeddings de audio a partir de LLM multimodales
Han Xiao
Abstract illustration of a sound wave or heartbeat, formed by blue, orange, and gray dots on a white background.
marzo 06, 2026 • 6 minutos de lectura
Identificación de modelos de embeddings a partir de valores numéricos brutos
Han Xiao
Fingerprint illustration made from numbers, showcasing digital and high-tech design on a light background.
septiembre 09, 2025 • 11 minutos de lectura
Vectores multimodales en Llama.cpp y GGUF
Andrei Ungureanu
Alex C-G
Cartoon llama in the center of a white background, emitting laser-like beams from its eyes. The illustration creates a playfu
Oficinas
location_on
Sunnyvale, California
710 Lakeway Dr, Ste 200, Sunnyvale, CA 94085, EE. UU.
location_on
Berlín, Alemania
Prinzessinnenstraße 19-20, 10969 Berlín, Alemania
Fundación de búsqueda
Lector
Incrustaciones
reclasificador
Obtener la clave API de Jina
Límite de velocidad
Estado de la API
Compañía
Sobre nosotros
Contactar con ventas
Sala de prensa
Programa de prácticas
Descargar el logotipo de Jina
open_in_new
Descargar el logotipo de Elastic
open_in_new
Términos
Seguridad
Términos y condiciones
Privacidad
Administrar cookies
email
Jina AI de Elastic © 2020-2026.