はじめに
七尾百合子さん、お誕生日 119日目 おめでとうございます! nikkieです。
LLMを使ったアプリケーション実装例の中で目にする機会が多かったTavily。
そのPythonクライアントを触ってみました。
目次
tavily-python
https://pypi.org/project/tavily-python/
記事執筆時の最新バージョンは 0.7.9。
TavilyはLLMが使う検索エンジンと理解していましたが、PyPIを見ていくと多様な機能があることに気づきます。
- Tavily Search
search():ふつうの検索get_search_context():RAG向けのコンテキストqna_search():質問に回答してくれます!
- Tavily Extract
extract()で、URLの内容をマークダウンで取得
- ベータとして
- Tavily Crawl
- Tavily Map
TavilyのAPIは月1000リクエストまで無料で使えます。
https://www.tavily.com/#pricing
クレジットカード登録は不要で、アカウントを作ってAPIキーを発行します1。
AsyncTavilyClientを動かす
syncなTavilyClientの例はPyPIにあるので、asyncなクライアントを動かしてみます。
https://docs.tavily.com/sdk/python/reference#asynchronous-client
uv run --python 3.12 --with tavily-python python -m asyncioでawaitが書ける対話モードです。
クライアントが読み取る環境変数TAVILY_API_KEYでAPIキーを渡しました2
>>> from tavily import AsyncTavilyClient >>> tavily_client = AsyncTavilyClient()
search()
>>> response = await tavily_client.search("Who is Leo Messi?")
responseは辞書で、抜粋して示すと
>>> from pprint import pprint >>> pprint(response) {'query': 'Who is Leo Messi?', 'results': [{'content': '略', 'title': 'Lionel Messi - Wikipedia', 'url': 'https://en.wikipedia.org/wiki/Lionel_Messi'}, # 略 {'content': '略', 'title': 'Lionel Messi - Player profile 2025 | Transfermarkt', 'url': 'https://www.transfermarkt.us/lionel-messi/profil/spieler/28003'}]}
scoreが高いものから低いものへと並んだ検索結果です。
SerpApiを思い出しました3
get_search_context()
JSON形式の文字列が返ってきました。
これをRAGのLLMにコンテキストとしてぶち込むことを想定しているんだと思います。
>>> context = await tavily_client.get_search_context("Who is Leo Messi?") >>> type(context) <class 'str'> >>> len(context) 2911 >>> context[:100] '[{"url": "https://en.wikipedia.org/wiki/Lionel_Messi", "content": "An Argentine international, Messi'
qna_search()
質問の回答が返ってきます!
>>> answer = await tavily_client.qna_search("Who is Leo Messi?") >>> answer 'Lionel Messi is an Argentine professional footballer who plays for Inter Miami CF and captains the Argentina national team. He is widely regarded as one of the greatest players in history, winning the World Cup with Argentina in 2022.'
Tavilyの公開している情報が少なめなのですが、SimpleQAでSoTAというのはqna_search()の精度が高いと解釈していいのかな?
extract()
当ブログの記事を渡してみると
>>> response = await tavily_client.extract(urls=["https://nikkie-ftnext.hatenablog.com/entry/nikkie-oss-release-2025-07-02"])
抜粋して示します
>>> pprint(response)
{'results': [{'raw_content': '<マークダウンにした内容>'
'url': 'https://nikkie-ftnext.hatenablog.com/entry/nikkie-oss-release-2025-07-02'}]}
extract()だけ見ると、Firecrawlっぽいですね4。
終わりに
tavily-pythonを触りました。
TavilyはSerpApiのような検索エンジンという認識だったのですが、(Perplexityや検索ありClaudeなどのような)質問応答ができたり、FirecrawlのようにURLの内容をマークダウンで取得できたりと、非常に多機能に発展していました5。
月1000リクエストまで無料というのは試しやすいですし、自分だけが使うアプリケーションにはこれだけで足りるかもしれませんね