Deepakraj2006 commited on
Commit
7ffcd85
·
verified ·
1 Parent(s): ebc892a

Upload 5 files

Browse files
Files changed (5) hide show
  1. index.html +69 -0
  2. script.js +204 -0
  3. server.py +55 -0
  4. style.css +219 -0
  5. worker_huggingFace.py +83 -0
index.html ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link
5
+ rel="stylesheet"
6
+ href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
7
+ integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
8
+ crossorigin="anonymous"
9
+ />
10
+ <link
11
+ rel="stylesheet"
12
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
13
+ />
14
+ <link rel="stylesheet" href="../static/style.css"/>
15
+ <link
16
+ rel="stylesheet"
17
+ href="{{ url_for('static', filename='style.css') }}"
18
+ />
19
+ <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
20
+ <script src="../static/script.js"></script>
21
+ </head>
22
+ <body>
23
+ <div class="container d-flex flex-column vh-100">
24
+ <div class="row">
25
+ <div class="col-12" style="margin-top: 2rem">
26
+ <h1 class="text-center mb-3">Personal Data Assistant</h1>
27
+ </div>
28
+ <div class="col-12 text-center">
29
+ <div class="custom-control custom-switch mb-3">
30
+ <input type="checkbox" class="custom-control-input" id="light-dark-mode-switch" />
31
+ <label class="custom-control-label" for="light-dark-mode-switch">Toggle light/dark mode</label>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="row flex-grow-1 overflow-auto">
36
+ <div class="col-12 col-md-8 mx-auto d-flex flex-column">
37
+ <div id="chat-window" class="p-3">
38
+ <div id="message-list"></div>
39
+ <div class="loading-animation my-loading">
40
+ <div class="loading-dots my-loading">
41
+ <div class="dot"></div>
42
+ <div class="dot"></div>
43
+ <div class="dot"></div>
44
+ </div>
45
+ </div>
46
+ <div class="loading-animation">
47
+ <div class="loading-dots">
48
+ <div class="dot"></div>
49
+ <div class="dot"></div>
50
+ <div class="dot"></div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <div class="input-group mt-1">
55
+ <input type="text" id="message-input" class="form-control" placeholder="Type your message here..." />
56
+ <div class="input-group-append">
57
+ <button id="send-button" class="btn btn-primary send">
58
+ <i class='fa fa-paper-plane'></i>
59
+ </button>
60
+ <button id="reset-button" class="btn btn-primary reset">
61
+ <i class="fa fa-refresh"></i>
62
+ </button>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </body>
69
+ </html>
script.js ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let lightMode = true;
2
+ let recorder = null;
3
+ let recording = false;
4
+ const responses = [];
5
+ const botRepeatButtonIDToIndexMap = {};
6
+ const userRepeatButtonIDToRecordingMap = {};
7
+ const baseUrl = window.location.origin
8
+
9
+ async function showBotLoadingAnimation() {
10
+ await sleep(200);
11
+ $(".loading-animation")[1].style.display = "inline-block";
12
+ document.getElementById('send-button').disabled = true;
13
+ }
14
+
15
+ function hideBotLoadingAnimation() {
16
+ $(".loading-animation")[1].style.display = "none";
17
+ if(!isFirstMessage){
18
+ document.getElementById('send-button').disabled = false;
19
+ }
20
+ }
21
+
22
+ async function showUserLoadingAnimation() {
23
+ await sleep(100);
24
+ $(".loading-animation")[0].style.display = "flex";
25
+ }
26
+
27
+ function hideUserLoadingAnimation() {
28
+ $(".loading-animation")[0].style.display = "none";
29
+ }
30
+
31
+
32
+ const processUserMessage = async (userMessage) => {
33
+ let response = await fetch(baseUrl + "/process-message", {
34
+ method: "POST",
35
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
36
+ body: JSON.stringify({ userMessage: userMessage }),
37
+ });
38
+ response = await response.json();
39
+ console.log(response);
40
+ return response;
41
+ };
42
+
43
+ const cleanTextInput = (value) => {
44
+ return value
45
+ .trim() // remove starting and ending spaces
46
+ .replace(/[\n\t]/g, "") // remove newlines and tabs
47
+ .replace(/<[^>]*>/g, "") // remove HTML tags
48
+ .replace(/[<>&;]/g, ""); // sanitize inputs
49
+ };
50
+
51
+ const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
52
+
53
+ const scrollToBottom = () => {
54
+ // Scroll the chat window to the bottom
55
+ $("#chat-window").animate({
56
+ scrollTop: $("#chat-window")[0].scrollHeight,
57
+ });
58
+ };
59
+
60
+ const populateUserMessage = (userMessage, userRecording) => {
61
+ // Clear the input field
62
+ $("#message-input").val("");
63
+
64
+ // Append the user's message to the message list
65
+ $("#message-list").append(
66
+ `<div class='message-line my-text'><div class='message-box my-text${
67
+ !lightMode ? " dark" : ""
68
+ }'><div class='me'>${userMessage}</div></div></div>`
69
+ );
70
+
71
+ scrollToBottom();
72
+ };
73
+
74
+ let isFirstMessage = true;
75
+
76
+ const populateBotResponse = async (userMessage) => {
77
+ await showBotLoadingAnimation();
78
+
79
+ let response;
80
+ let uploadButtonHtml = '';
81
+
82
+ if (isFirstMessage) {
83
+ response = { botResponse: "Hello there! I'm your friendly data assistant, ready to answer any questions regarding your data. Could you please upload a PDF file for me to analyze?"};
84
+ uploadButtonHtml = `
85
+ <input type="file" id="file-upload" accept=".pdf" hidden>
86
+ <button id="upload-button" class="btn btn-primary btn-sm">Upload File</button>
87
+ `;
88
+
89
+ } else {
90
+ response = await processUserMessage(userMessage);
91
+ }
92
+
93
+ renderBotResponse(response, uploadButtonHtml)
94
+
95
+ // Event listener for file upload
96
+ if (isFirstMessage) {
97
+ $("#upload-button").on("click", function () {
98
+ $("#file-upload").click();
99
+ });
100
+
101
+ $("#file-upload").on("change", async function () {
102
+ const file = this.files[0];
103
+
104
+ await showBotLoadingAnimation();
105
+
106
+ // Create a new FormData instance
107
+ const formData = new FormData();
108
+
109
+ // Append the file to the FormData instance
110
+ formData.append('file', file);
111
+
112
+ // Now send this data to /process-document endpoint
113
+ let response = await fetch(baseUrl + "/process-document", {
114
+ method: "POST",
115
+ headers: { Accept: "application/json" }, // "Content-Type" should not be explicitly set here, the browser will automatically set it to "multipart/form-data"
116
+ body: formData, // send the FormData instance as the body
117
+ });
118
+
119
+ if (response.status !== 400) {
120
+ document.querySelector('#upload-button').disabled = true;
121
+ }
122
+
123
+ response = await response.json();
124
+ console.log('/process-document', response)
125
+ renderBotResponse(response, '')
126
+ });
127
+
128
+
129
+ isFirstMessage = false; // after the first message, set this to false
130
+ }
131
+ };
132
+
133
+ const renderBotResponse = (response, uploadButtonHtml) => {
134
+ responses.push(response);
135
+
136
+ hideBotLoadingAnimation();
137
+
138
+ $("#message-list").append(
139
+ `<div class='message-line'><div class='message-box${!lightMode ? " dark" : ""}'>${response.botResponse.trim()}<br>${uploadButtonHtml}</div></div>`
140
+ );
141
+
142
+ scrollToBottom();
143
+ }
144
+
145
+ populateBotResponse()
146
+
147
+
148
+ $(document).ready(function () {
149
+
150
+ //start the chat with send button disabled
151
+ document.getElementById('send-button').disabled = true;
152
+
153
+ // Listen for the "Enter" key being pressed in the input field
154
+ $("#message-input").keyup(function (event) {
155
+ let inputVal = cleanTextInput($("#message-input").val());
156
+
157
+ if (event.keyCode === 13 && inputVal != "") {
158
+ const message = inputVal;
159
+
160
+ populateUserMessage(message, null);
161
+ populateBotResponse(message);
162
+ }
163
+
164
+ inputVal = $("#message-input").val();
165
+ });
166
+
167
+ // When the user clicks the "Send" button
168
+ $("#send-button").click(async function () {
169
+ // Get the message the user typed in
170
+ const message = cleanTextInput($("#message-input").val());
171
+
172
+ populateUserMessage(message, null);
173
+ populateBotResponse(message);
174
+
175
+ });
176
+
177
+ //reset chat
178
+ // When the user clicks the "Reset" button
179
+ $("#reset-button").click(async function () {
180
+ // Clear the message list
181
+ $("#message-list").empty();
182
+
183
+ // Reset the responses array
184
+ responses.length = 0;
185
+
186
+ // Reset isFirstMessage flag
187
+ isFirstMessage = true;
188
+
189
+ document.querySelector('#upload-button').disabled = false;
190
+
191
+ // Start over
192
+ populateBotResponse();
193
+ });
194
+
195
+
196
+ // handle the event of switching light-dark mode
197
+ $("#light-dark-mode-switch").change(function () {
198
+ $("body").toggleClass("dark-mode");
199
+ $(".message-box").toggleClass("dark");
200
+ $(".loading-dots").toggleClass("dark");
201
+ $(".dot").toggleClass("dark-dot");
202
+ lightMode = !lightMode;
203
+ });
204
+ });
server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from flask import Flask, render_template, request, jsonify
4
+ from flask_cors import CORS
5
+ import worker # Import the worker module
6
+
7
+ # Initialize Flask app and CORS
8
+ app = Flask(__name__)
9
+ cors = CORS(app, resources={r"/*": {"origins": "*"}})
10
+ app.logger.setLevel(logging.ERROR)
11
+
12
+ # Define the route for the index page
13
+ @app.route('/', methods=['GET'])
14
+ def index():
15
+ return render_template('index.html') # Render the index.html template
16
+
17
+ # Define the route for processing messages
18
+ @app.route('/process-message', methods=['POST'])
19
+ def process_message_route():
20
+ user_message = request.json['userMessage'] # Extract the user's message from the request
21
+ print('user_message', user_message)
22
+
23
+ bot_response = worker.process_prompt(user_message) # Process the user's message using the worker module
24
+
25
+ # Return the bot's response as JSON
26
+ return jsonify({
27
+ "botResponse": bot_response
28
+ }), 200
29
+
30
+ # Define the route for processing documents
31
+ @app.route('/process-document', methods=['POST'])
32
+ def process_document_route():
33
+ # Check if a file was uploaded
34
+ if 'file' not in request.files:
35
+ return jsonify({
36
+ "botResponse": "It seems like the file was not uploaded correctly, can you try "
37
+ "again. If the problem persists, try using a different file"
38
+ }), 400
39
+
40
+ file = request.files['file'] # Extract the uploaded file from the request
41
+
42
+ file_path = file.filename # Define the path where the file will be saved
43
+ file.save(file_path) # Save the file
44
+
45
+ worker.process_document(file_path) # Process the document using the worker module
46
+
47
+ # Return a success message as JSON
48
+ return jsonify({
49
+ "botResponse": "Thank you for providing your PDF document. I have analyzed it, so now you can ask me any "
50
+ "questions regarding it!"
51
+ }), 200
52
+
53
+ # Run the Flask app
54
+ if __name__ == "__main__":
55
+ app.run(debug=True, port=8000, host='0.0.0.0')
style.css ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Light mode */
2
+ body {
3
+ background-color: #d6ddec;
4
+ color: #121717;
5
+ }
6
+
7
+ /* Dark mode */
8
+ .dark-mode {
9
+ background-color: #121717;
10
+ color: #c9c9c9;
11
+ }
12
+
13
+ #chat-window {
14
+ position: relative;
15
+ height: 70vh;
16
+ overflow: auto;
17
+ }
18
+
19
+ .message-line {
20
+ padding-bottom: 8px;
21
+ width: 70%;
22
+ word-break: break-word;
23
+ display: flex;
24
+ }
25
+
26
+ .message-box {
27
+ padding: 12px;
28
+ border-radius: 15px;
29
+ display: inline-block;
30
+ position: relative;
31
+ background-color: #efefef;
32
+ min-width: 26px;
33
+ border-top-left-radius: 0;
34
+ word-wrap: break-word;
35
+ flex-grow: 0;
36
+ }
37
+
38
+ .message-line.my-text {
39
+ flex-direction: row-reverse;
40
+ width: 100%;
41
+ }
42
+
43
+ .message-box.my-text {
44
+ transform: rotateY(180deg);
45
+ background-color: #e7f9d8;
46
+ margin-left:150px;
47
+ }
48
+
49
+ .me {
50
+ transform: scale(-1, 1);
51
+ }
52
+
53
+ .message-box.my-text.dark {
54
+ background-color: #0f4c9e;
55
+ }
56
+
57
+ .message-box.dark {
58
+ background-color: #263443;
59
+ }
60
+
61
+ /* Input container */
62
+ #message-input {
63
+ bottom: 0;
64
+ width: 100%;
65
+ flex-grow: 1;
66
+ font-size: 16px;
67
+ box-sizing: border-box;
68
+ border: none;
69
+ padding: 10px 0 10px 12px;
70
+ border-radius: 40px 0 0 40px;
71
+ background-color: transparent;
72
+ height: auto;
73
+ }
74
+
75
+ #send-button {
76
+ border: none;
77
+ font: inherit;
78
+ background-color: transparent;
79
+ margin: 0;
80
+ appearance: none;
81
+ padding: 10px 12px;
82
+ cursor: pointer;
83
+ font-size: 24px;
84
+ display: flex;
85
+ }
86
+
87
+ #reset-button {
88
+ border: none;
89
+ font: inherit;
90
+ background-color: transparent;
91
+ margin: 0;
92
+ appearance: none;
93
+ padding: 10px 12px;
94
+ cursor: pointer;
95
+ font-size: 24px;
96
+ display: flex;
97
+ }
98
+
99
+ #repeat-button {
100
+ border: none;
101
+ background-color: transparent;
102
+ margin: 0 0 2px 0;
103
+ padding: 0 10px;
104
+ font-size: 24px;
105
+ }
106
+
107
+ .input-group {
108
+ position: relative;
109
+ display: flex;
110
+ flex-wrap: nowrap;
111
+ align-items: stretch;
112
+ width: 100%;
113
+ border-radius: 40px;
114
+ border: 1px solid #2d2d2d;
115
+ }
116
+
117
+ #upload-button {
118
+ color: white;
119
+ background-color: #007bff;
120
+ border: none;
121
+ padding: 5px 10px;
122
+ border-radius: 5px;
123
+ font-size: 14px;
124
+ cursor: pointer;
125
+ transition: background-color 0.3s ease;
126
+ margin-top: 12px;
127
+ }
128
+
129
+ #upload-button:hover {
130
+ background-color: #0056b3;
131
+ }
132
+
133
+ .send i {
134
+ display: block;
135
+ width: 25px;
136
+ color: #125ee5;
137
+ }
138
+
139
+ .reset i {
140
+ display: block;
141
+ width: 25px;
142
+ color: #125ee5;
143
+ }
144
+
145
+
146
+ .loading-animation {
147
+ padding-bottom: 8px;
148
+ word-break: break-word;
149
+ display: none;
150
+ width: 70%;
151
+ }
152
+
153
+ .loading-animation.my-loading {
154
+ flex-direction: row-reverse;
155
+ width: 100%;
156
+ }
157
+
158
+ .loading-dots {
159
+ padding: 12px;
160
+ border-radius: 15px;
161
+ position: relative;
162
+ background-color: #efefef;
163
+ min-width: 26px;
164
+ border-top-left-radius: 0;
165
+ display: flex;
166
+ justify-content: center;
167
+ align-items: baseline;
168
+ width: fit-content;
169
+ }
170
+
171
+ .loading-dots.my-loading {
172
+ transform: rotateY(180deg);
173
+ background-color: #e7f9d8;
174
+ float: right;
175
+ }
176
+
177
+ .dot {
178
+ width: 7px;
179
+ height: 7px;
180
+ margin: 0 2px;
181
+ border-radius: 50%;
182
+ animation: bounce 1.5s ease-in-out infinite;
183
+ background: #5a5a5a;
184
+ }
185
+
186
+ .loading-dots.my-loading.dark {
187
+ background-color: #0e4d9e;
188
+ }
189
+
190
+ .dark {
191
+ background-color: #263443;
192
+ }
193
+
194
+ .dark-dot {
195
+ background: #c9c9c9;
196
+ }
197
+
198
+ .dot:nth-of-type(1) {
199
+ margin-left: 5px;
200
+ animation-delay: 0s;
201
+ }
202
+
203
+ .dot:nth-of-type(2) {
204
+ animation-delay: 0.2s;
205
+ }
206
+
207
+ .dot:nth-of-type(3) {
208
+ animation-delay: 0.4s;
209
+ }
210
+
211
+ @keyframes bounce {
212
+ 0%,
213
+ 40% {
214
+ transform: translateY(0);
215
+ }
216
+ 20% {
217
+ transform: translateY(-10px);
218
+ }
219
+ }
worker_huggingFace.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ from langchain import PromptTemplate
4
+ from langchain.chains import RetrievalQA
5
+ from langchain.embeddings import HuggingFaceInstructEmbeddings
6
+ from langchain.document_loaders import PyPDFLoader
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain.vectorstores import Chroma
9
+ from langchain.llms import HuggingFaceHub
10
+
11
+ # Check for GPU availability and set the appropriate device for computation.
12
+ DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu"
13
+
14
+ # Global variables
15
+ conversation_retrieval_chain = None
16
+ chat_history = []
17
+ llm_hub = None
18
+ embeddings = None
19
+
20
+ # Function to initialize the language model and its embeddings
21
+ def init_llm():
22
+ global llm_hub, embeddings
23
+ # Set up the environment variable for HuggingFace and initialize the desired model.
24
+ os.environ["HUGGINGFACEHUB_API_TOKEN"] = "YOUR API KEY"
25
+
26
+ # repo name for the model
27
+ model_id = "tiiuae/falcon-7b-instruct"
28
+ # load the model into the HuggingFaceHub
29
+ llm_hub = HuggingFaceHub(repo_id=model_id, model_kwargs={"temperature": 0.1, "max_new_tokens": 600, "max_length": 600})
30
+
31
+ #Initialize embeddings using a pre-trained model to represent the text data.
32
+ embeddings = HuggingFaceInstructEmbeddings(
33
+ model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={"device": DEVICE}
34
+ )
35
+
36
+
37
+ # Function to process a PDF document
38
+ def process_document(document_path):
39
+ global conversation_retrieval_chain
40
+
41
+ # Load the document
42
+ loader = PyPDFLoader(document_path)
43
+ documents = loader.load()
44
+
45
+ # Split the document into chunks
46
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=64)
47
+ texts = text_splitter.split_documents(documents)
48
+
49
+ # Create an embeddings database using Chroma from the split text chunks.
50
+ db = Chroma.from_documents(texts, embedding=embeddings)
51
+
52
+
53
+ # --> Build the QA chain, which utilizes the LLM and retriever for answering questions.
54
+ # By default, the vectorstore retriever uses similarity search.
55
+ # If the underlying vectorstore support maximum marginal relevance search, you can specify that as the search type (search_type="mmr").
56
+ # You can also specify search kwargs like k to use when doing retrieval. k represent how many search results send to llm
57
+ conversation_retrieval_chain = RetrievalQA.from_chain_type(
58
+ llm=llm_hub,
59
+ chain_type="stuff",
60
+ retriever=db.as_retriever(search_type="mmr", search_kwargs={'k': 6, 'lambda_mult': 0.25}),
61
+ return_source_documents=False,
62
+ input_key = "question"
63
+ # chain_type_kwargs={"prompt": prompt} # if you are using prompt template, you need to uncomment this part
64
+ )
65
+
66
+
67
+ # Function to process a user prompt
68
+ def process_prompt(prompt):
69
+ global conversation_retrieval_chain
70
+ global chat_history
71
+
72
+ # Query the model
73
+ output = conversation_retrieval_chain({"question": prompt, "chat_history": chat_history})
74
+ answer = output["result"]
75
+
76
+ # Update the chat history
77
+ chat_history.append((prompt, answer))
78
+
79
+ # Return the model's response
80
+ return answer
81
+
82
+ # Initialize the language model
83
+ init_llm()