Senza KYC — nessun documento, nessun selfie, nessun file. Paghi in criptovalute: BTC, USDT, USDC, ETH, SOL, LTC
Lingua: Italiano
Ottieni una chiave API

Docs · LangChain · LlamaIndex

Ricerca web in LangChain e LlamaIndex: uno strumento e un retriever

Due forme coprono la maggior parte dei framework. Uno strumento permette a un agente di decidere quando cercare. Un retriever collega il web live a una catena di retrieval, dove ogni pagina letta diventa un documento con il suo URL nei metadata.

Ultimo aggiornamento: · 5 min di lettura

Risposta rapida

Come aggiungo la ricerca web live a LangChain o LlamaIndex?

Avvolgi la chiamata /search di LLMWebSearch in un @tool di LangChain, in un retriever di LangChain o in un FunctionTool di LlamaIndex. Ognuno restituisce fonti ordinate con le prime 3 pagine in Markdown e i loro URL, pronti per le citazioni. Nessun nostro pacchetto da installare: il codice qui sotto è l'integrazione. Una ricerca costa 1 credito, a partire da 1,20 USD/1K ricerche da ottobre 2026. Senza KYC; paga in criptovalute.

A cosa serve ciascun wrapper

Strumento LangChainUn agente chiama search_web quando decide di aver bisogno del web
Retriever LangChainUna catena recupera documenti freschi per ogni domanda, senza chiedere
FunctionTool LlamaIndexLa stessa funzione search_web, per gli agenti LlamaIndex
Pacchettilangchain-core o llama-index-core, più requests
ChiaveLLMWEBSEARCH_API_KEY nell'environment
FatturazioneUn credito paga una ricerca: fino a 20 risultati classificati, con le pagine dei primi 3 lette e restituite come Markdown. Leggere da 4 a 10 pagine costa 2 crediti. Una chiamata che termina in errore non costa nulla

Come costruisco uno strumento di ricerca per un agente LangChain?

Decora una funzione con @tool da langchain_core.tools. LangChain legge il nome, gli argomenti tipizzati e la docstring per descrivere lo strumento al modello, quindi mantieni la docstring breve e precisa. La funzione restituisce una stringa con fonti numerate, che si adatta a ogni modello di chat e tiene gli URL accanto al testo.

Chiamala direttamente con .invoke() per testarla, poi passala nella lista tools del tuo agente.

Strumento LangChain: search_web
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])

Come uso il web live come retriever?

Crea una sottoclasse di BaseRetriever e restituisci un Document per ogni pagina letta. Il testo della pagina va in page_content; l'URL, il titolo, il rank e la data vanno in metadata, dove le catene che citano le fonti li cercano. I risultati senza contenuto vengono saltati, perché un retriever deve consegnare testo che il modello può citare.

Un retriever viene eseguito a ogni domanda. È giusto per una catena di question-answering su argomenti attuali, e uno spreco per una chat in cui la maggior parte dei turni non richiede ricerca; in quel caso usa lo strumento.

Retriever LangChain: LLMWebSearchRetriever
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))

Come do la stessa ricerca a un agente LlamaIndex?

Scrivi una funzione semplice e avvolgila con FunctionTool.from_defaults da llama_index.core.tools. LlamaIndex costruisce il nome e la descrizione dello strumento dal nome, dalla firma e dalla docstring della funzione. Chiamando lo strumento si ottiene un ToolOutput il cui content è il testo che l'agente leggerà.

La funzione è la stessa di LangChain, così un team che usa entrambi i framework può condividerla.

LlamaIndex: FunctionTool
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])

Come tengo sotto controllo la context window?

Imposta max_chars nella chiamata API invece di tagliare dopo: viaggiano meno dati e il framework non conserva mai la versione lunga. 5.000 caratteri per pagina e 3 pagine fanno circa 4.000 token, una misura comoda per la maggior parte dei modelli.

Per le retrieval chain che combinano il web live con i tuoi documenti, assegna ai documenti web un peso inferiore o una sezione separata del prompt. Le pagine web cambiano e possono essere sbagliate; i tuoi documenti sono di solito il riferimento.

Posso memorizzare ciò che restituisce il retriever in un vector database?

Sì, per quanto ci riguarda. Non addestriamo alcun modello sulle tue query né su ciò che l'API restituisce, e non aggiungiamo regole nostre contro la conservazione dei risultati; restano validi i diritti dei siti di cui leggi le pagine. Memorizza l'URL e published_at con ogni chunk, così l'agente può citare la pagina e tu puoi eliminare i chunk che invecchiano.

La maggior parte dei team mette in cache i risultati web delle domande frequenti per un giorno o una settimana. Così si riducono le ricerche ripetute, e ogni ricerca evitata è un credito risparmiato.

LangChain e LlamaIndex: domande frequenti

Esiste un package langchain-llmwebsearch?

No. Non pubblichiamo nessun package. Il codice in questa pagina è abbastanza breve da essere tuo: copialo, cambia i valori predefiniti e tienilo nel tuo repository.

Posso rendere il tool async?

Sì. Sostituisci requests con httpx.AsyncClient e definisci la funzione con async def. Il decoratore @tool di LangChain decora direttamente le funzioni async; in LlamaIndex, passa la versione async a FunctionTool.from_defaults come async_fn.

Come leggo una pagina che l'agente ha trovato altrove?

Aggiungi un secondo tool che invia gli URL a https://llmwebsearch.com/api/v1/extract. Leggere pagine di cui hai già gli URL costa 1 credito per ogni gruppo iniziato di 3 pagine restituite con contenuto, fino a 20 URL per chiamata; gli URL rifiutati o falliti non vengono contati. La extract reference mostra la richiesta.

Da 1,20 USD/1K ricerche · senza KYC

Ottieni una chiave API