lakshyaag commited on
Commit
42cef40
β€’
1 Parent(s): 24f6105

feat: add documentation

Browse files
.chainlit/config.toml CHANGED
@@ -2,6 +2,7 @@
2
  # Whether to enable telemetry (default: true). No personal data is collected.
3
  enable_telemetry = true
4
 
 
5
  # List of environment variables to be provided by each user to use the app.
6
  user_env = []
7
 
@@ -11,54 +12,82 @@ session_timeout = 3600
11
  # Enable third parties caching (e.g LangChain cache)
12
  cache = false
13
 
 
 
 
14
  # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
15
  # follow_symlink = false
16
 
17
  [features]
18
- # Show the prompt playground
19
- prompt_playground = true
20
-
21
  # 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)
22
  unsafe_allow_html = false
23
 
24
  # Process and display mathematical expressions. This can clash with "$" characters in messages.
25
  latex = false
26
 
27
- # Authorize users to upload files with messages
28
- multi_modal = true
29
-
30
- # Allows user to use speech to text
31
- [features.speech_to_text]
32
- enabled = false
33
- # See all languages here https://github.com/JamesBrill/react-speech-recognition/blob/HEAD/docs/API.md#language-string
34
- # language = "en-US"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  [UI]
37
- # Name of the app and chatbot.
38
  name = "10-Q Bot"
39
 
40
- # Show the readme while the conversation is empty.
41
- show_readme_as_default = true
42
-
43
- # Description of the app and chatbot. This is used for HTML tags.
44
- description = "This is a 10-Q Bot, designed to assist with SEC filings and financial data queries."
45
 
46
  # Large size content are by default collapsed for a cleaner ui
47
  default_collapse_content = true
48
 
49
- # The default value for the expand messages settings.
50
- default_expand_messages = false
51
-
52
  # Hide the chain of thought details from the user in the UI.
53
  hide_cot = false
54
 
55
  # Link to your github repo. This will add a github button in the UI's header.
56
- # github = "https://github.com/lakshyaag/"
57
 
58
  # Specify a CSS file that can be used to customize the user interface.
59
  # The CSS file can be served from the public directory or via an external link.
60
  # custom_css = "/public/test.css"
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  # Override default MUI light theme. (Check theme.ts)
63
  [UI.theme.light]
64
  #background = "#FAFAFA"
@@ -68,6 +97,9 @@ hide_cot = false
68
  #main = "#F80061"
69
  #dark = "#980039"
70
  #light = "#FFE7EB"
 
 
 
71
 
72
  # Override default MUI dark theme. (Check theme.ts)
73
  [UI.theme.dark]
@@ -78,7 +110,9 @@ hide_cot = false
78
  #main = "#F80061"
79
  #dark = "#980039"
80
  #light = "#FFE7EB"
81
-
 
 
82
 
83
  [meta]
84
- generated_by = "0.7.700"
 
2
  # Whether to enable telemetry (default: true). No personal data is collected.
3
  enable_telemetry = true
4
 
5
+
6
  # List of environment variables to be provided by each user to use the app.
7
  user_env = []
8
 
 
12
  # Enable third parties caching (e.g LangChain cache)
13
  cache = false
14
 
15
+ # Authorized origins
16
+ allow_origins = ["*"]
17
+
18
  # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
19
  # follow_symlink = false
20
 
21
  [features]
 
 
 
22
  # 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)
23
  unsafe_allow_html = false
24
 
25
  # Process and display mathematical expressions. This can clash with "$" characters in messages.
26
  latex = false
27
 
28
+ # Automatically tag threads with the current chat profile (if a chat profile is used)
29
+ auto_tag_thread = true
30
+
31
+ # Authorize users to spontaneously upload files with messages
32
+ [features.spontaneous_file_upload]
33
+ enabled = true
34
+ accept = ["*/*"]
35
+ max_files = 20
36
+ max_size_mb = 500
37
+
38
+ [features.audio]
39
+ # Threshold for audio recording
40
+ min_decibels = -45
41
+ # Delay for the user to start speaking in MS
42
+ initial_silence_timeout = 3000
43
+ # Delay for the user to continue speaking in MS. If the user stops speaking for this duration, the recording will stop.
44
+ silence_timeout = 1500
45
+ # Above this duration (MS), the recording will forcefully stop.
46
+ max_duration = 15000
47
+ # Duration of the audio chunks in MS
48
+ chunk_duration = 1000
49
+ # Sample rate of the audio
50
+ sample_rate = 44100
51
 
52
  [UI]
53
+ # Name of the assistant.
54
  name = "10-Q Bot"
55
 
56
+ # Description of the assistant. This is used for HTML tags.
57
+ # description = "This chatbot is designed to answer questions about Airbnb's 10-Q financial statement for the quarter ended March 31, 2024."
 
 
 
58
 
59
  # Large size content are by default collapsed for a cleaner ui
60
  default_collapse_content = true
61
 
 
 
 
62
  # Hide the chain of thought details from the user in the UI.
63
  hide_cot = false
64
 
65
  # Link to your github repo. This will add a github button in the UI's header.
66
+ # github = "https://github.com/lakshyaag"
67
 
68
  # Specify a CSS file that can be used to customize the user interface.
69
  # The CSS file can be served from the public directory or via an external link.
70
  # custom_css = "/public/test.css"
71
 
72
+ # Specify a Javascript file that can be used to customize the user interface.
73
+ # The Javascript file can be served from the public directory.
74
+ # custom_js = "/public/test.js"
75
+
76
+ # Specify a custom font url.
77
+ # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
78
+
79
+ # Specify a custom meta image url.
80
+ # custom_meta_image_url = "https://chainlit-cloud.s3.eu-west-3.amazonaws.com/logo/chainlit_banner.png"
81
+
82
+ # Specify a custom build directory for the frontend.
83
+ # This can be used to customize the frontend code.
84
+ # Be careful: If this is a relative path, it should not start with a slash.
85
+ # custom_build = "./public/build"
86
+
87
+ [UI.theme]
88
+ default = "dark"
89
+ layout = "wide"
90
+ #font_family = "Inter, sans-serif"
91
  # Override default MUI light theme. (Check theme.ts)
92
  [UI.theme.light]
93
  #background = "#FAFAFA"
 
97
  #main = "#F80061"
98
  #dark = "#980039"
99
  #light = "#FFE7EB"
100
+ [UI.theme.light.text]
101
+ #primary = "#212121"
102
+ #secondary = "#616161"
103
 
104
  # Override default MUI dark theme. (Check theme.ts)
105
  [UI.theme.dark]
 
110
  #main = "#F80061"
111
  #dark = "#980039"
112
  #light = "#FFE7EB"
113
+ [UI.theme.dark.text]
114
+ #primary = "#EEEEEE"
115
+ #secondary = "#BDBDBD"
116
 
117
  [meta]
118
+ generated_by = "1.1.303"
.chainlit/translations/en-US.json ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "components": {
3
+ "atoms": {
4
+ "buttons": {
5
+ "userButton": {
6
+ "menu": {
7
+ "settings": "Settings",
8
+ "settingsKey": "S",
9
+ "APIKeys": "API Keys",
10
+ "logout": "Logout"
11
+ }
12
+ }
13
+ }
14
+ },
15
+ "molecules": {
16
+ "newChatButton": {
17
+ "newChat": "New Chat"
18
+ },
19
+ "tasklist": {
20
+ "TaskList": {
21
+ "title": "\ud83d\uddd2\ufe0f Task List",
22
+ "loading": "Loading...",
23
+ "error": "An error occurred"
24
+ }
25
+ },
26
+ "attachments": {
27
+ "cancelUpload": "Cancel upload",
28
+ "removeAttachment": "Remove attachment"
29
+ },
30
+ "newChatDialog": {
31
+ "createNewChat": "Create new chat?",
32
+ "clearChat": "This will clear the current messages and start a new chat.",
33
+ "cancel": "Cancel",
34
+ "confirm": "Confirm"
35
+ },
36
+ "settingsModal": {
37
+ "settings": "Settings",
38
+ "expandMessages": "Expand Messages",
39
+ "hideChainOfThought": "Hide Chain of Thought",
40
+ "darkMode": "Dark Mode"
41
+ },
42
+ "detailsButton": {
43
+ "using": "Using",
44
+ "used": "Used"
45
+ },
46
+ "auth": {
47
+ "authLogin": {
48
+ "title": "Login to access the app.",
49
+ "form": {
50
+ "email": "Email address",
51
+ "password": "Password",
52
+ "noAccount": "Don't have an account?",
53
+ "alreadyHaveAccount": "Already have an account?",
54
+ "signup": "Sign Up",
55
+ "signin": "Sign In",
56
+ "or": "OR",
57
+ "continue": "Continue",
58
+ "forgotPassword": "Forgot password?",
59
+ "passwordMustContain": "Your password must contain:",
60
+ "emailRequired": "email is a required field",
61
+ "passwordRequired": "password is a required field"
62
+ },
63
+ "error": {
64
+ "default": "Unable to sign in.",
65
+ "signin": "Try signing in with a different account.",
66
+ "oauthsignin": "Try signing in with a different account.",
67
+ "redirect_uri_mismatch": "The redirect URI is not matching the oauth app configuration.",
68
+ "oauthcallbackerror": "Try signing in with a different account.",
69
+ "oauthcreateaccount": "Try signing in with a different account.",
70
+ "emailcreateaccount": "Try signing in with a different account.",
71
+ "callback": "Try signing in with a different account.",
72
+ "oauthaccountnotlinked": "To confirm your identity, sign in with the same account you used originally.",
73
+ "emailsignin": "The e-mail could not be sent.",
74
+ "emailverify": "Please verify your email, a new email has been sent.",
75
+ "credentialssignin": "Sign in failed. Check the details you provided are correct.",
76
+ "sessionrequired": "Please sign in to access this page."
77
+ }
78
+ },
79
+ "authVerifyEmail": {
80
+ "almostThere": "You're almost there! We've sent an email to ",
81
+ "verifyEmailLink": "Please click on the link in that email to complete your signup.",
82
+ "didNotReceive": "Can't find the email?",
83
+ "resendEmail": "Resend email",
84
+ "goBack": "Go Back",
85
+ "emailSent": "Email sent successfully.",
86
+ "verifyEmail": "Verify your email address"
87
+ },
88
+ "providerButton": {
89
+ "continue": "Continue with {{provider}}",
90
+ "signup": "Sign up with {{provider}}"
91
+ },
92
+ "authResetPassword": {
93
+ "newPasswordRequired": "New password is a required field",
94
+ "passwordsMustMatch": "Passwords must match",
95
+ "confirmPasswordRequired": "Confirm password is a required field",
96
+ "newPassword": "New password",
97
+ "confirmPassword": "Confirm password",
98
+ "resetPassword": "Reset Password"
99
+ },
100
+ "authForgotPassword": {
101
+ "email": "Email address",
102
+ "emailRequired": "email is a required field",
103
+ "emailSent": "Please check the email address {{email}} for instructions to reset your password.",
104
+ "enterEmail": "Enter your email address and we will send you instructions to reset your password.",
105
+ "resendEmail": "Resend email",
106
+ "continue": "Continue",
107
+ "goBack": "Go Back"
108
+ }
109
+ }
110
+ },
111
+ "organisms": {
112
+ "chat": {
113
+ "history": {
114
+ "index": {
115
+ "showHistory": "Show history",
116
+ "lastInputs": "Last Inputs",
117
+ "noInputs": "Such empty...",
118
+ "loading": "Loading..."
119
+ }
120
+ },
121
+ "inputBox": {
122
+ "input": {
123
+ "placeholder": "Type your message here..."
124
+ },
125
+ "speechButton": {
126
+ "start": "Start recording",
127
+ "stop": "Stop recording"
128
+ },
129
+ "SubmitButton": {
130
+ "sendMessage": "Send message",
131
+ "stopTask": "Stop Task"
132
+ },
133
+ "UploadButton": {
134
+ "attachFiles": "Attach files"
135
+ },
136
+ "waterMark": {
137
+ "text": "Built with"
138
+ }
139
+ },
140
+ "Messages": {
141
+ "index": {
142
+ "running": "Running",
143
+ "executedSuccessfully": "executed successfully",
144
+ "failed": "failed",
145
+ "feedbackUpdated": "Feedback updated",
146
+ "updating": "Updating"
147
+ }
148
+ },
149
+ "dropScreen": {
150
+ "dropYourFilesHere": "Drop your files here"
151
+ },
152
+ "index": {
153
+ "failedToUpload": "Failed to upload",
154
+ "cancelledUploadOf": "Cancelled upload of",
155
+ "couldNotReachServer": "Could not reach the server",
156
+ "continuingChat": "Continuing previous chat"
157
+ },
158
+ "settings": {
159
+ "settingsPanel": "Settings panel",
160
+ "reset": "Reset",
161
+ "cancel": "Cancel",
162
+ "confirm": "Confirm"
163
+ }
164
+ },
165
+ "threadHistory": {
166
+ "sidebar": {
167
+ "filters": {
168
+ "FeedbackSelect": {
169
+ "feedbackAll": "Feedback: All",
170
+ "feedbackPositive": "Feedback: Positive",
171
+ "feedbackNegative": "Feedback: Negative"
172
+ },
173
+ "SearchBar": {
174
+ "search": "Search"
175
+ }
176
+ },
177
+ "DeleteThreadButton": {
178
+ "confirmMessage": "This will delete the thread as well as it's messages and elements.",
179
+ "cancel": "Cancel",
180
+ "confirm": "Confirm",
181
+ "deletingChat": "Deleting chat",
182
+ "chatDeleted": "Chat deleted"
183
+ },
184
+ "index": {
185
+ "pastChats": "Past Chats"
186
+ },
187
+ "ThreadList": {
188
+ "empty": "Empty...",
189
+ "today": "Today",
190
+ "yesterday": "Yesterday",
191
+ "previous7days": "Previous 7 days",
192
+ "previous30days": "Previous 30 days"
193
+ },
194
+ "TriggerButton": {
195
+ "closeSidebar": "Close sidebar",
196
+ "openSidebar": "Open sidebar"
197
+ }
198
+ },
199
+ "Thread": {
200
+ "backToChat": "Go back to chat",
201
+ "chatCreatedOn": "This chat was created on"
202
+ }
203
+ },
204
+ "header": {
205
+ "chat": "Chat",
206
+ "readme": "Readme"
207
+ }
208
+ }
209
+ },
210
+ "hooks": {
211
+ "useLLMProviders": {
212
+ "failedToFetchProviders": "Failed to fetch providers:"
213
+ }
214
+ },
215
+ "pages": {
216
+ "Design": {},
217
+ "Env": {
218
+ "savedSuccessfully": "Saved successfully",
219
+ "requiredApiKeys": "Required API Keys",
220
+ "requiredApiKeysInfo": "To use this app, the following API keys are required. The keys are stored on your device's local storage."
221
+ },
222
+ "Page": {
223
+ "notPartOfProject": "You are not part of this project."
224
+ },
225
+ "ResumeButton": {
226
+ "resumeChat": "Resume Chat"
227
+ }
228
+ }
229
+ }
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Airbnb 10-Q Chatbot
3
  emoji: πŸ“
4
  colorFrom: red
5
  colorTo: green
@@ -11,3 +11,85 @@ app_port: 7860
11
  This chatbot is designed to answer questions about Airbnb's 10-Q financial statement for the quarter ended March 31, 2024.
12
 
13
  It uses corrective RAG as the architecture to retrieve information based on the user's input, grading the relevance of the retrieved documents, and optionally querying Wikipedia for additional information, if necessary.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: 10-Q Chatbot RAG Application
3
  emoji: πŸ“
4
  colorFrom: red
5
  colorTo: green
 
11
  This chatbot is designed to answer questions about Airbnb's 10-Q financial statement for the quarter ended March 31, 2024.
12
 
13
  It uses corrective RAG as the architecture to retrieve information based on the user's input, grading the relevance of the retrieved documents, and optionally querying Wikipedia for additional information, if necessary.
14
+
15
+ ## Specifications
16
+
17
+ - Model type can be configured inside `utils/config.py` file. Default is set to `gpt-4o`.
18
+ - Vector store is set to `qdrant` (locally on disk) by default. The data directory and collection name can be configured in the `utils/config.py` file.
19
+ - Chainlit is used as the UI for the chatbot.
20
+ - The chatbot is deployed using Docker on HuggingFace Spaces.
21
+ - `LangChain` is used as the infrastructure and framework for the chatbot.
22
+ - `LangGraph` is used to compose the chatbot's flow.
23
+
24
+ ## Flow engineering
25
+
26
+ ### Ingestion
27
+
28
+ <!-- markdownlint-disable-next-line MD033 -->
29
+ <img src="./images/ingestion.png" alt="Ingestion pipeline" width="500"/>
30
+
31
+ The ingestion pipeline takes in documents, converts them into embeddings and stores them in a vectorstore to be used for retrieval.
32
+
33
+ ### Question Answering
34
+
35
+ To perform Q/A, the chatbot uses a corrective RAG architecture, which is a strategy that involves self-reflection on retrieved documents. The flow is as follows:
36
+ ![C-Rag](./images/crag.png)
37
+
38
+ The user provides a question, then:
39
+
40
+ 1. The query is sent to the vector store to retrieve the most relevant documents. This is done through the `retriever` node.
41
+ 2. The `grader` node receives the question and the retrieved documents and assigns a binary relevance score to each document with reasoning. This leads to filtering out irrelevant documents in the state and toggling the `wikipedia` node, both of which will be used in the next junction.
42
+ 3. Based on the logic defined in the conditional edge, the chatbot will either: decide to generate an answer from the retrieved documents, or rewrite the user's question and query Wikipedia for additional information.
43
+ 4. The `rewriter` node rewrites the question with semantic intent and sends it to the `wikipedia` node and updates the state with the rewritten question.
44
+ 5. The `wikipedia` node queries Wikipedia for additional information based on the rewritten question and updates the state with new documents.
45
+ 6. The `generate` node generates an answer based on the retrieved documents and the original / rewritten question and sends it to the user.
46
+
47
+ ## Sample traces
48
+
49
+ ### Trace 1
50
+
51
+ - Question: "What is Airbnb's 'Description of Business'?"
52
+ - Trace: [LangSmith](https://smith.langchain.com/public/74905526-a026-4a51-8e98-280ec53b8d91/r)
53
+ - Ground Truth: ![Trace 1](./images/trace-1.png)
54
+
55
+ ### Trace 2
56
+
57
+ - Question: "What was the total value of 'Cash and cash equivalents' as of December 31, 2023?"
58
+ - Trace: [LangSmith](https://smith.langchain.com/public/aa4ec48d-1028-492b-b1cd-c8896b815d1b/r)
59
+ - Ground Truth: ![Trace 2](./images/trace-2.png)
60
+
61
+ ### Trace 3
62
+
63
+ - Question: "What is the 'maximum number of shares to be sold under the 10b5-1 Trading plan' by Brian Chesky?"
64
+ - Trace: [LangSmith](https://smith.langchain.com/public/17d7d3f2-0c32-4ffe-85dd-8d5a2ea8a184/r)
65
+ - Ground Truth: ![Trace 3](./images/trace-3.png)
66
+
67
+ ## Configuration
68
+
69
+ ### Prompts
70
+
71
+ Prompts for each model can be configured in the `utils/prompts.py` file.
72
+
73
+ ### Models
74
+
75
+ Models can be configured in the `utils/config.py` file.
76
+
77
+ ### Vectorstore
78
+
79
+ The vectorstore can be changed in the `nodes/retriever.py` file. Note that the default vectorstore is set to `qdrant` and persists locally on disk. Ideally, this should be changed to a remote vectorstore for production.
80
+
81
+ ### Chains
82
+
83
+ Individual node chains can be configured in the `nodes` directory.
84
+
85
+ ### UI
86
+
87
+ Chainlit is used as the UI for the chatbot. The UI can be configured in the `app.py` file.
88
+
89
+ ### Server Configuration
90
+
91
+ A sample FastAPI server is provided in the `server.py` file. Note that this uses [LangServe](https://python.langchain.com/v0.2/docs/langserve/)
92
+
93
+ ## TODO
94
+
95
+ - [ ] Implement memory in the chatbot
app.py CHANGED
@@ -3,13 +3,14 @@ import chainlit as cl
3
  from dotenv import load_dotenv
4
  from graph import create_graph
5
  from langchain_core.runnables import RunnableConfig
6
-
7
 
8
  load_dotenv()
9
 
10
  OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
11
  graph = create_graph()
12
 
 
13
  @cl.on_message
14
  async def main(message: cl.Message):
15
  """
@@ -21,7 +22,7 @@ async def main(message: cl.Message):
21
  async for event in graph.astream_events(
22
  {"question": message.content},
23
  config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
24
- version="v1",
25
  ):
26
  if (
27
  event["event"] == "on_chat_model_stream"
 
3
  from dotenv import load_dotenv
4
  from graph import create_graph
5
  from langchain_core.runnables import RunnableConfig
6
+ from starters import set_starters
7
 
8
  load_dotenv()
9
 
10
  OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
11
  graph = create_graph()
12
 
13
+
14
  @cl.on_message
15
  async def main(message: cl.Message):
16
  """
 
22
  async for event in graph.astream_events(
23
  {"question": message.content},
24
  config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
25
+ version="v2",
26
  ):
27
  if (
28
  event["event"] == "on_chat_model_stream"
images/crag.png ADDED
images/ingestion.png ADDED
images/trace-1.png ADDED
images/trace-2.png ADDED
images/trace-3.png ADDED
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- chainlit==0.7.700
2
  langchain==0.2.5
3
  langchain_core==0.2.9
4
  langchain_community==0.2.5
 
1
+ chainlit==1.1.303
2
  langchain==0.2.5
3
  langchain_core==0.2.9
4
  langchain_community==0.2.5
starters.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+
3
+
4
+ @cl.set_starters
5
+ async def set_starters():
6
+ return [
7
+ cl.Starter(
8
+ label="πŸ›‹οΈ What is the business of Airbnb",
9
+ message="What is Airbnb's 'Description of Business'?",
10
+ ),
11
+ cl.Starter(
12
+ label="πŸ’΅ Cash and Cash Equivalents",
13
+ message="What was the total value of 'Cash and cash equivalents' as of December 31, 2023?",
14
+ ),
15
+ cl.Starter(
16
+ label="πŸ–‹οΈ Maximum allowed sales",
17
+ message="What is the 'maximum number of shares to be sold under the 10b5-1 Trading plan' by Brian Chesky?",
18
+ ),
19
+ ]