Snel antwoord
Hoe voeg ik live webzoekopdrachten toe aan LangChain of LlamaIndex?
Wik de /search-aanroep van LLMWebSearch** in een LangChain @tool, een LangChain-retriever of een LlamaIndex FunctionTool. Elk geeft gerangschikte bronnen terug met de top 3 pagina's als Markdown en hun URL's, klaar voor citaties. Je hoeft geen package van ons te installeren: de code hieronder is de integratie. Een zoekopdracht kost 1 credit, vanaf US$ 1,20/1K zoekopdrachten per oktober 2026. Zonder KYC; betalen met crypto.
Waarvoor elke wrapper dient
| LangChain-tool | Een agent roept search_web aan wanneer hij besluit het web nodig te hebben |
|---|---|
| LangChain-retriever | Een keten haalt voor elke vraag verse documenten op, zonder te vragen |
| LlamaIndex FunctionTool | Dezelfde search_web-functie, voor LlamaIndex-agents |
| Packages | langchain-core of llama-index-core, plus requests |
| Sleutel | LLMWEBSEARCH_API_KEY in de environment |
| Facturering | Eén credit betaalt één zoekopdracht: tot 20 gerangschikte resultaten, waarbij de pagina's van de eerste 3 worden gelezen en als Markdown teruggegeven. Het lezen van 4 tot 10 pagina's kost 2 credits. Een call die op een fout eindigt, kost niets |
Hoe bouw ik een zoektool voor een LangChain-agent?
Versier een functie met @tool uit langchain_core.tools. LangChain leest de naam, de getypeerde argumenten en de docstring om de tool aan het model te beschrijven, dus houd de docstring kort en precies. De functie geeft één string terug met genummerde bronnen, wat bij elk chatmodel past en de URL's naast de tekst houdt.
Roep hem direct aan met .invoke() om hem te testen, en geef hem daarna mee in de tools-lijst van je agent.
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])
Hoe gebruik ik het live web als retriever?
Subclass BaseRetriever en geef één Document terug per gelezen pagina. De paginatekst gaat in page_content; de URL, titel, rang en datum gaan in metadata, waar ketens die hun bronnen citeren ze zoeken. Resultaten zonder inhoud worden overgeslagen, want een retriever hoort tekst te overhandigen die het model kan citeren.
Een retriever draait bij elke vraag. Dat is goed voor een question-answering-keten over actuele onderwerpen, en verspilling voor een chat waarbij de meeste beurten geen zoekopdracht nodig hebben; gebruik in dat geval de tool.
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))
Hoe geef ik dezelfde zoekopdracht aan een LlamaIndex-agent?
Schrijf een gewone functie en wik** hem in met FunctionTool.from_defaults uit llama_index.core.tools. LlamaIndex bouwt de naam en beschrijving van de tool uit de naam, signatuur en docstring van de functie. Het aanroepen van de tool geeft een ToolOutput terug waarvan content de tekst is die de agent leest.
De functie is dezelfde als die voor LangChain, dus een team dat beide frameworks gebruikt, kan hem delen.
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])
Hoe houd ik het contextvenster onder controle?
Stel max_chars in bij de API-call in plaats van achteraf te trimmen: er reist minder data mee en het framework houdt de lange versie nooit vast. 5.000 tekens per pagina en 3 pagina's is ongeveer 4.000 tokens, comfortabel voor de meeste modellen.
Voor retrieval-chains die het live web combineren met je eigen documenten, geef webdocumenten een lager gewicht of een aparte prompt-sectie. Webpagina's veranderen en kunnen fout zijn; je eigen documenten zijn meestal de referentie.
Kan ik opslaan wat de retriever teruggeeft in een vector database?
Ja, wat ons betreft. We trainen geen enkel model op je zoekopdrachten of op wat de API teruggeeft, en we voegen geen eigen regel toe tegen het opslaan van resultaten; de rechten van de sites waarvan je pagina's leest, gelden nog steeds. Sla de URL en published_at op bij elk chunk, zodat de agent de pagina kan citeren en je chunks kunt laten vallen die verouderen.
De meeste teams cachen de webresultaten van veelgestelde vragen een dag of een week. Dat scheelt herhaalde zoekopdrachten, en elke vermeden zoekopdracht is een bespaarde credit.
LangChain en LlamaIndex: veelgestelde vragen
Is er een langchain-llmwebsearch-package?
Nee. We publiceren geen package. De code op deze pagina is kort genoeg om zelf te bezitten: kopieer hem, wijzig de defaults en houd hem in je repository.
Kan ik de tool async maken?
Ja. Vervang requests door httpx.AsyncClient en definieer de functie met async def. LangChain's @tool decoreert async-functies direct; geef in LlamaIndex de async-versie door aan FunctionTool.from_defaults als async_fn.
Hoe lees ik een pagina die de agent elders vond?
Voeg een tweede tool toe die URL's naar https://llmwebsearch.com/api/v1/extract stuurt. Het lezen van pagina's waarvan je de URL's al hebt, kost 1 credit per begonnen groep van 3 pagina's die met inhoud worden teruggegeven, tot 20 URL's per call; geweigerde of mislukte URL's tellen niet mee. De extract-referentie toont de request.