Tanpa KYC — tanpa identitas, tanpa selfie, tanpa dokumen. Bayar dengan kripto: BTC, USDT, USDC, ETH, SOL, LTC
Bahasa: Bahasa Indonesia
Dapatkan API key

Dokumentasi · LangChain · LlamaIndex

LangChain dan LlamaIndex: web page loader dan tool read_url

Dua cara menggunakan API di stack AI Python: memuat halaman sebagai dokumen untuk retrieval, atau memberi agent sebuah tool read_url. 20 baris kode perekat yang sama melayani LangChain dan LlamaIndex.

Terakhir diperbarui: · 4 menit baca

Jawaban singkat

Bagaimana cara memuat halaman web ke LangChain atau LlamaIndex sebagai Markdown yang bersih?

Panggil endpoint /read milik WebReaderAPI dan bungkus setiap jawaban dalam Document: Markdown sebagai content, final_url dan title sebagai metadata. Untuk agent, tampilkan panggilan yang sama sebagai tool read_url. Setiap halaman berbiaya 1 kredit, 2 kredit dengan browser, mulai dari US$0,07/1K halaman per Oktober 2026. Tidak perlu paket dari kami. Tanpa KYC; bayar dengan kripto.

Mengapa dokumen Markdown daripada HTML mentah?

Karena retrieval bekerja pada teks, dan Markdown mempertahankan struktur yang penting sambil membuang sisanya. Heading tetap ada, sehingga splitter dapat memotong pada pergantian topik. List dan tabel tetap ada, sehingga langkah-langkah dan spesifikasi tetap menyatu. Navigasi, cookie banner, dan iklan hilang, sehingga tidak mencemari embeddings Anda atau membuang token.

Metadata berasal dari panggilan yang sama: final_url sebagai sumber untuk dikutip, title, published_at dan language untuk penyaringan.

reader.py: helper bersama (simpan di samping kode Anda)
import os

import requests

API = "https://webreaderapi.com/api/v1/read"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


class PageError(Exception):
    pass


def read_page(url, **options):
    resp = requests.get(API, headers=HEADERS, params={"url": url, **options}, timeout=75)
    body = resp.json()
    if resp.status_code != 200:
        raise PageError(body["error"]["code"])
    return body

Bagaimana cara membuat document loader LangChain?

Ubah setiap halaman menjadi langchain_core.documents.Document, lalu pisahkan berdasarkan heading dengan MarkdownHeaderTextSplitter dari paket langchain-text-splitters. Setiap chunk menyimpan jalur heading di metadata-nya, dan Anda menambahkan URL sumber agar setiap jawaban dapat menunjuk kembali ke halamannya.

Halaman yang dilewati, seperti yang ditolak oleh robots.txt, memunculkan PageError beserta kodenya; catat di log lalu lanjutkan.

LangChain: memuat dan memisahkan halaman
from langchain_core.documents import Document
from langchain_text_splitters import MarkdownHeaderTextSplitter

from reader import PageError, read_page

splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("#", "h1"), ("##", "h2"), ("###", "h3")])


def load_pages(urls):
    chunks = []
    for url in urls:
        try:
            page = read_page(url)
        except PageError as exc:
            print("skipped", url, exc)
            continue
        for part in splitter.split_text(page["markdown"]):
            part.metadata.update({"source": page["final_url"], "title": page.get("title", "")})
            chunks.append(part)
    return chunks


docs = load_pages(["https://example.com/docs/install", "https://example.com/docs/configure"])
print(len(docs), "chunks", isinstance(docs[0], Document) if docs else "")

Bagaimana cara memberi agent LangChain sebuah tool read_url?

Hiasi sebuah fungsi dengan @tool dari langchain_core.tools. Docstring menjadi deskripsi tool yang dibaca model, jadi jelaskan apa yang dikembalikan tool dan kapan harus menggunakannya. Kembalikan teks biasa: baris judul, sumber, dan Markdown, dipotong dengan max_chars agar sesuai model Anda.

Ikat tool ke model chat apa pun yang mendukung tool calling, atau teruskan ke konstruktor agent Anda. Model kemudian memanggil read_url dengan URL dari percakapan atau dari hasil pencarian.

LangChain: tool read_url
import os

from langchain.chat_models import init_chat_model
from langchain_core.tools import tool

from reader import PageError, read_page


@tool
def read_url(url: str, max_chars: int = 20000) -> str:
    """Read a public web page and return its main content as Markdown, with its title and source URL."""
    try:
        page = read_page(url, max_chars=max_chars)
    except PageError as exc:
        return "Could not read the page: " + str(exc)
    return "# " + (page.get("title") or url) + "\nSource: " + page["final_url"] + "\n\n" + page["markdown"]


model = init_chat_model(os.environ.get("CHAT_MODEL", "openai:gpt-4.1-mini")).bind_tools([read_url])
reply = model.invoke("Summarise https://example.com/blog/first-post in three bullet points.")
print(reply.tool_calls)

Bagaimana cara melakukan hal yang sama di LlamaIndex?

LlamaIndex menggunakan kelas Document miliknya sendiri dengan text dan metadata, serta FunctionTool.from_defaults untuk mengubah fungsi menjadi tool. Helper-nya tetap sama. Bangun indeks dari dokumen dengan VectorStoreIndex.from_documents, yang menggunakan embedding model apa pun yang disebutkan di pengaturan LlamaIndex Anda.

LlamaIndex: mengindeks crawl, dan tool read_url
import os
import time

import requests
from llama_index.core import Document, VectorStoreIndex
from llama_index.core.tools import FunctionTool

from reader import HEADERS, PageError, read_page


def crawl_pages(start_url, limit=200):
    job = requests.post("https://webreaderapi.com/api/v1/crawl", headers=HEADERS, json={"url": start_url, "limit": limit}, timeout=30).json()
    pages, cursor = [], None
    while True:
        params = {"cursor": cursor} if cursor else {}
        res = requests.get("https://webreaderapi.com/api/v1/jobs/" + job["job_id"], headers=HEADERS, params=params, timeout=30).json()
        pages += [r for r in res["results"] if "error" not in r]
        cursor = res.get("next_cursor")
        if not cursor and res["status"] == "done":
            return pages
        if not cursor:
            time.sleep(5)


pages = crawl_pages("https://docs.example.com/")
docs = [Document(text=p["markdown"], metadata={"source": p["final_url"], "title": p.get("title", "")}) for p in pages]
index = VectorStoreIndex.from_documents(docs)
print(index.as_query_engine().query("How do I install the product?"))


def read_url(url: str, max_chars: int = 20000) -> str:
    """Read a public web page and return its main content as Markdown."""
    try:
        return read_page(url, max_chars=max_chars)["markdown"]
    except PageError as exc:
        return "Could not read the page: " + str(exc)


read_tool = FunctionTool.from_defaults(fn=read_url, name="read_url")
print(os.environ.get("CHAT_MODEL", "set CHAT_MODEL for your agent"), read_tool.metadata.name)

Seberapa besar crawl yang dibutuhkan indeks RAG kecil?

Lebih kecil dari yang Anda duga. Dokumentasi sebuah produk sering kali hanya beberapa ratus halaman, dan crawl dengan include_paths diatur ke bagian docs hanya membaca halaman tersebut. Dengan 1 kredit per halaman, situs docs 300 halaman berbiaya sekitar 300 kredit; 10.000 halaman (US$3,75) menyegarkannya berkali-kali.

Lakukan crawl ulang sesuai jadwal yang cocok dengan seberapa sering sumber berubah, dan bandingkan final_url serta word_count dengan run sebelumnya untuk hanya me-embed ulang halaman yang berubah. Kredit prabayar tidak pernah kedaluwarsa: halaman yang belum digunakan tetap ada di akun Anda sampai Anda memakainya.

LangChain dan LlamaIndex: pertanyaan umum

Apakah ada paket WebReaderAPI untuk LangChain atau LlamaIndex?

Tidak. Helper dan tool di halaman ini adalah keseluruhan integrasinya, jadi Anda dapat menyesuaikannya dengan bebas. WebReaderAPI adalah API HTTPS biasa yang dapat dipanggil oleh klien HTTP Python apa pun.

Versi LangChain mana yang dibutuhkan?

Versi terbaru apa pun yang memiliki langchain_core, langchain-text-splitters dan init_chat_model. Dekorator tool dan kelas Document tetap stabil di berbagai rilis terbaru.

Bagaimana cara menghindari membaca ulang halaman yang tidak berubah?

Simpan final_url, word_count dan tanggal setiap pembacaan. Baca ulang sesuai jadwal, dan embed ulang sebuah halaman hanya ketika jumlah kata atau hash kontennya berubah. Setiap pembacaan ulang berbiaya satu kredit, jadi pilih ritme yang cocok dengan sumbernya.

Bagaimana jika beberapa halaman ditolak?

Halaman tersebut memunculkan PageError dengan kode seperti blocked_by_robots, dan tidak dikenakan biaya. Jika suatu situs menolak permintaan kami, kami mengembalikan jawabannya: kami tidak pernah menyelesaikan CAPTCHA, masuk ke akun, atau mencoba mengatasi blokir atau paywall.

Mulai dari US$0,07/1K halaman · tanpa KYC

Dapatkan API key