Chainlit / chainlit

Build Conversational AI in minutes ⚡️
https://docs.chainlit.io
Apache License 2.0
7.13k stars 936 forks source link

LookupError in ChainlitContext: ContextVar 'local_steps' Not Found When Converting FastAPI to WSGI with a2wsgi #1494

Open seleniumpython2016 opened 1 week ago

seleniumpython2016 commented 1 week ago

I use fastapi mount chainlit,and I use a2wsgi conver to wsgi,beacase I use gunicorn。the chanlit version is 1.3.0rc1 .when I open the chainlit url,the page can open,but the page shows that " it can not connect the server ". the errror log as the follows, who can help me?

2024-10-31 17:38:59 - <ContextVar name='local_steps' at 0x7fde381385e0> Traceback (most recent call last): File "/opt/app/.venv/lib/python3.10/site-packages/chainlit/utils.py", line 44, in wrapper return await user_function(**params_values) File "/opt/app/.venv/lib/python3.10/site-packages/chainlit/step.py", line 99, in async_wrapper async with Step( File "/opt/app/.venv/lib/python3.10/site-packages/chainlit/step.py", line 431, in aenter previous_steps = local_steps.get() or [] LookupError: <ContextVar name='local_steps' at 0x7fde381385e0> 2024-10-31 17:39:44 - Translated markdown file for zh-CN not found. Defaulting to chainlit.md. 2024-10-31 17:39:45 - <ContextVar name='local_steps' at 0x7fde381385e0>

dosubot[bot] commented 1 week ago

Sorry you're experiencing issues.

Could you please attach the full code and all steps required for us to replicate the problem?

Written by @dosu, edited by dokterbob

seleniumpython2016 commented 6 days ago

@dokterbob Thank you for your reply.

The app. py code is as follows:

      from fastapi import FastAPI
      from chainlit.utils import mount_chainlit
      from a2wsgi import ASGIMiddleware
      application = FastAPI()
      @application.get("/app")
      def read_main():
          return {"message": "Hello World from main app"}
      mount_chainlit(app=application, target="my_cl_app.py", path="/chainlit")
      application = ASGIMiddleware(application)

the my_cl_app.py code as follows:

      import chainlit as cl
      from generate.case_generate import CaseGenerate
      @cl.on_chat_start
      async def on_chat_start():
          msg = cl.Message(content=f"I will help you!")
          await msg.send()

      @cl.on_message
      async def on_message(message: cl.Message):
          files = message.elements
          print(files)
          if files is None or len(files) ==0:
              await cl.Message(content="please upload the file!").send()
          files_path = []
          for file in files:
              files_path.append(file.path)
          chain = CaseGenerate.case_gen(files_path,message.content)
          human_input = "auto case format"
          stream = await chain.arun(
              {"human_input":human_input},
          )
          await cl.Message(content=stream).send()

I use gunicorn run the fastapi( a2wsgi conver to wsgi) ,looking forward to your reply!

dokterbob commented 2 days ago

@dosu Any idea what's going on?

dosubot[bot] commented 2 days ago

The error you're encountering, "LookupError: ", typically occurs when the local_steps context variable is accessed without being properly initialized. This can happen when using FastAPI with Chainlit and converting the application to WSGI using a2wsgi, especially when running with Gunicorn.

To resolve this issue, you need to ensure that the local_steps context variable is initialized before it is accessed. You can do this by modifying the context initialization functions in Chainlit to set local_steps with an empty list. Here's how you can adjust the init_ws_context and init_http_context functions:

def init_ws_context(session_or_sid):
    if not isinstance(session_or_sid, WebsocketSession):
        session = WebsocketSession.require(session_or_sid)
    else:
        session = session_or_sid
    context = ChainlitContext(session)
    context_var.set(context)
    local_steps.set([])  # Initialize local_steps with an empty list
    return context

def init_http_context(thread_id=None, user=None, auth_token=None, user_env=None, client_type="webapp"):
    from chainlit.data import get_data_layer

    session_id = str(uuid.uuid4())
    thread_id = thread_id or str(uuid.uuid4())
    session = HTTPSession(
        id=session_id,
        thread_id=thread_id,
        token=auth_token,
        user=user,
        client_type=client_type,
        user_env=user_env,
    )
    context = ChainlitContext(session)
    context_var.set(context)
    local_steps.set([])  # Initialize local_steps with an empty list

    if data_layer := get_data_layer():
        if user_id := getattr(user, "id", None):
            asyncio.create_task(
                data_layer.update_thread(thread_id=thread_id, user_id=user_id)
            )

    return context

By ensuring local_steps is initialized with an empty list, you prevent the LookupError when accessing it in the current_step and current_run properties [1].

To continue talking to Dosu, mention @dosu.

dokterbob commented 2 days ago

@dosu Could you please suggest a clearer title for the issue?

dosubot[bot] commented 2 days ago

A clearer title for the issue could be: "LookupError in ChainlitContext: ContextVar 'local_steps' Not Found When Converting FastAPI to WSGI with a2wsgi" [1].

To continue talking to Dosu, mention @dosu.

seleniumpython2016 commented 1 day ago

@dosu Can you provide specific instructions on how to use it based on the code I provided above?

dosubot[bot] commented 1 day ago

To address the LookupError you're encountering with the local_steps context variable in your FastAPI application using Chainlit, you need to ensure that local_steps is initialized properly. Here's how you can modify your setup based on the code you provided:

  1. Modify the init_ws_context and init_http_context Functions: Ensure that local_steps is initialized with an empty list in these functions. This will prevent the LookupError when accessing local_steps.

    Update your Chainlit context initialization functions as follows:

    def init_ws_context(session_or_sid):
       if not isinstance(session_or_sid, WebsocketSession):
           session = WebsocketSession.require(session_or_sid)
       else:
           session = session_or_sid
       context = ChainlitContext(session)
       context_var.set(context)
       local_steps.set([])  # Initialize local_steps with an empty list
       return context
    
    def init_http_context(thread_id=None, user=None, auth_token=None, user_env=None, client_type="webapp"):
       from chainlit.data import get_data_layer
    
       session_id = str(uuid.uuid4())
       thread_id = thread_id or str(uuid.uuid4())
       session = HTTPSession(
           id=session_id,
           thread_id=thread_id,
           token=auth_token,
           user=user,
           client_type=client_type,
           user_env=user_env,
       )
       context = ChainlitContext(session)
       context_var.set(context)
       local_steps.set([])  # Initialize local_steps with an empty list
    
       if data_layer := get_data_layer():
           if user_id := getattr(user, "id", None):
               asyncio.create_task(
                   data_layer.update_thread(thread_id=thread_id, user_id=user_id)
               )
    
       return context
  2. Ensure Proper Initialization: Make sure these changes are applied in your Chainlit setup. This will ensure that every time a new session is created, local_steps is initialized correctly.

  3. Re-deploy Your Application: After making these changes, re-deploy your application using Gunicorn with the a2wsgi middleware to convert your FastAPI app to WSGI.

By following these steps, you should be able to resolve the LookupError related to the local_steps context variable.

To continue talking to Dosu, mention @dosu.