chainlit 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of chainlit might be problematic. Click here for more details.

Files changed (48) hide show
  1. {chainlit-0.4.0 → chainlit-0.4.2}/PKG-INFO +8 -3
  2. {chainlit-0.4.0 → chainlit-0.4.2}/README.md +6 -1
  3. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/__init__.py +30 -7
  4. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/action.py +2 -4
  5. chainlit-0.4.2/chainlit/cache.py +45 -0
  6. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/cli/__init__.py +64 -21
  7. chainlit-0.4.2/chainlit/client/base.py +152 -0
  8. chainlit-0.4.2/chainlit/client/cloud.py +440 -0
  9. chainlit-0.4.2/chainlit/client/local.py +257 -0
  10. chainlit-0.4.2/chainlit/client/utils.py +23 -0
  11. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/config.py +92 -29
  12. chainlit-0.4.2/chainlit/context.py +29 -0
  13. chainlit-0.4.2/chainlit/db/__init__.py +35 -0
  14. chainlit-0.4.2/chainlit/db/prisma/schema.prisma +48 -0
  15. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/element.py +54 -41
  16. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/emitter.py +1 -30
  17. chainlit-0.4.2/chainlit/frontend/dist/assets/index-995e21ad.js +11 -0
  18. chainlit-0.4.2/chainlit/frontend/dist/assets/index-f93cc942.css +1 -0
  19. chainlit-0.4.2/chainlit/frontend/dist/assets/index-fb1e167a.js +523 -0
  20. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/frontend/dist/index.html +2 -2
  21. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/lc/agent.py +1 -0
  22. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/lc/callbacks.py +6 -21
  23. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/logger.py +7 -2
  24. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/message.py +22 -16
  25. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/server.py +169 -59
  26. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/session.py +1 -3
  27. chainlit-0.4.2/chainlit/sync.py +25 -0
  28. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/types.py +26 -1
  29. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/user_session.py +1 -1
  30. {chainlit-0.4.0 → chainlit-0.4.2}/pyproject.toml +2 -2
  31. chainlit-0.4.0/chainlit/cache.py +0 -22
  32. chainlit-0.4.0/chainlit/client.py +0 -287
  33. chainlit-0.4.0/chainlit/frontend/dist/assets/index-0cc9e355.css +0 -1
  34. chainlit-0.4.0/chainlit/frontend/dist/assets/index-9e4bccd1.js +0 -717
  35. chainlit-0.4.0/chainlit/sync.py +0 -37
  36. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/__main__.py +0 -0
  37. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/cli/auth.py +0 -0
  38. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/cli/deploy.py +0 -0
  39. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/cli/mock.py +0 -0
  40. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/cli/utils.py +0 -0
  41. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/frontend/dist/assets/logo_dark-bc7401f6.svg +0 -0
  42. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/frontend/dist/assets/logo_light-f19fc2ea.svg +0 -0
  43. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/frontend/dist/favicon.svg +0 -0
  44. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/hello.py +0 -0
  45. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/lc/__init__.py +0 -0
  46. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/markdown.py +0 -0
  47. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/telemetry.py +0 -0
  48. {chainlit-0.4.0 → chainlit-0.4.2}/chainlit/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: chainlit
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A faster way to build chatbot UIs.
5
5
  Home-page: https://github.com/Chainlit/chainlit
6
6
  License: Apache-2.0 license
@@ -21,8 +21,8 @@ Requires-Dist: click (>=8.1.3,<9.0.0)
21
21
  Requires-Dist: dataclasses_json (>=0.5.7,<0.6.0)
22
22
  Requires-Dist: fastapi (>=0.96.0,<0.97.0)
23
23
  Requires-Dist: fastapi-socketio (>=0.0.10,<0.0.11)
24
- Requires-Dist: nest-asyncio (>=1.5.6,<2.0.0)
25
24
  Requires-Dist: openai (>=0.27.7,<0.28.0)
25
+ Requires-Dist: prisma (>=0.9.0,<0.10.0)
26
26
  Requires-Dist: pydantic (>=1.10.8,<2.0.0)
27
27
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
28
28
  Requires-Dist: python-graphql-client (>=0.4.3,<0.5.0)
@@ -44,6 +44,8 @@ Chainlit lets you create ChatGPT-like UIs on top of any Python code in minutes!
44
44
  [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/chainlit_io.svg?style=social&label=Follow%20%40chainlit_io)](https://twitter.com/chainlit_io)
45
45
  [![CI](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml/badge.svg)](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml)
46
46
 
47
+ https://github.com/Chainlit/chainlit/assets/13104895/e347e52c-35b2-4c35-8a88-f8ac02dd198e
48
+
47
49
  ## Installation
48
50
 
49
51
  Open a terminal and run:
@@ -90,7 +92,10 @@ $ chainlit run demo.py -w
90
92
 
91
93
  ### 🔗 With LangChain
92
94
 
93
- Checkout our plug and play [integration](https://docs.chainlit.io/langchain) with LangChain!
95
+ Check out our plug-and-play [integration](https://docs.chainlit.io/langchain) with LangChain!
96
+
97
+ ### 📚 More Examples - Cookbook
98
+ You can find various examples of Chainlit apps [here](https://github.com/Chainlit/cookbook) that leverage tools and services such as OpenAI, Anthropiс, LangChain, LlamaIndex, ChromaDB, Pinecone and more.
94
99
 
95
100
  ## 🛣 Roadmap
96
101
  - [ ] New UI elements (spreadsheet, video, carousel...)
@@ -8,6 +8,8 @@ Chainlit lets you create ChatGPT-like UIs on top of any Python code in minutes!
8
8
  [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/chainlit_io.svg?style=social&label=Follow%20%40chainlit_io)](https://twitter.com/chainlit_io)
9
9
  [![CI](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml/badge.svg)](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml)
10
10
 
11
+ https://github.com/Chainlit/chainlit/assets/13104895/e347e52c-35b2-4c35-8a88-f8ac02dd198e
12
+
11
13
  ## Installation
12
14
 
13
15
  Open a terminal and run:
@@ -54,7 +56,10 @@ $ chainlit run demo.py -w
54
56
 
55
57
  ### 🔗 With LangChain
56
58
 
57
- Checkout our plug and play [integration](https://docs.chainlit.io/langchain) with LangChain!
59
+ Check out our plug-and-play [integration](https://docs.chainlit.io/langchain) with LangChain!
60
+
61
+ ### 📚 More Examples - Cookbook
62
+ You can find various examples of Chainlit apps [here](https://github.com/Chainlit/cookbook) that leverage tools and services such as OpenAI, Anthropiс, LangChain, LlamaIndex, ChromaDB, Pinecone and more.
58
63
 
59
64
  ## 🛣 Roadmap
60
65
  - [ ] New UI elements (spreadsheet, video, carousel...)
@@ -1,15 +1,17 @@
1
1
  from dotenv import load_dotenv
2
- from typing import Callable, Any
2
+ from typing import Callable, Any, TYPE_CHECKING
3
3
  import inspect
4
4
  import os
5
5
  import asyncio
6
6
 
7
+ if TYPE_CHECKING:
8
+ from chainlit.client.base import BaseClient
9
+
7
10
  from chainlit.lc import LANGCHAIN_INSTALLED
8
11
  from chainlit.config import config
9
12
  from chainlit.telemetry import trace
10
13
  from chainlit.version import __version__
11
14
  from chainlit.logger import logger
12
- from chainlit.emitter import ChainlitEmitter
13
15
  from chainlit.types import LLMSettings
14
16
  from chainlit.message import ErrorMessage
15
17
  from chainlit.action import Action
@@ -17,6 +19,8 @@ from chainlit.element import Image, Text, Pdf, Avatar, Pyplot
17
19
  from chainlit.message import Message, ErrorMessage, AskUserMessage, AskFileMessage
18
20
  from chainlit.user_session import user_session
19
21
  from chainlit.sync import run_sync, make_async
22
+ from chainlit.cache import cache
23
+ from chainlit.context import get_emitter
20
24
 
21
25
  if LANGCHAIN_INSTALLED:
22
26
  from chainlit.lc.callbacks import (
@@ -42,7 +46,7 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
42
46
  Callable: The wrapped function.
43
47
  """
44
48
 
45
- async def wrapper(*args, __chainlit_emitter__: ChainlitEmitter):
49
+ async def wrapper(*args):
46
50
  # Get the parameter names of the user-defined function
47
51
  user_function_params = list(inspect.signature(user_function).parameters.keys())
48
52
 
@@ -51,8 +55,10 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
51
55
  param_name: arg for param_name, arg in zip(user_function_params, args)
52
56
  }
53
57
 
58
+ emitter = get_emitter()
59
+
54
60
  if with_task:
55
- await __chainlit_emitter__.task_start()
61
+ await emitter.task_start()
56
62
 
57
63
  try:
58
64
  # Call the user-defined function with the arguments
@@ -64,10 +70,12 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
64
70
  pass
65
71
  except Exception as e:
66
72
  logger.exception(e)
67
- await ErrorMessage(content=str(e), author="Error").send()
73
+ await ErrorMessage(
74
+ content=str(e) or e.__class__.__name__, author="Error"
75
+ ).send()
68
76
  finally:
69
77
  if with_task:
70
- await __chainlit_emitter__.task_end()
78
+ await emitter.task_end()
71
79
 
72
80
  return wrapper
73
81
 
@@ -205,7 +213,7 @@ def action_callback(name: str) -> Callable:
205
213
  Callback to call when an action is clicked in the UI.
206
214
 
207
215
  Args:
208
- func (Callable[[Action], Any]): The action callback to exexute. First parameter is the action.
216
+ func (Callable[[Action], Any]): The action callback to execute. First parameter is the action.
209
217
  """
210
218
 
211
219
  def decorator(func: Callable[[Action], Any]):
@@ -215,6 +223,19 @@ def action_callback(name: str) -> Callable:
215
223
  return decorator
216
224
 
217
225
 
226
+ @trace
227
+ def client_factory(func: Callable[[], "BaseClient"]) -> Callable[[], "BaseClient"]:
228
+ """
229
+ Callback to call when to initialize the custom client.
230
+
231
+ Args:
232
+ func (Callable[[str], BaseClient]): The action callback to execute. First parameter is the session id.
233
+ """
234
+
235
+ config.code.client_factory = func
236
+ return func
237
+
238
+
218
239
  def sleep(duration: int):
219
240
  """
220
241
  Sleep for a given duration.
@@ -247,6 +268,8 @@ __all__ = [
247
268
  "sleep",
248
269
  "ChainlitCallbackHandler",
249
270
  "AsyncChainlitCallbackHandler",
271
+ "client_factory",
250
272
  "run_sync",
251
273
  "make_async",
274
+ "cache",
252
275
  ]
@@ -1,7 +1,7 @@
1
1
  from pydantic.dataclasses import dataclass
2
2
  from dataclasses_json import dataclass_json
3
3
 
4
- from chainlit.emitter import get_emit_fn
4
+ from chainlit.context import get_emitter
5
5
  from chainlit.telemetry import trace_event
6
6
 
7
7
 
@@ -21,9 +21,7 @@ class Action:
21
21
 
22
22
  def __post_init__(self) -> None:
23
23
  trace_event(f"init {self.__class__.__name__}")
24
- self.emit = get_emit_fn()
25
- if not self.emit:
26
- raise RuntimeError("Action should be instantiated in a Chainlit context")
24
+ self.emit = get_emitter().emit
27
25
 
28
26
  async def send(self, for_id: str):
29
27
  trace_event(f"send {self.__class__.__name__}")
@@ -0,0 +1,45 @@
1
+ import os
2
+ import threading
3
+
4
+ from chainlit.config import config
5
+ from chainlit.logger import logger
6
+ from chainlit.lc import LANGCHAIN_INSTALLED
7
+
8
+
9
+ def init_lc_cache():
10
+ use_cache = config.run.no_cache is False and config.run.ci is False
11
+
12
+ if LANGCHAIN_INSTALLED and use_cache:
13
+ import langchain
14
+ from langchain.cache import SQLiteCache
15
+
16
+ if config.project.lc_cache_path is not None:
17
+ langchain.llm_cache = SQLiteCache(
18
+ database_path=config.project.lc_cache_path
19
+ )
20
+ if not os.path.exists(config.project.lc_cache_path):
21
+ logger.info(
22
+ f"LangChain cache created at: {config.project.lc_cache_path}"
23
+ )
24
+
25
+
26
+ _cache = {}
27
+ _cache_lock = threading.Lock()
28
+
29
+
30
+ def cache(func):
31
+ def wrapper(*args, **kwargs):
32
+ # Create a cache key based on the function name, arguments, and keyword arguments
33
+ cache_key = (
34
+ (func.__name__,) + args + tuple((k, v) for k, v in sorted(kwargs.items()))
35
+ )
36
+
37
+ with _cache_lock:
38
+ # Check if the result is already in the cache
39
+ if cache_key not in _cache:
40
+ # If not, call the function and store the result in the cache
41
+ _cache[cache_key] = func(*args, **kwargs)
42
+
43
+ return _cache[cache_key]
44
+
45
+ return wrapper
@@ -2,10 +2,6 @@ import click
2
2
  import os
3
3
  import sys
4
4
  import uvicorn
5
- import asyncio
6
- import nest_asyncio
7
-
8
- nest_asyncio.apply()
9
5
 
10
6
  from chainlit.config import (
11
7
  config,
@@ -21,6 +17,7 @@ from chainlit.cli.deploy import deploy
21
17
  from chainlit.cli.utils import check_file
22
18
  from chainlit.telemetry import trace_event
23
19
  from chainlit.cache import init_lc_cache
20
+ from chainlit.db import init_local_db, migrate_local_db
24
21
  from chainlit.logger import logger
25
22
  from chainlit.server import app
26
23
 
@@ -50,36 +47,74 @@ def run_chainlit(target: str):
50
47
  # Initialize the LangChain cache if installed and enabled
51
48
  init_lc_cache()
52
49
 
53
- log_level = "debug" if config.run.debug else "error"
50
+ # Initialize the local database if configured to use it
51
+ init_local_db()
54
52
 
55
- # Start the server
56
- async def start():
57
- config = uvicorn.Config(app, host=host, port=port, log_level=log_level)
58
- server = uvicorn.Server(config)
59
- await server.serve()
53
+ log_level = "debug" if config.run.debug else "error"
60
54
 
61
- # Run the asyncio event loop instead of uvloop to enable re entrance
62
- asyncio.run(start())
63
- # uvicorn.run(app, host=host, port=port)
55
+ uvicorn.run(app, host=host, port=port, log_level=log_level)
64
56
 
65
57
 
66
58
  # Define the "run" command for Chainlit CLI
67
59
  @cli.command("run")
68
60
  @click.argument("target", required=True, envvar="RUN_TARGET")
69
- @click.option("-w", "--watch", default=False, is_flag=True, envvar="WATCH")
70
- @click.option("-h", "--headless", default=False, is_flag=True, envvar="HEADLESS")
71
- @click.option("-d", "--debug", default=False, is_flag=True, envvar="DEBUG")
72
- @click.option("-c", "--ci", default=False, is_flag=True, envvar="CI")
73
- @click.option("--no-cache", default=False, is_flag=True, envvar="NO_CACHE")
74
- @click.option("--host")
75
- @click.option("--port")
76
- def chainlit_run(target, watch, headless, debug, ci, no_cache, host, port):
61
+ @click.option(
62
+ "-w",
63
+ "--watch",
64
+ default=False,
65
+ is_flag=True,
66
+ envvar="WATCH",
67
+ help="Reload the app when the module changes",
68
+ )
69
+ @click.option(
70
+ "-h",
71
+ "--headless",
72
+ default=False,
73
+ is_flag=True,
74
+ envvar="HEADLESS",
75
+ help="Will prevent to auto open the app in the browser",
76
+ )
77
+ @click.option(
78
+ "-d",
79
+ "--debug",
80
+ default=False,
81
+ is_flag=True,
82
+ envvar="DEBUG",
83
+ help="Set the log level to debug",
84
+ )
85
+ @click.option(
86
+ "-c",
87
+ "--ci",
88
+ default=False,
89
+ is_flag=True,
90
+ envvar="CI",
91
+ help="Flag to run in CI mode",
92
+ )
93
+ @click.option(
94
+ "--no-cache",
95
+ default=False,
96
+ is_flag=True,
97
+ envvar="NO_CACHE",
98
+ help="Useful to disable third parties cache, such as langchain.",
99
+ )
100
+ @click.option(
101
+ "--db",
102
+ type=click.Choice(["cloud", "local"]),
103
+ help="Useful to control database mode when running CI.",
104
+ )
105
+ @click.option("--host", help="Specify a different host to run the server on")
106
+ @click.option("--port", help="Specify a different port to run the server on")
107
+ def chainlit_run(target, watch, headless, debug, ci, no_cache, db, host, port):
77
108
  if host:
78
109
  os.environ["CHAINLIT_HOST"] = host
79
110
  if port:
80
111
  os.environ["CHAINLIT_PORT"] = port
81
112
  if ci:
82
113
  logger.info("Running in CI mode")
114
+
115
+ if db:
116
+ config.project.database = db
117
+
83
118
  config.project.enable_telemetry = False
84
119
  no_cache = True
85
120
  from chainlit.cli.mock import mock_openai
@@ -131,6 +166,14 @@ def chainlit_logout(args=None, **kwargs):
131
166
  sys.exit(0)
132
167
 
133
168
 
169
+ @cli.command("migrate")
170
+ @click.argument("args", nargs=-1)
171
+ def chainlit_migrate(args=None, **kwargs):
172
+ trace_event("chainlit migrate")
173
+ migrate_local_db()
174
+ sys.exit(0)
175
+
176
+
134
177
  @cli.command("init")
135
178
  @click.argument("args", nargs=-1)
136
179
  def chainlit_init(args=None, **kwargs):
@@ -0,0 +1,152 @@
1
+ from typing import (
2
+ Dict,
3
+ Any,
4
+ List,
5
+ TypedDict,
6
+ Optional,
7
+ Union,
8
+ Literal,
9
+ TypeVar,
10
+ Generic,
11
+ )
12
+
13
+ from abc import ABC, abstractmethod
14
+ from pydantic.dataclasses import dataclass
15
+ from dataclasses_json import dataclass_json
16
+
17
+ from chainlit.types import (
18
+ Pagination,
19
+ ConversationFilter,
20
+ ElementType,
21
+ ElementSize,
22
+ ElementDisplay,
23
+ )
24
+
25
+
26
+ class MessageDict(TypedDict):
27
+ conversationId: Optional[str]
28
+ id: Optional[int]
29
+ tempId: Optional[str]
30
+ createdAt: Optional[int]
31
+ content: str
32
+ author: str
33
+ prompt: Optional[str]
34
+ llmSettings: Dict
35
+ language: Optional[str]
36
+ indent: Optional[int]
37
+ authorIsUser: Optional[bool]
38
+ waitForAnswer: Optional[bool]
39
+ isError: Optional[bool]
40
+ humanFeedback: Optional[int]
41
+
42
+
43
+ class UserDict(TypedDict):
44
+ name: str
45
+ email: str
46
+ role: str
47
+
48
+
49
+ class ElementDict(TypedDict):
50
+ id: Optional[int]
51
+ conversationId: Optional[int]
52
+ type: ElementType
53
+ url: str
54
+ name: str
55
+ display: ElementDisplay
56
+ size: ElementSize
57
+ language: str
58
+ forIds: Optional[List[Union[str, int]]]
59
+
60
+
61
+ class ConversationDict(TypedDict):
62
+ id: Optional[int]
63
+ createdAt: Optional[int]
64
+ elementCount: Optional[int]
65
+ messageCount: Optional[int]
66
+ author: Optional[UserDict]
67
+ messages: List[MessageDict]
68
+ elements: Optional[List[ElementDict]]
69
+
70
+
71
+ @dataclass
72
+ class PageInfo:
73
+ hasNextPage: bool
74
+ endCursor: Any
75
+
76
+
77
+ T = TypeVar("T")
78
+
79
+
80
+ @dataclass_json
81
+ @dataclass
82
+ class PaginatedResponse(Generic[T]):
83
+ pageInfo: PageInfo
84
+ data: List[T]
85
+
86
+
87
+ class BaseClient(ABC):
88
+ project_id: str
89
+
90
+ @abstractmethod
91
+ async def is_project_member(self, access_token: str) -> bool:
92
+ pass
93
+
94
+ @abstractmethod
95
+ async def get_member_role(self, access_token: str) -> str:
96
+ pass
97
+
98
+ @abstractmethod
99
+ async def get_project_members(self) -> List[UserDict]:
100
+ pass
101
+
102
+ @abstractmethod
103
+ async def create_conversation(self) -> int:
104
+ pass
105
+
106
+ @abstractmethod
107
+ async def delete_conversation(self, conversation_id: int) -> bool:
108
+ pass
109
+
110
+ @abstractmethod
111
+ async def get_conversation(self, conversation_id: int) -> ConversationDict:
112
+ pass
113
+
114
+ @abstractmethod
115
+ async def get_conversations(
116
+ self, pagination: "Pagination", filter: "ConversationFilter"
117
+ ) -> PaginatedResponse[ConversationDict]:
118
+ pass
119
+
120
+ @abstractmethod
121
+ async def get_message(self, conversation_id: str, message_id: str) -> Dict:
122
+ pass
123
+
124
+ @abstractmethod
125
+ async def create_message(self, variables: MessageDict) -> int:
126
+ pass
127
+
128
+ @abstractmethod
129
+ async def update_message(self, message_id: int, variables: MessageDict) -> bool:
130
+ pass
131
+
132
+ @abstractmethod
133
+ async def delete_message(self, message_id: int) -> bool:
134
+ pass
135
+
136
+ @abstractmethod
137
+ async def upload_element(self, content: bytes, mime: str) -> str:
138
+ pass
139
+
140
+ @abstractmethod
141
+ async def upsert_element(self, variables: ElementDict) -> ElementDict:
142
+ pass
143
+
144
+ @abstractmethod
145
+ async def get_element(self, conversation_id: int, element_id: int) -> ElementDict:
146
+ pass
147
+
148
+ @abstractmethod
149
+ async def set_human_feedback(
150
+ self, message_id: int, feedback: Literal[-1, 0, 1]
151
+ ) -> bool:
152
+ pass