langflow-ai / langflow

Langflow is a low-code app builder for RAG and multi-agent AI applications. It’s Python-based and agnostic to any model, API, or database.
http://www.langflow.org
MIT License
31.62k stars 3.91k forks source link

SubFlow not working #2852

Closed azaidiuk closed 2 months ago

azaidiuk commented 2 months ago

Bug Description

SubFlow component does not load flows

Reproduction

  1. Load SubFlow Components
  2. Select Dropdown
  3. No Fields found

Expected behavior

List of existing flows to select from

Who can help?

@ogabrielluiz

Operating System

Mac OSX

Langflow Version

V1.11

Python Version

3.10

dosubot[bot] commented 2 months ago

The issue with the SubFlow component in Langflow Version 1.11 on Mac OSX with Python 3.10, where it shows "No Fields found" when selecting from the dropdown, is likely due to the update_build_config method not properly updating the build_config with the available flow names. Specifically, the build_config["flow_name"]["options"] is not being populated correctly.

Here is the relevant part of the code:

def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
    logger.debug(f"Updating build config with field value {field_value} and field name {field_name}")
    if field_name == "flow_name":
        build_config["flow_name"]["options"] = self.get_flow_names()
    # Clean up the build config
    for key in list(build_config.keys()):
        if key not in self.field_order + ["code", "_type", "get_final_results_only"]:
            del build_config[key]
    if field_value is not None and field_name == "flow_name":
        try:
            flow_data = self.get_flow(field_value)
            if not flow_data:
                raise ValueError(f"Flow {field_value} not found.")
            graph = Graph.from_payload(flow_data.data["data"])
            # Get all inputs from the graph
            inputs = get_flow_inputs(graph)
            # Add inputs to the build config
            build_config = self.add_inputs_to_build_config(inputs, build_config)
        except Exception as e:
            logger.error(f"Error getting flow {field_value}: {str(e)}")

    return build_config

The get_flow_names method is supposed to return a list of flow names, but if list_flows does not return any flows or if there is an issue with fetching the flow names, the options list will remain empty, leading to "No Fields found" in the dropdown.

To resolve this, ensure that list_flows is correctly implemented and returning the expected flow data. Additionally, verify that get_flow_names is correctly extracting the flow names from the returned data. Here is the implementation of get_flow_names and get_flow:

def get_flow_names(self) -> List[str]:
    flow_datas = self.list_flows()
    return [flow_data.data["name"] for flow_data in flow_datas]

def get_flow(self, flow_name: str) -> Optional[Data]:
    flow_datas = self.list_flows()
    for flow_data in flow_datas:
        if flow_data.data["name"] == flow_name:
            return flow_data
    return None

Additionally, ensure that the add_inputs_to_build_config method is correctly adding the inputs to the build_config:

def add_inputs_to_build_config(self, inputs: List[Vertex], build_config: dotdict):
    new_fields: list[Input] = []
    for vertex in inputs:
        field = Input(
            display_name=vertex.display_name,
            name=vertex.id,
            info=vertex.description,
            field_type="str",
            value=None,
        )
        new_fields.append(field)
    logger.debug(new_fields)
    for field in new_fields:
        build_config[field.name] = field.to_dict()
    return build_config

By ensuring these methods are correctly implemented and functioning, the "No Fields found" issue should be resolved [1][2][3].

To continue talking to Dosu, mention @dosu.

azaidiuk commented 2 months ago
                        Traceback (most recent call last):

                           File "/opt/anaconda3/bin/langflow", line 8, in <module>
                             sys.exit(main())
                             |   |    -> <function main at 0x10e8e02c0>
                             |   -> <built-in function exit>
                             -> <module 'sys' (built-in)>
                           File "/opt/anaconda3/lib/python3.11/site-packages/langflow/__main__.py", line 605, in main
                             app()
                             -> <typer.main.Typer object at 0x10e58a690>
                           File "/opt/anaconda3/lib/python3.11/site-packages/typer/main.py", line 309, in __call__
                             return get_command(self)(*args, **kwargs)
                                    |           |      |       -> {}
                                    |           |      -> ()
                                    |           -> <typer.main.Typer object at 0x10e58a690>
                                    -> <function get_command at 0x106609a80>
                           File "/opt/anaconda3/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
                             return self.main(*args, **kwargs)
                                    |    |     |       -> {}
                                    |    |     -> ()
                                    |    -> <function TyperGroup.main at 0x106608360>
                                    -> <TyperGroup >
                           File "/opt/anaconda3/lib/python3.11/site-packages/typer/core.py", line 723, in main
                             return _main(
                                    -> <function _main at 0x1066034c0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/typer/core.py", line 193, in _main
                             rv = self.invoke(ctx)
                                  |    |      -> <click.core.Context object at 0x10e3e4450>
                                  |    -> <function MultiCommand.invoke at 0x104e35300>
                                  -> <TyperGroup >
                           File "/opt/anaconda3/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
                             return _process_result(sub_ctx.command.invoke(sub_ctx))
                                    |               |       |       |      -> <click.core.Context object at 0x10c2d03d0>
                                    |               |       |       -> <function Command.invoke at 0x104e34cc0>
                                    |               |       -> <TyperCommand run>
                                    |               -> <click.core.Context object at 0x10c2d03d0>
                                    -> <function MultiCommand.invoke.<locals>._process_result at 0x10e8e07c0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
                             return ctx.invoke(self.callback, **ctx.params)
                                    |   |      |    |           |   -> {'host': '192.168.0.109', 'workers': 1, 'timeout': 300, 'port': 7860, 'components_path':
                         PosixPath('/opt/anaconda3/lib/python...
                                    |   |      |    |           -> <click.core.Context object at 0x10c2d03d0>
                                    |   |      |    -> <function run at 0x10e8e0540>
                                    |   |      -> <TyperCommand run>
                                    |   -> <function Context.invoke at 0x104e2b600>
                                    -> <click.core.Context object at 0x10c2d03d0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/click/core.py", line 783, in invoke
                             return __callback(*args, **kwargs)
                                                |       -> {'host': '192.168.0.109', 'workers': 1, 'timeout': 300, 'port': 7860, 'components_path': PosixPath('/opt/anaconda3/lib/python...
                                                -> ()
                           File "/opt/anaconda3/lib/python3.11/site-packages/typer/main.py", line 692, in wrapper
                             return callback(**use_params)
                                    |          -> {'host': '192.168.0.109', 'workers': 1, 'timeout': 300, 'port': 7860, 'components_path': PosixPath('/opt/anaconda3/lib/python...
                                    -> <function run at 0x10e87f600>
                           File "/opt/anaconda3/lib/python3.11/site-packages/langflow/__main__.py", line 194, in run
                             process = run_on_mac_or_linux(host, port, log_level, options, app)
                                       |                   |     |     |          |        -> <fastapi.applications.FastAPI object at 0x10e507e90>
                                       |                   |     |     |          -> {'bind': '192.168.0.109:7860', 'workers': 1, 'timeout': 300, 'worker_class':
                         'langflow.server.LangflowUvicornWorker', 'logger...
                                       |                   |     |     -> 'critical'
                                       |                   |     -> 7860
                                       |                   -> '192.168.0.109'
                                       -> <function run_on_mac_or_linux at 0x10e87f6a0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/langflow/__main__.py", line 222, in run_on_mac_or_linux
                             webapp_process.start()
                             |              -> <function BaseProcess.start at 0x10662dbc0>
                             -> <Process name='Process-1' parent=27852 started>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/process.py", line 121, in start
                             self._popen = self._Popen(self)
                             |    |        |    |      -> <Process name='Process-1' parent=27852 started>
                             |    |        |    -> <staticmethod(<function Process._Popen at 0x106724ae0>)>
                             |    |        -> <Process name='Process-1' parent=27852 started>
                             |    -> None
                             -> <Process name='Process-1' parent=27852 started>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/context.py", line 224, in _Popen
                             return _default_context.get_context().Process._Popen(process_obj)
                                    |                |                            -> <Process name='Process-1' parent=27852 started>
                                    |                -> <function DefaultContext.get_context at 0x106724cc0>
                                    -> <multiprocess.context.DefaultContext object at 0x10671b150>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/context.py", line 281, in _Popen
                             return Popen(process_obj)
                                    |     -> <Process name='Process-1' parent=27852 started>
                                    -> <class 'multiprocess.popen_fork.Popen'>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/popen_fork.py", line 19, in __init__
                             self._launch(process_obj)
                             |    |       -> <Process name='Process-1' parent=27852 started>
                             |    -> <function Popen._launch at 0x10ea99d00>
                             -> <multiprocess.popen_fork.Popen object at 0x10e915590>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/popen_fork.py", line 71, in _launch
                             code = process_obj._bootstrap(parent_sentinel=child_r)
                                    |           |                          -> 6
                                    |           -> <function BaseProcess._bootstrap at 0x10662e5c0>
                                    -> <Process name='Process-1' parent=27852 started>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/process.py", line 314, in _bootstrap
                             self.run()
                             |    -> <function BaseProcess.run at 0x10662db20>
                             -> <Process name='Process-1' parent=27852 started>
                           File "/opt/anaconda3/lib/python3.11/site-packages/multiprocess/process.py", line 108, in run
                             self._target(*self._args, **self._kwargs)
                             |    |        |    |        |    -> {}
                             |    |        |    |        -> <Process name='Process-1' parent=27852 started>
                             |    |        |    -> ('192.168.0.109', 7860, 'critical', {'bind': '192.168.0.109:7860', 'workers': 1, 'timeout': 300, 'worker_class': 'langflow.se...
                             |    |        -> <Process name='Process-1' parent=27852 started>
                             |    -> <function run_langflow at 0x10e87fec0>
                             -> <Process name='Process-1' parent=27852 started>
                           File "/opt/anaconda3/lib/python3.11/site-packages/langflow/__main__.py", line 444, in run_langflow
                             LangflowApplication(app, options).run()
                             |                   |    -> {'bind': '192.168.0.109:7860', 'workers': 1, 'timeout': 300, 'worker_class': 'langflow.server.LangflowUvicornWorker', 'logger...
                             |                   -> <fastapi.applications.FastAPI object at 0x10e507e90>
                             -> <class 'langflow.server.LangflowApplication'>
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/app/base.py", line 72, in run
                             Arbiter(self).run()
                             |       -> <langflow.server.LangflowApplication object at 0x10e456f90>
                             -> <class 'gunicorn.arbiter.Arbiter'>
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/arbiter.py", line 202, in run
                             self.manage_workers()
                             |    -> <function Arbiter.manage_workers at 0x10eb0e840>
                             -> <gunicorn.arbiter.Arbiter object at 0x10e9154d0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/arbiter.py", line 571, in manage_workers
                             self.spawn_workers()
                             |    -> <function Arbiter.spawn_workers at 0x10eb0e980>
                             -> <gunicorn.arbiter.Arbiter object at 0x10e9154d0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/arbiter.py", line 642, in spawn_workers
                             self.spawn_worker()
                             |    -> <function Arbiter.spawn_worker at 0x10eb0e8e0>
                             -> <gunicorn.arbiter.Arbiter object at 0x10e9154d0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/arbiter.py", line 609, in spawn_worker
                             worker.init_process()
                             |      -> <function UvicornWorker.init_process at 0x10eb79e40>
                             -> <langflow.server.LangflowUvicornWorker object at 0x10e916f50>
                           File "/opt/anaconda3/lib/python3.11/site-packages/uvicorn/workers.py", line 75, in init_process
                             super().init_process()
                           File "/opt/anaconda3/lib/python3.11/site-packages/gunicorn/workers/base.py", line 142, in init_process
                             self.run()
                             |    -> <function UvicornWorker.run at 0x10ebd74c0>
                             -> <langflow.server.LangflowUvicornWorker object at 0x10e916f50>
                           File "/opt/anaconda3/lib/python3.11/site-packages/uvicorn/workers.py", line 107, in run
                             return asyncio.run(self._serve())
                                    |       |   |    -> <function LangflowUvicornWorker._serve at 0x10eb0efc0>
                                    |       |   -> <langflow.server.LangflowUvicornWorker object at 0x10e916f50>
                                    |       -> <function _patch_asyncio.<locals>.run at 0x10a9880e0>
                                    -> <module 'asyncio' from '/opt/anaconda3/lib/python3.11/asyncio/__init__.py'>
                           File "/opt/anaconda3/lib/python3.11/asyncio/runners.py", line 190, in run
                             return runner.run(main)
                                    |      |   -> <coroutine object LangflowUvicornWorker._serve at 0x10ebf1a40>
                                    |      -> <function Runner.run at 0x106882160>
                                    -> <asyncio.runners.Runner object at 0x10e194fd0>
                           File "/opt/anaconda3/lib/python3.11/asyncio/runners.py", line 118, in run
                             return self._loop.run_until_complete(task)
                                    |    |     |                  -> <Task pending name='Task-1' coro=<LangflowUvicornWorker._serve() running at
                         /opt/anaconda3/lib/python3.11/site-packages/langf...
                                    |    |     -> <function _patch_loop.<locals>.run_until_complete at 0x10ee722a0>
                                    |    -> <_UnixSelectorEventLoop running=True closed=False debug=False>
                                    -> <asyncio.runners.Runner object at 0x10e194fd0>
                           File "/opt/anaconda3/lib/python3.11/asyncio/base_events.py", line 640, in run_until_complete
                             self.run_forever()
                             |    -> <function _patch_loop.<locals>.run_forever at 0x10ee72200>
                             -> <_UnixSelectorEventLoop running=True closed=False debug=False>
                           File "/opt/anaconda3/lib/python3.11/asyncio/base_events.py", line 607, in run_forever
                             self._run_once()
                             |    -> <function _patch_loop.<locals>._run_once at 0x10ee72340>
                             -> <_UnixSelectorEventLoop running=True closed=False debug=False>
                           File "/opt/anaconda3/lib/python3.11/site-packages/nest_asyncio.py", line 133, in _run_once
                             handle._run()
                             |      -> <function Handle._run at 0x1067f2980>
                             -> <Handle Task.__wakeup(<Future finis... 42, 199421))>)>
                           File "/opt/anaconda3/lib/python3.11/asyncio/events.py", line 80, in _run
                             self._context.run(self._callback, *self._args)
                             |    |            |    |           |    -> <member '_args' of 'Handle' objects>
                             |    |            |    |           -> <Handle Task.__wakeup(<Future finis... 42, 199421))>)>
                             |    |            |    -> <member '_callback' of 'Handle' objects>
                             |    |            -> <Handle Task.__wakeup(<Future finis... 42, 199421))>)>
                             |    -> <member '_context' of 'Handle' objects>
                             -> <Handle Task.__wakeup(<Future finis... 42, 199421))>)>
                           File "/opt/anaconda3/lib/python3.11/asyncio/tasks.py", line 360, in __wakeup
                             self.__step()
                             -> <Task pending name='starlette.middleware.base.BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.coro' coro=<BaseHTTPMid...
                           File "/opt/anaconda3/lib/python3.11/asyncio/tasks.py", line 277, in __step
                             result = coro.send(None)
                                      |    -> <method 'send' of 'coroutine' objects>
                                      -> <coroutine object BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.coro at 0x16683f780>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/middleware/base.py", line 151, in coro
                             await self.app(scope, receive_or_disconnect, send_no_error)
                                   |    |   |      |                      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.send_no_error at 0x166f85300>
                                   |    |   |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |    |   -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |    -> <starlette.middleware.cors.CORSMiddleware object at 0x10ee6d310>
                                   -> <langflow.main.JavaScriptMIMETypeMiddleware object at 0x10ee6d3d0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/middleware/cors.py", line 93, in __call__
                             await self.simple_response(scope, receive, send, request_headers=headers)
                                   |    |               |      |        |                     -> Headers({'host': '192.168.0.109:7860', 'connection': 'keep-alive', 'content-length': '10462',
                         'accept': 'application/json, te...
                                   |    |               |      |        -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.send_no_error at 0x166f85300>
                                   |    |               |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |    |               -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |    -> <function CORSMiddleware.simple_response at 0x107fd0540>
                                   -> <starlette.middleware.cors.CORSMiddleware object at 0x10ee6d310>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/middleware/cors.py", line 148, in simple_response
                             await self.app(scope, receive, send)
                                   |    |   |      |        -> functools.partial(<bound method CORSMiddleware.send of <starlette.middleware.cors.CORSMiddleware object at 0x10ee6d310>>, sen...
                                   |    |   |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |    |   -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |    -> <starlette.middleware.exceptions.ExceptionMiddleware object at 0x10ee6d290>
                                   -> <starlette.middleware.cors.CORSMiddleware object at 0x10ee6d310>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
                             await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
                                   |                            |    |    |     |      |        -> functools.partial(<bound method CORSMiddleware.send of <starlette.middleware.cors.CORSMiddleware
                         object at 0x10ee6d310>>, sen...
                                   |                            |    |    |     |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |                            |    |    |     -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server':
                         ('192.168.0.109', 7860),...
                                   |                            |    |    -> <starlette.requests.Request object at 0x166e3b510>
                                   |                            |    -> <fastapi.routing.APIRouter object at 0x10e457750>
                                   |                            -> <starlette.middleware.exceptions.ExceptionMiddleware object at 0x10ee6d290>
                                   -> <function wrap_app_handling_exceptions at 0x107f451c0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
                             await app(scope, receive, sender)
                                   |   |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86520>
                                   |   |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |   -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   -> <fastapi.routing.APIRouter object at 0x10e457750>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/routing.py", line 756, in __call__
                             await self.middleware_stack(scope, receive, send)
                                   |    |                |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86520>
                                   |    |                |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |    |                -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |    -> <bound method Router.app of <fastapi.routing.APIRouter object at 0x10e457750>>
                                   -> <fastapi.routing.APIRouter object at 0x10e457750>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/routing.py", line 776, in app
                             await route.handle(scope, receive, send)
                                   |     |      |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86520>
                                   |     |      |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |     |      -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |     -> <function Route.handle at 0x107f46840>
                                   -> APIRoute(path='/api/v1/custom_component/update', name='custom_component_update', methods=['POST'])
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/routing.py", line 297, in handle
                             await self.app(scope, receive, send)
                                   |    |   |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86520>
                                   |    |   |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |    |   -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   |    -> <function request_response.<locals>.app at 0x10e988ae0>
                                   -> APIRoute(path='/api/v1/custom_component/update', name='custom_component_update', methods=['POST'])
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/routing.py", line 77, in app
                             await wrap_app_handling_exceptions(app, request)(scope, receive, send)
                                   |                            |    |        |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86520>
                                   |                            |    |        |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |                            |    |        -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server':
                         ('192.168.0.109', 7860),...
                                   |                            |    -> <starlette.requests.Request object at 0x166e3b090>
                                   |                            -> <function request_response.<locals>.app.<locals>.app at 0x166f85800>
                                   -> <function wrap_app_handling_exceptions at 0x107f451c0>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
                             await app(scope, receive, sender)
                                   |   |      |        -> <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x166f86c00>
                                   |   |      -> <function BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.receive_or_disconnect at 0x166f85940>
                                   |   -> {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.4'}, 'http_version': '1.1', 'server': ('192.168.0.109', 7860),...
                                   -> <function request_response.<locals>.app.<locals>.app at 0x166f85800>
                           File "/opt/anaconda3/lib/python3.11/site-packages/starlette/routing.py", line 72, in app
                             response = await func(request)
                                              |    -> <starlette.requests.Request object at 0x166e3b090>
                                              -> <function get_request_handler.<locals>.app at 0x10e988d60>
                           File "/opt/anaconda3/lib/python3.11/site-packages/fastapi/routing.py", line 278, in app
                             raw_response = await run_endpoint_function(
                                                  -> <function run_endpoint_function at 0x107f46340>
                           File "/opt/anaconda3/lib/python3.11/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
                             return await dependant.call(**values)
                                          |         |      -> {'user': User(id=UUID('6f965e5d-dedd-4238-9541-1a5ddcbc9698'), username='langflow', profile_image=None, is_superuser=True, up...
                                          |         -> <function custom_component_update at 0x10e49f6a0>
                                          -> <fastapi.dependencies.models.Dependant object at 0x10e9932d0>
                         > File "/opt/anaconda3/lib/python3.11/site-packages/langflow/api/v1/endpoints.py", line 593, in custom_component_update
                             params = {key: value_dict["value"] for key, value_dict in template.items() if isinstance(value_dict, dict)}
                                                                                       |        -> <method 'items' of 'dict' objects>
                                                                                       -> {'_type': 'CustomComponent', 'code': {'type': 'code', 'required': True, 'placeholder': '', 'list': False,
                         'show': True, 'mult...
                           File "/opt/anaconda3/lib/python3.11/site-packages/langflow/api/v1/endpoints.py", line 593, in <dictcomp>
                             params = {key: value_dict["value"] for key, value_dict in template.items() if isinstance(value_dict, dict)}
                                       |    |                       |    |                                            -> {'type': 'str', 'required': True, 'placeholder': '', 'list': True, 'show':
                         True, 'multiline': False, 'fileTypes': [], 'file_p...
                                       |    |                       |    -> {'type': 'str', 'required': True, 'placeholder': '', 'list': True, 'show': True, 'multiline': False, 'fileTypes': [],
                         'file_p...
                                       |    |                       -> 'flow_name'
                                       |    -> {'type': 'str', 'required': True, 'placeholder': '', 'list': True, 'show': True, 'multiline': False, 'fileTypes': [], 'file_p...
                                       -> 'flow_name'

                         KeyError: 'value'

                         ╭────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────╮
                         │ /opt/anaconda3/lib/python3.11/site-packages/langflow/api/v1/endpoints.py:593 in custom_component_update                                                                │
                         │                                                                                                                                                                        │
                         │   590 │   │   )                                                                                                                                                        │
                         │   591 │   │   if hasattr(cc_instance, "set_attributes"):                                                                                                               │
                         │   592 │   │   │   template = code_request.get_template()                                                                                                               │
                         │ ? 593 │   │   │   params = {key: value_dict["value"] for key, value_dict in template.items()                                                                           │
                         │       if isinstance(value_dict, dict)}                                                                                                                                 │
                         │   594 │   │   │   load_from_db_fields = [                                                                                                                              │
                         │   595 │   │   │   │   field_name                                                                                                                                       │
                         │   596 │   │   │   │   for field_name, field_dict in template.items()                                                                                                   │
                         │                                                                                                                                                                        │
                         │ /opt/anaconda3/lib/python3.11/site-packages/langflow/api/v1/endpoints.py:593 in <dictcomp>                                                                             │
                         │                                                                                                                                                                        │
                         │   590 │   │   )                                                                                                                                                        │
                         │   591 │   │   if hasattr(cc_instance, "set_attributes"):                                                                                                               │
                         │   592 │   │   │   template = code_request.get_template()                                                                                                               │
                         │ ? 593 │   │   │   params = {key: value_dict["value"] for key, value_dict in template.items()                                                                           │
                         │       if isinstance(value_dict, dict)}                                                                                                                                 │
                         │   594 │   │   │   load_from_db_fields = [                                                                                                                              │
                         │   595 │   │   │   │   field_name                                                                                                                                       │
                         │   596 │   │   │   │   for field_name, field_dict in template.items()                                                                                                   │
                         ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
                         KeyError: 'value'

From: dosubot[bot] @.> Date: Saturday, 20 July 2024 at 11:31 To: langflow-ai/langflow @.> Cc: azaidiuk @.>, Author @.> Subject: Re: [langflow-ai/langflow] SubFlow not working (Issue #2852)

The issue with the SubFlow component in Langflow Version 1.11 on Mac OSX with Python 3.10, where it shows "No Fields found" when selecting from the dropdown, is likely due to the update_build_config method not properly updating the build_config with the available flow names. Specifically, the build_config["flow_name"]["options"] is not being populated correctly.

Here is the relevant part of the code:

def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):

logger.debug(f"Updating build config with field value {field_value} and field name {field_name}")

if field_name == "flow_name":

    build_config["flow_name"]["options"] = self.get_flow_names()

# Clean up the build config

for key in list(build_config.keys()):

    if key not in self.field_order + ["code", "_type", "get_final_results_only"]:

        del build_config[key]

if field_value is not None and field_name == "flow_name":

    try:

        flow_data = self.get_flow(field_value)

        if not flow_data:

            raise ValueError(f"Flow {field_value} not found.")

        graph = Graph.from_payload(flow_data.data["data"])

        # Get all inputs from the graph

        inputs = get_flow_inputs(graph)

        # Add inputs to the build config

        build_config = self.add_inputs_to_build_config(inputs, build_config)

    except Exception as e:

        logger.error(f"Error getting flow {field_value}: {str(e)}")

return build_config

The get_flow_names method is supposed to return a list of flow names, but if list_flows does not return any flows or if there is an issue with fetching the flow names, the options list will remain empty, leading to "No Fields found" in the dropdown.

To resolve this, ensure that list_flows is correctly implemented and returning the expected flow data. Additionally, verify that get_flow_names is correctly extracting the flow names from the returned data. Here is the implementation of get_flow_names and get_flow:

def get_flow_names(self) -> List[str]:

flow_datas = self.list_flows()

return [flow_data.data["name"] for flow_data in flow_datas]

def get_flow(self, flow_name: str) -> Optional[Data]:

flow_datas = self.list_flows()

for flow_data in flow_datas:

    if flow_data.data["name"] == flow_name:

        return flow_data

return None

Additionally, ensure that the add_inputs_to_build_config method is correctly adding the inputs to the build_config:

def add_inputs_to_build_config(self, inputs: List[Vertex], build_config: dotdict):

new_fields: list[Input] = []

for vertex in inputs:

    field = Input(

        display_name=vertex.display_name,

        name=vertex.id,

        info=vertex.description,

        field_type="str",

        value=None,

    )

    new_fields.append(field)

logger.debug(new_fields)

for field in new_fields:

    build_config[field.name] = field.to_dict()

return build_config

By ensuring these methods are correctly implemented and functioning, the "No Fields found" issue should be resolved [1]https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/components/experimental/SubFlow.py[2]https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/components/prototypes/SubFlow.py[3]https://github.com/langflow-ai/langflow/blob/dev/src/backend/base/langflow/components/deactivated/SubFlow.py.

To continue talking to Dosuhttps://dosu.dev, mention @dosuhttps://github.com/dosu.

— Reply to this email directly, view it on GitHubhttps://github.com/langflow-ai/langflow/issues/2852#issuecomment-2241079121, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJIB6Y5RQNL7JNSMBX2KR3DZNI37DAVCNFSM6AAAAABLF2I6KGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENBRGA3TSMJSGE. You are receiving this because you authored the thread.Message ID: @.***>

dosubot[bot] commented 2 months ago

The KeyError: 'value' in the custom_component_update function occurs because value_dict does not contain the key "value". To resolve this, you need to ensure that the value_dict contains the key "value" before attempting to access it.

Here is the updated code with the necessary check:

def update_template_values(frontend_template, raw_template):
    """Updates the frontend template with values from the raw template."""
    for key, value_dict in raw_template.items():
        if key == "code" or not isinstance(value_dict, dict):
            continue

        update_template_field(frontend_template, key, value_dict)

def update_template_field(frontend_template, key, value_dict):
    """Updates a specific field in the frontend template."""
    template_field = frontend_template.get(key)
    if not template_field or template_field.get("type") != value_dict.get("type"):
        return

    if "value" in value_dict and value_dict["value"]:
        template_field["value"] = value_dict["value"]

    if "file_path" in value_dict and value_dict["file_path"]:
        file_path_value = get_file_path_value(value_dict["file_path"])
        if not file_path_value:
            # If the file does not exist, remove the value from the template_field["value"]
            template_field["value"] = ""
        template_field["file_path"] = file_path_value

    if "load_from_db" in value_dict and value_dict["load_from_db"]:
        template_field["load_from_db"] = value_dict["load_from_db"]

By adding the check if "value" in value_dict and value_dict["value"]: before accessing value_dict["value"], you ensure that the key "value" exists in value_dict and is not None or an empty string, thus preventing the KeyError [1].

To continue talking to Dosu, mention @dosu.

lucaseduoli commented 2 months ago

Hello!

I'm sorry to hear about the problem you're having! I'm closing this issue because there is an existing issue that is more generic, but you can follow the progress of the issue #2972 to be notified when your problem gets resolved.

Thanks!