Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Playwright Tools bug with Pydantic schemas #27050

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion libs/community/langchain_community/tools/playwright/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from langchain_core.tools import BaseTool
from langchain_core.utils import guard_import
from pydantic import model_validator
from pydantic import model_validator, BaseModel

if TYPE_CHECKING:
from playwright.async_api import Browser as AsyncBrowser
Expand All @@ -31,10 +31,14 @@ def lazy_import_playwright_browsers() -> Tuple[Type[AsyncBrowser], Type[SyncBrow
guard_import(module_name="playwright.sync_api").Browser,
)

class BaseBrowserToolInput(BaseModel):
"""Base class for browser tool input when tool has no arguments."""

class BaseBrowserTool(BaseTool):
"""Base class for browser tools."""

args_schema: Type[BaseModel] = BaseBrowserToolInput

sync_browser: Optional["SyncBrowser"] = None
async_browser: Optional["AsyncBrowser"] = None

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from __future__ import annotations

from typing import Optional, Type
from typing import Optional

from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from pydantic import BaseModel

from langchain_community.tools.playwright.base import BaseBrowserTool
from langchain_community.tools.playwright.utils import (
Expand All @@ -20,7 +19,6 @@ class CurrentWebPageTool(BaseBrowserTool):

name: str = "current_webpage"
description: str = "Returns the URL of the current page"
args_schema: Type[BaseModel] = BaseModel

def _run(
self,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
from __future__ import annotations

from typing import Any, Optional, Type
from typing import Any, Optional

from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from pydantic import BaseModel, model_validator
from pydantic import model_validator

from langchain_community.tools.playwright.base import BaseBrowserTool
from langchain_community.tools.playwright.utils import (
aget_current_page,
get_current_page,
)


class ExtractTextTool(BaseBrowserTool):
"""Tool for extracting all the text on the current webpage."""

name: str = "extract_text"
description: str = "Extract all the text on the current webpage"
args_schema: Type[BaseModel] = BaseModel

@model_validator(mode="before")
@classmethod
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from __future__ import annotations

from typing import Optional, Type
from typing import Optional

from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from pydantic import BaseModel

from langchain_community.tools.playwright.base import BaseBrowserTool
from langchain_community.tools.playwright.utils import (
Expand All @@ -20,7 +19,6 @@ class NavigateBackTool(BaseBrowserTool):

name: str = "previous_webpage"
description: str = "Navigate back to the previous page in the browser history"
args_schema: Type[BaseModel] = BaseModel

def _run(self, run_manager: Optional[CallbackManagerForToolRun] = None) -> str:
"""Use the tool."""
Expand Down
Empty file.
18 changes: 18 additions & 0 deletions libs/community/tests/unit_tests/tools/playwright/test_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Test Playwright's Tools."""

from langchain_community.agent_toolkits import PlayWrightBrowserToolkit

from langchain_community.tools.playwright.utils import create_sync_playwright_browser


def test_playwright_tools_schemas() -> None:
"""Test calling 'tool_call_schema' for every tool to check to serialization issues."""

sync_browser = create_sync_playwright_browser()
tools = PlayWrightBrowserToolkit.from_browser(sync_browser=sync_browser).get_tools()

for tool in tools:
try:
tool.tool_call_schema
except Exception as e:
raise AssertionError(f"Error for '{tool.name}' tool: {type(e).__name__}: {e}") from e