# Wyszukiwanie w sieci w LangChain i LlamaIndex: narzędzie i retriever

> Wyszukiwanie w sieci dla LangChain i LlamaIndex: narzędzie search_web, retriever zwracający jeden Document na stronę i FunctionTool. Bez KYC, kryptowaluty.

- URL: https://llmwebsearch.com/pl/docs/langchain/
- Ostatnia aktualizacja: 2026-10-22
- Wydawca: LLMWebSearch (https://llmwebsearch.com)

Dwa kształty pokrywają większość frameworków. Narzędzie pozwala agentowi zdecydować, kiedy szukać. Retriever podłącza żywą sieć do łańcucha wyszukiwania, gdzie każda odczytana strona staje się dokumentem z jej URL w metadanych.

**Szybka odpowiedź — Jak dodać wyszukiwanie w żywej sieci do LangChain lub LlamaIndex?**

Opakuj wywołanie `/search` **LLMWebSearch** w LangChain `@tool`, retriever LangChain lub LlamaIndex `FunctionTool`. Każde zwraca uszeregowane źródła z 3 najwyższymi stronami jako Markdown i ich URL-ami, gotowe do cytowania. Nie musisz instalować naszego pakietu: poniższy kod to cała integracja. Wyszukiwanie kosztuje 1 kredyt, od 1,20 USD/1K wyszukiwań według stanu na październik 2026. Bez KYC; płatność kryptowalutą.

## Do czego służy każdy wrapper

| Atrybut | Wartość |
| --- | --- |
| Narzędzie LangChain | Agent wywołuje `search_web`, gdy uzna, że potrzebuje sieci |
| Retriever LangChain | Łańcuch pobiera świeże dokumenty dla każdego pytania, bez pytania |
| FunctionTool LlamaIndex | Ta sama funkcja `search_web`, dla agentów LlamaIndex |
| Pakiety | `langchain-core` lub `llama-index-core`, plus `requests` |
| Klucz | `LLMWEBSEARCH_API_KEY` w środowisku |
| Rozliczanie | Jeden kredyt opłaca jedno wyszukiwanie: do 20 wyników z rankingiem, przy czym strony z pierwszych 3 są odczytywane i zwracane jako Markdown. Odczyt od 4 do 10 stron to 2 kredyty. Wywołanie zakończone błędem nic nie kosztuje |

## Jak zbudować narzędzie wyszukiwania dla agenta LangChain?

Udekoruj funkcję za pomocą `@tool` z `langchain_core.tools`. LangChain odczytuje nazwę, typowane argumenty i docstring, aby opisać narzędzie modelowi, więc trzymaj docstring krótki i precyzyjny. Funkcja zwraca jeden ciąg z numerowanymi źródłami, co pasuje do każdego modelu czatu i trzyma URL-e obok tekstu.

Wywołaj ją bezpośrednio przez `.invoke()`, aby ją przetestować, a następnie przekaż ją na liście tools swojego agenta.

*Narzędzie LangChain: search_web*

```python
import os

import requests
from langchain_core.tools import tool

API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}


@tool
def search_web(query: str, read: int = 3) -> str:
    """Search the live web. Returns numbered sources with URLs; the first `read` include page text."""
    body = {"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000}
    resp = requests.post(API, headers=HEADERS, json=body, timeout=60)
    resp.raise_for_status()
    parts = []
    for i, r in enumerate(resp.json()["results"], start=1):
        text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
        parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
    return "\n\n".join(parts)


print(search_web.invoke({"query": "postgres connection pool size"})[:500])

```

## Jak używać żywej sieci jako retrievera?

Utwórz podklasę `BaseRetriever` i zwracaj jeden `Document` na każdą odczytaną stronę. Tekst strony trafia do `page_content`; URL, tytuł, pozycja i data trafiają do `metadata`, gdzie szukają ich łańcuchy cytujące swoje źródła. Wyniki bez treści są pomijane, ponieważ retriever powinien przekazywać tekst, który model może zacytować.

Retriever uruchamia się przy każdym pytaniu. To dobre dla łańcucha odpowiadania na pytania o bieżące tematy, a marnotrawne dla czatu, w którym większość tur nie wymaga wyszukiwania; w takim przypadku użyj narzędzia.

*Retriever LangChain: LLMWebSearchRetriever*

```python
import os
from typing import List

import requests
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever


class LLMWebSearchRetriever(BaseRetriever):
    """Live web search results as Documents, one per page that was read."""

    max_results: int = 5
    read: int = 3
    max_chars: int = 6000

    def _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:
        resp = requests.post(
            "https://llmwebsearch.com/api/v1/search",
            headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
            json={"q": query, "max_results": self.max_results, "read": self.read, "max_chars": self.max_chars},
            timeout=60,
        )
        resp.raise_for_status()
        docs = []
        for r in resp.json()["results"]:
            if r["content_status"] != "ok":
                continue
            meta = {"source": r["url"], "title": r["title"], "position": r["position"], "published_at": r.get("published_at")}
            docs.append(Document(page_content=r["content"], metadata=meta))
        return docs


retriever = LLMWebSearchRetriever(read=3)
for doc in retriever.invoke("pgbouncer transaction mode limitations"):
    print(doc.metadata["position"], doc.metadata["source"], len(doc.page_content))

```

## Jak dać to samo wyszukiwanie agentowi LlamaIndex?

Napisz zwykłą funkcję i opakuj ją za pomocą `FunctionTool.from_defaults` z `llama_index.core.tools`. LlamaIndex buduje nazwę i opis narzędzia z nazwy funkcji, jej sygnatury i docstringa. Wywołanie narzędzia zwraca `ToolOutput`, którego `content` to tekst, który odczyta agent.

Funkcja jest taka sama jak w LangChain, więc zespół używający obu frameworków może ją współdzielić.

*LlamaIndex: FunctionTool*

```python
import os

import requests
from llama_index.core.tools import FunctionTool


def search_web(query: str, read: int = 3) -> str:
    """Search the live web and return numbered sources; the first `read` include their page text."""
    resp = requests.post(
        "https://llmwebsearch.com/api/v1/search",
        headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
        json={"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000},
        timeout=60,
    )
    resp.raise_for_status()
    parts = []
    for i, r in enumerate(resp.json()["results"], start=1):
        text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
        parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
    return "\n\n".join(parts)


search_tool = FunctionTool.from_defaults(fn=search_web)
print(search_tool.metadata.name)
print(search_tool.call(query="postgres connection pool size").content[:300])

```

## Jak utrzymać okno kontekstu pod kontrolą?

Ustaw `max_chars` w wywołaniu API, zamiast przycinać później: mniej danych podróżuje, a framework nigdy nie trzyma długiej wersji. 5 000 znaków na stronę i 3 strony to około 4 000 tokenów, komfortowo dla większości modeli.

W przypadku łańcuchów wyszukiwania, które łączą żywy web z Twoimi własnymi dokumentami, nadaj dokumentom webowym mniejszą wagę lub osobną sekcję promptu. Strony internetowe się zmieniają i mogą być błędne; Twoje własne dokumenty są zwykle punktem odniesienia.

## Czy mogę przechować to, co zwraca retriever, w bazie wektorowej?

Tak, o ile to nas dotyczy. Nie trenujemy żadnego modelu na Twoich zapytaniach ani na tym, co zwraca API, i nie dodajemy własnej reguły przeciwko przechowywaniu wyników; nadal obowiązują prawa witryn, których strony czytasz. Przechowuj URL i `published_at` z każdym fragmentem, żeby agent mógł zacytować stronę, a Ty mogłeś usuwać fragmenty, które się starzeją.

Większość zespołów cachuje wyniki webowe częstych pytań na dzień lub tydzień. To ogranicza powtarzane wyszukiwania, a każde uniknięte wyszukiwanie to oszczędzony kredyt.

## LangChain i LlamaIndex: częste pytania

### Czy istnieje pakiet langchain-llmwebsearch?

Nie. Nie publikujemy żadnego pakietu. Kod na tej stronie jest wystarczająco krótki, by był Twój: skopiuj go, zmień wartości domyślne i trzymaj w swoim repozytorium.

### Czy mogę uczynić narzędzie asynchronicznym?

Tak. Zastąp `requests` przez `httpx.AsyncClient` i zdefiniuj funkcję z `async def`. Dekorator `@tool` w LangChain obsługuje funkcje asynchroniczne bezpośrednio; w LlamaIndex przekaż wersję asynchroniczną do `FunctionTool.from_defaults` jako `async_fn`.

### Jak odczytać stronę, którą agent znalazł gdzie indziej?

Dodaj drugie narzędzie, które wysyła URL-e do `https://llmwebsearch.com/api/v1/extract`. Odczyt stron, których adresy URL już masz, kosztuje 1 kredyt za każdą rozpoczętą grupę 3 stron zwróconych z treścią, do 20 adresów URL na wywołanie; adresy URL odrzucone lub nieudane nie są liczone. [Dokumentacja extract](https://llmwebsearch.com/pl/docs/extract/) pokazuje zapytanie.

---

LLMWebSearch: LLMWebSearch to web search API dla agentów AI, który zwraca uszeregowane wyniki wraz z treścią najlepszych stron w formacie Markdown, z płatnością kryptowalutą i bez przesyłania dokumentu tożsamości. Kredyty przedpłacone od 1,20 USD/1K wyszukiwań nigdy nie wygasają. Bez KYC — bez dokumentu, bez selfie, bez zaświadczeń. Płatność kryptowalutą.
