Bez KYC — bez dowodu, bez selfie, bez dokumentów. Płatność kryptowalutą: BTC, USDT, USDC, ETH, SOL, LTC
Język: Polski
Uzyskaj klucz API

Dokumentacja · LangChain · LlamaIndex

LangChain i LlamaIndex: loader stron internetowych i narzędzie read_url

Dwa sposoby użycia API w stosie AI w Pythonie: ładowanie stron jako dokumentów do wyszukiwania lub danie agentowi narzędzia read_url. Te same 20 linii kleju obsługują LangChain i LlamaIndex.

Ostatnia aktualizacja: · 4 min czytania

Szybka odpowiedź

Jak załadować strony internetowe do LangChain lub LlamaIndex jako czysty Markdown?

Wywołaj endpoint /read WebReaderAPI i opakuj każdą odpowiedź w Document: Markdown jako zawartość, final_url i tytuł jako metadane. Dla agentów udostępnij to samo wywołanie jako narzędzie read_url. Strony kosztują 1 kredyt każda, 2 z przeglądarką, od 0,07 USD/1K stron na dzień października 2026. Nie potrzebujesz żadnego naszego pakietu. Bez KYC; płatność kryptowalutą.

Dlaczego dokumenty Markdown, a nie surowy HTML?

Bo wyszukiwanie działa na tekście, a Markdown zachowuje strukturę, która ma znaczenie, i odrzuca resztę. Nagłówki zostają, więc splitter może ciąć na zmianach tematu. Listy i tabele zostają, więc kroki i specyfikacje trzymają się razem. Nawigacja, bannery cookies i reklamy znikają, więc nie zanieczyszczają Twoich embeddingów i nie marnują tokenów.

Metadane pochodzą z tego samego wywołania: final_url jako źródło do cytowania, title, published_at i language do filtrowania.

reader.py: wspólny helper (zapisz go obok swojego kodu)
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

Jak zbudować loader dokumentów LangChain?

Zamień każdą stronę w langchain_core.documents.Document, a następnie podziel ją według nagłówków za pomocą MarkdownHeaderTextSplitter z pakietu langchain-text-splitters. Każdy fragment zachowuje ścieżkę nagłówków w metadanych, a Ty dodajesz URL źródła, aby każda odpowiedź mogła wskazać swoją stronę.

Pominięte strony, takie jak te odrzucone przez robots.txt, zgłaszają PageError z kodem; zaloguj je i kontynuuj.

LangChain: ładowanie i dzielenie stron
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 "")

Jak dać agentowi LangChain narzędzie read_url?

Udekoruj funkcję za pomocą @tool z langchain_core.tools. Docstring staje się opisem narzędzia, który czyta model, więc napisz, co narzędzie zwraca i kiedy go używać. Zwracaj czysty tekst: linię tytułu, źródło i Markdown, przycięty za pomocą max_chars do rozmiaru Twojego modelu.

Powiąż narzędzie z dowolnym modelem czatu, który obsługuje tool calling, lub przekaż je do konstruktora agenta. Model wywołuje wtedy read_url z URL-em z rozmowy lub z wyniku wyszukiwania.

LangChain: narzędzie 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)

Jak zrobić to samo w LlamaIndex?

LlamaIndex używa własnej klasy Document z text i metadata oraz FunctionTool.from_defaults do zamiany funkcji w narzędzie. Helper pozostaje ten sam. Zbuduj indeks z dokumentów za pomocą VectorStoreIndex.from_documents, który używa modelu embeddingów wskazanego w ustawieniach LlamaIndex.

LlamaIndex: indeks crawlingu i narzędzie 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)

Jak duży crawling potrzebuje mały indeks RAG?

Mniejszy, niż myślisz. Dokumentacja produktu to często kilkaset stron, a crawling z include_paths ustawionym na sekcję dokumentacji czyta tylko je. Przy 1 kredycie za stronę witryna z dokumentacją licząca 300 stron kosztuje około 300 kredytów; 10 000 stron (3,75 USD) odświeża ją wiele razy.

Ponawiaj crawling zgodnie z harmonogramem dopasowanym do częstotliwości zmian źródła i porównuj final_url i word_count z poprzednim przebiegiem, aby ponownie osadzić tylko zmienione strony. Przedpłacone kredyty nigdy nie wygasają: niewykorzystane strony pozostają na Twoim koncie, dopóki ich nie wykorzystasz.

LangChain i LlamaIndex: najczęstsze pytania

Czy istnieje pakiet WebReaderAPI dla LangChain lub LlamaIndex?

Nie. Helper i narzędzie na tej stronie to cała integracja, więc możesz je dowolnie dostosować. WebReaderAPI to zwykłe API HTTPS, które może wywołać dowolny klient HTTP w Pythonie.

Której wersji LangChain to wymaga?

Dowolnej niedawnej z langchain_core, langchain-text-splitters i init_chat_model. Dekorator narzędzia i klasa Document są stabilne w ostatnich wydaniach.

Jak uniknąć ponownego odczytu stron, które się nie zmieniły?

Zapisuj final_url, word_count i datę każdego odczytu. Odczytuj ponownie zgodnie z harmonogramem i ponownie osadzaj stronę tylko wtedy, gdy zmieni się jej liczba słów lub hash treści. Każdy ponowny odczyt kosztuje kredyt, więc wybierz rytm dopasowany do źródła.

Co jeśli niektóre strony są odrzucane?

Zgłaszają PageError z kodem takim jak blocked_by_robots i nic nie kosztują. Jeśli witryna odrzuci nasze zapytanie, zwracamy jej odpowiedź: nigdy nie rozwiązujemy CAPTCHA, nie logujemy się do kont ani nie próbujemy obejść blokady lub paywalla.

Od 0,07 USD/1K stron · bez KYC

Uzyskaj klucz API