JulsdL commited on
Commit
14c0e58
Β·
1 Parent(s): 1843050

Added RAG application for Jupyter Notebook QA, integrated with Chainlit platform, and updated project configuration and dependencies.

Browse files
.chainlit/config.toml ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
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
+
9
+ # Duration (in seconds) during which the session is saved when the connection is lost
10
+ session_timeout = 3600
11
+
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
+ # Show the prompt playground
23
+ prompt_playground = true
24
+
25
+ # 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)
26
+ unsafe_allow_html = false
27
+
28
+ # Process and display mathematical expressions. This can clash with "$" characters in messages.
29
+ latex = false
30
+
31
+ # Automatically tag threads with the current chat profile (if a chat profile is used)
32
+ auto_tag_thread = true
33
+
34
+ # Authorize users to upload files with messages
35
+ [features.multi_modal]
36
+ enabled = true
37
+ accept = ["*/*"]
38
+ max_files = 20
39
+ max_size_mb = 500
40
+
41
+ # Allows user to use speech to text
42
+ [features.speech_to_text]
43
+ enabled = false
44
+ # See all languages here https://github.com/JamesBrill/react-speech-recognition/blob/HEAD/docs/API.md#language-string
45
+ # language = "en-US"
46
+
47
+ [UI]
48
+ # Name of the app and chatbot.
49
+ name = "Chatbot"
50
+
51
+ # Show the readme while the thread is empty.
52
+ show_readme_as_default = true
53
+
54
+ # Description of the app and chatbot. This is used for HTML tags.
55
+ # description = ""
56
+
57
+ # Large size content are by default collapsed for a cleaner ui
58
+ default_collapse_content = true
59
+
60
+ # The default value for the expand messages settings.
61
+ default_expand_messages = false
62
+
63
+ # Hide the chain of thought details from the user in the UI.
64
+ hide_cot = false
65
+
66
+ # Link to your github repo. This will add a github button in the UI's header.
67
+ # github = ""
68
+
69
+ # Specify a CSS file that can be used to customize the user interface.
70
+ # The CSS file can be served from the public directory or via an external link.
71
+ # custom_css = "/public/test.css"
72
+
73
+ # Specify a Javascript file that can be used to customize the user interface.
74
+ # The Javascript file can be served from the public directory.
75
+ # custom_js = "/public/test.js"
76
+
77
+ # Specify a custom font url.
78
+ # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
79
+
80
+ # Specify a custom build directory for the frontend.
81
+ # This can be used to customize the frontend code.
82
+ # Be careful: If this is a relative path, it should not start with a slash.
83
+ # custom_build = "./public/build"
84
+
85
+ # Override default MUI light theme. (Check theme.ts)
86
+ [UI.theme]
87
+ #font_family = "Inter, sans-serif"
88
+ [UI.theme.light]
89
+ #background = "#FAFAFA"
90
+ #paper = "#FFFFFF"
91
+
92
+ [UI.theme.light.primary]
93
+ #main = "#F80061"
94
+ #dark = "#980039"
95
+ #light = "#FFE7EB"
96
+
97
+ # Override default MUI dark theme. (Check theme.ts)
98
+ [UI.theme.dark]
99
+ #background = "#FAFAFA"
100
+ #paper = "#FFFFFF"
101
+
102
+ [UI.theme.dark.primary]
103
+ #main = "#F80061"
104
+ #dark = "#980039"
105
+ #light = "#FFE7EB"
106
+
107
+
108
+ [meta]
109
+ generated_by = "1.0.506"
.chainlit/translations/en-US.json ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 occured"
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
+ "running": "Running",
45
+ "took_one": "Took {{count}} step",
46
+ "took_other": "Took {{count}} steps"
47
+ },
48
+ "auth": {
49
+ "authLogin": {
50
+ "title": "Login to access the app.",
51
+ "form": {
52
+ "email": "Email address",
53
+ "password": "Password",
54
+ "noAccount": "Don't have an account?",
55
+ "alreadyHaveAccount": "Already have an account?",
56
+ "signup": "Sign Up",
57
+ "signin": "Sign In",
58
+ "or": "OR",
59
+ "continue": "Continue",
60
+ "forgotPassword": "Forgot password?",
61
+ "passwordMustContain": "Your password must contain:",
62
+ "emailRequired": "email is a required field",
63
+ "passwordRequired": "password is a required field"
64
+ },
65
+ "error": {
66
+ "default": "Unable to sign in.",
67
+ "signin": "Try signing in with a different account.",
68
+ "oauthsignin": "Try signing in with a different account.",
69
+ "redirect_uri_mismatch": "The redirect URI is not matching the oauth app configuration.",
70
+ "oauthcallbackerror": "Try signing in with a different account.",
71
+ "oauthcreateaccount": "Try signing in with a different account.",
72
+ "emailcreateaccount": "Try signing in with a different account.",
73
+ "callback": "Try signing in with a different account.",
74
+ "oauthaccountnotlinked": "To confirm your identity, sign in with the same account you used originally.",
75
+ "emailsignin": "The e-mail could not be sent.",
76
+ "emailverify": "Please verify your email, a new email has been sent.",
77
+ "credentialssignin": "Sign in failed. Check the details you provided are correct.",
78
+ "sessionrequired": "Please sign in to access this page."
79
+ }
80
+ },
81
+ "authVerifyEmail": {
82
+ "almostThere": "You're almost there! We've sent an email to ",
83
+ "verifyEmailLink": "Please click on the link in that email to complete your signup.",
84
+ "didNotReceive": "Can't find the email?",
85
+ "resendEmail": "Resend email",
86
+ "goBack": "Go Back",
87
+ "emailSent": "Email sent successfully.",
88
+ "verifyEmail": "Verify your email address"
89
+ },
90
+ "providerButton": {
91
+ "continue": "Continue with {{provider}}",
92
+ "signup": "Sign up with {{provider}}"
93
+ },
94
+ "authResetPassword": {
95
+ "newPasswordRequired": "New password is a required field",
96
+ "passwordsMustMatch": "Passwords must match",
97
+ "confirmPasswordRequired": "Confirm password is a required field",
98
+ "newPassword": "New password",
99
+ "confirmPassword": "Confirm password",
100
+ "resetPassword": "Reset Password"
101
+ },
102
+ "authForgotPassword": {
103
+ "email": "Email address",
104
+ "emailRequired": "email is a required field",
105
+ "emailSent": "Please check the email address {{email}} for instructions to reset your password.",
106
+ "enterEmail": "Enter your email address and we will send you instructions to reset your password.",
107
+ "resendEmail": "Resend email",
108
+ "continue": "Continue",
109
+ "goBack": "Go Back"
110
+ }
111
+ }
112
+ },
113
+ "organisms": {
114
+ "chat": {
115
+ "history": {
116
+ "index": {
117
+ "showHistory": "Show history",
118
+ "lastInputs": "Last Inputs",
119
+ "noInputs": "Such empty...",
120
+ "loading": "Loading..."
121
+ }
122
+ },
123
+ "inputBox": {
124
+ "input": {
125
+ "placeholder": "Type your message here..."
126
+ },
127
+ "speechButton": {
128
+ "start": "Start recording",
129
+ "stop": "Stop recording"
130
+ },
131
+ "SubmitButton": {
132
+ "sendMessage": "Send message",
133
+ "stopTask": "Stop Task"
134
+ },
135
+ "UploadButton": {
136
+ "attachFiles": "Attach files"
137
+ },
138
+ "waterMark": {
139
+ "text": "Built with"
140
+ }
141
+ },
142
+ "Messages": {
143
+ "index": {
144
+ "running": "Running",
145
+ "executedSuccessfully": "executed successfully",
146
+ "failed": "failed",
147
+ "feedbackUpdated": "Feedback updated",
148
+ "updating": "Updating"
149
+ }
150
+ },
151
+ "dropScreen": {
152
+ "dropYourFilesHere": "Drop your files here"
153
+ },
154
+ "index": {
155
+ "failedToUpload": "Failed to upload",
156
+ "cancelledUploadOf": "Cancelled upload of",
157
+ "couldNotReachServer": "Could not reach the server",
158
+ "continuingChat": "Continuing previous chat"
159
+ },
160
+ "settings": {
161
+ "settingsPanel": "Settings panel",
162
+ "reset": "Reset",
163
+ "cancel": "Cancel",
164
+ "confirm": "Confirm"
165
+ }
166
+ },
167
+ "threadHistory": {
168
+ "sidebar": {
169
+ "filters": {
170
+ "FeedbackSelect": {
171
+ "feedbackAll": "Feedback: All",
172
+ "feedbackPositive": "Feedback: Positive",
173
+ "feedbackNegative": "Feedback: Negative"
174
+ },
175
+ "SearchBar": {
176
+ "search": "Search"
177
+ }
178
+ },
179
+ "DeleteThreadButton": {
180
+ "confirmMessage": "This will delete the thread as well as it's messages and elements.",
181
+ "cancel": "Cancel",
182
+ "confirm": "Confirm",
183
+ "deletingChat": "Deleting chat",
184
+ "chatDeleted": "Chat deleted"
185
+ },
186
+ "index": {
187
+ "pastChats": "Past Chats"
188
+ },
189
+ "ThreadList": {
190
+ "empty": "Empty...",
191
+ "today": "Today",
192
+ "yesterday": "Yesterday",
193
+ "previous7days": "Previous 7 days",
194
+ "previous30days": "Previous 30 days"
195
+ },
196
+ "TriggerButton": {
197
+ "closeSidebar": "Close sidebar",
198
+ "openSidebar": "Open sidebar"
199
+ }
200
+ },
201
+ "Thread": {
202
+ "backToChat": "Go back to chat",
203
+ "chatCreatedOn": "This chat was created on"
204
+ }
205
+ },
206
+ "header": {
207
+ "chat": "Chat",
208
+ "readme": "Readme"
209
+ }
210
+ }
211
+ },
212
+ "hooks": {
213
+ "useLLMProviders": {
214
+ "failedToFetchProviders": "Failed to fetch providers:"
215
+ }
216
+ },
217
+ "pages": {
218
+ "Design": {},
219
+ "Env": {
220
+ "savedSuccessfully": "Saved successfully",
221
+ "requiredApiKeys": "Required API Keys",
222
+ "requiredApiKeysInfo": "To use this app, the following API keys are required. The keys are stored on your device's local storage."
223
+ },
224
+ "Page": {
225
+ "notPartOfProject": "You are not part of this project."
226
+ },
227
+ "ResumeButton": {
228
+ "resumeChat": "Resume Chat"
229
+ }
230
+ }
231
+ }
CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ version 0.1.0 [2024-05-13]
2
+
3
+ ## Added
4
+
5
+ - Introduced a RAG application for QA in a Jupyter Notebook, enhancing the project's capabilities for document processing and query answering.
6
+ - Implemented Chainlit's `chainlit` Python package to support the RAG application's integration with the Chainlit platform.
7
+ - Added a new `app.py` script, establishing the core functionality for the RAG application, including document loading, retrieval QA chain, query processing, and user interaction.
8
+ - Updated project configuration and dependencies to support the new RAG application features.
app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from operator import itemgetter
3
+
4
+ import chainlit as cl
5
+ import tiktoken
6
+ from dotenv import load_dotenv
7
+
8
+
9
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
10
+ from langchain.retrievers import MultiQueryRetriever
11
+ from langchain_core.prompts import ChatPromptTemplate
12
+ from langchain_core.runnables import RunnablePassthrough
13
+ from langchain_community.document_loaders import PyMuPDFLoader, PythonLoader, NotebookLoader
14
+ from langchain_community.vectorstores import Qdrant
15
+ from langchain_openai import ChatOpenAI
16
+ from langchain_openai.embeddings import OpenAIEmbeddings
17
+
18
+ # Load environment variables
19
+ load_dotenv()
20
+
21
+ # Configuration for OpenAI
22
+ OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
23
+ openai_chat_model = ChatOpenAI(model="gpt-4-turbo", temperature=0)
24
+
25
+ # Define the RAG prompt
26
+ RAG_PROMPT = """
27
+ CONTEXT:
28
+ {context}
29
+
30
+ QUERY:
31
+ {question}
32
+
33
+ Answer the query in a pretty format if the context is related to it; otherwise, answer: 'Sorry, I can't answer.'
34
+ """
35
+ rag_prompt = ChatPromptTemplate.from_template(RAG_PROMPT)
36
+
37
+
38
+ # ChainLit setup for chat interaction
39
+ @cl.on_chat_start
40
+ async def start_chat():
41
+ settings = {
42
+ "model": "gpt-3.5-turbo",
43
+ "temperature": 0,
44
+ "top_p": 1,
45
+ "frequency_penalty": 0,
46
+ "presence_penalty": 0,
47
+ }
48
+ cl.user_session.set("settings", settings)
49
+
50
+ # Display a welcoming message with instructions
51
+ welcome_message = "Welcome to the AIMS-Tutor! Please upload a Jupyter notebook (.ipynb and max. 5mb) to start."
52
+ await cl.Message(content=welcome_message).send()
53
+
54
+ # Wait for the user to upload a file
55
+ files = None
56
+ while files is None:
57
+ files = await cl.AskFileMessage(
58
+ content="Please upload a Jupyter notebook (.ipynb, max. 5mb):",
59
+ accept={"application/x-ipynb+json": [".ipynb"]},
60
+ max_size_mb=5
61
+ ).send()
62
+
63
+ file = files[0] # Get the first file
64
+
65
+ if file:
66
+ # Load the Jupyter notebook
67
+ notebook_path = file.path # Extract the path from the AskFileResponse object
68
+
69
+ loader = NotebookLoader(
70
+ notebook_path,
71
+ include_outputs=True,
72
+ max_output_length=20,
73
+ remove_newline=True,
74
+ traceback=False
75
+ )
76
+ docs = loader.load()
77
+ cl.user_session.set("docs", docs) # Store the docs in the user session
78
+
79
+ # Initialize the retriever components after loading document
80
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=50, length_function=tiktoken_len) # Initialize the text splitter
81
+ split_chunks = text_splitter.split_documents(docs) # Split the documents into chunks
82
+ embedding_model = OpenAIEmbeddings(model="text-embedding-3-small") # Initialize the embedding model
83
+ qdrant_vectorstore = Qdrant.from_documents(split_chunks, embedding_model, location=":memory:", collection_name="Notebook") # Create a Qdrant vector store
84
+ qdrant_retriever = qdrant_vectorstore.as_retriever() # Set the Qdrant vector store as a retriever
85
+ multiquery_retriever = MultiQueryRetriever.from_llm(retriever=qdrant_retriever, llm=openai_chat_model) # Create a multi-query retriever on top of the Qdrant retriever
86
+
87
+ # Store the multiquery_retriever in the user session
88
+ cl.user_session.set("multiquery_retriever", multiquery_retriever)
89
+
90
+ @cl.on_message
91
+ async def main(message: cl.Message):
92
+ # Retrieve the multi-query retriever from session
93
+ multiquery_retriever = cl.user_session.get("multiquery_retriever")
94
+
95
+ if not multiquery_retriever:
96
+ await message.reply("No document processing chain found. Please upload a Jupyter notebook first.")
97
+ return
98
+
99
+ question = message.content
100
+ response = handle_query(question, multiquery_retriever) # Process the question
101
+
102
+ msg = cl.Message(content=response)
103
+ await msg.send()
104
+
105
+
106
+ @cl.on_message
107
+ async def main(message: cl.Message):
108
+ # Retrieve the multi-query retriever from session
109
+ multiquery_retriever = cl.user_session.get("multiquery_retriever")
110
+ if not multiquery_retriever:
111
+ await message.reply("No document processing setup found. Please upload a Jupyter notebook first.")
112
+ return
113
+
114
+ question = message.content
115
+ response = handle_query(question, multiquery_retriever) # Process the question
116
+
117
+ msg = cl.Message(content=response)
118
+ await msg.send()
119
+
120
+ def handle_query(question, retriever):
121
+ # Define the retrieval augmented query-answering chain
122
+ retrieval_augmented_qa_chain = (
123
+ {"context": itemgetter("question") | retriever, "question": itemgetter("question")}
124
+ | RunnablePassthrough.assign(context=itemgetter("context"))
125
+ | {"response": rag_prompt | openai_chat_model, "context": itemgetter("context")}
126
+ )
127
+ response = retrieval_augmented_qa_chain.invoke({"question": question})
128
+ return response["response"].content
129
+
130
+ # Tokenization function
131
+ def tiktoken_len(text):
132
+ tokens = tiktoken.encoding_for_model("gpt-3.5-turbo").encode(text)
133
+ return len(tokens)
chainlit.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Welcome to Chainlit! πŸš€πŸ€–
2
+
3
+ Hi there, Developer! πŸ‘‹ We're excited to have you on board. Chainlit is a powerful tool designed to help you prototype, debug and share applications built on top of LLMs.
4
+
5
+ ## Useful Links πŸ”—
6
+
7
+ - **Documentation:** Get started with our comprehensive [Chainlit Documentation](https://docs.chainlit.io) πŸ“š
8
+ - **Discord Community:** Join our friendly [Chainlit Discord](https://discord.gg/k73SQ3FyUh) to ask questions, share your projects, and connect with other developers! πŸ’¬
9
+
10
+ We can't wait to see what you create with Chainlit! Happy coding! πŸ’»πŸ˜Š
11
+
12
+ ## Welcome screen
13
+
14
+ To modify the welcome screen, edit the `chainlit.md` file at the root of your project. If you do not want a welcome screen, just leave this file empty.
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ langchain==0.1.20
2
+ crewai==0.30.0
3
+ qdrant-client==1.9.1
4
+ python-dotenv==1.0.1
5
+ chainlit==1.0.506