chainlit 1.0.401__py3-none-any.whl → 2.0.4__py3-none-any.whl
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.
- chainlit/__init__.py +98 -279
- chainlit/_utils.py +8 -0
- chainlit/action.py +12 -10
- chainlit/{auth.py → auth/__init__.py} +28 -36
- chainlit/auth/cookie.py +123 -0
- chainlit/auth/jwt.py +39 -0
- chainlit/cache.py +4 -6
- chainlit/callbacks.py +362 -0
- chainlit/chat_context.py +64 -0
- chainlit/chat_settings.py +3 -1
- chainlit/cli/__init__.py +77 -8
- chainlit/config.py +191 -102
- chainlit/context.py +42 -13
- chainlit/copilot/dist/index.js +8750 -903
- chainlit/data/__init__.py +101 -416
- chainlit/data/acl.py +6 -2
- chainlit/data/base.py +107 -0
- chainlit/data/chainlit_data_layer.py +614 -0
- chainlit/data/dynamodb.py +590 -0
- chainlit/data/literalai.py +500 -0
- chainlit/data/sql_alchemy.py +721 -0
- chainlit/data/storage_clients/__init__.py +0 -0
- chainlit/data/storage_clients/azure.py +81 -0
- chainlit/data/storage_clients/azure_blob.py +89 -0
- chainlit/data/storage_clients/base.py +26 -0
- chainlit/data/storage_clients/gcs.py +88 -0
- chainlit/data/storage_clients/s3.py +75 -0
- chainlit/data/utils.py +29 -0
- chainlit/discord/__init__.py +6 -0
- chainlit/discord/app.py +354 -0
- chainlit/element.py +91 -33
- chainlit/emitter.py +81 -29
- chainlit/frontend/dist/assets/DailyMotion-Ce9dQoqZ.js +1 -0
- chainlit/frontend/dist/assets/Dataframe-C1XonMcV.js +22 -0
- chainlit/frontend/dist/assets/Facebook-DVVt6lrr.js +1 -0
- chainlit/frontend/dist/assets/FilePlayer-c7stW4vz.js +1 -0
- chainlit/frontend/dist/assets/Kaltura-BmMmgorA.js +1 -0
- chainlit/frontend/dist/assets/Mixcloud-Cw8hDmiO.js +1 -0
- chainlit/frontend/dist/assets/Mux-DiRZfeUf.js +1 -0
- chainlit/frontend/dist/assets/Preview-6Jt2mRHx.js +1 -0
- chainlit/frontend/dist/assets/SoundCloud-DKwcT58_.js +1 -0
- chainlit/frontend/dist/assets/Streamable-BVdxrEeX.js +1 -0
- chainlit/frontend/dist/assets/Twitch-DFqZR7Gu.js +1 -0
- chainlit/frontend/dist/assets/Vidyard-0BQAAtVk.js +1 -0
- chainlit/frontend/dist/assets/Vimeo-CRFSH0Vu.js +1 -0
- chainlit/frontend/dist/assets/Wistia-CKrmdQaG.js +1 -0
- chainlit/frontend/dist/assets/YouTube-CQpL-rvU.js +1 -0
- chainlit/frontend/dist/assets/index-DQmLRKyv.css +1 -0
- chainlit/frontend/dist/assets/index-QdmxtIMQ.js +8665 -0
- chainlit/frontend/dist/assets/react-plotly-B9hvVpUG.js +3484 -0
- chainlit/frontend/dist/index.html +2 -4
- chainlit/haystack/callbacks.py +4 -7
- chainlit/input_widget.py +8 -4
- chainlit/langchain/callbacks.py +103 -68
- chainlit/langflow/__init__.py +1 -0
- chainlit/llama_index/callbacks.py +65 -40
- chainlit/markdown.py +22 -6
- chainlit/message.py +54 -56
- chainlit/mistralai/__init__.py +50 -0
- chainlit/oauth_providers.py +266 -8
- chainlit/openai/__init__.py +10 -18
- chainlit/secret.py +1 -1
- chainlit/server.py +789 -228
- chainlit/session.py +108 -90
- chainlit/slack/__init__.py +6 -0
- chainlit/slack/app.py +397 -0
- chainlit/socket.py +199 -116
- chainlit/step.py +141 -89
- chainlit/sync.py +2 -1
- chainlit/teams/__init__.py +6 -0
- chainlit/teams/app.py +338 -0
- chainlit/translations/bn.json +244 -0
- chainlit/translations/en-US.json +122 -8
- chainlit/translations/gu.json +244 -0
- chainlit/translations/he-IL.json +244 -0
- chainlit/translations/hi.json +244 -0
- chainlit/translations/ja.json +242 -0
- chainlit/translations/kn.json +244 -0
- chainlit/translations/ml.json +244 -0
- chainlit/translations/mr.json +244 -0
- chainlit/translations/nl-NL.json +242 -0
- chainlit/translations/ta.json +244 -0
- chainlit/translations/te.json +244 -0
- chainlit/translations/zh-CN.json +243 -0
- chainlit/translations.py +60 -0
- chainlit/types.py +133 -28
- chainlit/user.py +14 -3
- chainlit/user_session.py +6 -3
- chainlit/utils.py +52 -5
- chainlit/version.py +3 -2
- {chainlit-1.0.401.dist-info → chainlit-2.0.4.dist-info}/METADATA +48 -50
- chainlit-2.0.4.dist-info/RECORD +107 -0
- chainlit/cli/utils.py +0 -24
- chainlit/frontend/dist/assets/index-9711593e.js +0 -723
- chainlit/frontend/dist/assets/index-d088547c.css +0 -1
- chainlit/frontend/dist/assets/react-plotly-d8762cc2.js +0 -3602
- chainlit/playground/__init__.py +0 -2
- chainlit/playground/config.py +0 -40
- chainlit/playground/provider.py +0 -108
- chainlit/playground/providers/__init__.py +0 -13
- chainlit/playground/providers/anthropic.py +0 -118
- chainlit/playground/providers/huggingface.py +0 -75
- chainlit/playground/providers/langchain.py +0 -89
- chainlit/playground/providers/openai.py +0 -408
- chainlit/playground/providers/vertexai.py +0 -171
- chainlit/translations/pt-BR.json +0 -155
- chainlit-1.0.401.dist-info/RECORD +0 -66
- /chainlit/copilot/dist/assets/{logo_dark-2a3cf740.svg → logo_dark-IkGJ_IwC.svg} +0 -0
- /chainlit/copilot/dist/assets/{logo_light-b078e7bc.svg → logo_light-Bb_IPh6r.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_dark-2a3cf740.svg → logo_dark-IkGJ_IwC.svg} +0 -0
- /chainlit/frontend/dist/assets/{logo_light-b078e7bc.svg → logo_light-Bb_IPh6r.svg} +0 -0
- {chainlit-1.0.401.dist-info → chainlit-2.0.4.dist-info}/WHEEL +0 -0
- {chainlit-1.0.401.dist-info → chainlit-2.0.4.dist-info}/entry_points.txt +0 -0
chainlit/cli/__init__.py
CHANGED
|
@@ -5,24 +5,38 @@ import click
|
|
|
5
5
|
import nest_asyncio
|
|
6
6
|
import uvicorn
|
|
7
7
|
|
|
8
|
+
# Not sure if it is necessary to call nest_asyncio.apply() before the other imports
|
|
8
9
|
nest_asyncio.apply()
|
|
9
10
|
|
|
11
|
+
# ruff: noqa: E402
|
|
10
12
|
from chainlit.auth import ensure_jwt_secret
|
|
11
13
|
from chainlit.cache import init_lc_cache
|
|
12
|
-
from chainlit.cli.utils import check_file
|
|
13
14
|
from chainlit.config import (
|
|
14
15
|
BACKEND_ROOT,
|
|
15
16
|
DEFAULT_HOST,
|
|
16
17
|
DEFAULT_PORT,
|
|
18
|
+
DEFAULT_ROOT_PATH,
|
|
17
19
|
config,
|
|
18
20
|
init_config,
|
|
21
|
+
lint_translations,
|
|
19
22
|
load_module,
|
|
20
23
|
)
|
|
21
24
|
from chainlit.logger import logger
|
|
22
25
|
from chainlit.markdown import init_markdown
|
|
23
26
|
from chainlit.secret import random_secret
|
|
24
|
-
from chainlit.server import app, register_wildcard_route_handler
|
|
25
27
|
from chainlit.telemetry import trace_event
|
|
28
|
+
from chainlit.utils import check_file
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def assert_app():
|
|
32
|
+
if (
|
|
33
|
+
not config.code.on_chat_start
|
|
34
|
+
and not config.code.on_message
|
|
35
|
+
and not config.code.on_audio_chunk
|
|
36
|
+
):
|
|
37
|
+
raise Exception(
|
|
38
|
+
"You need to configure at least one of on_chat_start, on_message or on_audio_chunk callback"
|
|
39
|
+
)
|
|
26
40
|
|
|
27
41
|
|
|
28
42
|
# Create the main command group for Chainlit CLI
|
|
@@ -34,8 +48,14 @@ def cli():
|
|
|
34
48
|
|
|
35
49
|
# Define the function to run Chainlit with provided options
|
|
36
50
|
def run_chainlit(target: str):
|
|
51
|
+
from chainlit.server import app
|
|
52
|
+
|
|
37
53
|
host = os.environ.get("CHAINLIT_HOST", DEFAULT_HOST)
|
|
38
54
|
port = int(os.environ.get("CHAINLIT_PORT", DEFAULT_PORT))
|
|
55
|
+
root_path = os.environ.get("CHAINLIT_ROOT_PATH", DEFAULT_ROOT_PATH)
|
|
56
|
+
|
|
57
|
+
ssl_certfile = os.environ.get("CHAINLIT_SSL_CERT", None)
|
|
58
|
+
ssl_keyfile = os.environ.get("CHAINLIT_SSL_KEY", None)
|
|
39
59
|
|
|
40
60
|
ws_per_message_deflate_env = os.environ.get(
|
|
41
61
|
"UVICORN_WS_PER_MESSAGE_DEFLATE", "true"
|
|
@@ -46,8 +66,11 @@ def run_chainlit(target: str):
|
|
|
46
66
|
"yes",
|
|
47
67
|
] # Convert to boolean
|
|
48
68
|
|
|
69
|
+
ws_protocol = os.environ.get("UVICORN_WS_PROTOCOL", "auto")
|
|
70
|
+
|
|
49
71
|
config.run.host = host
|
|
50
72
|
config.run.port = port
|
|
73
|
+
config.run.root_path = root_path
|
|
51
74
|
|
|
52
75
|
check_file(target)
|
|
53
76
|
# Load the module provided by the user
|
|
@@ -55,8 +78,7 @@ def run_chainlit(target: str):
|
|
|
55
78
|
load_module(config.run.module_name)
|
|
56
79
|
|
|
57
80
|
ensure_jwt_secret()
|
|
58
|
-
|
|
59
|
-
register_wildcard_route_handler()
|
|
81
|
+
assert_app()
|
|
60
82
|
|
|
61
83
|
# Create the chainlit.md file if it doesn't exist
|
|
62
84
|
init_markdown(config.root)
|
|
@@ -72,8 +94,11 @@ def run_chainlit(target: str):
|
|
|
72
94
|
app,
|
|
73
95
|
host=host,
|
|
74
96
|
port=port,
|
|
97
|
+
ws=ws_protocol,
|
|
75
98
|
log_level=log_level,
|
|
76
99
|
ws_per_message_deflate=ws_per_message_deflate,
|
|
100
|
+
ssl_keyfile=ssl_keyfile,
|
|
101
|
+
ssl_certfile=ssl_certfile,
|
|
77
102
|
)
|
|
78
103
|
server = uvicorn.Server(config)
|
|
79
104
|
await server.serve()
|
|
@@ -125,13 +150,47 @@ def run_chainlit(target: str):
|
|
|
125
150
|
envvar="NO_CACHE",
|
|
126
151
|
help="Useful to disable third parties cache, such as langchain.",
|
|
127
152
|
)
|
|
153
|
+
@click.option(
|
|
154
|
+
"--ssl-cert",
|
|
155
|
+
default=None,
|
|
156
|
+
envvar="CHAINLIT_SSL_CERT",
|
|
157
|
+
help="Specify the file path for the SSL certificate.",
|
|
158
|
+
)
|
|
159
|
+
@click.option(
|
|
160
|
+
"--ssl-key",
|
|
161
|
+
default=None,
|
|
162
|
+
envvar="CHAINLIT_SSL_KEY",
|
|
163
|
+
help="Specify the file path for the SSL key",
|
|
164
|
+
)
|
|
128
165
|
@click.option("--host", help="Specify a different host to run the server on")
|
|
129
166
|
@click.option("--port", help="Specify a different port to run the server on")
|
|
130
|
-
|
|
167
|
+
@click.option("--root-path", help="Specify a different root path to run the server on")
|
|
168
|
+
def chainlit_run(
|
|
169
|
+
target,
|
|
170
|
+
watch,
|
|
171
|
+
headless,
|
|
172
|
+
debug,
|
|
173
|
+
ci,
|
|
174
|
+
no_cache,
|
|
175
|
+
ssl_cert,
|
|
176
|
+
ssl_key,
|
|
177
|
+
host,
|
|
178
|
+
port,
|
|
179
|
+
root_path,
|
|
180
|
+
):
|
|
131
181
|
if host:
|
|
132
182
|
os.environ["CHAINLIT_HOST"] = host
|
|
133
183
|
if port:
|
|
134
184
|
os.environ["CHAINLIT_PORT"] = port
|
|
185
|
+
if bool(ssl_cert) != bool(ssl_key):
|
|
186
|
+
raise click.UsageError(
|
|
187
|
+
"Both --ssl-cert and --ssl-key must be provided together."
|
|
188
|
+
)
|
|
189
|
+
if ssl_cert:
|
|
190
|
+
os.environ["CHAINLIT_SSL_CERT"] = ssl_cert
|
|
191
|
+
os.environ["CHAINLIT_SSL_KEY"] = ssl_key
|
|
192
|
+
if root_path:
|
|
193
|
+
os.environ["CHAINLIT_ROOT_PATH"] = root_path
|
|
135
194
|
if ci:
|
|
136
195
|
logger.info("Running in CI mode")
|
|
137
196
|
|
|
@@ -139,8 +198,8 @@ def chainlit_run(target, watch, headless, debug, ci, no_cache, host, port):
|
|
|
139
198
|
no_cache = True
|
|
140
199
|
# This is required to have OpenAI LLM providers available for the CI run
|
|
141
200
|
os.environ["OPENAI_API_KEY"] = "sk-FAKE-OPENAI-API-KEY"
|
|
142
|
-
# This is required for
|
|
143
|
-
os.environ["CHAINLIT_AUTH_SECRET"] = "SUPER_SECRET"
|
|
201
|
+
# This is required for authentication tests
|
|
202
|
+
os.environ["CHAINLIT_AUTH_SECRET"] = "SUPER_SECRET" # nosec B105
|
|
144
203
|
else:
|
|
145
204
|
trace_event("chainlit run")
|
|
146
205
|
|
|
@@ -149,6 +208,8 @@ def chainlit_run(target, watch, headless, debug, ci, no_cache, host, port):
|
|
|
149
208
|
config.run.no_cache = no_cache
|
|
150
209
|
config.run.ci = ci
|
|
151
210
|
config.run.watch = watch
|
|
211
|
+
config.run.ssl_cert = ssl_cert
|
|
212
|
+
config.run.ssl_key = ssl_key
|
|
152
213
|
|
|
153
214
|
run_chainlit(target)
|
|
154
215
|
|
|
@@ -174,5 +235,13 @@ def chainlit_create_secret(args=None, **kwargs):
|
|
|
174
235
|
trace_event("chainlit secret")
|
|
175
236
|
|
|
176
237
|
print(
|
|
177
|
-
f
|
|
238
|
+
f'Copy the following secret into your .env file. Once it is set, changing it will logout all users with active sessions.\nCHAINLIT_AUTH_SECRET="{random_secret()}"'
|
|
178
239
|
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@cli.command("lint-translations")
|
|
243
|
+
@click.argument("args", nargs=-1)
|
|
244
|
+
def chainlit_lint_translations(args=None, **kwargs):
|
|
245
|
+
trace_event("chainlit lint-translation")
|
|
246
|
+
|
|
247
|
+
lint_translations()
|
chainlit/config.py
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
import site
|
|
3
4
|
import sys
|
|
4
5
|
from importlib import util
|
|
5
6
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
7
|
+
from typing import (
|
|
8
|
+
TYPE_CHECKING,
|
|
9
|
+
Any,
|
|
10
|
+
Awaitable,
|
|
11
|
+
Callable,
|
|
12
|
+
Dict,
|
|
13
|
+
List,
|
|
14
|
+
Literal,
|
|
15
|
+
Optional,
|
|
16
|
+
Union,
|
|
17
|
+
)
|
|
7
18
|
|
|
8
19
|
import tomli
|
|
9
|
-
from chainlit.logger import logger
|
|
10
|
-
from chainlit.version import __version__
|
|
11
20
|
from dataclasses_json import DataClassJsonMixin
|
|
12
|
-
from pydantic
|
|
21
|
+
from pydantic import Field
|
|
22
|
+
from pydantic.dataclasses import dataclass
|
|
13
23
|
from starlette.datastructures import Headers
|
|
14
24
|
|
|
25
|
+
from chainlit.data.base import BaseDataLayer
|
|
26
|
+
from chainlit.logger import logger
|
|
27
|
+
from chainlit.translations import lint_translation_json
|
|
28
|
+
from chainlit.version import __version__
|
|
29
|
+
|
|
30
|
+
from ._utils import is_path_inside
|
|
31
|
+
|
|
15
32
|
if TYPE_CHECKING:
|
|
16
|
-
from chainlit.action import Action
|
|
17
|
-
from chainlit.types import ChatProfile, ThreadDict
|
|
18
|
-
from chainlit.user import User
|
|
19
33
|
from fastapi import Request, Response
|
|
20
34
|
|
|
35
|
+
from chainlit.action import Action
|
|
36
|
+
from chainlit.message import Message
|
|
37
|
+
from chainlit.types import ChatProfile, InputAudioChunk, Starter, ThreadDict
|
|
38
|
+
from chainlit.user import User
|
|
39
|
+
else:
|
|
40
|
+
# Pydantic needs to resolve forward annotations. Because all of these are used
|
|
41
|
+
# within `typing.Callable`, alias to `Any` as Pydantic does not perform validation
|
|
42
|
+
# of callable argument/return types anyway.
|
|
43
|
+
Request = Response = Action = Message = ChatProfile = InputAudioChunk = Starter = ThreadDict = User = Any # fmt: off
|
|
21
44
|
|
|
22
45
|
BACKEND_ROOT = os.path.dirname(__file__)
|
|
23
46
|
PACKAGE_ROOT = os.path.dirname(os.path.dirname(BACKEND_ROOT))
|
|
@@ -25,13 +48,14 @@ TRANSLATIONS_DIR = os.path.join(BACKEND_ROOT, "translations")
|
|
|
25
48
|
|
|
26
49
|
|
|
27
50
|
# Get the directory the script is running from
|
|
28
|
-
APP_ROOT = os.getcwd()
|
|
51
|
+
APP_ROOT = os.getenv("CHAINLIT_APP_ROOT", os.getcwd())
|
|
29
52
|
|
|
30
53
|
# Create the directory to store the uploaded files
|
|
31
54
|
FILES_DIRECTORY = Path(APP_ROOT) / ".files"
|
|
32
55
|
FILES_DIRECTORY.mkdir(exist_ok=True)
|
|
33
56
|
|
|
34
57
|
config_dir = os.path.join(APP_ROOT, ".chainlit")
|
|
58
|
+
public_dir = os.path.join(APP_ROOT, "public")
|
|
35
59
|
config_file = os.path.join(config_dir, "config.toml")
|
|
36
60
|
config_translation_dir = os.path.join(config_dir, "translations")
|
|
37
61
|
|
|
@@ -47,52 +71,61 @@ user_env = []
|
|
|
47
71
|
# Duration (in seconds) during which the session is saved when the connection is lost
|
|
48
72
|
session_timeout = 3600
|
|
49
73
|
|
|
74
|
+
# Duration (in seconds) of the user session expiry
|
|
75
|
+
user_session_timeout = 1296000 # 15 days
|
|
76
|
+
|
|
50
77
|
# Enable third parties caching (e.g LangChain cache)
|
|
51
78
|
cache = false
|
|
52
79
|
|
|
53
|
-
# Authorized origins
|
|
80
|
+
# Authorized origins
|
|
54
81
|
allow_origins = ["*"]
|
|
55
82
|
|
|
56
|
-
# Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
|
|
57
|
-
# follow_symlink = false
|
|
58
|
-
|
|
59
83
|
[features]
|
|
60
|
-
# Show the prompt playground
|
|
61
|
-
prompt_playground = true
|
|
62
|
-
|
|
63
84
|
# Process and display HTML in messages. This can be a security risk (see https://stackoverflow.com/questions/19603097/why-is-it-dangerous-to-render-user-generated-html-or-javascript)
|
|
64
85
|
unsafe_allow_html = false
|
|
65
86
|
|
|
66
87
|
# Process and display mathematical expressions. This can clash with "$" characters in messages.
|
|
67
88
|
latex = false
|
|
68
89
|
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
# Automatically tag threads with the current chat profile (if a chat profile is used)
|
|
91
|
+
auto_tag_thread = true
|
|
92
|
+
|
|
93
|
+
# Allow users to edit their own messages
|
|
94
|
+
edit_message = true
|
|
95
|
+
|
|
96
|
+
# Authorize users to spontaneously upload files with messages
|
|
97
|
+
[features.spontaneous_file_upload]
|
|
98
|
+
enabled = true
|
|
99
|
+
# Define accepted file types using MIME types
|
|
100
|
+
# Examples:
|
|
101
|
+
# 1. For specific file types:
|
|
102
|
+
# accept = ["image/jpeg", "image/png", "application/pdf"]
|
|
103
|
+
# 2. For all files of certain type:
|
|
104
|
+
# accept = ["image/*", "audio/*", "video/*"]
|
|
105
|
+
# 3. For specific file extensions:
|
|
106
|
+
# accept = {{ "application/octet-stream" = [".xyz", ".pdb"] }}
|
|
107
|
+
# Note: Using "*/*" is not recommended as it may cause browser warnings
|
|
108
|
+
accept = ["*/*"]
|
|
109
|
+
max_files = 20
|
|
110
|
+
max_size_mb = 500
|
|
111
|
+
|
|
112
|
+
[features.audio]
|
|
113
|
+
# Sample rate of the audio
|
|
114
|
+
sample_rate = 24000
|
|
77
115
|
|
|
78
116
|
[UI]
|
|
79
|
-
# Name of the
|
|
80
|
-
name = "
|
|
81
|
-
|
|
82
|
-
# Show the readme while the thread is empty.
|
|
83
|
-
show_readme_as_default = true
|
|
117
|
+
# Name of the assistant.
|
|
118
|
+
name = "Assistant"
|
|
84
119
|
|
|
85
|
-
#
|
|
86
|
-
# description = ""
|
|
120
|
+
# default_theme = "dark"
|
|
87
121
|
|
|
88
|
-
#
|
|
89
|
-
default_collapse_content = true
|
|
122
|
+
# layout = "wide"
|
|
90
123
|
|
|
91
|
-
#
|
|
92
|
-
|
|
124
|
+
# Description of the assistant. This is used for HTML tags.
|
|
125
|
+
# description = ""
|
|
93
126
|
|
|
94
|
-
#
|
|
95
|
-
|
|
127
|
+
# Chain of Thought (CoT) display mode. Can be "hidden", "tool_call" or "full".
|
|
128
|
+
cot = "full"
|
|
96
129
|
|
|
97
130
|
# Link to your github repo. This will add a github button in the UI's header.
|
|
98
131
|
# github = ""
|
|
@@ -105,39 +138,22 @@ hide_cot = false
|
|
|
105
138
|
# The Javascript file can be served from the public directory.
|
|
106
139
|
# custom_js = "/public/test.js"
|
|
107
140
|
|
|
108
|
-
# Specify a custom
|
|
109
|
-
#
|
|
110
|
-
|
|
111
|
-
# Override default MUI light theme. (Check theme.ts)
|
|
112
|
-
[UI.theme]
|
|
113
|
-
#font_family = "Inter, sans-serif"
|
|
114
|
-
[UI.theme.light]
|
|
115
|
-
#background = "#FAFAFA"
|
|
116
|
-
#paper = "#FFFFFF"
|
|
117
|
-
|
|
118
|
-
[UI.theme.light.primary]
|
|
119
|
-
#main = "#F80061"
|
|
120
|
-
#dark = "#980039"
|
|
121
|
-
#light = "#FFE7EB"
|
|
122
|
-
|
|
123
|
-
# Override default MUI dark theme. (Check theme.ts)
|
|
124
|
-
[UI.theme.dark]
|
|
125
|
-
#background = "#FAFAFA"
|
|
126
|
-
#paper = "#FFFFFF"
|
|
127
|
-
|
|
128
|
-
[UI.theme.dark.primary]
|
|
129
|
-
#main = "#F80061"
|
|
130
|
-
#dark = "#980039"
|
|
131
|
-
#light = "#FFE7EB"
|
|
141
|
+
# Specify a custom meta image url.
|
|
142
|
+
# custom_meta_image_url = "https://chainlit-cloud.s3.eu-west-3.amazonaws.com/logo/chainlit_banner.png"
|
|
132
143
|
|
|
144
|
+
# Specify a custom build directory for the frontend.
|
|
145
|
+
# This can be used to customize the frontend code.
|
|
146
|
+
# Be careful: If this is a relative path, it should not start with a slash.
|
|
147
|
+
# custom_build = "./public/build"
|
|
133
148
|
|
|
134
149
|
[meta]
|
|
135
150
|
generated_by = "{__version__}"
|
|
136
151
|
"""
|
|
137
152
|
|
|
138
153
|
|
|
139
|
-
DEFAULT_HOST = "
|
|
154
|
+
DEFAULT_HOST = "127.0.0.1"
|
|
140
155
|
DEFAULT_PORT = 8000
|
|
156
|
+
DEFAULT_ROOT_PATH = ""
|
|
141
157
|
|
|
142
158
|
|
|
143
159
|
@dataclass()
|
|
@@ -146,6 +162,9 @@ class RunSettings:
|
|
|
146
162
|
module_name: Optional[str] = None
|
|
147
163
|
host: str = DEFAULT_HOST
|
|
148
164
|
port: int = DEFAULT_PORT
|
|
165
|
+
ssl_cert: Optional[str] = None
|
|
166
|
+
ssl_key: Optional[str] = None
|
|
167
|
+
root_path: str = DEFAULT_ROOT_PATH
|
|
149
168
|
headless: bool = False
|
|
150
169
|
watch: bool = False
|
|
151
170
|
no_cache: bool = False
|
|
@@ -160,50 +179,60 @@ class PaletteOptions(DataClassJsonMixin):
|
|
|
160
179
|
dark: Optional[str] = ""
|
|
161
180
|
|
|
162
181
|
|
|
182
|
+
@dataclass()
|
|
183
|
+
class TextOptions(DataClassJsonMixin):
|
|
184
|
+
primary: Optional[str] = ""
|
|
185
|
+
secondary: Optional[str] = ""
|
|
186
|
+
|
|
187
|
+
|
|
163
188
|
@dataclass()
|
|
164
189
|
class Palette(DataClassJsonMixin):
|
|
165
190
|
primary: Optional[PaletteOptions] = None
|
|
166
191
|
background: Optional[str] = ""
|
|
167
192
|
paper: Optional[str] = ""
|
|
193
|
+
text: Optional[TextOptions] = None
|
|
168
194
|
|
|
169
195
|
|
|
170
|
-
@dataclass
|
|
171
|
-
class
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
196
|
+
@dataclass
|
|
197
|
+
class SpontaneousFileUploadFeature(DataClassJsonMixin):
|
|
198
|
+
enabled: Optional[bool] = None
|
|
199
|
+
accept: Optional[Union[List[str], Dict[str, List[str]]]] = None
|
|
200
|
+
max_files: Optional[int] = None
|
|
201
|
+
max_size_mb: Optional[int] = None
|
|
175
202
|
|
|
176
203
|
|
|
177
204
|
@dataclass
|
|
178
|
-
class
|
|
179
|
-
|
|
180
|
-
|
|
205
|
+
class AudioFeature(DataClassJsonMixin):
|
|
206
|
+
sample_rate: int = 24000
|
|
207
|
+
enabled: bool = False
|
|
181
208
|
|
|
182
209
|
|
|
183
210
|
@dataclass()
|
|
184
211
|
class FeaturesSettings(DataClassJsonMixin):
|
|
185
|
-
|
|
186
|
-
|
|
212
|
+
spontaneous_file_upload: Optional[SpontaneousFileUploadFeature] = None
|
|
213
|
+
audio: Optional[AudioFeature] = Field(default_factory=AudioFeature)
|
|
187
214
|
latex: bool = False
|
|
188
215
|
unsafe_allow_html: bool = False
|
|
189
|
-
|
|
216
|
+
auto_tag_thread: bool = True
|
|
217
|
+
edit_message: bool = True
|
|
190
218
|
|
|
191
219
|
|
|
192
220
|
@dataclass()
|
|
193
221
|
class UISettings(DataClassJsonMixin):
|
|
194
222
|
name: str
|
|
195
|
-
show_readme_as_default: bool = True
|
|
196
223
|
description: str = ""
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
224
|
+
cot: Literal["hidden", "tool_call", "full"] = "full"
|
|
225
|
+
font_family: Optional[str] = None
|
|
226
|
+
default_theme: Optional[Literal["light", "dark"]] = "dark"
|
|
227
|
+
layout: Optional[Literal["default", "wide"]] = "default"
|
|
201
228
|
github: Optional[str] = None
|
|
202
|
-
theme: Optional[Theme] = None
|
|
203
229
|
# Optional custom CSS file that allows you to customize the UI
|
|
204
230
|
custom_css: Optional[str] = None
|
|
205
231
|
custom_js: Optional[str] = None
|
|
206
|
-
|
|
232
|
+
# Optional custom meta tag for image preview
|
|
233
|
+
custom_meta_image_url: Optional[str] = None
|
|
234
|
+
# Optional custom build directory for the frontend
|
|
235
|
+
custom_build: Optional[str] = None
|
|
207
236
|
|
|
208
237
|
|
|
209
238
|
@dataclass()
|
|
@@ -213,27 +242,42 @@ class CodeSettings:
|
|
|
213
242
|
# Module object loaded from the module_name
|
|
214
243
|
module: Any = None
|
|
215
244
|
# Bunch of callbacks defined by the developer
|
|
216
|
-
password_auth_callback: Optional[
|
|
217
|
-
|
|
245
|
+
password_auth_callback: Optional[
|
|
246
|
+
Callable[[str, str], Awaitable[Optional["User"]]]
|
|
247
|
+
] = None
|
|
248
|
+
header_auth_callback: Optional[Callable[[Headers], Awaitable[Optional["User"]]]] = (
|
|
249
|
+
None
|
|
250
|
+
)
|
|
218
251
|
oauth_callback: Optional[
|
|
219
|
-
Callable[[str, str, Dict[str, str], "User"], Optional["User"]]
|
|
252
|
+
Callable[[str, str, Dict[str, str], "User"], Awaitable[Optional["User"]]]
|
|
220
253
|
] = None
|
|
221
254
|
on_logout: Optional[Callable[["Request", "Response"], Any]] = None
|
|
222
255
|
on_stop: Optional[Callable[[], Any]] = None
|
|
223
256
|
on_chat_start: Optional[Callable[[], Any]] = None
|
|
224
257
|
on_chat_end: Optional[Callable[[], Any]] = None
|
|
225
258
|
on_chat_resume: Optional[Callable[["ThreadDict"], Any]] = None
|
|
226
|
-
on_message: Optional[Callable[[
|
|
227
|
-
|
|
259
|
+
on_message: Optional[Callable[["Message"], Any]] = None
|
|
260
|
+
on_window_message: Optional[Callable[[str], Any]] = None
|
|
261
|
+
on_audio_start: Optional[Callable[[], Any]] = None
|
|
262
|
+
on_audio_chunk: Optional[Callable[["InputAudioChunk"], Any]] = None
|
|
263
|
+
on_audio_end: Optional[Callable[[], Any]] = None
|
|
264
|
+
|
|
265
|
+
author_rename: Optional[Callable[[str], Awaitable[str]]] = None
|
|
228
266
|
on_settings_update: Optional[Callable[[Dict[str, Any]], Any]] = None
|
|
229
|
-
set_chat_profiles: Optional[
|
|
267
|
+
set_chat_profiles: Optional[
|
|
268
|
+
Callable[[Optional["User"]], Awaitable[List["ChatProfile"]]]
|
|
269
|
+
] = None
|
|
270
|
+
set_starters: Optional[Callable[[Optional["User"]], Awaitable[List["Starter"]]]] = (
|
|
230
271
|
None
|
|
231
272
|
)
|
|
273
|
+
data_layer: Optional[Callable[[], BaseDataLayer]] = None
|
|
232
274
|
|
|
233
275
|
|
|
234
276
|
@dataclass()
|
|
235
277
|
class ProjectSettings(DataClassJsonMixin):
|
|
236
278
|
allow_origins: List[str] = Field(default_factory=lambda: ["*"])
|
|
279
|
+
# Socket.io client transports option
|
|
280
|
+
transports: Optional[List[str]] = None
|
|
237
281
|
enable_telemetry: bool = True
|
|
238
282
|
# List of environment variables to be provided by each user to use the app. If empty, no environment variables will be asked to the user.
|
|
239
283
|
user_env: Optional[List[str]] = None
|
|
@@ -242,10 +286,10 @@ class ProjectSettings(DataClassJsonMixin):
|
|
|
242
286
|
# Path to the local chat db
|
|
243
287
|
# Duration (in seconds) during which the session is saved when the connection is lost
|
|
244
288
|
session_timeout: int = 3600
|
|
289
|
+
# Duration (in seconds) of the user session expiry
|
|
290
|
+
user_session_timeout: int = 1296000 # 15 days
|
|
245
291
|
# Enable third parties caching (e.g LangChain cache)
|
|
246
292
|
cache: bool = False
|
|
247
|
-
# Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
|
|
248
|
-
follow_symlink: bool = False
|
|
249
293
|
|
|
250
294
|
|
|
251
295
|
@dataclass()
|
|
@@ -263,23 +307,44 @@ class ChainlitConfig:
|
|
|
263
307
|
def load_translation(self, language: str):
|
|
264
308
|
translation = {}
|
|
265
309
|
default_language = "en-US"
|
|
310
|
+
# fallback to root language (ex: `de` when `de-DE` is not found)
|
|
311
|
+
parent_language = language.split("-")[0]
|
|
266
312
|
|
|
267
|
-
|
|
268
|
-
config_translation_dir, f"{language}.json"
|
|
269
|
-
)
|
|
270
|
-
default_translation_lib_file_path = os.path.join(
|
|
271
|
-
config_translation_dir, f"{default_language}.json"
|
|
272
|
-
)
|
|
313
|
+
translation_dir = Path(config_translation_dir)
|
|
273
314
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
315
|
+
translation_lib_file_path = translation_dir / f"{language}.json"
|
|
316
|
+
translation_lib_parent_language_file_path = (
|
|
317
|
+
translation_dir / f"{parent_language}.json"
|
|
318
|
+
)
|
|
319
|
+
default_translation_lib_file_path = translation_dir / f"{default_language}.json"
|
|
320
|
+
|
|
321
|
+
if (
|
|
322
|
+
is_path_inside(translation_lib_file_path, translation_dir)
|
|
323
|
+
and translation_lib_file_path.is_file()
|
|
324
|
+
):
|
|
325
|
+
translation = json.loads(
|
|
326
|
+
translation_lib_file_path.read_text(encoding="utf-8")
|
|
327
|
+
)
|
|
328
|
+
elif (
|
|
329
|
+
is_path_inside(translation_lib_parent_language_file_path, translation_dir)
|
|
330
|
+
and translation_lib_parent_language_file_path.is_file()
|
|
331
|
+
):
|
|
332
|
+
logger.warning(
|
|
333
|
+
f"Translation file for {language} not found. Using parent translation {parent_language}."
|
|
334
|
+
)
|
|
335
|
+
translation = json.loads(
|
|
336
|
+
translation_lib_parent_language_file_path.read_text(encoding="utf-8")
|
|
337
|
+
)
|
|
338
|
+
elif (
|
|
339
|
+
is_path_inside(default_translation_lib_file_path, translation_dir)
|
|
340
|
+
and default_translation_lib_file_path.is_file()
|
|
341
|
+
):
|
|
278
342
|
logger.warning(
|
|
279
343
|
f"Translation file for {language} not found. Using default translation {default_language}."
|
|
280
344
|
)
|
|
281
|
-
|
|
282
|
-
|
|
345
|
+
translation = json.loads(
|
|
346
|
+
default_translation_lib_file_path.read_text(encoding="utf-8")
|
|
347
|
+
)
|
|
283
348
|
|
|
284
349
|
return translation
|
|
285
350
|
|
|
@@ -305,7 +370,7 @@ def init_config(log=False):
|
|
|
305
370
|
dst = os.path.join(config_translation_dir, file)
|
|
306
371
|
if not os.path.exists(dst):
|
|
307
372
|
src = os.path.join(TRANSLATIONS_DIR, file)
|
|
308
|
-
with open(src,
|
|
373
|
+
with open(src, encoding="utf-8") as f:
|
|
309
374
|
translation = json.load(f)
|
|
310
375
|
with open(dst, "w", encoding="utf-8") as f:
|
|
311
376
|
json.dump(translation, f, indent=4)
|
|
@@ -322,12 +387,16 @@ def load_module(target: str, force_refresh: bool = False):
|
|
|
322
387
|
sys.path.insert(0, target_dir)
|
|
323
388
|
|
|
324
389
|
if force_refresh:
|
|
390
|
+
# Get current site packages dirs
|
|
391
|
+
site_package_dirs = site.getsitepackages()
|
|
392
|
+
|
|
325
393
|
# Clear the modules related to the app from sys.modules
|
|
326
394
|
for module_name, module in list(sys.modules.items()):
|
|
327
395
|
if (
|
|
328
396
|
hasattr(module, "__file__")
|
|
329
397
|
and module.__file__
|
|
330
398
|
and module.__file__.startswith(target_dir)
|
|
399
|
+
and not any(module.__file__.startswith(p) for p in site_package_dirs)
|
|
331
400
|
):
|
|
332
401
|
sys.modules.pop(module_name, None)
|
|
333
402
|
|
|
@@ -358,7 +427,7 @@ def load_settings():
|
|
|
358
427
|
|
|
359
428
|
if not meta or meta.get("generated_by") <= "0.3.0":
|
|
360
429
|
raise ValueError(
|
|
361
|
-
"Your config file is outdated. Please delete it and restart the app to regenerate it."
|
|
430
|
+
f"Your config file '{config_file}' is outdated. Please delete it and restart the app to regenerate it."
|
|
362
431
|
)
|
|
363
432
|
|
|
364
433
|
lc_cache_path = os.path.join(config_dir, ".langchain.db")
|
|
@@ -372,11 +441,13 @@ def load_settings():
|
|
|
372
441
|
|
|
373
442
|
ui_settings = UISettings(**ui_settings)
|
|
374
443
|
|
|
444
|
+
code_settings = CodeSettings(action_callbacks={})
|
|
445
|
+
|
|
375
446
|
return {
|
|
376
447
|
"features": features_settings,
|
|
377
448
|
"ui": ui_settings,
|
|
378
449
|
"project": project_settings,
|
|
379
|
-
"code":
|
|
450
|
+
"code": code_settings,
|
|
380
451
|
}
|
|
381
452
|
|
|
382
453
|
|
|
@@ -411,4 +482,22 @@ def load_config():
|
|
|
411
482
|
return config
|
|
412
483
|
|
|
413
484
|
|
|
485
|
+
def lint_translations():
|
|
486
|
+
# Load the ground truth (en-US.json file from chainlit source code)
|
|
487
|
+
src = os.path.join(TRANSLATIONS_DIR, "en-US.json")
|
|
488
|
+
with open(src, encoding="utf-8") as f:
|
|
489
|
+
truth = json.load(f)
|
|
490
|
+
|
|
491
|
+
# Find the local app translations
|
|
492
|
+
for file in os.listdir(config_translation_dir):
|
|
493
|
+
if file.endswith(".json"):
|
|
494
|
+
# Load the translation file
|
|
495
|
+
to_lint = os.path.join(config_translation_dir, file)
|
|
496
|
+
with open(to_lint, encoding="utf-8") as f:
|
|
497
|
+
translation = json.load(f)
|
|
498
|
+
|
|
499
|
+
# Lint the translation file
|
|
500
|
+
lint_translation_json(file, truth, translation)
|
|
501
|
+
|
|
502
|
+
|
|
414
503
|
config = load_config()
|