chainlit icon indicating copy to clipboard operation
chainlit copied to clipboard

1.2.0 breaks Custom Data Layer

Open marketneutral opened this issue 1 year ago • 2 comments

Describe the bug Release 1.2.0 breaks the example(s) in https://docs.chainlit.io/data-persistence/custom

To Reproduce

This is the code that works prior to 1.2.0

storage_client = S3StorageClient(bucket=bucket_name)
cl_data._data_layer = SQLAlchemyDataLayer(conninfo=db, storage_provider=storage_client)

After 1.2.0, on startup, I get the TypeError

2024-10-01 14:26:12 - S3StorageClient initialized
Traceback (most recent call last):
  File "/home/jlarkin/.conda/envs/chatimc/bin/chainlit", line 8, in <module>
    sys.exit(cli())
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/chainlit/cli/__init__.py", line 199, in chainlit_run
    run_chainlit(target)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/chainlit/cli/__init__.py", line 64, in run_chainlit
    load_module(config.run.module_name)
  File "/home/jlarkin/.conda/envs/chatimc/lib/python3.10/site-packages/chainlit/config.py", line 446, in load_module
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/jlarkin/chatimc/app.py", line 45, in <module>
    cl_data._data_layer = SQLAlchemyDataLayer(conninfo=db, storage_provider=storage_client)
TypeError: Can't instantiate abstract class SQLAlchemyDataLayer with abstract method get_element

Could you adivse on a new example for 1.2.0?

marketneutral avatar Oct 01 '24 18:10 marketneutral

Hey @marketneutral! I'm here to help you with any bugs, questions, or contributions. Let's tackle this together!

In version 1.2.0, the SQLAlchemyDataLayer class requires the implementation of certain abstract methods, such as get_element. This is likely causing the TypeError you're encountering.

To resolve this, you need to ensure that all required abstract methods are implemented in your custom data layer. Here's a basic example of how you might implement the get_element method:

from typing import Optional, Dict, Any, List, Union
import chainlit.data as cl_data
from chainlit.data.sql_alchemy import SQLAlchemyDataLayer
from chainlit.data.storage_clients import S3StorageClient

class CustomSQLAlchemyDataLayer(SQLAlchemyDataLayer):
    async def get_element(self, thread_id: str, element_id: str) -> Optional["ElementDict"]:
        # Implement the method logic here
        query = """SELECT * FROM elements WHERE "threadId" = :thread_id AND "id" = :element_id"""
        parameters = {"thread_id": thread_id, "element_id": element_id}
        element: Union[List[Dict[str, Any]], int, None] = await self.execute_sql(
            query=query, parameters=parameters
        )
        if isinstance(element, list) and element:
            element_dict: Dict[str, Any] = element[0]
            return ElementDict(
                id=element_dict["id"],
                threadId=element_dict.get("threadId"),
                type=element_dict["type"],
                chainlitKey=element_dict.get("chainlitKey"),
                url=element_dict.get("url"),
                objectKey=element_dict.get("objectKey"),
                name=element_dict["name"],
                display=element_dict["display"],
                size=element_dict.get("size"),
                language=element_dict.get("language"),
                page=element_dict.get("page"),
                autoPlay=element_dict.get("autoPlay"),
                playerConfig=element_dict.get("playerConfig"),
                forId=element_dict.get("forId"),
                mime=element_dict.get("mime"),
            )
        else:
            return None

# Usage
storage_client = S3StorageClient(bucket="your_bucket_name")
cl_data._data_layer = CustomSQLAlchemyDataLayer(conninfo="your_conninfo", storage_provider=storage_client)

Make sure to replace "your_bucket_name" and "your_conninfo" with your actual S3 bucket name and database connection information. This should help you get started with the updated version.

To continue talking to Dosu, mention @dosu.

dosubot[bot] avatar Oct 01 '24 18:10 dosubot[bot]

Fixed in #1346 a couple weeks ago but they haven't made a new release to include it

hayescode avatar Oct 01 '24 23:10 hayescode

Please make a new release, this blocks the update for us.

LeonKalt avatar Oct 08 '24 08:10 LeonKalt

@LeonKalt @hayescode Fix is part of 1.3.0rc0. Would love feedback on that. We'll probably release 1.3.0 start of next week.

dokterbob avatar Oct 10 '24 13:10 dokterbob