🦔

【AI Agent】browser-useを使って、自分のブラウザを操作させてみる

2025/01/04に公開

browser-useという、AI Agentがウェブサイトにアクセスできるようにするライブラリが話題となっているので触ってみました。

https://github.com/browser-use/browser-use

何ができる?

指定したタスクに応じてブラウザを操作し、期待した結果を取得することができます。

以下は私がコードを実行し、最も安い航空券の金額を取得した時の動画です。カーソルが動いていますが、最初のコードを実行してからの操作は一切しておらず、Agentがブラウザを操作しています。

https://youtu.be/ItdRG5im8OY

とりあえず動かす

READMEにしたがって、とりあえず動かしてみます。Python(v3.11)です。

(その前にプロジェクトの諸々を準備しておきます)

$ mkdir browser-use
$ cd browser-use
$ python3.11 -m venv venv
$ . ./venv/bin/activate

browser-useとplaywrightををinstallします。

$ pip install browser-use
$ playwright install

OpenAIのAPIキーを設定します。(こちらから取得できます)

.env
OPENAI_API_KEY=

READMEのプロンプトを日本語にして指示してみました。

main.py
from langchain_openai import ChatOpenAI
from browser_use import Agent
import asyncio

async def main():
    agent = Agent(
        task="2025年1月12日のバリからオマーンへの片道便をGoogle Flightsで検索し、最安値のオプションを返してください。",
        llm=ChatOpenAI(model="gpt-4o"),
    )
    result = await agent.run()
    print(result)

asyncio.run(main())

※ステップが実行されているログはこのようになっています

最終的な出力は以下のようになり、期待した結果は返ってきていそうです(本当に最安値で最寄りの空港かは定かではない)

 {'done': {'text': 'The cheapest flight option from Bali to Oman on January 12, 2025, is to Muscat with 2 stops, taking 44 hours and 55 minutes, costing ¥126,689.'}}

カスタムアクションの設定

カスタムアクションとして定義することで、ブラウザから取得した情報に対してAgenticなアクションを設定することができます。

カスタムアクションを登録するには、以下のコードのようにcontroller.actionを設定します。
それによって、AIが判断に迷った時に人間に「これどうする?」と聞けるような処理を登録することができます。LangGraphなどを使ってHuman-in-the-loopの処理を書いている人は想像しやすいと思います。
(ただし「AIが判断に迷う」の定義も曖昧にしておくと、思った通りに聞いてくれなかったり)

例:

@custom_controller.action("ユーザーに確認を取る")
def ask_user(question: str) -> str:
    return input(f"\n{question}\n回答を入力してください (はい/いいえ): ")

以下、ユーザーの確認をとる処理と求人情報を保存する処理のサンプルコードです。サンプルなので、保存はprintだけになっています。

main.py
from browser_use import Agent, Browser
from browser_use.agent.service import Controller
from pydantic import BaseModel
from typing import Optional
from langchain_openai import ChatOpenAI
import asyncio


# 求人応募情報を格納するためのPydanticモデル
class JobApplication(BaseModel):
    company_name: str  # 会社名
    position: str  # 職位
    application_status: str  # 応募状況
    notes: Optional[str] = None  # メモ(任意)


# コントローラーの初期化
custom_controller = Controller()


# ユーザーに確認を取るためのアクション
@custom_controller.action("ユーザーに確認を取る")
def ask_user(question: str) -> str:
    return input(f"\n{question}\n回答を入力してください (はい/いいえ): ")


# 求人応募情報を保存するためのアクション
@custom_controller.action(
    "求人応募情報を保存", param_model=JobApplication, requires_browser=True
)
async def save_job_application(params: JobApplication, browser: Browser):
    # 現在のページを取得
    page = browser.get_current_page()

    # 実際のアプリケーションでは、データベースやファイルに保存する処理を実装
    print("以下の応募情報を保存します:")
    print(f"会社名: {params.company_name}")
    print(f"職位: {params.position}")
    print(f"応募状況: {params.application_status}")
    if params.notes:
        print(f"メモ: {params.notes}")


async def main():
    model = ChatOpenAI(
        model="gpt-4o",
        temperature=0.3,
    )

    agent = Agent(
        task="東京でのソフトウェアエンジニアの求人を検索し、興味深い求人を保存してください",
        llm=model,
        controller=custom_controller,
    )

    # Agentを実行し、アクション履歴を取得
    history = await agent.run()
    print("アクション履歴:", history)


if __name__ == "__main__":
    asyncio.run(main())

ちゃんと保存のログが出力されていたので、actionが実行されていることが確認できました。

Agentの並列化

以下のように記述することで、複数のAgentを並列に実行できます。
ほぼ全てのケースではbrowserインスタンスは1つで、Agentごとにcontextを作成する必要があります。

browser = Browser()

for i in range(10):
    # This create a new context and automatically closes it after the agent finishes (with `__aexit__`)
    async with browser.new_context() as context:
        agent = Agent(task=f"Task {i}", llm=model, browser_context=context)

Agentが実行した履歴を確認

Agentが実行したタスクの履歴を出力できます。
※先ほどのコードでもアクション履歴として表示しています。

history: list[AgentHistory] = await agent.run()
print(history)

まとめ

MCP, browser-useなど、他でもブラウザ操作のサービスがいくつかあるのでまだこれが最善の選択肢と断言できませんが、プロンプトを簡単に書くだけでかなり正確にステップを刻んで実行してくれた感覚です。

ちなみに、ブラウザの操作に係る処理(スクレイピングなど)は特定のwebサイトでは規約で禁止されている可能性があるので、必ず規約を読んで問題ないことを確認してから実行しましょう。規約で明記されていなくても、一度に大量のアクセスを実行するような行為はNGです。ご注意ください。

Discussion