# LangChainとLlamaIndexでのWeb検索: ツールとretriever

> LangChainとLlamaIndex向けWeb検索: search_webツール、読み取ったページごとに1つのDocumentを返すretriever、そしてLlamaIndex FunctionTool。KYC不要、暗号資産で支払い。

- URL: https://llmwebsearch.com/ja/docs/langchain/
- 最終更新: 2026-10-22
- 発行者: LLMWebSearch (https://llmwebsearch.com)

2つの形でほとんどのフレームワークをカバーできます。ツールはエージェントが検索のタイミングを判断できるようにします。retrieverはライブWebを検索チェーンに接続し、読み取った各ページがメタデータにそのURLを持つドキュメントになります。

**クイック回答 — LangChainやLlamaIndexにライブWeb検索を追加するには？**

**LLMWebSearch**の`/search`呼び出しを、LangChain `@tool`、LangChain retriever、またはLlamaIndex `FunctionTool`でラップします。それぞれがランク付けされたソースを返し、上位3ページをMarkdownとそのURLで返すので、引用にすぐ使えます。インストールする当社のパッケージはありません: 以下のコードがその統合です。検索は1クレジットで、2026年10月時点で$1.20/1K検索から。KYC不要; 暗号資産で支払い。

## 各ラッパーの用途

| 属性 | 値 |
| --- | --- |
| LangChainツール | エージェントがWebが必要と判断したときに`search_web`を呼び出します |
| LangChain retriever | チェーンが質問ごとに新しいドキュメントを取得します。問い合わせる必要はありません |
| LlamaIndex FunctionTool | 同じ`search_web`関数を、LlamaIndexエージェント向けに使用 |
| パッケージ | `langchain-core`または`llama-index-core`、加えて`requests` |
| キー | 環境変数に`LLMWEBSEARCH_API_KEY` |
| 課金 | 1クレジットで検索1回分です。最大20件のランク付けされた結果を取得でき、上位3ページは本文抽出されてMarkdownで返されます。4〜10ページを読む場合は2クレジットです。エラーで終わった呼び出しは無料です |

## LangChainエージェント用の検索ツールを作るには？

`langchain_core.tools`から`@tool`で関数をデコレートします。LangChainは名前、型付き引数、docstringを読み取ってモデルにツールを説明するので、docstringは短く正確にしてください。関数は番号付きソースを含む1つの文字列を返すので、あらゆるチャットモデルに適しており、URLをテキストの近くに保てます。

`.invoke()`で直接呼び出してテストしてから、エージェントのtoolsリストに渡してください。

*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])

```

## ライブWebをretrieverとして使うには？

`BaseRetriever`をサブクラス化し、読み取ったページごとに1つの`Document`を返します。ページテキストは`page_content`に入れます; URL、タイトル、ランク、日付は`metadata`に入れます。引用元を示すチェーンはそこでそれらを探します。コンテンツのない結果はスキップされます。retrieverはモデルが引用できるテキストを渡すべきだからです。

retrieverは質問ごとに実行されます。これは時事トピックに関する質問応答チェーンには適していますが、ほとんどのターンで検索が不要なチャットには無駄です。その場合はツールを使用してください。

*LangChain retriever: 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))

```

## 同じ検索をLlamaIndexエージェントに与えるには？

プレーンな関数を書き、`llama_index.core.tools`から`FunctionTool.from_defaults`でラップします。LlamaIndexは関数の名前、シグネチャ、docstringからツールの名前と説明を構築します。ツールを呼び出すと`ToolOutput`が返され、その`content`がエージェントの読むテキストになります。

関数はLangChainのものと同じなので、両方のフレームワークを使うチームは共有できます。

*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])

```

## コンテキストウィンドウを制御するにはどうすればよいですか？

後から切り詰めるのではなく、API呼び出し時に`max_chars`を設定してください。転送されるデータが減り、フレームワークが長いバージョンを保持することもありません。1ページあたり5,000文字、3ページで約4,000トークンとなり、ほとんどのモデルにとって余裕のある量です。

ライブWebと自分のドキュメントを組み合わせる検索チェーンでは、Webドキュメントの重みを下げるか、別のプロンプトセクションに分けてください。Webページは変化し、誤っていることもあります。自分のドキュメントが通常は参照元です。

## レトリーバーが返した結果をベクトルデータベースに保存できますか？

はい、当社としては問題ないと考えています。当社はあなたの検索クエリやAPIが返す内容でモデルを学習させることはなく、結果の保存を禁じる独自のルールも設けていません。ただし、あなたが読むページのサイトの権利は引き続き適用されます。各チャンクと一緒にURLと`published_at`を保存すれば、エージェントがページを引用でき、古くなったチャンクを削除できます。

多くのチームは、頻出する質問のWeb結果を1日または1週間キャッシュしています。これにより繰り返しの検索が減り、回避した検索1回ごとにクレジットを1つ節約できます。

## LangChainとLlamaIndex: よくある質問

### langchain-llmwebsearchパッケージはありますか？

いいえ。当社はパッケージを公開していません。このページのコードは自分で管理できるほど短いものです。コピーしてデフォルト値を変更し、リポジトリに保存してください。

### ツールを非同期にできますか？

はい。`requests`を`httpx.AsyncClient`に置き換え、関数を`async def`で定義してください。LangChainの`@tool`は非同期関数を直接デコレートします。LlamaIndexでは、非同期バージョンを`async_fn`として`FunctionTool.from_defaults`に渡してください。

### エージェントが別の場所で見つけたページを読むにはどうすればよいですか？

URLを`https://llmwebsearch.com/api/v1/extract`にポストする2つ目のツールを追加してください。URLをすでに持っているページを読む場合は、コンテンツ付きで返される3ページごとの開始グループにつき1クレジットで、1回の呼び出しにつき最大20 URLです。拒否されたURLや失敗したURLはカウントされません。[extractリファレンス](https://llmwebsearch.com/ja/docs/extract/)にリクエスト例があります。

---

LLMWebSearch: LLMWebSearchは、AIエージェント向けのWeb検索APIです。ランキング済みの検索結果を、上位ページの本文をMarkdownに変換した内容とともに返し、暗号資産で支払えます。本人確認書類のアップロードは不要です。プリペイドのクレジットは$1.20/1K検索から購入でき、有効期限はありません。KYC不要 — 身分証も自撮りも書類も不要。暗号資産で支払い。
