TL;DR
- Một pipeline nạp dữ liệu RAG cần một crawl nguồn chân thực, một danh tính tài liệu ổn định và một lộ trình làm mới; chỉ có embeddings không giữ cho câu trả lời được cập nhật.
- Sử dụng một crawl trang web để khám phá tài liệu có giới hạn, sau đó xác thực từng trang trước khi làm sạch, phân đoạn, nhúng và lập chỉ mục.
- Lưu trữ
source_url,crawled_at,content_hashvà một ID trang ổn định với mỗi đoạn để các cập nhật và trích dẫn vẫn có thể quản lý được. - Đối xử với mã dưới đây như một bảng thiết kế tích hợp: các trường API tuân theo tài liệu Nstdata và thư viện hiện tại, nhưng lộ trình đầu cuối chưa được thực hiện với thông tin xác thực trực tiếp.
Giới thiệu: Dữ liệu web mới là một vấn đề nạp dữ liệu
Nstdata Crawl là lớp thu thập trong quy trình làm việc này; tổng quan sản phẩm của nó mô tả việc truy xuất trang và trang web cho các pipeline dữ liệu phía sau.
Một mô hình ngôn ngữ có thể giải thích một API từ dữ liệu đào tạo của nó và vẫn cung cấp cho bạn tên tham số lỗi thời. Một hệ thống RAG thu hẹp khoảng cách đó bằng cách truy xuất tài liệu tại thời điểm trả lời, nhưng việc truy xuất chỉ có thể cập nhật như các tài liệu đã được lập chỉ mục. Để cung cấp cho một hệ thống RAG dữ liệu web mới, bạn cần một lộ trình có thể lặp lại từ các URL nguồn đến các hồ sơ đã được xác thực và một cách để thay thế hoặc loại bỏ các hồ sơ cũ.
Hướng dẫn này xây dựng lộ trình đó cho tài liệu công khai: Nstdata Crawl → Xác thực Markdown → Các đoạn có nhận thức về tiêu đề → Nhúng → Chroma → Truy xuất. Nó tập trung vào việc nạp dữ liệu và tính mới, không phải trên việc đào tạo một mô hình. Nstdata Crawl đảm nhận việc thu thập trang và chuyển đổi nội dung; ứng dụng của bạn vẫn sở hữu chính sách dữ liệu, phân đoạn, lập chỉ mục, kiểm soát truy cập và đánh giá câu trả lời. Hướng dẫn Crawl hiện tại mô tả đầu ra Markdown, các nhiệm vụ trang/web, SDK Python, trạng thái nhiệm vụ và tham chiếu kết quả lớn trong tài liệu Crawl của nó.
Nạp dữ liệu RAG có nghĩa là gì
Nạp dữ liệu RAG là quá trình biến liệu liệu đầu vào thành các hồ sơ mà một hệ thống truy xuất có thể tìm kiếm. Dữ liệu đào tạo mô hình được tích hợp vào trọng số mô hình. Một chỉ mục RAG là một bộ sưu tập tài liệu và embeddings bên ngoài, có thể thay thế. Dữ liệu web trực tiếp là những gì bộ thu thập của bạn truy xuất từ một trang web hiện tại; nó không đến với mô hình cho đến khi pipeline của bạn xác thực và lập chỉ mục nó.
Nếu một trang tài liệu thay đổi lúc 10:00 nhưng chỉ mục của bạn được xây dựng lại hàng tuần, một truy vấn vào lúc 10:05 có thể vẫn truy xuất hướng dẫn của tuần trước. Câu trả lời có thể nghe trôi chảy và vẫn lỗi thời. Ghi lại cả khi nào nguồn được thu thập và phiên bản nội dung nào đã được lập chỉ mục để làm cho sự chậm trễ đó trở nên rõ ràng.
Pipeline cái nhìn tổng quan
| Giai đoạn | Đầu vào → đầu ra | Kiểm tra chính |
|---|---|---|
| Khám phá | tên miền, sơ đồ trang web, hoặc danh sách URL → URL cho phép | Các URL có nằm trong phạm vi và được phép không? |
| Crawl | URL → Markdown và siêu dữ liệu trang | Nhiệm vụ có hoàn thành không và nội dung bên trong có đúng như mong đợi không? |
| Chuẩn hóa | trang đã lấy → hồ sơ tài liệu chính thống | URL, tiêu đề, phiên bản, và băm nội dung có ổn định không? |
| Phân đoạn | tài liệu → các đoạn có thể truy xuất | Các tiêu đề, mã, và bảng có được giữ nguyên không? |
| Nhúng và lưu trữ | các đoạn → vector cộng thêm siêu dữ liệu | Kích thước vector và ID hồ sơ có khớp với chỉ mục không? |
| Truy xuất và trả lời | câu hỏi → bằng chứng và câu trả lời đã trích dẫn | Câu trả lời có thể được truy nguyên về các đoạn nguồn hiện tại không? |
Điều kiện tiên quyết và ngăn xếp ví dụ
Sử dụng Python 3.10 hoặc phiên bản mới hơn, một mã thông báo Nstdata Crawl, một khóa nhà cung cấp nhúng, và một bộ sưu tập Chroma. Cài đặt các SDK và khóa các phiên bản đã giải quyết trong dự án của bạn sau một lần chạy thử nghiệm:
python -m venv .venv source .venv/bin/activate pip install nstdata-ai-crawl openai chromadb export NSTDATA_API_TOKEN="..." export OPENAI_API_KEY="..."
Các phiên bản chính xác nên được ghi lại trong tập tin khóa của bạn vì hành vi của SDK có thể thay đổi. Môi trường được sử dụng để chuẩn bị bản nháp này không có thông tin xác thực Crawl hoặc OpenAI, vì vậy các cuộc gọi dịch vụ dưới đây chưa được thực hiện trực tiếp.
Bước 1: Chọn và khám phá các nguồn web
Bắt đầu với một danh sách ngắn thay vì thu thập toàn bộ một tên miền. Đối với một trang tài liệu, bao gồm các trang tham khảo sản phẩm và API hiện tại, sau đó loại bỏ các đường dẫn đăng nhập, tìm kiếm, lưu trữ nhật ký thay đổi và các đường dẫn tiếp thị không liên quan nếu chúng nằm ngoài cơ sở tri thức. Sử dụng một sơ đồ trang web và các liên kết điều hướng cùng nhau khi bạn cần so sánh các URL đã được công bố với các trang có thể truy cập. Sơ đồ trang web là một gợi ý khám phá, không phải bằng chứng rằng mỗi trang được liệt kê là hữu ích hoặc hiện tại.
Sử dụng một scrape một trang khi một URL đã biết là toàn bộ đầu vào. Sử dụng Crawl rộng toàn bộ trang web khi bạn muốn khám phá có giới hạn từ một trang bắt đầu. Các yêu cầu Crawl hiện tại tiết lộ maxDepth, maxPages, includeUrls, excludeUrls, ignoreQuery, và onlyMainContent; chọn các ranh giới bảo thủ và kiểm tra danh sách trang đã khám phá trước khi lập chỉ mục. Để có hướng dẫn riêng về phía cơ sở dữ liệu vector, xem Crawl đến Pinecone.
Bước 2: Crawl một trang thành Markdown
Tài liệu SDK Python được ghi lại cung cấp submit_scrape_task_sync và get_markdown(). Yêu cầu này phù hợp cho một URL đã biết với thời gian phản hồi dự đoán:
import os from nstdata_ai_crawl import Format, NstDataClient, ScrapeRequestDto with NstDataClient(os.environ["NSTDATA_API_TOKEN"]) as client: result = client.submit_scrape_task_sync(ScrapeRequestDto( url="https://docs.example.com/api/authentication", formats=[Format.MARKDOWN], timeout=60_000, onlyMainContent=True, )) markdown = result.data.get_markdown() if not markdown or len(markdown.strip()) < 200: raise ValueError("Crawl returned empty or unexpectedly short content")
Một trao đổi HTTP thành công không giống với một trang có thể sử dụng. Kiểm tra sự thành công của nhiệm vụ, độ dài của nội dung, tiêu đề mong đợi hoặc một cụm từ đã biết, và siêu dữ liệu trả về trước khi bạn đánh dấu trang đã được chấp nhận. Đối với các trang chậm hơn, hãy sử dụng luồng tác vụ bất đồng bộ và lấy ID đã trả về; hướng dẫn chính thức cũng ghi lại tiến trình trang và tài liệu tham khảo kết quả. Đừng giả định rằng một callback webhook tồn tại: tài liệu hiện tại nói rằng webhook không được hỗ trợ.
Đối với các trang được kết xuất bằng JavaScript, trước tiên kiểm tra xem văn bản cần thiết có bị thiếu trong đầu ra bình thường hay không. Chỉ bật tính năng kết xuất trình duyệt hoặc một hành động/chờ đã được ghi lại khi một trang thực sự cần nó. Việc kết xuất thêm sẽ làm tăng độ trễ và có thể làm cho việc thu thập dữ liệu trở nên phức tạp hơn để chẩn đoán.
Bước 3: Chuẩn hóa và bảo tồn nguồn gốc
Trước khi chia nhỏ, hãy biến kết quả đã lấy thành một bản ghi ổn định. Giữ siêu dữ liệu nguồn tách biệt với văn bản nội dung:
from dataclasses import dataclass from datetime import datetime, timezone from hashlib import sha256 @dataclass class PageRecord: url: str title: str markdown: str crawled_at: str content_hash: str def make_record(url: str, title: str, markdown: str) -> PageRecord: normalized = "\n".join(line.rstrip() for line in markdown.splitlines()).strip() return PageRecord( url=url, title=title or url, markdown=normalized, crawled_at=datetime.now(timezone.utc).isoformat(), content_hash=sha256(normalized.encode("utf-8")).hexdigest(), )
Một hàm băm nội dung cho phép quy trình bỏ qua các trang không thay đổi. Chỉ chuẩn hóa những tiếng ồn thực sự không liên quan: bảo tồn tiêu đề, khung mã, bảng tham số, cảnh báo và liên kết nguồn. Việc loại bỏ mẫu cố định không phải là quyền để viết lại các sự kiện của tác giả.
Bước 4: Chia nhỏ theo cấu trúc tài liệu
Đối với tài liệu kỹ thuật, hãy chia nhỏ theo tiêu đề trước khi áp dụng giới hạn token hoặc ký tự. Một đoạn văn nên mang theo đường dẫn tiêu đề của nó để một đoạn văn được thu hồi vẫn có ngữ cảnh:
def heading_sections(markdown: str): current = [] body = [] in_fence = False for line in markdown.splitlines(): if line.strip().startswith("```"): in_fence = not in_fence if line.startswith("#") and not in_fence and body: yield " / ".join(current), "\n".join(body).strip() body = [] if line.startswith("#") and not in_fence: level = len(line) - len(line.lstrip("#")) current = current[:level - 1] + [line[level:].strip()] body.append(line) if body: yield " / ".join(current), "\n".join(body).strip()
Trình chia nhỏ nhỏ này giữ các ví dụ được phân vùng lại với nhau nhưng không thực thi giới hạn token. Thêm một lần chạy thứ hai nhận thức về tokenizer cho các phần dài và thử nghiệm nó với mẫu mã dài nhất của bạn. Người dùng framework có thể so sánh tiêu chuẩn đó với các khái niệm chia nhỏ văn bản LangChain. Tránh việc đoán kích thước đoạn toàn cầu: so sánh việc thu hồi trên các câu hỏi yêu cầu chi tiết tham số, bối cảnh cắt ngang và mã.
Bước 5: Nhúng và lưu trữ bản ghi
Tạo một nhúng cho mỗi đoạn và ghi lại văn bản và siêu dữ liệu cùng với nó. Chroma có thể duy trì một bộ sưu tập cục bộ; các API upsert và query của nó được ghi lại trong hướng dẫn bộ sưu tập Chroma. Mô hình nhà cung cấp và kích thước nhúng Chroma phải đồng ý nếu bạn truyền các vector đã được tính toán trước. Hướng dẫn nhúng OpenAI hiện tại ghi lại điểm kết nối văn bản thành vector được sử dụng trong ví dụ này.
import chromadb from openai import OpenAI client = OpenAI() vector_db = chromadb.PersistentClient(path="./chroma-data") collection = vector_db.get_or_create_collection("public_docs") texts = [section_text] embedding = client.embeddings.create( model="text-embedding-3-small", input=texts, ).data[0].embedding collection.upsert( ids=[chunk_id], embeddings=[embedding], documents=texts, metadatas=[{ "source_url": page.url, "title": page.title, "heading_path": heading_path, "crawled_at": page.crawled_at, ```json "content_hash": page.content_hash, }], )
Trong môi trường sản xuất, gửi các embedding theo lô, chỉ thử lại lỗi nhà cung cấp tạm thời, và giới hạn kích thước lô theo giới hạn của nhà cung cấp. Làm cho các ID có tính quyết định, ví dụ sha256(canonical_url + heading_path + chunk_text). Khi một trang thay đổi, xóa ID các chunk của trang cũ trước khi chèn bộ mới, hoặc sử dụng một không gian tên có phiên bản và chuyển đổi sau khi xác thực.
Bước 6: Thu thập và trả lời với bằng chứng
Nhúng câu hỏi của người dùng với cùng một mô hình, truy vấn bộ sưu tập, và truyền các đoạn văn hàng đầu cùng với URL nguồn cho LLM. Yêu cầu câu trả lời trích dẫn các URL đã cung cấp và cho biết khi bằng chứng thu thập được không đủ. Đầu ra truy xuất là bằng chứng cần kiểm tra, không phải là chứng minh rằng câu trả lời là đúng.
Một tập đánh giá hữu ích bao gồm các sự thật trực tiếp, câu hỏi tham số API, các câu hỏi mà câu trả lời trải dài qua hai phần, và các câu hỏi mà nên trả về “không tìm thấy.” Theo dõi tỷ lệ truy xuất và độ chính xác của trích dẫn tách biệt với độ trôi chảy của câu trả lời.
Bước 7: Giữ cho chỉ mục luôn mới
Lên lịch thu crawls theo mức độ biến động của nguồn và hậu quả của các câu trả lời đã cũ. Lưu giữ hash thành công cuối cùng cho mỗi URL chuẩn. Nếu một crawl thành công mới có cùng hash, bỏ qua việc nhúng lại. Nếu nó khác, thay thế các chunk cũ. Đối xử với một trường hợp timeout hoặc 403 tạm thời như không xác định, không phải là chứng minh rằng nguồn đã bị xóa. Xác nhận sự xóa với các kiểm tra lặp lại hoặc thay đổi sơ đồ trang chính thức trước khi xóa nội dung đã chỉ mục.
Một cron job có thể khởi động một lệnh nhập Python, nhưng công việc nên ghi lại một bản ghi chạy: ID chạy, thời gian bắt đầu/kết thúc, các URL được phát hiện, các trang đã chấp nhận, các hash đã thay đổi, các trang đã xóa, các URL thất bại, và số lượng nhúng. Để có cái nhìn tổng quan về những gì Crawl xử lý so với công việc thuộc về ứng dụng, xem hướng dẫn về ngăn xếp dữ liệu web của Nstdata.
Chi phí, quy mô và các chế độ thất bại thông thường
Một số lượng trang không phải là ước tính chi phí hoàn chỉnh. Bao gồm yêu cầu Crawl, lưu lượng proxy tính phí riêng khi được sử dụng, token nhúng cho nội dung đã thay đổi, ghi/lưu trữ vector, và sử dụng mô hình thời gian trả lời. Công thức riêng của bạn nên là:
chi phí nhập hàng tháng = đơn vị crawl thành công + lưu lượng proxy + token nhúng nội dung đã thay đổi + lưu trữ vector + lịch trình/hoạt động
Đo số trang đã chấp nhận thay vì các URL đã gửi. Các lỗi phổ biến bao gồm lập chỉ mục các trang trống, kích thước nhúng không phù hợp, để lại các vector đã cũ sau một cập nhật, mất URL nguồn trong quá trình chia nhỏ, và chỉ đo chất lượng câu trả lời trong khi bỏ qua các trường hợp truy xuất bị thiếu. Thêm một cổng xác thực trước khi lập chỉ mục và một bài kiểm tra nguồn đối kháng trước khi đưa kết quả crawl đến mô hình.
Danh sách kiểm tra nhập đầy đủ
- Giữ một danh sách cho phép và một kho URL với các URL chuẩn.
- Xác thực trạng thái, độ hoàn chỉnh của thân, tiêu đề, và metadata nguồn sau mỗi lần crawl.
- Giữ nguyên các tiêu đề, mã, bảng, và hash nội dung thông qua chuẩn hóa.
- Sử dụng ID chunk có tính quyết định và giữ lại bản đồ trang đến chunk.
- Chỉ nhúng lại nội dung đã thay đổi; phân biệt các trang đã xóa với các yêu cầu thất bại.
- Đánh giá truy xuất, trích dẫn, hành vi câu trả lời đã cũ, và chi phí trên một tập câu hỏi cố định.
Đối với các mẫu bộ sưu tập liên quan, xem hướng dẫn tự động hóa trình duyệt của Nstdata.
Kết luận
Dữ liệu web mới đến được câu trả lời RAG chỉ sau khi đường ống của bạn khám phá, thu thập, xác thực, chuẩn hóa, chia nhỏ, nhúng, và lập chỉ mục nó. Nstdata Crawl có thể cung cấp lớp thu thập trang và chuyển đổi Markdown; ứng dụng vẫn phải sở hữu nguồn gốc, chính sách cập nhật, vòng đời vector, và kiểm tra câu trả lời. Bắt đầu với một tập hợp nhỏ các URL đại diện, chứng minh độ phủ và hành vi xóa, và sau đó mở rộng lịch trình.
Câu hỏi thường gặp
Q: Dữ liệu nhập RAG là gì?
Nhập dữ liệu RAG chuyển đổi các tài liệu nguồn thành các bản ghi đã xác thực, đã chia nhỏ, đã nhúng mà hệ thống truy xuất có thể tìm kiếm.
Q: Làm thế nào để giữ dữ liệu web trong RAG luôn mới?
Theo dõi các URL chuẩn và hash nội dung, thu crawl theo lịch trình phù hợp với mức độ biến động của nguồn, và thay thế hoặc xóa các chunk cũ chỉ sau khi xác thực trạng thái nguồn mới.
Q: RAG có thể sử dụng trực tiếp các trang web trực tiếp không?
Một chỉ mục RAG không tự động làm mới từ một trang web trực tiếp; một công cụ thu thập và công việc nhập phải lấy và lập chỉ mục nội dung mới trước khi truy xuất có thể sử dụng nó.
Q: Tôi nên cập nhật cơ sở tri thức RAG bao lâu một lần?
Chọn một khoảng thời gian làm mới từ mức độ thường xuyên thay đổi của nguồn và tác động của một câu trả lời đã cũ, sau đó đo tỷ lệ thay đổi thực tế và độ trễ cập nhật.
Q: Crawl có thay thế việc chia nhỏ và nhúng không?
Không. Crawl lấy và biến đổi các trang; ứng dụng của bạn vẫn chọn các đoạn, mô hình nhúng, lưu trữ vector, quy tắc cập nhật và đánh giá.





