1. الواستجابة (Retrievers)

الواستجابة (Retriever) هو واجهة تم تجميعها بواسطة لانج تشين (LangChain)، والتي يمكن أن تقوم بإرجاع الوثائق ذات الصلة بناءً على الاستفسارات غير المهيكلة. الهدف من تصميم الواستجابة هو تسهيل الاستعلام عن البيانات المحلية. يمكن استخدام تخزين الفيكتور كالتنفيذ الأساسي للواستجابة، كما أن لانج تشين تدعم متعددة التنفيذات الأساسية لواجهة الواستجابة.

2. البدء مع الواستجابة (Retriever)

2.1. التثبيت (Installation)

لنقم بتثبيت الواستجابة كمثال باستخدام قاعدة بيانات Qdrant كمثال.

%pip install --upgrade --quiet qdrant-client

2.2. الحصول على مفتاح API لـ OpenAI

قبل استخدام OpenAIEmbeddings، يتعين علينا الحصول على مفتاح API لـ OpenAI.

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass("مفتاح API لـ OpenAI:")

2.3. استيراد بيانات الوثيقة والحصول على عميل قاعدة بيانات Qdrant

يُظهر الكود التالي كيفية استيراد بيانات الوثيقة والحصول على عميل Qdrant لإنشاء الواستجابة:

from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

loader = TextLoader("../../modules/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()

qdrant = Qdrant.from_documents(
    docs,
    embeddings,
    path="/tmp/local_qdrant",
    collection_name="my_documents",
)

2.4. الحصول على الواستجابة

يُظهر الكود التالي كيفية الحصول على الواستجابة من Qdrant:

retriever = qdrant.as_retriever()
retriever

يمكنك الاستعلام عن الوثائق ذات الصلة بسؤال مثل هذا:

docs = retriever.get_relevant_documents("ماذا قال عن Ketanji Brown Jackson")

يمكنك أيضًا تعيين عتبة الشبه للواستجابة بهذه الطريقة:

retriever = db.as_retriever(
    search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)

بالإضافة إلى ذلك، يمكنك تعيين الواستجابة لترجع 'K' أكثر السجلات التي تشابهًا، مثلاً، لرجوع 2 من أكثر السجلات التي تشابه:

retriever = db.as_retriever(search_kwargs={"k": 2})

2.5. الاستخدام الواستجابة في LCEL

نظرًا لأن الواستجابات هي 'Runnable' أو مشغلات، يمكننا دمجها بسهولة مع مشغلات أخرى لتنسيق سير العمل:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

template = """الإجابة على الأسئلة استنادًا إلى السياق التالي:

{context}

السؤال: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()

def format_docs(docs):
    return "\n\n".join([d.page_content for d in docs])

chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

chain.invoke("ماذا قال الرئيس عن التكنولوجيا؟")

شرح للعملية:

  • الخطوة 1: الهدف هو توليد قاموس يحتوي على خاصيتين، 'السياق' و 'السؤال'، لتحضير المعلمات لقالب الاستفسار. العمل 'retriever' يقوم بتوليد المعلمة 'السياق' استنادًا إلى المعلمة الممررة إلى الطريقة 'invoke'، والتي هي "ماذا قال الرئيس عن التكنولوجيا؟". هذا يسترجع وثائق مشابهة للسؤال، ثم يقوم بتنسيق مصفوفة الوثائق باستخدام وظيفة 'format_docs' ويُسند ذلك إلى خاصية 'السياق'. الدالة 'RunnablePassthrough' تقوم بنسخ المعلمة (سؤال المستخدم) للسلسلة إلى خاصية 'السؤال'.
  • الخطوة 2: يتمرر القاموس الذي تم توليده في الخطوة الأولى إلى قالب الاستفسار للتنسيق.
  • الخطوة 3: يتمرر الاستفسار المنسق من قالب الاستفسار إلى النموذج.
  • الخطوة 4: يتمرر نتيجة دعوة النموذج إلى تحليل الإخراج 'StrOutputParser'.

3. الواستجابة المخصصة (Custom Retriever)

4.1. مقدمة إلى واجهة الواستجابة

واجهة الواستجابة بسيطة للغاية، ويمكننا بسهولة كتابة واستجابات مخصصة.

4.2. مثال على المُستخرج المُخصص

فيما يلي مثال على مُستخرج مُخصص يُظهر كيفية كتابة مُستخرج مُخصص واستخدامه لاسترداد المستندات ذات الصلة:

from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from typing import List

class CustomRetriever(BaseRetriever):
  
    def _get_relevant_documents(
        self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List[Document]:
        return [Document(page_content=query]

retriever = CustomRetriever()

retriever.get_relevant_documents("bar")

من خلال دراسة الأقسام أعلاه، ستكتسب فهمًا أعمق للمفهوم وأساليب الاسترجاع، وتخصيص المُستخرجات.