You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following fails due to errors serialization the playwright_agent function and passing it to the scraping_agent:
fromcontrolflowimportflowasCFFlow, TaskasCFTask, Agentfromplaywrightimportsync_apidefplaywright_agent(url: str) ->sync_api.Page:
""" Uses Playwright to scrape the site at the given URL and returns the playwright page object. """withsync_api.sync_playwright() asp:
browser=p.chromium.launch(headless=True)
page=browser.new_page()
page.goto(url)
returnpagescraping_agent=Agent(name="WesleyScrapes", tools=[playwright_agent])
@CFFlowdefscrape_details(url: str) ->str:
""" Given a url, this task scrapes the site for details about the tool. """returnCFTask(
objective="Scrape the site for details about the tool, following links to get more information if necessary.",
result_type=str,
agents=[scraping_agent],
context={"url": url},
).run()
if__name__=="__main__":
scrape_details("https://prefect.io")
with the following:
16:23:26.558 | ERROR | Flow run 'zealous-baboon' - Finished in state Failed("Flow run encountered an exception: PydanticSerializationError: Error calling function `_serialize_tools`: PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <class 'playwright.sync_api._generated.Page'>. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.\n\nIf you got this error by calling handler(<some type>) within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema(<some type>)` since we do not call `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.\n\nFor further information visit https://errors.pydantic.dev/2.7/u/schema-for-unknown-type")
Traceback (most recent call last):
File "/Users/nicholas/.pyenv/versions/workflow-webscraper/lib/python3.12/site-packages/pydantic/type_adapter.py", line 217, in __init__
validator = _getattr_no_parents(type, '__pydantic_validator__')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/.pyenv/versions/workflow-webscraper/lib/python3.12/site-packages/pydantic/type_adapter.py", line 98, in _getattr_no_parents
raise AttributeError(attribute)
AttributeError: __pydantic_validator__
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/nicholas/projects/flows/workflow-webscraper/cf_bug.py", line 31, in <module>
scrape_details("https://prefect.io")
File "/Users/nicholas/projects/prefect/src/prefect/flows.py", line 1326, in __call__
return run_flow(
^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 798, in run_flow
return run_flow_sync(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 678, in run_flow_sync
return engine.state if return_type == "state" else engine.result()
^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 243, in result
raise self._raised
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 635, in run_context
yield self
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 676, in run_flow_sync
engine.call_flow_fn()
File "/Users/nicholas/projects/prefect/src/prefect/flow_engine.py", line 655, in call_flow_fn
result = call_with_parameters(self.flow.fn, self.parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/utilities/callables.py", line 208, in call_with_parameters
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/decorators.py", line 110, in wrapper
result = fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/flows/workflow-webscraper/cf_bug.py", line 28, in scrape_details
).run()
^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/tasks.py", line 845, in __call__
return run_task(
^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 918, in run_task
return run_task_sync(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 731, in run_task_sync
return engine.state if return_type == "state" else engine.result()
^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 343, in result
raise self._raised
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 673, in run_context
yield self
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 729, in run_task_sync
engine.call_task_fn(txn)
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 702, in call_task_fn
result = call_with_parameters(self.task.fn, parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/utilities/callables.py", line 208, in call_with_parameters
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/tasks/task.py", line 360, in run
controller.run()
File "/Users/nicholas/projects/prefect/src/prefect/tasks.py", line 845, in __call__
return run_task(
^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 918, in run_task
return run_task_sync(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 731, in run_task_sync
return engine.state if return_type == "state" else engine.result()
^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 343, in result
raise self._raised
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 673, in run_context
yield self
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 729, in run_task_sync
engine.call_task_fn(txn)
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 702, in call_task_fn
result = call_with_parameters(self.task.fn, parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/utilities/callables.py", line 208, in call_with_parameters
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/controllers/controller.py", line 340, in run
new_messages = self.run_once()
^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/tasks.py", line 845, in __call__
return run_task(
^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 918, in run_task
return run_task_sync(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 731, in run_task_sync
return engine.state if return_type == "state" else engine.result()
^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 343, in result
raise self._raised
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 673, in run_context
yield self
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 729, in run_task_sync
engine.call_task_fn(txn)
File "/Users/nicholas/projects/prefect/src/prefect/task_engine.py", line 702, in call_task_fn
result = call_with_parameters(self.task.fn, parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/prefect/src/prefect/utilities/callables.py", line 208, in call_with_parameters
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/controllers/controller.py", line 270, in run_once
payload = self._setup_run()
^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/controllers/controller.py", line 192, in _setup_run
tools.extend(task.get_tools())
^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/tasks/task.py", line 526, in get_tools
tools.extend([self._create_fail_tool(), self._create_success_tool()])
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/tasks/task.py", line 468, in _create_fail_tool
return Tool.from_function(
^^^^^^^^^^^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/llm/tools.py", line 83, in from_function
parameters = TypeAdapter(fn).json_schema()
^^^^^^^^^^^^^^^
File "/Users/nicholas/.pyenv/versions/workflow-webscraper/lib/python3.12/site-packages/pydantic/type_adapter.py", line 223, in __init__
core_schema, type, module, str(type), 'TypeAdapter', core_config, config_wrapper.plugin_settings
^^^^^^^^^
File "/Users/nicholas/projects/control-flow/src/controlflow/tasks/task.py", line 175, in __repr__
serialized = self.model_dump()
^^^^^^^^^^^^^^^^^
File "/Users/nicholas/.pyenv/versions/workflow-webscraper/lib/python3.12/site-packages/pydantic/main.py", line 347, in model_dump
return self.__pydantic_serializer__.to_python(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.PydanticSerializationError: Error calling function `_serialize_tools`: PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <class 'playwright.sync_api._generated.Page'>. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.
If you got this error by calling handler(<some type>) within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema(<some type>)` since we do not call `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.
For further information visit https://errors.pydantic.dev/2.7/u/schema-for-unknown-type
Prior to launch this worked without issue so it's likely some tool serialization logic has changed.
The text was updated successfully, but these errors were encountered:
Thanks @znicholasbrown -- the change is that we started using return annotations to add more information to the tool description, but since your return annotation isn't Pydantic-serializable, it errored when trying to introspect it.
I've modified the logic to just ignore incompatible return annotations. However, function arguments must be serializable.
The following fails due to errors serialization the
playwright_agent
function and passing it to thescraping_agent
:with the following:
Prior to launch this worked without issue so it's likely some tool serialization logic has changed.
The text was updated successfully, but these errors were encountered: