Riordinamento semantico con la funzione rank() in Azure HorizonDB (anteprima)

La ricerca vettoriale restituisce risultati semanticamente simili a una query, ma essere "vicini" nello spazio degli embedding non significa sempre essere "rilevanti" rispetto all'intento dell'utente. Sinonimi, cambiamenti di intento, formulazioni long-tail e sfumature specifiche di dominio possono far sì che il documento più pertinente si posizioni al terzo o al decimo posto invece che al primo. Gli utenti valutano i risultati in base alla loro finalità, non ai punteggi di distanza non elaborati.

Il reranking semantico risolve questo problema. Dopo che una fase iniziale di recupero (ricerca vettoriale, ricerca full-text o ricerca ibrida) ha restituito un ampio insieme di candidati, un modello di reranking cross-encoder ricalcola il punteggio di ciascun candidato rispetto alla query originale. A differenza dell'incorporamento di modelli che codificano separatamente la query e il documento, un codificatore incrociato elabora la query e il documento insieme, acquisendo interazioni con granularità fine tra di esse e producendo punteggi di pertinenza più accurati.

La azure_ai.rank() funzione nell'estensione azure_ai introduce questa funzionalità direttamente in SQL, quindi è possibile aggiungere una fase di reranking senza uscire dal database.

Perché il riordinamento è importante

Il divario tra distanza e pertinenza

Gli incorporamenti vettoriali sono ottimizzati per una somiglianza rapida e approssimativa su larga scala. Codificano il significato in vettori a dimensione fissa in modo indipendente, uno per la query, uno per ogni documento. Questo approccio bi-codificatore è efficiente (è possibile indicizzare miliardi di vettori con DiskANN), ma comprime le interazioni con granularità fine tra query e documento.

Un cross-encoder, invece, elabora la query e il documento come un'unica coppia di input. Presta attenzione a ogni parola in entrambi i testi, catturando interazioni a livello di token che i bi-encoder non colgono. Il risultato è più accurato dei punteggi di pertinenza, ma a costi di calcolo più elevati, perché ogni candidato richiede una chiamata di inferenza separata.

Perché non usare un codificatore incrociato per tutti gli elementi?

I codificatori incrociati sono accurati ma costosi. Attribuire un punteggio a 1 milione di documenti con un cross-encoder al momento della query non è praticabile, poiché richiederebbe da secondi a minuti per ogni query. Ecco perché il recupero di produzione usa una pipeline a due fasi:

  1. Fase 1: recuperare un ampio set di candidati a basso costo (ricerca vettoriale, BM25 o ricerca ibrida). Questo passaggio restringe milioni di documenti fino ai primi 50-100.
  2. Fase 2: riordina solo quei 50-100 candidati con un cross-encoder per migliorare la precisione dei risultati più importanti.

Questo modello offre la velocità della ricerca basata su incorporamento con l'accuratezza del punteggio del cross-encoder, a una frazione del costo necessario per eseguire il cross-encoder sull'intero corpus.

Quando usare il reranking semantico

Usa il riordinamento quando Salta il reranking quando
La qualità della ricerca influisce direttamente sull'esperienza utente (ricerca di prodotti, ricerca di supporto, knowledge base) Ricerche con corrispondenza esatta semplice (codice prodotto, ricerca ID)
Le query sono linguaggio naturale con sfumature, sinonimi o varianti delle finalità Il corpus è sufficientemente piccolo e omogeneo che la ricerca vettoriale da sola ottiene una precisione elevata
Stai creando RAG o Implement durable AI pipelines in Azure HorizonDB (Preview) e hai bisogno del miglior contesto possibile per la generazione con modelli linguistici di grandi dimensioni (LLM) Il budget di latenza non può consentire la chiamata aggiuntiva al modello
La ricerca ibrida restituisce un elenco unificato e si desidera un miglioramento finale dell'accuratezza I risultati sono già filtrati in base a un piccolo set (meno di 5)

Prerequisiti

Un'istanza di Azure HorizonDB con uno dei seguenti elementi:

Funzione rank()

La azure_ai.rank() funzione classifica un set di documenti in base alla pertinenza di una query usando un modello di codificatore incrociato.

Syntax

azure_ai.rank(
    query text,
    document_contents text[],
    document_ids text[] DEFAULT NULL,
    model text DEFAULT NULL
)

Arguments

Argument Type Description
query text La query di ricerca in base alla quale valutare la pertinenza.
document_contents text[] Array di testi dei documenti da riordinare.
document_ids (facoltativo) text[] Matrice di identificatori corrispondenti a ogni documento.
model (facoltativo) text Alias del modello registrato nel registro dei modelli. Se omesso, usa il default-reranker modello gestito (Cohere-rerank-v4.0-fast).

Tipo di ritorno

Restituisce una tabella con colonne: document_id, ranke relevance_score.

Note

Utenti BYOM: passare l'alias registrato del modello reranker come argomento model. Ad esempio: azure_ai.rank('query', documents, ids, 'my-reranker'). Per informazioni dettagliate sulla registrazione dei modelli, vedere funzioni AI nell'estensione azure_ai per Azure HorizonDB (anteprima).

Esempio semplice di riordinamento

Riordinare un insieme di descrizioni di prodotti rispetto a una query di ricerca:

SELECT * FROM azure_ai.rank(
    'wireless noise cancelling headphones',
    ARRAY[
        'Over-ear wireless headphones with active noise cancellation and 30-hour battery life.',
        'Wired earbuds with inline microphone, no noise cancellation.',
        'Bluetooth speaker with 360-degree sound and waterproof design.',
        'Compact noise cancelling earbuds with transparency mode and wireless charging case.'
    ]
);

Note

Per gli utenti BYOM: Aggiungete l'alias del modello come ultimo argomento: azure_ai.rank('wireless noise cancelling headphones', ARRAY[...], NULL, 'my-reranker').

Recupero a due fasi: ricerca vettoriale + reranking

Lo schema più comune consiste nel recuperare i candidati con la ricerca vettoriale, quindi riordinare i risultati migliori per migliorarne la precisione:

WITH candidates AS (
    SELECT id, title, description
    FROM products
    ORDER BY embedding <=> azure_openai.create_embeddings(
        input => 'wireless noise cancelling headphones'
    )::vector
    LIMIT 20
),
reranked AS (
    SELECT *
    FROM azure_ai.rank(
        'wireless noise cancelling headphones',
        ARRAY(SELECT description FROM candidates),
        ARRAY(SELECT id::text FROM candidates)
    )
)
SELECT c.id, c.title, r.rank, r.relevance_score
FROM candidates c
JOIN reranked r ON r.document_id = c.id::text
ORDER BY r.rank ASC
LIMIT 10;

Note

Utenti BYOM: Sostituire azure_openai.create_embeddings(input => 'wireless noise cancelling headphones') con azure_openai.create_embeddings('my-embedding', 'wireless noise cancelling headphones') e aggiungere 'my-reranker' come ultimo argomento a azure_ai.rank().

Ricerca ibrida e reranking

Per ottenere la migliore qualità del recupero, combina la ricerca full-text BM25 e la ricerca vettoriale con Reciprocal Rank Fusion, quindi riordina i risultati combinati. Se si vuole eseguire questo modello come flusso di lavoro durevole e a tolleranza di errore con tentativi e checkpoint automatici, vedere Implementare pipeline di intelligenza artificiale durevole in Azure HorizonDB (anteprima), che supporta ai.rank() come passaggio integrato della pipeline.

WITH query AS (
    SELECT
        'wireless noise cancelling headphones' AS q_text,
        azure_openai.create_embeddings(
            input => 'wireless noise cancelling headphones'
        )::vector AS q_vec
),
bm25 AS (
    SELECT p.id,
           ROW_NUMBER() OVER (
               ORDER BY p.description <@> to_bm25query(query.q_text, 'idx_products_bm25')
           ) AS bm25_rank
    FROM products p, query
    ORDER BY p.description <@> to_bm25query(query.q_text, 'idx_products_bm25')
    LIMIT 50
),
vec AS (
    SELECT p.id, ROW_NUMBER() OVER (ORDER BY p.embedding <=> query.q_vec) AS vec_rank
    FROM products p, query
    ORDER BY p.embedding <=> query.q_vec
    LIMIT 50
),
fused AS (
    SELECT p.id, p.description,
           (1.0 / (60 + COALESCE(b.bm25_rank, 1000))) +
           (1.0 / (60 + COALESCE(v.vec_rank, 1000))) AS rrf_score
    FROM products p
    LEFT JOIN bm25 b ON b.id = p.id
    LEFT JOIN vec v ON v.id = p.id
    WHERE b.id IS NOT NULL OR v.id IS NOT NULL
    ORDER BY rrf_score DESC
    LIMIT 20
),
reranked AS (
    SELECT *
    FROM azure_ai.rank(
        'wireless noise cancelling headphones',
        ARRAY(SELECT description FROM fused),
        ARRAY(SELECT id::text FROM fused)
    )
)
SELECT f.id, f.description, r.rank, r.relevance_score
FROM fused f
JOIN reranked r ON r.document_id = f.id::text
ORDER BY r.rank ASC
LIMIT 10;

Note

Utenti BYOM: Passate gli alias del modello a create_embeddings() e rank() come illustrato negli esempi precedenti.

Considerazioni sulle prestazioni

Fattore Raccomandazione
Dimensione del pool di candidati Riordina 20-50 candidati. Altri candidati migliorano il richiamo, ma aumentano la latenza e i costi in modo lineare.
Latency L'assegnazione dei punteggi tra codificatori aggiunge da decine a poche centinaia di millisecondi a seconda delle dimensioni del pool e della lunghezza del documento.
Lunghezza documento I documenti più brevi vengono riordinati più velocemente. Se i documenti sono lunghi, prendere in considerazione la possibilità di eseguire il reranking rispetto ai riepiloghi o al blocco più rilevante anziché al testo completo.
Quando saltare Se la fase di recupero restituisce già meno di cinque risultati, il reranking comporta costi aggiuntivi a fronte di miglioramenti marginali dell'accuratezza.