إعادة الترتيب باستخدام نماذج التضمين

كود بايثون لإعادة الترتيب في RAG

Page content

إعادة الترتيب هو خطوة ثانية في توليد المحتوى المعزز بالاسترجاع (RAG) الأنظمة, بين الاسترجاع والتكوين.

كُبّات كهربائية في الفضاء الرقمي

الصورة أعلاه تُظهر كيف يتخيل Flux-1 dev كُبّات كهربائية في الفضاء الرقمي.

الاسترجاع مع إعادة الترتيب

إذا قمنا بتخزين الوثائق على شكل إدخالات في قاعدة البيانات المتجهية من البداية - فسيعطي الاسترجاع لنا قائمة بالوثائق المشابهة فورًا.

إعادة الترتيب المستقلة

لكن إذا قمنا أولاً بتنزيل الوثائق من الإنترنت، فقد تتأثر استجابة نظام البحث بتحيزات/خوارزميات مزودي البحث، والمحتوى المدفوع، وتحسين SEO، وغيرها، لذا نحتاج إلى إعادة ترتيب ما بعد البحث.

ما كنت أقوم به -

  • الحصول على إدخالات للسؤال البحثي
  • الحصول على إدخالات لكل وثيقة. لم يكن من المتوقع أن تتجاوز الوثيقة 8000 رمز من أي حال
  • حساب التشابه بين السؤال والإدخالات لكل وثيقة
  • ترتيب الوثائق حسب هذا التشابه.

لا توجد قاعدة بيانات متجهية هنا، لنذهب.

كود نموذجي

استخدام Langchain للاتصال بـ Ollama ووظيفة cosine_similarity من langchain. يمكنك فلترة النتائج حسب مقياس التشابه، لكن تذكر أن العتبة ستختلف حسب المجال والنماذج المختلفة للإدخالات ونماذج LLMs.

سأكون سعيدًا إذا كان هذا الكود مفيدًا لك بأي شكل من الأشكال. ترخيص Copy/Paste/UseAnyWayYouWant. تحياتي.

from langchain_core.documents import Document
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.utils.math import cosine_similarity
import numpy as np


def cosine_distance(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    return 1.0 - cosine_similarity(a, b)

def compute_score(vectors: np.ndarray) -> float:
    score = cosine_distance(vectors[0].reshape(1, -1), vectors[1].reshape(1, -1)).item()
    return score

def list_to_array(lst):
    return np.array(lst, dtype=float)   

def compute_scorel(lists) -> float:
    v1 = list_to_array(lists[0])
    v2 = list_to_array(lists[1])
    return compute_score([v1, v2])

def filter_docs(emb_model_name, docs, query, num_docs):
    content_arr = [doc.page_content for doc in docs]

    ollama_emb = OllamaEmbeddings(
        model=emb_model_name
    )

    docs_embs = ollama_emb.embed_documents(content_arr)
    query_embs = ollama_emb.embed_query(query)
    sims = []
    for i, emb in enumerate(docs_embs):
        idx = docs[i].id
        s = compute_scorel([query_embs, docs_embs[i]])
        simstr = str(round(s, 4))
        docs[i].metadata["sim"] = simstr
        sim = {
            "idx": idx,
            "i": i,
            "sim": s,
        }
        sims.append(sim)

    sims.sort(key=sortFn)

    sorted_docs = [docs[x["i"]] for x in sims]
    filtered_docs = sorted_docs[:num_docs]
    return filtered_docs

أفضل نماذج الإدخال

للمساهمات الخاصة بي، النموذج الأفضل للإدخال حاليًا هو bge-large:335m-en-v1.5-fp16

احتل المكان الثاني النموذجان nomic-embed-text:137m-v1.5-fp16 و jina/jina-embeddings-v2-base-en:latest.

لكن قم بإجراء اختباراتك الخاصة لمساهماتك وسؤالك.

روابط مفيدة