langflow icon indicating copy to clipboard operation
langflow copied to clipboard

feat: Add AgentQL integration

Open colriot opened this issue 1 year ago • 8 comments

AgentQL is a query language and a set of supporting developer tools designed to identify web elements and their data using natural language and return them in the shape you define. Added AgentQL data extraction component. See: https://docs.agentql.com/rest-api/api-reference

This pull request introduces a new component, AgentQL, to both the backend and frontend of the project. The changes include the implementation of the AgentQL component, its integration into the frontend, and the addition of a new icon for AgentQL.

Backend changes:

  • src/backend/base/langflow/components/agentql/__init__.py: Added the AgentQL import and included it in __all__.
  • src/backend/base/langflow/components/agentql/agentql_api.py: Implemented the AgentQL class, which uses the AgentQL API to extract structured data from a given URL. This includes defining inputs, outputs, and the build_output method for making API requests and handling responses.

Frontend changes:

  • src/frontend/src/icons/AgentQL/AgentQL.jsx: Added the SVG component for the AgentQL icon.
  • src/frontend/src/icons/AgentQL/index.tsx: Created a forward reference component for the AgentQL icon.
  • src/frontend/src/utils/styleUtils.ts: Integrated the AgentQL icon and added AgentQL to the sidebar bundles and node icons. [1] [2] [3]

colriot avatar Dec 02 '24 16:12 colriot

cc @ogabrielluiz for feedback and thoughts. Plus, can you point me to the right way to add examples for Langflow + AgentQL, please?

colriot avatar Dec 06 '24 12:12 colriot

@colriot Thank you for the pull request. We will test it and let you know if any changes are required.

edwinjosechittilappilly avatar Dec 10 '24 01:12 edwinjosechittilappilly

I was trying out the example at https://github.com/tinyfish-io/agentql/blob/main/examples/python/run_script_online_in_google_colab/main.ipynb.

I received a timeout error. If possible, could you also share a sample flow that works well and look into this timeout issue?

Screenshot 2024-12-09 at 9 16 45 PM

Error:

"""" ReadTimeout: The read operation timed out

                         The above exception was the direct cause of the following exception:                                                                                       
                                                                                                                                                                                    
                         ╭───────────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────────╮            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/graph/vertex/base.py:709 in _build_results                            │            
                         │                                                                                                                                             │            
                         │   706 │   │   self, custom_component, custom_params, base_type: str, *,                                                                     │            
                         │       fallback_to_env_vars=False                                                                                                            │            
                         │   707 │   ) -> None:                                                                                                                        │            
                         │   708 │   │   try:                                                                                                                          │            
                         │ ❱ 709 │   │   │   result = await initialize.loading.get_instance_results(                                                                   │            
                         │   710 │   │   │   │   custom_component=custom_component,                                                                                    │            
                         │   711 │   │   │   │   custom_params=custom_params,                                                                                          │            
                         │   712 │   │   │   │   vertex=self,                                                                                                          │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/interface/initialize/loading.py:68 in get_instance_results            │            
                         │                                                                                                                                             │            
                         │    65 │   │   if base_type == "custom_components":                                                                                          │            
                         │    66 │   │   │   return await build_custom_component(params=custom_params,                                                                 │            
                         │       custom_component=custom_component)                                                                                                    │            
                         │    67 │   │   if base_type == "component":                                                                                                  │            
                         │ ❱  68 │   │   │   return await build_component(params=custom_params,                                                                        │            
                         │       custom_component=custom_component)                                                                                                    │            
                         │    69 │   │   msg = f"Base type {base_type} not found."                                                                                     │            
                         │    70 │   │   raise ValueError(msg)                                                                                                         │            
                         │    71                                                                                                                                       │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/interface/initialize/loading.py:145 in build_component                │            
                         │                                                                                                                                             │            
                         │   142 ):                                                                                                                                    │            
                         │   143 │   # Now set the params as attributes of the custom_component                                                                        │            
                         │   144 │   custom_component.set_attributes(params)                                                                                           │            
                         │ ❱ 145 │   build_results, artifacts = await custom_component.build_results()                                                                 │            
                         │   146 │                                                                                                                                     │            
                         │   147 │   return custom_component, build_results, artifacts                                                                                 │            
                         │   148                                                                                                                                       │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/custom/custom_component/component.py:847 in build_results             │            
                         │                                                                                                                                             │            
                         │    844 │   │   │   session_id = None                                                                                                        │            
                         │    845 │   │   try:                                                                                                                         │            
                         │    846 │   │   │   if self._tracing_service:                                                                                                │            
                         │ ❱  847 │   │   │   │   return await self._build_with_tracing()                                                                              │            
                         │    848 │   │   │   return await self._build_without_tracing()                                                                               │            
                         │    849 │   │   except StreamingError as e:                                                                                                  │            
                         │    850 │   │   │   await self.send_error(                                                                                                   │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/custom/custom_component/component.py:829 in _build_with_tracing       │            
                         │                                                                                                                                             │            
                         │    826 │   │   inputs = self.get_trace_as_inputs()                                                                                          │            
                         │    827 │   │   metadata = self.get_trace_as_metadata()                                                                                      │            
                         │    828 │   │   async with self._tracing_service.trace_context(self, self.trace_name, inputs,                                                │            
                         │        metadata):                                                                                                                           │            
                         │ ❱  829 │   │   │   results, artifacts = await self._build_results()                                                                         │            
                         │    830 │   │   │   self._tracing_service.set_outputs(self.trace_name, results)                                                              │            
                         │    831 │   │                                                                                                                                │            
                         │    832 │   │   return results, artifacts                                                                                                    │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/src/backend/base/langflow/custom/custom_component/component.py:895 in _build_results            │            
                         │                                                                                                                                             │            
                         │    892 │   │   │   │   │   │   if inspect.iscoroutinefunction(method):                                                                      │            
                         │    893 │   │   │   │   │   │   │   result = await method()                                                                                  │            
                         │    894 │   │   │   │   │   │   else:                                                                                                        │            
                         │ ❱  895 │   │   │   │   │   │   │   result = await asyncio.to_thread(method)                                                                 │            
                         │    896 │   │   │   │   │   │   if (                                                                                                         │            
                         │    897 │   │   │   │   │   │   │   self._vertex is not None                                                                                 │            
                         │    898 │   │   │   │   │   │   │   and isinstance(result, Message)                                                                          │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none/lib/python3.12/asyncio/threads.py:25 in to_thread                │            
                         │                                                                                                                                             │            
                         │   22 │   loop = events.get_running_loop()                                                                                                   │            
                         │   23 │   ctx = contextvars.copy_context()                                                                                                   │            
                         │   24 │   func_call = functools.partial(ctx.run, func, *args, **kwargs)                                                                      │            
                         │ ❱ 25 │   return await loop.run_in_executor(None, func_call)                                                                                 │            
                         │   26                                                                                                                                        │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none/lib/python3.12/concurrent/futures/thread.py:58 in run            │            
                         │                                                                                                                                             │            
                         │    55 │   │   │   return                                                                                                                    │            
                         │    56 │   │                                                                                                                                 │            
                         │    57 │   │   try:                                                                                                                          │            
                         │ ❱  58 │   │   │   result = self.fn(*self.args, **self.kwargs)                                                                               │            
                         │    59 │   │   except BaseException as exc:                                                                                                  │            
                         │    60 │   │   │   self.future.set_exception(exc)                                                                                            │            
                         │    61 │   │   │   # Break a reference cycle with the exception 'exc'                                                                        │            
                         │ in build_output:60                                                                                                                          │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_api.py:319 in post                                    │            
                         │                                                                                                                                             │            
                         │   316 │                                                                                                                                     │            
                         │   317 │   **Parameters**: See `httpx.request`.                                                                                              │            
                         │   318 │   """                                                                                                                               │            
                         │ ❱ 319 │   return request(                                                                                                                   │            
                         │   320 │   │   "POST",                                                                                                                       │            
                         │   321 │   │   url,                                                                                                                          │            
                         │   322 │   │   content=content,                                                                                                              │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_api.py:106 in request                                 │            
                         │                                                                                                                                             │            
                         │   103 │   │   timeout=timeout,                                                                                                              │            
                         │   104 │   │   trust_env=trust_env,                                                                                                          │            
                         │   105 │   ) as client:                                                                                                                      │            
                         │ ❱ 106 │   │   return client.request(                                                                                                        │            
                         │   107 │   │   │   method=method,                                                                                                            │            
                         │   108 │   │   │   url=url,                                                                                                                  │            
                         │   109 │   │   │   content=content,                                                                                                          │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_client.py:827 in request                              │            
                         │                                                                                                                                             │            
                         │    824 │   │   │   timeout=timeout,                                                                                                         │            
                         │    825 │   │   │   extensions=extensions,                                                                                                   │            
                         │    826 │   │   )                                                                                                                            │            
                         │ ❱  827 │   │   return self.send(request, auth=auth, follow_redirects=follow_redirects)                                                      │            
                         │    828 │                                                                                                                                    │            
                         │    829 │   @contextmanager                                                                                                                  │            
                         │    830 │   def stream(                                                                                                                      │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_client.py:914 in send                                 │            
                         │                                                                                                                                             │            
                         │    911 │   │                                                                                                                                │            
                         │    912 │   │   auth = self._build_request_auth(request, auth)                                                                               │            
                         │    913 │   │                                                                                                                                │            
                         │ ❱  914 │   │   response = self._send_handling_auth(                                                                                         │            
                         │    915 │   │   │   request,                                                                                                                 │            
                         │    916 │   │   │   auth=auth,                                                                                                               │            
                         │    917 │   │   │   follow_redirects=follow_redirects,                                                                                       │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_client.py:942 in _send_handling_auth                  │            
                         │                                                                                                                                             │            
                         │    939 │   │   │   request = next(auth_flow)                                                                                                │            
                         │    940 │   │   │                                                                                                                            │            
                         │    941 │   │   │   while True:                                                                                                              │            
                         │ ❱  942 │   │   │   │   response = self._send_handling_redirects(                                                                            │            
                         │    943 │   │   │   │   │   request,                                                                                                         │            
                         │    944 │   │   │   │   │   follow_redirects=follow_redirects,                                                                               │            
                         │    945 │   │   │   │   │   history=history,                                                                                                 │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_client.py:979 in _send_handling_redirects             │            
                         │                                                                                                                                             │            
                         │    976 │   │   │   for hook in self._event_hooks["request"]:                                                                                │            
                         │    977 │   │   │   │   hook(request)                                                                                                        │            
                         │    978 │   │   │                                                                                                                            │            
                         │ ❱  979 │   │   │   response = self._send_single_request(request)                                                                            │            
                         │    980 │   │   │   try:                                                                                                                     │            
                         │    981 │   │   │   │   for hook in self._event_hooks["response"]:                                                                           │            
                         │    982 │   │   │   │   │   hook(response)                                                                                                   │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_client.py:1015 in _send_single_request                │            
                         │                                                                                                                                             │            
                         │   1012 │   │   │   )                                                                                                                        │            
                         │   1013 │   │                                                                                                                                │            
                         │   1014 │   │   with request_context(request=request):                                                                                       │            
                         │ ❱ 1015 │   │   │   response = transport.handle_request(request)                                                                             │            
                         │   1016 │   │                                                                                                                                │            
                         │   1017 │   │   assert isinstance(response.stream, SyncByteStream)                                                                           │            
                         │   1018                                                                                                                                      │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_transports/default.py:232 in handle_request           │            
                         │                                                                                                                                             │            
                         │   229 │   │   │   content=request.stream,                                                                                                   │            
                         │   230 │   │   │   extensions=request.extensions,                                                                                            │            
                         │   231 │   │   )                                                                                                                             │            
                         │ ❱ 232 │   │   with map_httpcore_exceptions():                                                                                               │            
                         │   233 │   │   │   resp = self._pool.handle_request(req)                                                                                     │            
                         │   234 │   │                                                                                                                                 │            
                         │   235 │   │   assert isinstance(resp.stream, typing.Iterable)                                                                               │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none/lib/python3.12/contextlib.py:158 in __exit__                     │            
                         │                                                                                                                                             │            
                         │   155 │   │   │   │   # tell if we get the same exception back                                                                              │            
                         │   156 │   │   │   │   value = typ()                                                                                                         │            
                         │   157 │   │   │   try:                                                                                                                      │            
                         │ ❱ 158 │   │   │   │   self.gen.throw(value)                                                                                                 │            
                         │   159 │   │   │   except StopIteration as exc:                                                                                              │            
                         │   160 │   │   │   │   # Suppress StopIteration *unless* it's the same exception that                                                        │            
                         │   161 │   │   │   │   # was passed to throw().  This prevents a StopIteration                                                               │            
                         │                                                                                                                                             │            
                         │ /Users/edwin.jose/Documents/GitHub/langflow/.venv/lib/python3.12/site-packages/httpx/_transports/default.py:86 in map_httpcore_exceptions   │            
                         │                                                                                                                                             │            
                         │    83 │   │   │   raise                                                                                                                     │            
                         │    84 │   │                                                                                                                                 │            
                         │    85 │   │   message = str(exc)                                                                                                            │            
                         │ ❱  86 │   │   raise mapped_exc(message) from exc                                                                                            │            
                         │    87                                                                                                                                       │            
                         │    88                                                                                                                                       │            
                         │    89 HTTPCORE_EXC_MAP = {                                                                                                                  │            
                         ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯            
                         ReadTimeout: The read operation timed out       

""""

edwinjosechittilappilly avatar Dec 10 '24 02:12 edwinjosechittilappilly

To integrate this component as a tool for agents, we also need to ensure tool_mode=True is set for the relevant inputs. This is important for enabling the tool functionality as described in the documentation.

You can refer to the implementation in the Langflow URL component code for guidance on how to properly configure this.

Let me know if you need assistance updating the inputs to align with this requirement!

edwinjosechittilappilly avatar Dec 10 '24 02:12 edwinjosechittilappilly

cc @ogabrielluiz for feedback and thoughts. Plus, can you point me to the right way to add examples for Langflow + AgentQL, please?

Hey @colriot

Thank you for the PR! About the examples, we are still managing those internally just so we have good ways of making sure they are all working.

ogabrielluiz avatar Dec 10 '24 11:12 ogabrielluiz

Hi @edwinjosechittilappilly @ogabrielluiz , thanks for you feedback! Let me address it.

Regarding the examples, I found this repo: https://github.com/langflow-ai/langflow_examples. Would you recommend it for adding an example or is there a better/other way?

colriot avatar Dec 10 '24 15:12 colriot

Updated PR with tool support, different Input types and better error messages

colriot avatar Dec 11 '24 17:12 colriot

Tested! Changes looks good to me! @ogabrielluiz and @NadirJ Awaiting your approval!

LGTM!

edwinjosechittilappilly avatar Dec 13 '24 06:12 edwinjosechittilappilly