1. Máy tìm kiếm
Retriever là một giao diện được bao bọc bởi LangChain, có thể trả về các tài liệu liên quan dựa trên các truy vấn không cấu trúc. Mục đích của thiết kế retriever là để thuận tiện cho việc truy vấn dữ liệu cục bộ. Lưu trữ vectơ có thể được sử dụng như là triển khai cơ bản của retriever và LangChain hỗ trợ nhiều triển khai cơ bản của giao diện retriever.
2. Bắt đầu với Retriever
2.1. Cài đặt
Để minh họa cách lấy retriever, chúng ta sẽ sử dụng cơ sở dữ liệu vector Qdrant làm ví dụ.
%pip install --upgrade --quiet qdrant-client
2.2. Lấy Khóa API OpenAI
Trước khi sử dụng OpenAIEmbeddings
, chúng ta cần lấy khóa API OpenAI.
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")
2.3. Nhập Dữ Liệu Tài Liệu và Lấy Khách Hàng Qdrant
Đoạn mã dưới đây minh họa cách nhập dữ liệu tài liệu và lấy khách hàng Qdrant để tạo một retriever:
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. Lấy Retriever
Đoạn mã dưới đây minh họa cách lấy retriever từ Qdrant:
retriever = qdrant.as_retriever()
retriever
Bạn có thể truy vấn tài liệu liên quan đến một câu hỏi như sau:
docs = retriever.get_relevant_documents("ông ý nói gì về ketanji brown jackson")
Bạn cũng có thể đặt ngưỡng tương đồng cho retriever như sau:
retriever = db.as_retriever(
search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)
Ngoài ra, bạn có thể thiết lập retriever để trả về 'K' bản ghi tương tự nhất, ví dụ, trả về 2 bản ghi tương tự nhất:
retriever = db.as_retriever(search_kwargs={"k": 2})
2.5. Sử dụng Retriever trong LCEL
Vì retrievers là các đối tượng Runnable
, chúng ta có thể dễ dàng kết hợp chúng với các đối tượng Runnable
khác để điều phối các quy trình:
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 = """Trả lời các câu hỏi chỉ dựa trên ngữ cảnh sau đây:
{context}
Câu hỏi: {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("Ông Tổng thống nói gì về công nghệ?")
Giải thích về quy trình:
- Bước 1: Mục tiêu là tạo một từ điển chứa hai thuộc tính,
context
vàquestion
, để chuẩn bị tham số cho mẫu prompt. Tham sốcontext
được tạo ra bởi retriever dựa trên tham số được truyền vào phương thứcinvoke
, đó là "Ông Tổng thống nói gì về công nghệ?". Điều này lấy các tài liệu tương tự với câu hỏi, sau đó định dạng mảng tài liệu bằng cách sử dụng hàmformat_docs
và gán nó cho thuộc tínhcontext
. HàmRunnablePassthrough
sao chép tham số (câu hỏi của người dùng) của chuỗi vào thuộc tínhquestion
. - Bước 2: Truyền từ điển được tạo ra trong bước 1 vào mẫu prompt để định dạng.
- Bước 3: Truyền prompt được định dạng từ mẫu prompt qua mô hình.
- Bước 4: Truyền kết quả của cuộc gọi mô hình vào bộ phân tích kết quả
StrOutputParser
.
3. Retriever Tùy chỉnh
4.1. Giới thiệu về Giao diện Retriever
Giao diện retriever rất đơn giản, và chúng ta có thể dễ dàng viết các retriever tùy chỉnh.
4.2. Ví dụ về Trình tìm kiếm Tùy chỉnh
Dưới đây là một ví dụ về trình tìm kiếm tùy chỉnh, minh họa cách viết một trình tìm kiếm tùy chỉnh và sử dụng nó để truy xuất các tài liệu liên quan:
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")
Qua việc nghiên cứu các phần trên, bạn sẽ hiểu rõ hơn về khái niệm, phương pháp truy xuất và tùy chỉnh của các trình tìm kiếm.