chainlit 提供了工具方法,可以方便的将同步转异步,同时将异步转同步

使用

  • 同步转异步
from chainlit import make_async
 
def my_sync_function():
    # Your synchronous code goes here
    import time
    time.sleep(10)
    return 0
 
async_function = make_async(my_sync_function)
 
async def main():
    result = await async_function()
异步转同步
from chainlit import run_sync
 
async def my_async_function():
    # Your asynchronous code goes here
 
def main():
    result = run_sync(my_async_function())
 
main()

 

内部处理

内部处理上chainlit使用了syncer以及asyncer 这几个包asyncer,是直接使用的,对于异步转同步,基于上下文进行了判断处理

  • 参考处理
import sys
from typing import Any, Coroutine, TypeVar
 
if sys.version_info >= (3, 10):
    from typing import ParamSpec
else:
    from typing_extensions import ParamSpec
 
import asyncio
import threading
 
from asyncer import asyncify
from chainlit.context import context_var
from syncer import sync
 
make_async = asyncify
 
T_Retval = TypeVar("T_Retval")
T_ParamSpec = ParamSpec("T_ParamSpec")
T = TypeVar("T")
 
 
def run_sync(co: Coroutine[Any, Any, T_Retval]) -> T_Retval:
    """Run the coroutine synchronously."""
 
    # Copy the current context
    current_context = context_var.get()
 
    # Define a wrapper coroutine that sets the context before running the original coroutine
    async def context_preserving_coroutine():
        # Set the copied context to the coroutine
        context_var.set(current_context)
        return await co
 
    # Execute from the main thread in the main event loop
    if threading.current_thread() == threading.main_thread():
        return sync(context_preserving_coroutine())
    else:  # Execute from a thread in the main event loop
        result = asyncio.run_coroutine_threadsafe(
            context_preserving_coroutine(), loop=current_context.loop
        )
        return result.result()
from typing import Any, Coroutine, TypeVar

参考资料

https://docs.chainlit.io/guides/sync-async
https://github.com/miyakogi/syncer
https://github.com/fastapi/asyncer