簡潔な回答
LangChainエージェントにWeb検索ツールを渡すには?
langchain_core.tools の @tool でPython関数をデコレートし、その関数が https://serpcrypto.com/api/v1/search を呼び出して短いテキストを返すようにします。そしてエージェント作成時に tools=[...] で渡します。SerpCrypto の場合、エージェントが実行する検索1回につき1クレジット($0.30/1K検索 から)で、失敗した呼び出しは無料です。クレジットは暗号資産で支払い、KYC不要です。
検索ツールはどう書けばいいですか?
LangChainツールは、型ヒントとdocstringを持つ関数です。デコレータはシグネチャを引数スキーマに、docstringをモデルが読む説明に変換するので、どちらも丁寧に書く価値があります。引数はモデルがそのように考えるべき名前を付けましょう。検索クエリ、国、言語などです。
返すのはJSON全体ではなくテキストです。タイトル、リンク、スニペットを含む5件の結果があれば、モデルが回答して引用するのに十分で、生の応答に比べてトークン数はわずかです。エラー時は例外を発生させるのではなく短いメッセージを返し、エージェントが説明したり再試行したりできるようにします。
"""A LangChain tool that searches Google through the SerpCrypto SERP API."""
import os
import requests
from langchain_core.tools import tool
API_URL = "https://serpcrypto.com/api/v1/search"
@tool
def google_search(query: str, gl: str = "us", hl: str = "en") -> str:
"""Search Google for current information. Returns the top results with title, link and snippet.
Args:
query: the search query, as a person would type it.
gl: two-letter country code of the results, for example us, gb or de.
hl: language code, for example en, de or pt-BR.
"""
r = requests.get(
API_URL,
params={"q": query, "gl": gl, "hl": hl},
headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
timeout=90,
)
if r.status_code != 200:
return f"Search failed with HTTP {r.status_code}."
results = r.json().get("organic_results", [])[:5]
return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in results) or "No results."エージェントにいつ検索するかを判断させるには?
ツールを create_agent に渡します。これはLangChain 1.0から利用できます。モデルは説明を読み、質問に新しい事実が必要なときにツールを呼び出します。AGENT_MODEL にはアカウントが対応するモデル文字列を設定します。例えば openai: や anthropic: の後にモデル名を続けます。ツール呼び出しに対応したチャットモデルであればどれでも動作します。
システムプロンプトはコードと同じくらい重要です。学習データより新しい情報のときだけ検索すること、リンクを引用することをエージェントに指示すれば、回答が根拠に基づき、有料検索の回数も抑えられます。
"""An agent that decides when to search (LangChain 1.0 or later)."""
import os
from langchain.agents import create_agent
from search_tool import google_search
agent = create_agent(
model=os.environ["AGENT_MODEL"], # a provider:model string, such as one of your OpenAI or Anthropic models
tools=[google_search],
system_prompt="Answer with current facts. Use google_search when you need information newer than your training data, and cite the links you used.",
)
result = agent.invoke({"messages": [{"role": "user", "content": "What changed in Google's search results pages this year?"}]})
print(result["messages"][-1].content)LlamaIndexで同じことをするには?
型ヒントとdocstringを持つ通常の関数を書き、FunctionTool.from_defaults でラップします。LlamaIndexはLangChainと同様に、名前、型ヒント、docstringを読んでツールスキーマを構築します。ツールのリストを受け取るLlamaIndexエージェントであればどれにでもツールを追加できます。
"""The same search as a LlamaIndex FunctionTool."""
import os
import requests
from llama_index.core.tools import FunctionTool
def google_search(query: str, gl: str = "us", hl: str = "en") -> str:
"""Search Google for current information and return the top results with title, link and snippet."""
r = requests.get(
"https://serpcrypto.com/api/v1/search",
params={"q": query, "gl": gl, "hl": hl},
headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
timeout=90,
)
r.raise_for_status()
results = r.json().get("organic_results", [])[:5]
return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in results)
search_tool = FunctionTool.from_defaults(fn=google_search)
# Pass search_tool in the tools list of your LlamaIndex agent.ツールはJSONとテキストのどちらを返すべきですか?
ほとんどの場合はテキストです。モデルは短くラベル付けされたテキストをよく読み、ネストしたJSONよりもトークン数が少なくて済みます。JSONを返すのは、チェーン内の後続ステップがそれをパースする場合(例えばランキングを保存する場合)だけにしましょう。
出力にはリンクを残してください。モデルが情報源を引用でき、後から回答がどのページに依拠したかを確認できます。
エージェントの検索コストをどう管理すればいいですか?
成功したツール呼び出し1回につき1クレジットです。回数を抑える習慣は3つあります。検索すべきでない場面をシステムプロンプトでモデルに伝える、エージェントループ内で1回の実行あたりのツール呼び出し回数に上限を設ける、繰り返される質問への回答を自分のコードでキャッシュする、です。
100,000検索 のパックは $56.25、プリペイドの検索クレジットに有効期限はありません。未使用の検索は、使用するまでアカウントに残ります なので、静かな月でも無駄になりません。
LangChainに関する質問
これは公式のLangChain統合ですか?
いいえ。LangChainの公開 @tool デコレータで作られた小さなカスタムツールです。あなた自身のコードなので、出力形式を変更したり、location や engine などのパラメータを追加したり、Google News用の2つ目のツールを追加したりできます。
ツールで特定の都市を検索できますか?
はい。location 引数を追加し、City, Region, Country の形式で書いて params で渡します。形式と例についてはlocations をご覧ください。
エージェントは失敗した検索に対しても支払いますか?
いいえ。1クレジット = 1回の成功した検索リクエストで、対応するすべてのエンジンで結果の1ページを返します。失敗したリクエストは課金されません。タイムアウトや一時的なエラーに当たったツール呼び出しはクレジットを消費しません。
このツールを使えるモデルはどれですか?
LangChainまたはLlamaIndexでツール呼び出しに対応したチャットモデルであればどれでも使えます。ツール自体はHTTPSリクエストを送るだけなので、モデルプロバイダーに依存しません。