AI Engineering Academy · Pelajaran

Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor

Laksanakan penggabungan kedudukan timbal balik untuk menggabungkan senarai hasil tersusun daripada pengambil padat dan jarang tanpa perlu menormalkan skor persamaan yang tidak serasi.

Pelajaran 3 daripada 413 langkah

Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor ialah pelajaran AI Engineering Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran AI Engineering Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus AI Engineering Academy merangkumi sejumlah 4 pelajaran.

Masalah Ketidakserasian Skor

Pemeroleh padat menghasilkan skor keserupaan kosinus antara -1 dan 1, manakala BM25 menghasilkan skor positif tanpa had yang bergantung pada saiz korpus dan kekerapan istilah. Anda tidak boleh menjumlahkan nombor ini secara terus — skor BM25 3.7 dan keserupaan kosinus 0.85 membawa maksud yang sama sekali berbeza. Penormalan skor mudah (membahagikan dengan skor maksimum) rapuh kerana dokumen terpencil memesongkan skala. Kita memerlukan kaedah yang tidak bergantung pada nilai skor mutlak.

Idea Teras di Sebalik RRF

Gabungan Kedudukan Timbal Balik (RRF) memintas masalah ketidakserasian skor dengan menukarkan hasil setiap pemeroleh kepada kedudukan yang disusun dan menggabungkan kedudukan tersebut, bukannya skor mentah. Dokumen pada kedudukan pertama mendapat sumbangan RRF yang tinggi, dokumen pada kedudukan kesepuluh mendapat sumbangan yang jauh lebih rendah, dan skor akhir ialah jumlah sumbangan RRF merentas semua pemeroleh. Formulanya ialah: RRF(d) = sum(1 / (k + rank_i(d))) dengan k ialah pemalar pelicinan (biasanya 60).

# RRF formula
# For each retriever i, document d receives:
#   contribution = 1 / (k + rank_i(d))
# Final RRF score = sum of contributions from all retrievers
# k = 60 is the standard constant from the original 2009 paper

# Example:
# Document A: rank 1 in BM25, rank 4 in dense
#   RRF(A) = 1/(60+1) + 1/(60+4) = 0.01639 + 0.01563 = 0.03202
# Document B: rank 2 in BM25, rank 2 in dense
#   RRF(B) = 1/(60+2) + 1/(60+2) = 0.01613 + 0.01613 = 0.03226
# Document B scores slightly higher due to consistent top-2 ranking

Melaksanakan RRF dari Awal

Pelaksanaannya amat mudah. Bagi setiap pemeroleh, lelar melalui senarai hasilnya yang telah disusun dan kumpulkan skor RRF ke dalam kamus yang dikunci mengikut ID dokumen. Dokumen yang muncul dalam berbilang pemeroleh mengumpulkan sumbangan daripada setiap pemeroleh. Akhir sekali, susun mengikut jumlah skor RRF secara menurun untuk menghasilkan kedudukan gabungan.

from collections import defaultdict

def reciprocal_rank_fusion(
    result_lists: list[list[str]],
    k: int = 60,
) -> list[tuple[str, float]]:
    '''Merge multiple ranked result lists using RRF.
    result_lists: each inner list is a ranked list of document IDs
    Returns: sorted list of (doc_id, rrf_score) tuples
    '''
    rrf_scores = defaultdict(float)

    for ranked_list in result_lists:
        for rank, doc_id in enumerate(ranked_list, start=1):
            rrf_scores[doc_id] += 1.0 / (k + rank)

    sorted_results = sorted(rrf_scores.items(), key=lambda x: x[1], reverse=True)
    return sorted_results

Carian Hibrid Hujung ke Hujung dengan RRF

Dalam amalan, anda menjalankan kedua-dua pemeroleh, mengumpulkan senarai ID dokumen yang telah disusun, menghantarnya kepada RRF dan mencari ID dokumen K teratas dalam stor dokumen anda. Perhatikan bahawa tiada penormalan skor diperlukan — hanya susunan kedudukan hasil setiap pemeroleh yang penting. Hal ini menjadikan RRF sangat teguh terhadap perubahan taburan dan perubahan saiz korpus.

def hybrid_search_rrf(
    query: str,
    bm25_index,
    dense_retriever,
    documents: dict,  # id -> text
    top_k: int = 5,
) -> list[dict]:
    # Get ranked lists from each retriever
    bm25_ids = bm25_index.search(query, top_k=20)  # over-retrieve then fuse
    dense_ids = dense_retriever.search(query, top_k=20)

    # Run RRF
    fused = reciprocal_rank_fusion([bm25_ids, dense_ids])

    # Return top-K with scores
    results = []
    for doc_id, score in fused[:top_k]:
        results.append({
            'id': doc_id,
            'text': documents[doc_id],
            'rrf_score': round(score, 6),
        })
    return results

Sebab Mendapatkan Lebih Banyak Hasil Sebelum Gabungan

Perhatikan corak mendapatkan 20 calon daripada setiap pemeroleh dan kemudian mengambil 5 teratas selepas gabungan. Strategi pemerolehan berlebihan ini penting kerana dokumen yang muncul pada kedudukan 10 dalam BM25 tetapi pada kedudukan 1 dalam pemerolehan padat sepatutnya naik dalam senarai gabungan. Jika anda hanya mendapatkan 5 daripada setiap pemeroleh, dokumen sedemikian akan terlepas. Amalan biasa ialah mendapatkan top_k * 4 daripada setiap pemeroleh sebelum penggabungan, kemudian mengembalikan top_k hasil akhir.

Pemalar Pelicinan K

Pemalar k dalam formula RRF mengawal jumlah pemberat yang diberikan kepada dokumen berkedudukan teratas berbanding dokumen berkedudukan lebih rendah. k yang kecil memperbesar perbezaan antara kedudukan (kedudukan 1 jauh lebih baik daripada kedudukan 2), manakala k yang besar meratakan taburan (semua kedudukan lebih kurang sama penting). Makalah asal menggunakan k=60 dan kajian empirikal menunjukkan nilai antara 30 hingga 100 memberikan prestasi yang serupa. k=60 ialah nilai lalai yang teguh.

# Visualize effect of k on contribution weights
for k in [10, 60, 100]:
    weights = [1.0 / (k + rank) for rank in range(1, 11)]
    print(f'k={k}: rank1={weights[0]:.4f}, rank5={weights[4]:.4f}, rank10={weights[9]:.4f}')

# k=10:  rank1=0.0909, rank5=0.0667, rank10=0.0500  (steep)
# k=60:  rank1=0.0164, rank5=0.0154, rank10=0.0143  (flat)
# k=100: rank1=0.0099, rank5=0.0095, rank10=0.0091  (very flat)

Mengendalikan Dokumen yang Tiada dalam Salah Satu Pemeroleh

RRF mengendalikan dokumen yang hilang dengan baik: dokumen yang muncul dalam hanya satu pemeroleh masih mengumpulkan sumbangan RRF daripada pemeroleh tersebut. Dokumen itu cuma tidak menerima sumbangan kedua. Ini bermakna dokumen yang dipersetujui oleh kedua-dua pemeroleh secara semula jadi akan mendapat skor lebih tinggi daripada dokumen yang ditemui oleh hanya satu pemeroleh. Isyarat konsensus ini tepat seperti yang anda perlukan dalam sistem hibrid.

# Example showing consensus effect
example_docs = {
    'doc_A': [1, 3],   # ranks in [bm25, dense]
    'doc_B': [2, 2],   # both retrievers like it
    'doc_C': [3, None],  # only in BM25
    'doc_D': [None, 1],  # only in dense
}

k = 60
for doc, ranks in example_docs.items():
    score = sum(1/(k + r) for r in ranks if r is not None)
    print(f'{doc}: RRF = {score:.5f}')
# doc_B ranks highest because both retrievers agree
# doc_D (rank 1 in dense only) may outscore doc_A (1,3) despite lower consensus

RRF dengan Lebih daripada Dua Pemeroleh

RRF berkembang secara semula jadi kepada tiga pemeroleh atau lebih. Anda mungkin menggabungkan BM25, pemeroleh terbenam padat dan pemeroleh jarang terlatih (seperti SPLADE) yang mengoptimumkan pemadanan kata kunci secara khusus dalam ruang jarang terlatih. Setiap pemeroleh tambahan menambah satu lagi sumbangan RRF bagi setiap dokumen, dan dokumen yang berada pada kedudukan tinggi merentas semua pemeroleh menang dengan perbezaan yang jelas.

# Three-way hybrid: BM25 + dense + SPLADE
bm25_ids = ['doc_B', 'doc_A', 'doc_C', 'doc_D']
dense_ids = ['doc_D', 'doc_A', 'doc_B', 'doc_E']
splade_ids = ['doc_B', 'doc_D', 'doc_A', 'doc_F']

fused = reciprocal_rank_fusion([bm25_ids, dense_ids, splade_ids])
print('Fused ranking:')
for doc_id, score in fused:
    print(f'  {doc_id}: {score:.5f}')
# doc_A and doc_B likely dominate because they appear in all three lists

RRF Berpemberat untuk Pemeroleh Tidak Simetri

RRF standard melayan semua pemeroleh secara sama rata, tetapi dalam amalan, satu pemeroleh mungkin lebih boleh dipercayai daripada yang lain untuk domain khusus anda. RRF berpemberat mendarabkan sumbangan setiap pemeroleh dengan satu pemberat sebelum menjumlahkannya. Pemberat 1.5 pada pemeroleh padat dan 0.5 pada BM25 menekankan pemadanan semantik, manakala pemberat sama 1.0 melayan kedua-duanya secara simetri. Tala pemberat pada set pengesahan.

def weighted_rrf(
    result_lists: list[list[str]],
    weights: list[float],
    k: int = 60,
) -> list[tuple[str, float]]:
    from collections import defaultdict
    scores = defaultdict(float)
    for ranked_list, weight in zip(result_lists, weights):
        for rank, doc_id in enumerate(ranked_list, start=1):
            scores[doc_id] += weight * (1.0 / (k + rank))
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

# Emphasize dense retrieval (0.7) over BM25 (0.3)
fused = weighted_rrf([bm25_ids, dense_ids], weights=[0.3, 0.7])

RRF berbanding Penormalan Skor: Sebab RRF Menang

Alternatif kepada RRF termasuk normalisasi min-maks (menskalakan skor setiap pengambil semula kepada [0,1]) dan normalisasi skor-z. Kedua-duanya sensitif terhadap dokumen luar biasa yang meningkatkan skor maksimum lalu menyebabkan skor lain menghampiri sifar. RRF tahan terhadap nilai luar biasa kerana ia hanya menggunakan kedudukan, bukan skor mentah. Penanda aras empirikal secara konsisten menunjukkan bahawa RRF mengatasi pendekatan penggabungan berasaskan normalisasi.

Melaksanakan RRF dengan LangChain

EnsembleRetriever LangChain melaksanakan penggabungan RRF secara dalaman. Ia menerima senarai pengambil semula dan pemberat pilihan, menjalankannya secara selari, kemudian mengembalikan hasil yang digabungkan menggunakan RRF. Ini membolehkan anda mengintegrasikan carian hibrid ke dalam rantaian LCEL dengan kod sokongan yang minimum serta menukar pengambil semula individu tanpa mengubah logik penggabungan.

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

# Dense retriever
vectorstore = FAISS.from_documents(langchain_docs, OpenAIEmbeddings())
vector_retriever = vectorstore.as_retriever(search_kwargs={'k': 20})

# Sparse retriever
bm25_retriever = BM25Retriever.from_documents(langchain_docs, k=20)

# Hybrid ensemble using RRF internally
ensemble = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6],
)
results = ensemble.invoke('hybrid search reciprocal rank fusion')

Semakan Pantas

Uji pemahaman anda tentang penggabungan kedudukan salingan daripada pelajaran ini.

Imbas Kembali Pelajaran

Dalam pelajaran ini, anda telah mempelajari bahawa: RRF menggabungkan senarai berperingkat tanpa menormalkan skor yang tidak serasi, formula 1/(k + rank) memberikan sumbangan kepada setiap dokumen daripada setiap pengambil semula, dan dokumen yang mendapat kedudukan tinggi daripada berbilang pengambil semula memperoleh skor gabungan tertinggi. Pemalar pelicinan k=60 ialah nilai lalai yang kukuh. EnsembleRetriever LangChain melaksanakan RRF secara natif. Seterusnya, kita akan mengkonfigurasi carian hibrid secara terus dalam Pinecone dan pgvector.

Percuma untuk bermula

Pelajari Python dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
30
Pelajaran
120

Soalan Lazim

Adakah pelajaran “Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor” percuma?

Ya — teks penuh “Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus AI Engineering Academy, tingkat taraf kepada CoddyKit PRO. Kursus AI Engineering Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor”?

Laksanakan penggabungan kedudukan timbal balik untuk menggabungkan senarai hasil tersusun daripada pengambil padat dan jarang tanpa perlu menormalkan skor persamaan yang tidak serasi. Anda berlatih AI Engineering Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan AI Engineering Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran AI Engineering Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Pengambilan Padat berbanding Jarang: Pertukaran
  2. Melaksanakan Carian Kata Kunci BM25
  3. Penggabungan Kedudukan Timbal Balik untuk Menggabungkan Skor
  4. Carian Hibrid dalam Pinecone dan pgvector
← Kembali ke AI Engineering Academy