Reordenamiento de documentos con Ollama y el modelo Qwen3 Reranker - en Go
¿Implementando RAG? Aquí tienes algunos fragmentos de código en Go - 2...
Dado que Ollama estándar no tiene una API de reranking directa, necesitará implementar reranking usando Qwen3 Reranker en GO generando embeddings para pares de consulta-documento y puntuándolos.
La semana pasada hice un poco de Reranking de documentos de texto con Ollama y el modelo de Embedding Qwen3 - en Go.
Hoy intentaré algunos modelos Qwen3 Reranker. Esto es parte del Tutorial de Generación Aumentada por Recuperación (RAG) más amplio, que cubre patrones de arquitectura e implementación.
Existe un conjunto bastante amplio de Modelos de Embedding y Reranker Qwen3 en Ollama disponibles; yo uso el modelo de tamaño medio: dengcao/Qwen3-Reranker-4B:Q5_K_M

La prueba de ejecución: TL;DR
Funciona, y bastante rápido, aunque no de una manera muy estándar, pero aun así:
$ ./rnk ./example_query.txt ./example_docs
Usando modelo de embedding: dengcao/Qwen3-Embedding-4B:Q5_K_M
URL base de Ollama: http://localhost:11434
Procesando archivo de consulta: ./example_query.txt, directorio objetivo: ./example_docs
Consulta: ¿Qué es la inteligencia artificial y cómo funciona el aprendizaje automático?
Se encontraron 7 documentos
Extrayendo embedding de la consulta...
Procesando documentos...
=== ORDENAMIENTO POR SIMILARIDAD ===
1. example_docs/ai_introduction.txt (Puntuación: 0.451)
2. example_docs/machine_learning.md (Puntuación: 0.388)
3. example_docs/qwen3-reranking-models.md (Puntuación: 0.354)
4. example_docs/ollama-parallelism.md (Puntuación: 0.338)
5. example_docs/ollama-reranking-models.md (Puntuación: 0.318)
6. example_docs/programming_basics.txt (Puntuación: 0.296)
7. example_docs/setup.log (Puntuación: 0.282)
Procesados 7 documentos en 2.023s (promedio: 0.289s por documento)
Reordenando documentos con el modelo reranker...
Implementando reranking usando el enfoque de cross-encoder con dengcao/Qwen3-Reranker-4B:Q5_K_M
=== ORDENAMIENTO CON RERANKER ===
1. example_docs/ai_introduction.txt (Puntuación: 0.343)
2. example_docs/machine_learning.md (Puntuación: 0.340)
3. example_docs/programming_basics.txt (Puntuación: 0.320)
4. example_docs/setup.log (Puntuación: 0.313)
5. example_docs/ollama-parallelism.md (Puntuación: 0.313)
6. example_docs/qwen3-reranking-models.md (Puntuación: 0.312)
7. example_docs/ollama-reranking-models.md (Puntuación: 0.306)
Procesados 7 documentos en 1.984s (promedio: 0.283s por documento)
Código Reranker en Go para llamar a Ollama
Tome la mayor parte del código de la publicación Reranking text documents with Ollama using Embedding...
y añada estos fragmentos:
Al final de la función runRnk():
startTime = time.Now()
// rerank usando modelo de reranking
fmt.Println("Reordenando documentos con el modelo reranker...")
// rerankingModel := "dengcao/Qwen3-Reranker-0.6B:F16"
rerankingModel := "dengcao/Qwen3-Reranker-4B:Q5_K_M"
rerankedDocs, err := rerankDocuments(validDocs, query, rerankingModel, ollamaBaseURL)
if err != nil {
log.Fatalf("Error al reordenar documentos: %v", err)
}
fmt.Println("\n=== ORDENAMIENTO CON RERANKER ===")
for i, doc := range rerankedDocs {
fmt.Printf("%d. %s (Puntuación: %.3f)\n", i+1, doc.Path, doc.Score)
}
totalTime = time.Since(startTime)
avgTimePerDoc = totalTime / time.Duration(len(rerankedDocs))
fmt.Printf("\nProcesados %d documentos en %.3fs (promedio: %.3fs por documento)\n",
len(rerankedDocs), totalTime.Seconds(), avgTimePerDoc.Seconds())
Luego añada un par de funciones más:
func rerankDocuments(validDocs []Document, query, rerankingModel, ollamaBaseURL string) ([]Document, error) {
// Dado que Ollama estándar no tiene una API de reranking directa, implementaremos
// el reranking generando embeddings para pares de consulta-documento y puntuándolos
fmt.Println("Implementando reranking usando el enfoque de cross-encoder con", rerankingModel)
rerankedDocs := make([]Document, len(validDocs))
copy(rerankedDocs, validDocs)
for i, doc := range validDocs {
// Crear un prompt para reranking combinando la consulta y el documento
rerankPrompt := fmt.Sprintf("Consulta: %s\n\nDocumento: %s\n\nRelevancia:", query, doc.Content)
// Obtener embedding para el prompt combinado
embedding, err := getEmbedding(rerankPrompt, rerankingModel, ollamaBaseURL)
if err != nil {
fmt.Printf("Advertencia: Error al obtener embedding de reranking para el documento %d: %v\n", i, err)
// Caída a una puntuación neutral
rerankedDocs[i].Score = 0.5
continue
}
// Usar la magnitud del embedding como puntuación de relevancia
// (Este es un enfoque simplificado; en la práctica, usaría un reranker entrenado)
score := calculateRelevanceScore(embedding)
rerankedDocs[i].Score = score
// fmt.Printf("Documento %d reordenado con puntuación: %.4f\n", i, score)
}
// Ordenar documentos por puntuación de reranking (de mayor a menor)
sort.Slice(rerankedDocs, func(i, j int) bool {
return rerankedDocs[i].Score > rerankedDocs[j].Score
})
return rerankedDocs, nil
}
func calculateRelevanceScore(embedding []float64) float64 {
// Puntuación simple basada en la magnitud del embedding y valores positivos
var sumPositive, sumTotal float64
for _, val := range embedding {
sumTotal += val * val
if val > 0 {
sumPositive += val
}
}
if sumTotal == 0 {
return 0
}
// Normalizar y combinar magnitud con sesgo positivo
magnitude := math.Sqrt(sumTotal) / float64(len(embedding))
positiveRatio := sumPositive / float64(len(embedding))
return (magnitude + positiveRatio) / 2
}
No olvide importar un poco de matemáticas
import (
"math"
)
Ahora compílemos
go build -o rnk
y ahora ejecutemos este simple prototipo tecnológico de RAG reranker
./rnk ./example_query.txt ./example_docs
Enlaces útiles
- Reranking de textos con modelos de embedding
- Reranking de documentos de texto con Ollama y el modelo de Embedding Qwen3 - en Go
- Modelos de Embedding y Reranker Qwen3 en Ollama: Rendimiento de vanguardia
- Hoja de trucos de Ollama
- Instalar y configurar la ubicación de los modelos de Ollama
- Cómo Ollama maneja las solicitudes paralelas
- Prueba: Cómo Ollama utiliza el rendimiento del CPU de Intel y núcleos eficientes