chainlit 0.4.1__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 (46) hide show
  1. {chainlit-0.4.1 → chainlit-0.4.2}/PKG-INFO +6 -3
  2. {chainlit-0.4.1 → chainlit-0.4.2}/README.md +4 -1
  3. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/__init__.py +28 -7
  4. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/action.py +2 -4
  5. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cli/__init__.py +64 -21
  6. chainlit-0.4.2/chainlit/client/base.py +152 -0
  7. chainlit-0.4.2/chainlit/client/cloud.py +440 -0
  8. chainlit-0.4.2/chainlit/client/local.py +257 -0
  9. chainlit-0.4.2/chainlit/client/utils.py +23 -0
  10. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/config.py +27 -4
  11. chainlit-0.4.2/chainlit/context.py +29 -0
  12. chainlit-0.4.2/chainlit/db/__init__.py +35 -0
  13. chainlit-0.4.2/chainlit/db/prisma/schema.prisma +48 -0
  14. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/element.py +54 -41
  15. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/emitter.py +1 -30
  16. chainlit-0.4.1/chainlit/frontend/dist/assets/index-51a1a88f.js → chainlit-0.4.2/chainlit/frontend/dist/assets/index-995e21ad.js +1 -1
  17. chainlit-0.4.2/chainlit/frontend/dist/assets/index-fb1e167a.js +523 -0
  18. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/frontend/dist/index.html +1 -1
  19. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/lc/agent.py +1 -0
  20. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/lc/callbacks.py +6 -21
  21. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/logger.py +7 -2
  22. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/message.py +22 -16
  23. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/server.py +136 -36
  24. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/session.py +1 -3
  25. chainlit-0.4.2/chainlit/sync.py +25 -0
  26. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/types.py +26 -1
  27. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/user_session.py +1 -1
  28. {chainlit-0.4.1 → chainlit-0.4.2}/pyproject.toml +2 -2
  29. chainlit-0.4.1/chainlit/client.py +0 -287
  30. chainlit-0.4.1/chainlit/frontend/dist/assets/index-68c36c96.js +0 -707
  31. chainlit-0.4.1/chainlit/sync.py +0 -37
  32. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/__main__.py +0 -0
  33. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cache.py +0 -0
  34. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cli/auth.py +0 -0
  35. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cli/deploy.py +0 -0
  36. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cli/mock.py +0 -0
  37. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/cli/utils.py +0 -0
  38. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/frontend/dist/assets/index-f93cc942.css +0 -0
  39. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/frontend/dist/assets/logo_dark-bc7401f6.svg +0 -0
  40. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/frontend/dist/assets/logo_light-f19fc2ea.svg +0 -0
  41. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/frontend/dist/favicon.svg +0 -0
  42. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/hello.py +0 -0
  43. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/lc/__init__.py +0 -0
  44. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/markdown.py +0 -0
  45. {chainlit-0.4.1 → chainlit-0.4.2}/chainlit/telemetry.py +0 -0
  46. {chainlit-0.4.1 → 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.1
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)
@@ -92,7 +92,10 @@ $ chainlit run demo.py -w
92
92
 
93
93
  ### 🔗 With LangChain
94
94
 
95
- 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.
96
99
 
97
100
  ## 🛣 Roadmap
98
101
  - [ ] New UI elements (spreadsheet, video, carousel...)
@@ -56,7 +56,10 @@ $ chainlit run demo.py -w
56
56
 
57
57
  ### 🔗 With LangChain
58
58
 
59
- 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.
60
63
 
61
64
  ## 🛣 Roadmap
62
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
@@ -18,6 +20,7 @@ from chainlit.message import Message, ErrorMessage, AskUserMessage, AskFileMessa
18
20
  from chainlit.user_session import user_session
19
21
  from chainlit.sync import run_sync, make_async
20
22
  from chainlit.cache import cache
23
+ from chainlit.context import get_emitter
21
24
 
22
25
  if LANGCHAIN_INSTALLED:
23
26
  from chainlit.lc.callbacks import (
@@ -43,7 +46,7 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
43
46
  Callable: The wrapped function.
44
47
  """
45
48
 
46
- async def wrapper(*args, __chainlit_emitter__: ChainlitEmitter):
49
+ async def wrapper(*args):
47
50
  # Get the parameter names of the user-defined function
48
51
  user_function_params = list(inspect.signature(user_function).parameters.keys())
49
52
 
@@ -52,8 +55,10 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
52
55
  param_name: arg for param_name, arg in zip(user_function_params, args)
53
56
  }
54
57
 
58
+ emitter = get_emitter()
59
+
55
60
  if with_task:
56
- await __chainlit_emitter__.task_start()
61
+ await emitter.task_start()
57
62
 
58
63
  try:
59
64
  # Call the user-defined function with the arguments
@@ -65,10 +70,12 @@ def wrap_user_function(user_function: Callable, with_task=False) -> Callable:
65
70
  pass
66
71
  except Exception as e:
67
72
  logger.exception(e)
68
- await ErrorMessage(content=str(e), author="Error").send()
73
+ await ErrorMessage(
74
+ content=str(e) or e.__class__.__name__, author="Error"
75
+ ).send()
69
76
  finally:
70
77
  if with_task:
71
- await __chainlit_emitter__.task_end()
78
+ await emitter.task_end()
72
79
 
73
80
  return wrapper
74
81
 
@@ -206,7 +213,7 @@ def action_callback(name: str) -> Callable:
206
213
  Callback to call when an action is clicked in the UI.
207
214
 
208
215
  Args:
209
- 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.
210
217
  """
211
218
 
212
219
  def decorator(func: Callable[[Action], Any]):
@@ -216,6 +223,19 @@ def action_callback(name: str) -> Callable:
216
223
  return decorator
217
224
 
218
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
+
219
239
  def sleep(duration: int):
220
240
  """
221
241
  Sleep for a given duration.
@@ -248,6 +268,7 @@ __all__ = [
248
268
  "sleep",
249
269
  "ChainlitCallbackHandler",
250
270
  "AsyncChainlitCallbackHandler",
271
+ "client_factory",
251
272
  "run_sync",
252
273
  "make_async",
253
274
  "cache",
@@ -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__}")
@@ -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