Reranking de documentos com Ollama e modelo Qwen3 Reranker - em Go
Implementando RAG? Aqui estão alguns trechos de código em Go - 2...
Como o Ollama padrão não possui uma API de rerank direta, você precisará implementar reranking usando o Qwen3 Reranker em GO gerando embeddings para pares de consulta-documento e classificando-os.
Na semana passada, fiz um pouco de Reranking de documentos de texto com Ollama e Qwen3 Embedding model - em Go.
Hoje, vou tentar alguns modelos Qwen3 Reranker.
Existe um conjunto considerável de novos Qwen3 Embedding & Reranker Models no Ollama disponíveis, uso o médio - dengcao/Qwen3-Reranker-4B:Q5_K_M
Execução do teste: TL;DR
Funciona, e é bastante rápido, não é um método muito padrão, mas ainda assim:
$ ./rnk ./example_query.txt ./example_docs
Usando modelo de embedding: dengcao/Qwen3-Embedding-4B:Q5_K_M
URL base do Ollama: http://localhost:11434
Processando arquivo de consulta: ./example_query.txt, diretório-alvo: ./example_docs
Consulta: O que é inteligência artificial e como funciona o aprendizado de máquina?
Encontrados 7 documentos
Extraindo embedding da consulta...
Processando documentos...
=== CLASSIFICAÇÃO POR SIMILARIDADE ===
1. example_docs/ai_introduction.txt (Pontuação: 0,451)
2. example_docs/machine_learning.md (Pontuação: 0,388)
3. example_docs/qwen3-reranking-models.md (Pontuação: 0,354)
4. example_docs/ollama-parallelism.md (Pontuação: 0,338)
5. example_docs/ollama-reranking-models.md (Pontuação: 0,318)
6. example_docs/programming_basics.txt (Pontuação: 0,296)
7. example_docs/setup.log (Pontuação: 0,282)
Processados 7 documentos em 2,023s (média: 0,289s por documento)
Classificando documentos com modelo de reranker...
Implementando classificação usando abordagem de cross-encoder com dengcao/Qwen3-Reranker-4B:Q5_K_M
=== CLASSIFICAÇÃO COM RERANKER ===
1. example_docs/ai_introduction.txt (Pontuação: 0,343)
2. example_docs/machine_learning.md (Pontuação: 0,340)
3. example_docs/programming_basics.txt (Pontuação: 0,320)
4. example_docs/setup.log (Pontuação: 0,313)
5. example_docs/ollama-parallelism.md (Pontuação: 0,313)
6. example_docs/qwen3-reranking-models.md (Pontuação: 0,312)
7. example_docs/ollama-reranking-models.md (Pontuação: 0,306)
Processados 7 documentos em 1,984s (média: 0,283s por documento)
Código do reranker em Go para chamar o Ollama
Pegue a maior parte do código do post Reranking de documentos de texto com Ollama usando Embedding...
e adicione estes trechos:
No final da função runRnk():
startTime = time.Now()
// classificar documentos usando modelo de reranker
fmt.Println("Classificando documentos com modelo de 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("Erro ao classificar documentos: %v", err)
}
fmt.Println("\n=== CLASSIFICAÇÃO COM RERANKER ===")
for i, doc := range rerankedDocs {
fmt.Printf("%d. %s (Pontuação: %.3f)\n", i+1, doc.Path, doc.Score)
}
totalTime = time.Since(startTime)
avgTimePerDoc = totalTime / time.Duration(len(rerankedDocs))
fmt.Printf("\nProcessados %d documentos em %.3fs (média: %.3fs por documento)\n",
len(rerankedDocs), totalTime.Seconds(), avgTimePerDoc.Seconds())
Depois, adicione algumas funções adicionais:
func rerankDocuments(validDocs []Document, query, rerankingModel, ollamaBaseURL string) ([]Document, error) {
// Como o Ollama padrão não possui uma API de rerank direta, implementaremos
// a classificação gerando embeddings para pares de consulta e documento
fmt.Println("Implementando classificação usando abordagem de cross-encoder com", rerankingModel)
rerankedDocs := make([]Document, len(validDocs))
copy(rerankedDocs, validDocs)
for i, doc := range validDocs {
// Crie um prompt para classificação combinando consulta e documento
rerankPrompt := fmt.Sprintf("Consulta: %s\n\nDocumento: %s\n\nRelevância:", query, doc.Content)
// Obtenha o embedding para o prompt combinado
embedding, err := getEmbedding(rerankPrompt, rerankingModel, ollamaBaseURL)
if err != nil {
fmt.Printf("Aviso: Falha ao obter embedding de classificação para documento %d: %v\n", i, err)
// Fallback para uma pontuação neutra
rerankedDocs[i].Score = 0.5
continue
}
// Use a magnitude do embedding como uma pontuação de relevância
// (Este é um abordagem simplificada - na prática, você usaria um reranker treinado)
score := calculateRelevanceScore(embedding)
rerankedDocs[i].Score = score
// fmt.Printf("Documento %d classificado com pontuação: %.4f\n", i, score)
}
// Classifique os documentos pela pontuação de classificação (ordem decrescente)
sort.Slice(rerankedDocs, func(i, j int) bool {
return rerankedDocs[i].Score > rerankedDocs[j].Score
})
return rerankedDocs, nil
}
func calculateRelevanceScore(embedding []float64) float64 {
// Pontuação simples baseada na magnitude do embedding e valores positivos
var sumPositive, sumTotal float64
for _, val := range embedding {
sumTotal += val * val
if val > 0 {
sumPositive += val
}
}
if sumTotal == 0 {
return 0
}
// Normalize e combine magnitude com viés positivo
magnitude := math.Sqrt(sumTotal) / float64(len(embedding))
positiveRatio := sumPositive / float64(len(embedding))
return (magnitude + positiveRatio) / 2
}
Não se esqueça de importar um pouco de math
import (
"math"
)
Agora, compile-o
go build -o rnk
e agora execute este protótipo simples de reranker RAG
./rnk ./example_query.txt ./example_docs
Links úteis
- Reranking de documentos de texto com Ollama e Qwen3 Embedding model - em Go
- Qwen3 Embedding & Reranker Models no Ollama: Desempenho de Estado da Arte
- Ollama cheatsheet
- Instale e configure a localização dos modelos Ollama
- Como o Ollama lida com solicitações paralelas
- Teste: Como o Ollama está usando o desempenho da CPU Intel e núcleos eficientes