Tùy chỉnh Chatbot AI với Python
Giới thiệu
Trong bài viết này, chúng ta sẽ khám phá cách tạo ra một chatbot sử dụng Python, với khả năng tùy chỉnh dựa trên tài liệu của bạn. Bằng cách sử dụng một số thư viện mạnh mẽ như PyPDF2 để trích xuất văn bản từ PDF và sentence-transformers để chuyển đổi văn bản thành vector, chúng ta có thể xây dựng một chatbot thông minh có khả năng hiểu và trả lời dựa trên nội dung tài liệu mà bạn cung cấp.
Mục tiêu bài viết
Bài viết sẽ hướng dẫn bạn từng bước để:
- Đọc và trích xuất văn bản từ các tài liệu PDF.
- Chia nhỏ văn bản thành các phần có kích thước cố định.
- Tạo chỉ mục FAISS từ các vector để tìm kiếm và truy xuất thông tin dễ dàng.
- Triển khai mã nguồn trong một ứng dụng Streamlit.
Nội dung
1. Tóm tắt mã nguồn
Mã nguồn backend.py thực hiện các bước sau:
- Đọc tất cả các tệp PDF trong thư mục
docs/. - Trích xuất văn bản và chia nó thành các phần có kích thước cố định (có chồng lắp).
- Chuyển đổi các phần này thành vector embeddings bằng cách sử dụng
sentence-transformers. - Xây dựng chỉ mục FAISS từ các vector.
- Lưu chỉ mục FAISS (
faiss_index.bin) và danh sách các phần (chunks.pkl) vào đĩa để ứng dụng Streamlit có thể tải chúng để truy xuất.
2. Nhập khẩu và cấu hình
python
import os
import pickle
import numpy as np
from PyPDF2 import PdfReader
from sentence_transformers import SentenceTransformer
import faiss
os: Thực hiện các thao tác trên hệ thống tệp (liệt kê tệp, kết hợp đường dẫn).pickle: Lưu trữ các đối tượng Python (được sử dụng để lưu danh sáchchunks).numpy: Mảng số được sử dụng bởi FAISS.PyPDF2.PdfReader: Trích xuất văn bản từ các trang PDF.SentenceTransformer: Mô hình embedding (all-MiniLM-L6-v2) để chuyển đổi văn bản thành vector dày đặc.faiss: Thư viện tìm kiếm tương tự Facebook AI để lập chỉ mục vector hiệu quả và tìm kiếm k-láng giềng gần nhất.
Cấu hình:
python
embedder = SentenceTransformer("all-MiniLM-L6-v2")
INDEX_FILE = "faiss_index.bin"
CHUNKS_FILE = "chunks.pkl"
embedderlà một thể hiện của mô hình, việc tải này sẽ tải xuống trọng số của mô hình (lần chạy đầu tiên có thể mất thời gian).INDEX_FILEvàCHUNKS_FILElà tên tệp để lưu đầu ra.
3. Hàm load_pdf(file_path) — Đọc tệp PDF và trả về văn bản đầy đủ
python
def load_pdf(file_path):
pdf = PdfReader(file_path)
text = ""
for page in pdf.pages:
text += page.extract_text() + "\n"
return text
- Hàm này lặp qua các trang và kết hợp kết quả từ
page.extract_text().
4. Hàm chunk_text(text, chunk_size=500, overlap=100) — Chia nhỏ văn bản cơ bản
python
def chunk_text(text, chunk_size=500, overlap=100):
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunks.append(text[start:end])
start += chunk_size - overlap
return chunks
- Chia văn bản thành các phần có kích thước
chunk_sizeký tự, với độ chồng lắp làoverlapký tự. - Lý do: Độ chồng lắp đảm bảo tính liên tục của ngữ cảnh: ranh giới hiếm khi cắt đứt thông tin quan trọng hoàn toàn.
5. Hàm build_index(pdf_folder="docs") — Quy trình đầy đủ
Hướng dẫn thực hiện:
- Thu thập các phần cho tất cả các PDF:
python
all_chunks = []
for filename in os.listdir(pdf_folder):
if filename.endswith(".pdf"):
text = load_pdf(os.path.join(pdf_folder, filename))
chunks = chunk_text(text)
all_chunks.extend(chunks)
all_chunkstrở thành danh sách các chuỗi, thứ tự quan trọng (id chỉ mục phù hợp với thứ tự).
- Nhúng các phần:
python
vectors = embedder.encode(all_chunks)
vectors = np.array(vectors)
embedder.encode(list_of_texts)trả về một danh sách/mảng các vector. FAISS mong đợifloat32. An toàn hơn nên buộc kiểu dữ liệu thànhfloat32.- Lưu ý quan trọng: Nhúng tất cả các phần cùng một lúc có thể gây ra lỗi OOM nếu bạn có nhiều phần. Sử dụng batching:
python
vectors = embedder.encode(all_chunks, batch_size=32, show_progress_bar=True)
vectors = np.array(vectors).astype('float32')
- Tạo chỉ mục FAISS:
python
dim = vectors.shape[1]
index = faiss.IndexFlatL2(dim)
index.add(vectors)
IndexFlatL2: tìm kiếm k-láng giềng gần nhất chính xác (brute-force) sử dụng khoảng cách L2.index.add(vectors)thêm các vector theo thứ tự củaall_chunks.
- Lưu chỉ mục và các phần:
python
faiss.write_index(index, INDEX_FILE)
with open(CHUNKS_FILE, "wb") as f:
pickle.dump(all_chunks, f)
- Lưu các tệp vĩnh viễn mà giao diện người dùng Streamlit của bạn tải tại thời gian chạy.
6. Cách chạy mã này
python
# đảm bảo các PDF của bạn nằm trong docs/
python -m backend
# đầu ra: faiss_index.bin và chunks.pkl trong thư mục hiện tại
Các phương pháp tốt nhất
- Tối ưu hóa kích thước chunk: Chọn kích thước chunk và độ chồng lắp phù hợp để tăng cường độ chính xác của chatbot.
- Quản lý bộ nhớ: Sử dụng batching khi nhúng để tránh lỗi bộ nhớ.
Những cạm bẫy phổ biến
- Văn bản trống: Một số trang PDF có thể không chứa văn bản, dẫn đến lỗi trong quá trình trích xuất.
- Tốc độ xử lý: Các tệp PDF lớn có thể làm chậm quá trình trích xuất và nhúng.
Mẹo hiệu suất
- Sử dụng bộ nhớ đệm: Nếu bạn thường xuyên truy cập vào cùng một tài liệu, hãy xem xét việc lưu trữ kết quả đã xử lý để tiết kiệm thời gian.
Giải quyết sự cố
- Nếu bạn gặp lỗi khi chạy mã, hãy kiểm tra các đường dẫn tệp và đảm bảo rằng tất cả các thư viện cần thiết đã được cài đặt.
Kết luận
Bằng cách làm theo hướng dẫn này, bạn đã tạo ra một chatbot AI có khả năng tương tác dựa trên tài liệu. Hãy thử nghiệm với các tài liệu khác nhau để tối ưu hóa chatbot của bạn và cải thiện khả năng trả lời.
Câu hỏi thường gặp
1. Tôi cần cài đặt những thư viện nào?
Bạn cần cài đặt PyPDF2, sentence-transformers, và faiss.
2. Làm thế nào để cải thiện độ chính xác của chatbot?
Cải thiện kích thước chunk và sử dụng các tài liệu đa dạng hơn để huấn luyện mô hình của bạn.
Hãy bắt đầu xây dựng chatbot của bạn ngay hôm nay và khám phá những khả năng mà nó có thể mang lại!