XThomasBU commited on
Commit
b409192
1 Parent(s): c658776

saving commit - needs cleanup

Browse files
code/main.py CHANGED
@@ -1,5 +1,5 @@
1
  import chainlit.data as cl_data
2
-
3
  from modules.config.constants import (
4
  LLAMA_PATH,
5
  LITERAL_API_KEY_LOGGING,
@@ -13,10 +13,15 @@ import os
13
  from typing import Any, Dict, no_type_check
14
  import chainlit as cl
15
  from modules.chat.llm_tutor import LLMTutor
16
- from modules.chat.helpers import get_sources
 
 
 
 
17
  import copy
18
  from typing import Optional
19
  from chainlit.types import ThreadDict
 
20
 
21
  USER_TIMEOUT = 60_000
22
  SYSTEM = "System 🖥️"
@@ -25,19 +30,30 @@ AGENT = "Agent <>"
25
  YOU = "You 😃"
26
  ERROR = "Error 🚫"
27
 
 
 
28
 
29
- cl_data._data_layer = CustomLiteralDataLayer(
30
- api_key=LITERAL_API_KEY_LOGGING, server=LITERAL_API_URL
31
- )
 
 
 
 
 
 
 
 
 
 
32
 
33
 
34
  class Chatbot:
35
- def __init__(self):
36
  """
37
  Initialize the Chatbot class.
38
  """
39
- self.config = self._load_config()
40
- self.literal_client = cl_data._data_layer.client
41
 
42
  def _load_config(self):
43
  """
@@ -51,6 +67,8 @@ class Chatbot:
51
  """
52
  Set up the LLM with the provided settings. Update the configuration and initialize the LLM tutor.
53
  """
 
 
54
  llm_settings = cl.user_session.get("llm_settings", {})
55
  chat_profile, retriever_method, memory_window, llm_style = (
56
  llm_settings.get("chat_model"),
@@ -60,7 +78,6 @@ class Chatbot:
60
  )
61
 
62
  chain = cl.user_session.get("chain")
63
- print(list(chain.store.values()))
64
  memory_list = cl.user_session.get(
65
  "memory",
66
  (
@@ -69,35 +86,7 @@ class Chatbot:
69
  else []
70
  ),
71
  )
72
- conversation_list = []
73
- for message in memory_list:
74
- # Convert to dictionary if possible
75
- message_dict = message.to_dict() if hasattr(message, "to_dict") else message
76
-
77
- # Check if the type attribute is present as a key or attribute
78
- message_type = (
79
- message_dict.get("type", None)
80
- if isinstance(message_dict, dict)
81
- else getattr(message, "type", None)
82
- )
83
-
84
- # Check if content is present as a key or attribute
85
- message_content = (
86
- message_dict.get("content", None)
87
- if isinstance(message_dict, dict)
88
- else getattr(message, "content", None)
89
- )
90
-
91
- if message_type in ["ai", "ai_message"]:
92
- conversation_list.append(
93
- {"type": "ai_message", "content": message_content}
94
- )
95
- elif message_type in ["human", "user_message"]:
96
- conversation_list.append(
97
- {"type": "user_message", "content": message_content}
98
- )
99
- else:
100
- raise ValueError("Invalid message type")
101
  print("\n\n\n")
102
  print("history at setup_llm", conversation_list)
103
  print("\n\n\n")
@@ -111,13 +100,18 @@ class Chatbot:
111
  self.llm_tutor.update_llm(
112
  old_config, self.config
113
  ) # update only attributes that are changed
114
- self.chain = self.llm_tutor.qa_bot(memory=conversation_list)
 
 
 
115
 
116
  tags = [chat_profile, self.config["vectorstore"]["db_option"]]
117
 
118
  cl.user_session.set("chain", self.chain)
119
  cl.user_session.set("llm_tutor", self.llm_tutor)
120
 
 
 
121
  @no_type_check
122
  async def update_llm(self, new_settings: Dict[str, Any]):
123
  """
@@ -176,7 +170,7 @@ class Chatbot:
176
  cl.input_widget.Select(
177
  id="llm_style",
178
  label="Type of Conversation (Default Normal)",
179
- values=["Normal", "ELI5", "Socratic"],
180
  initial_index=0,
181
  ),
182
  ]
@@ -268,6 +262,8 @@ class Chatbot:
268
  and display and load previous conversation if chat logging is enabled.
269
  """
270
 
 
 
271
  await self.make_llm_settings_widgets(self.config)
272
  user = cl.user_session.get("user")
273
  self.user = {
@@ -280,10 +276,20 @@ class Chatbot:
280
 
281
  cl.user_session.set("user", self.user)
282
  self.llm_tutor = LLMTutor(self.config, user=self.user)
283
- self.chain = self.llm_tutor.qa_bot(memory=memory)
 
 
 
 
 
 
 
 
284
  cl.user_session.set("llm_tutor", self.llm_tutor)
285
  cl.user_session.set("chain", self.chain)
286
 
 
 
287
  async def stream_response(self, response):
288
  """
289
  Stream the response from the LLM.
@@ -314,6 +320,8 @@ class Chatbot:
314
  message: The incoming chat message.
315
  """
316
 
 
 
317
  chain = cl.user_session.get("chain")
318
 
319
  print("\n\n\n")
@@ -348,64 +356,72 @@ class Chatbot:
348
  res = chain.stream(user_query=user_query_dict, config=chain_config)
349
  res = await self.stream_response(res)
350
  else:
351
- res = await chain.invoke(user_query=user_query_dict, config=chain_config)
 
 
 
352
 
353
  answer = res.get("answer", res.get("result"))
354
 
355
- with cl_data._data_layer.client.step(
356
- type="retrieval",
357
- name="RAG",
358
- thread_id=cl.context.session.thread_id,
359
- # tags=self.tags,
360
- ) as step:
361
- step.input = {"question": user_query_dict["input"]}
362
- step.output = {
363
- "chat_history": res.get("chat_history"),
364
- "context": res.get("context"),
365
- "answer": answer,
366
- "rephrase_prompt": res.get("rephrase_prompt"),
367
- "qa_prompt": res.get("qa_prompt"),
368
- }
369
- step.metadata = self.config
 
 
 
370
 
371
  answer_with_sources, source_elements, sources_dict = get_sources(
372
  res, answer, stream=stream, view_sources=view_sources
373
  )
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  await cl.Message(
376
- content=answer_with_sources, elements=source_elements, author=LLM
 
 
 
377
  ).send()
378
 
379
  async def on_chat_resume(self, thread: ThreadDict):
380
  steps = thread["steps"]
381
- # conversation_pairs = []
382
- conversation_list = []
383
-
384
- user_message = None
385
  k = self.config["llm_params"]["memory_window"]
386
- count = 0
387
-
388
- print(steps)
389
-
390
- for step in reversed(steps):
391
- print(step["type"])
392
- if step["name"] not in [SYSTEM]:
393
- if step["type"] == "user_message":
394
- conversation_list.append(
395
- {"type": "user_message", "content": step["output"]}
396
- )
397
- elif step["type"] == "assistant_message":
398
- if step["name"] == LLM:
399
- conversation_list.append(
400
- {"type": "ai_message", "content": step["output"]}
401
- )
402
- else:
403
- raise ValueError("Invalid message type")
404
- count += 1
405
- if count >= 2 * k: # 2 * k to account for both user and assistant messages
406
- break
407
-
408
- conversation_list = conversation_list[::-1]
409
 
410
  print("\n\n\n")
411
  print("history at on_chat_resume", conversation_list)
@@ -423,11 +439,30 @@ class Chatbot:
423
  ) -> Optional[cl.User]:
424
  return default_user
425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
 
427
- chatbot = Chatbot()
428
- cl.set_starters(chatbot.set_starters)
429
- cl.author_rename(chatbot.rename)
430
- cl.on_chat_start(chatbot.start)
431
- cl.on_chat_resume(chatbot.on_chat_resume)
432
- cl.on_message(chatbot.main)
433
- cl.on_settings_update(chatbot.update_llm)
 
1
  import chainlit.data as cl_data
2
+ import asyncio
3
  from modules.config.constants import (
4
  LLAMA_PATH,
5
  LITERAL_API_KEY_LOGGING,
 
13
  from typing import Any, Dict, no_type_check
14
  import chainlit as cl
15
  from modules.chat.llm_tutor import LLMTutor
16
+ from modules.chat.helpers import (
17
+ get_sources,
18
+ get_history_chat_resume,
19
+ get_history_setup_llm,
20
+ )
21
  import copy
22
  from typing import Optional
23
  from chainlit.types import ThreadDict
24
+ import time
25
 
26
  USER_TIMEOUT = 60_000
27
  SYSTEM = "System 🖥️"
 
30
  YOU = "You 😃"
31
  ERROR = "Error 🚫"
32
 
33
+ with open("modules/config/config.yml", "r") as f:
34
+ config = yaml.safe_load(f)
35
 
36
+
37
+ async def setup_data_layer():
38
+ """
39
+ Set up the data layer for chat logging.
40
+ """
41
+ if config["chat_logging"]["log_chat"]:
42
+ data_layer = CustomLiteralDataLayer(
43
+ api_key=LITERAL_API_KEY_LOGGING, server=LITERAL_API_URL
44
+ )
45
+ else:
46
+ data_layer = None
47
+
48
+ return data_layer
49
 
50
 
51
  class Chatbot:
52
+ def __init__(self, config):
53
  """
54
  Initialize the Chatbot class.
55
  """
56
+ self.config = config
 
57
 
58
  def _load_config(self):
59
  """
 
67
  """
68
  Set up the LLM with the provided settings. Update the configuration and initialize the LLM tutor.
69
  """
70
+ start_time = time.time()
71
+
72
  llm_settings = cl.user_session.get("llm_settings", {})
73
  chat_profile, retriever_method, memory_window, llm_style = (
74
  llm_settings.get("chat_model"),
 
78
  )
79
 
80
  chain = cl.user_session.get("chain")
 
81
  memory_list = cl.user_session.get(
82
  "memory",
83
  (
 
86
  else []
87
  ),
88
  )
89
+ conversation_list = get_history_setup_llm(memory_list)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  print("\n\n\n")
91
  print("history at setup_llm", conversation_list)
92
  print("\n\n\n")
 
100
  self.llm_tutor.update_llm(
101
  old_config, self.config
102
  ) # update only attributes that are changed
103
+ self.chain = self.llm_tutor.qa_bot(
104
+ memory=conversation_list,
105
+ callbacks=[cl.LangchainCallbackHandler()] if cl_data._data_layer else None,
106
+ )
107
 
108
  tags = [chat_profile, self.config["vectorstore"]["db_option"]]
109
 
110
  cl.user_session.set("chain", self.chain)
111
  cl.user_session.set("llm_tutor", self.llm_tutor)
112
 
113
+ print("Time taken to setup LLM: ", time.time() - start_time)
114
+
115
  @no_type_check
116
  async def update_llm(self, new_settings: Dict[str, Any]):
117
  """
 
170
  cl.input_widget.Select(
171
  id="llm_style",
172
  label="Type of Conversation (Default Normal)",
173
+ values=["Normal", "ELI5"],
174
  initial_index=0,
175
  ),
176
  ]
 
262
  and display and load previous conversation if chat logging is enabled.
263
  """
264
 
265
+ start_time = time.time()
266
+
267
  await self.make_llm_settings_widgets(self.config)
268
  user = cl.user_session.get("user")
269
  self.user = {
 
276
 
277
  cl.user_session.set("user", self.user)
278
  self.llm_tutor = LLMTutor(self.config, user=self.user)
279
+
280
+ print(cl.LangchainCallbackHandler())
281
+ print(cl_data._data_layer)
282
+ self.chain = self.llm_tutor.qa_bot(
283
+ memory=memory,
284
+ callbacks=[cl.LangchainCallbackHandler()] if cl_data._data_layer else None,
285
+ )
286
+ self.question_generator = self.llm_tutor.question_generator
287
+ print(self.question_generator)
288
  cl.user_session.set("llm_tutor", self.llm_tutor)
289
  cl.user_session.set("chain", self.chain)
290
 
291
+ print("Time taken to start LLM: ", time.time() - start_time)
292
+
293
  async def stream_response(self, response):
294
  """
295
  Stream the response from the LLM.
 
320
  message: The incoming chat message.
321
  """
322
 
323
+ start_time = time.time()
324
+
325
  chain = cl.user_session.get("chain")
326
 
327
  print("\n\n\n")
 
356
  res = chain.stream(user_query=user_query_dict, config=chain_config)
357
  res = await self.stream_response(res)
358
  else:
359
+ res = await chain.invoke(
360
+ user_query=user_query_dict,
361
+ config=chain_config,
362
+ )
363
 
364
  answer = res.get("answer", res.get("result"))
365
 
366
+ if cl_data._data_layer is not None:
367
+ with cl_data._data_layer.client.step(
368
+ type="run",
369
+ name="step_info",
370
+ thread_id=cl.context.session.thread_id,
371
+ # tags=self.tags,
372
+ ) as step:
373
+
374
+ step.input = {"question": user_query_dict["input"]}
375
+
376
+ step.output = {
377
+ "chat_history": res.get("chat_history"),
378
+ "context": res.get("context"),
379
+ "answer": answer,
380
+ "rephrase_prompt": res.get("rephrase_prompt"),
381
+ "qa_prompt": res.get("qa_prompt"),
382
+ }
383
+ step.metadata = self.config
384
 
385
  answer_with_sources, source_elements, sources_dict = get_sources(
386
  res, answer, stream=stream, view_sources=view_sources
387
  )
388
 
389
+ print("Time taken to process the message: ", time.time() - start_time)
390
+
391
+ list_of_questions = self.question_generator.generate_questions(
392
+ query=user_query_dict["input"],
393
+ response=answer,
394
+ chat_history=res.get("chat_history"),
395
+ context=res.get("context"),
396
+ )
397
+
398
+ print("\n\n\n")
399
+ print("Questions: ", list_of_questions)
400
+ print("\n\n\n")
401
+
402
+ actions = []
403
+ for question in list_of_questions:
404
+
405
+ actions.append(
406
+ cl.Action(
407
+ name="follow up question",
408
+ value="example_value",
409
+ description=question,
410
+ label=question,
411
+ )
412
+ )
413
+
414
  await cl.Message(
415
+ content=answer_with_sources,
416
+ elements=source_elements,
417
+ author=LLM,
418
+ actions=actions,
419
  ).send()
420
 
421
  async def on_chat_resume(self, thread: ThreadDict):
422
  steps = thread["steps"]
 
 
 
 
423
  k = self.config["llm_params"]["memory_window"]
424
+ conversation_list = get_history_chat_resume(steps, k, SYSTEM, LLM)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
 
426
  print("\n\n\n")
427
  print("history at on_chat_resume", conversation_list)
 
439
  ) -> Optional[cl.User]:
440
  return default_user
441
 
442
+ async def on_action(self, action: cl.Action):
443
+ print("Action Callback")
444
+ print(action)
445
+ # main(message=action.description)\
446
+ message = await cl.Message(content=action.description, author=YOU).send()
447
+ await self.main(message)
448
+
449
+
450
+ chatbot = Chatbot(config=config)
451
+
452
+
453
+ async def start():
454
+ print("Setting up data layer...")
455
+ cl_data._data_layer = await setup_data_layer()
456
+ print("Data layer set up.")
457
+ print(cl_data._data_layer)
458
+ chatbot.literal_client = cl_data._data_layer.client if cl_data._data_layer else None
459
+ cl.set_starters(chatbot.set_starters)
460
+ cl.author_rename(chatbot.rename)
461
+ cl.on_chat_start(chatbot.start)
462
+ cl.on_chat_resume(chatbot.on_chat_resume)
463
+ cl.on_message(chatbot.main)
464
+ cl.on_settings_update(chatbot.update_llm)
465
+ cl.action_callback("follow up question")(chatbot.on_action)
466
+
467
 
468
+ asyncio.run(start())
 
 
 
 
 
 
code/modules/chat/helpers.py CHANGED
@@ -116,3 +116,58 @@ def get_prompt(config, prompt_type):
116
  return prompts["openai"]["prompt_no_history"]
117
  elif prompt_type == "rephrase":
118
  return prompts["openai"]["rephrase_prompt"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  return prompts["openai"]["prompt_no_history"]
117
  elif prompt_type == "rephrase":
118
  return prompts["openai"]["rephrase_prompt"]
119
+
120
+
121
+ def get_history_chat_resume(steps, k, SYSTEM, LLM):
122
+ conversation_list = []
123
+ count = 0
124
+ for step in reversed(steps):
125
+ print(step["type"])
126
+ if step["name"] not in [SYSTEM]:
127
+ if step["type"] == "user_message":
128
+ conversation_list.append(
129
+ {"type": "user_message", "content": step["output"]}
130
+ )
131
+ elif step["type"] == "assistant_message":
132
+ if step["name"] == LLM:
133
+ conversation_list.append(
134
+ {"type": "ai_message", "content": step["output"]}
135
+ )
136
+ else:
137
+ raise ValueError("Invalid message type")
138
+ count += 1
139
+ if count >= 2 * k: # 2 * k to account for both user and assistant messages
140
+ break
141
+ conversation_list = conversation_list[::-1]
142
+ return conversation_list
143
+
144
+
145
+ def get_history_setup_llm(memory_list):
146
+ conversation_list = []
147
+ for message in memory_list:
148
+ message_dict = message.to_dict() if hasattr(message, "to_dict") else message
149
+
150
+ # Check if the type attribute is present as a key or attribute
151
+ message_type = (
152
+ message_dict.get("type", None)
153
+ if isinstance(message_dict, dict)
154
+ else getattr(message, "type", None)
155
+ )
156
+
157
+ # Check if content is present as a key or attribute
158
+ message_content = (
159
+ message_dict.get("content", None)
160
+ if isinstance(message_dict, dict)
161
+ else getattr(message, "content", None)
162
+ )
163
+
164
+ if message_type in ["ai", "ai_message"]:
165
+ conversation_list.append({"type": "ai_message", "content": message_content})
166
+ elif message_type in ["human", "user_message"]:
167
+ conversation_list.append(
168
+ {"type": "user_message", "content": message_content}
169
+ )
170
+ else:
171
+ raise ValueError("Invalid message type")
172
+
173
+ return conversation_list
code/modules/chat/langchain/langchain_rag.py CHANGED
@@ -9,11 +9,21 @@ from langchain.memory import (
9
  ConversationSummaryBufferMemory,
10
  )
11
 
 
 
 
12
 
13
  class Langchain_RAG_V1(BaseRAG):
14
 
15
  def __init__(
16
- self, llm, memory, retriever, qa_prompt: str, rephrase_prompt: str, config: dict
 
 
 
 
 
 
 
17
  ):
18
  """
19
  Initialize the Langchain_RAG class.
@@ -77,9 +87,29 @@ class Langchain_RAG_V1(BaseRAG):
77
  return res
78
 
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  class Langchain_RAG_V2(BaseRAG):
81
  def __init__(
82
- self, llm, memory, retriever, qa_prompt: str, rephrase_prompt: str, config: dict
 
 
 
 
 
 
 
83
  ):
84
  """
85
  Initialize the Langchain_RAG class.
@@ -171,6 +201,9 @@ class Langchain_RAG_V2(BaseRAG):
171
  ],
172
  )
173
 
 
 
 
174
  def get_session_history(
175
  self, user_id: str, conversation_id: str, memory_window: int
176
  ) -> BaseChatMessageHistory:
@@ -192,7 +225,7 @@ class Langchain_RAG_V2(BaseRAG):
192
  ) # add previous messages to the store. Note: the store is in-memory.
193
  return self.store[(user_id, conversation_id)]
194
 
195
- async def invoke(self, user_query, config):
196
  """
197
  Invoke the chain.
198
 
@@ -202,7 +235,7 @@ class Langchain_RAG_V2(BaseRAG):
202
  Returns:
203
  dict: The output variables.
204
  """
205
- res = await self.rag_chain.ainvoke(user_query, config)
206
  res["rephrase_prompt"] = self.rephrase_prompt
207
  res["qa_prompt"] = self.qa_prompt
208
  return res
 
9
  ConversationSummaryBufferMemory,
10
  )
11
 
12
+ import chainlit as cl
13
+ from langchain_community.chat_models import ChatOpenAI
14
+
15
 
16
  class Langchain_RAG_V1(BaseRAG):
17
 
18
  def __init__(
19
+ self,
20
+ llm,
21
+ memory,
22
+ retriever,
23
+ qa_prompt: str,
24
+ rephrase_prompt: str,
25
+ config: dict,
26
+ callbacks=None,
27
  ):
28
  """
29
  Initialize the Langchain_RAG class.
 
87
  return res
88
 
89
 
90
+ class QuestionGenerator:
91
+ """
92
+ Generate a question from the LLMs response and users input and past conversations.
93
+ """
94
+
95
+ def __init__(self):
96
+ pass
97
+
98
+ def generate_questions(self, query, response, chat_history, context):
99
+ questions = return_questions(query, response, chat_history, context)
100
+ return questions
101
+
102
+
103
  class Langchain_RAG_V2(BaseRAG):
104
  def __init__(
105
+ self,
106
+ llm,
107
+ memory,
108
+ retriever,
109
+ qa_prompt: str,
110
+ rephrase_prompt: str,
111
+ config: dict,
112
+ callbacks=None,
113
  ):
114
  """
115
  Initialize the Langchain_RAG class.
 
201
  ],
202
  )
203
 
204
+ if callbacks is not None:
205
+ self.rag_chain = self.rag_chain.with_config(callbacks=callbacks)
206
+
207
  def get_session_history(
208
  self, user_id: str, conversation_id: str, memory_window: int
209
  ) -> BaseChatMessageHistory:
 
225
  ) # add previous messages to the store. Note: the store is in-memory.
226
  return self.store[(user_id, conversation_id)]
227
 
228
+ async def invoke(self, user_query, config, **kwargs):
229
  """
230
  Invoke the chain.
231
 
 
235
  Returns:
236
  dict: The output variables.
237
  """
238
+ res = await self.rag_chain.ainvoke(user_query, config, **kwargs)
239
  res["rephrase_prompt"] = self.rephrase_prompt
240
  res["qa_prompt"] = self.qa_prompt
241
  return res
code/modules/chat/langchain/utils.py CHANGED
@@ -311,3 +311,39 @@ def create_retrieval_chain(
311
  ).with_config(run_name="retrieval_chain")
312
 
313
  return retrieval_chain
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  ).with_config(run_name="retrieval_chain")
312
 
313
  return retrieval_chain
314
+
315
+
316
+ def return_questions(query, response, chat_history_str, context):
317
+
318
+ system = (
319
+ "You are someone that suggests a question based on the student's input and chat history. "
320
+ "Generate a question that is relevant to the student's input and chat history. "
321
+ "Incorporate relevant details from the chat history to make the question clearer and more specific. "
322
+ "Chat history: \n{chat_history_str}\n"
323
+ "Use the context to generate a question that is relevant to the student's input and chat history: Context: {context}"
324
+ "Generate 3 short and concise questions from the students voice based on the following input and response: "
325
+ "The 3 short and concise questions should be sperated by dots. Example: 'What is the capital of France?...What is the population of France?...What is the currency of France?'"
326
+ "User Query: {query}"
327
+ "AI Response: {response}"
328
+ "The 3 short and concise questions seperated by dots (...) are:"
329
+ )
330
+
331
+ prompt = ChatPromptTemplate.from_messages(
332
+ [
333
+ ("system", system),
334
+ ("human", "{chat_history_str}, {context}, {query}, {response}"),
335
+ ]
336
+ )
337
+ llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
338
+ question_generator = prompt | llm | StrOutputParser()
339
+ new_questions = question_generator.invoke(
340
+ {
341
+ "chat_history_str": chat_history_str,
342
+ "context": context,
343
+ "query": query,
344
+ "response": response,
345
+ }
346
+ )
347
+
348
+ list_of_questions = new_questions.split("...")
349
+ return list_of_questions
code/modules/chat/llm_tutor.py CHANGED
@@ -2,7 +2,11 @@ from modules.chat.helpers import get_prompt
2
  from modules.chat.chat_model_loader import ChatModelLoader
3
  from modules.vectorstore.store_manager import VectorStoreManager
4
  from modules.retriever.retriever import Retriever
5
- from modules.chat.langchain.langchain_rag import Langchain_RAG_V1, Langchain_RAG_V2
 
 
 
 
6
 
7
 
8
  class LLMTutor:
@@ -86,7 +90,9 @@ class LLMTutor:
86
  compare_dicts(old_config, new_config)
87
  return changes
88
 
89
- def retrieval_qa_chain(self, llm, qa_prompt, rephrase_prompt, db, memory=None):
 
 
90
  """
91
  Create a Retrieval QA Chain.
92
 
@@ -110,7 +116,10 @@ class LLMTutor:
110
  qa_prompt=qa_prompt,
111
  rephrase_prompt=rephrase_prompt,
112
  config=self.config,
 
113
  )
 
 
114
  else:
115
  raise ValueError(
116
  f"Invalid LLM Architecture: {self.config['llm_params']['llm_arch']}"
@@ -128,7 +137,7 @@ class LLMTutor:
128
  llm = chat_model_loader.load_chat_model()
129
  return llm
130
 
131
- def qa_bot(self, memory=None):
132
  """
133
  Create a QA bot instance.
134
 
@@ -147,7 +156,12 @@ class LLMTutor:
147
  )
148
 
149
  qa = self.retrieval_qa_chain(
150
- self.llm, self.qa_prompt, self.rephrase_prompt, self.vector_db, memory
 
 
 
 
 
151
  )
152
 
153
  return qa
 
2
  from modules.chat.chat_model_loader import ChatModelLoader
3
  from modules.vectorstore.store_manager import VectorStoreManager
4
  from modules.retriever.retriever import Retriever
5
+ from modules.chat.langchain.langchain_rag import (
6
+ Langchain_RAG_V1,
7
+ Langchain_RAG_V2,
8
+ QuestionGenerator,
9
+ )
10
 
11
 
12
  class LLMTutor:
 
90
  compare_dicts(old_config, new_config)
91
  return changes
92
 
93
+ def retrieval_qa_chain(
94
+ self, llm, qa_prompt, rephrase_prompt, db, memory=None, callbacks=None
95
+ ):
96
  """
97
  Create a Retrieval QA Chain.
98
 
 
116
  qa_prompt=qa_prompt,
117
  rephrase_prompt=rephrase_prompt,
118
  config=self.config,
119
+ callbacks=callbacks,
120
  )
121
+
122
+ self.question_generator = QuestionGenerator()
123
  else:
124
  raise ValueError(
125
  f"Invalid LLM Architecture: {self.config['llm_params']['llm_arch']}"
 
137
  llm = chat_model_loader.load_chat_model()
138
  return llm
139
 
140
+ def qa_bot(self, memory=None, callbacks=None):
141
  """
142
  Create a QA bot instance.
143
 
 
156
  )
157
 
158
  qa = self.retrieval_qa_chain(
159
+ self.llm,
160
+ self.qa_prompt,
161
+ self.rephrase_prompt,
162
+ self.vector_db,
163
+ memory,
164
+ callbacks=callbacks,
165
  )
166
 
167
  return qa
code/modules/config/config.yml CHANGED
@@ -28,7 +28,7 @@ llm_params:
28
  llm_arch: 'langchain' # [langchain, langgraph_agentic]
29
  use_history: True # bool
30
  memory_window: 3 # int
31
- llm_style: 'Normal' # str [Normal, ELI5, Socratic]
32
  llm_loader: 'gpt-4o-mini' # str [local_llm, gpt-3.5-turbo-1106, gpt-4, gpt-4o-mini]
33
  openai_params:
34
  temperature: 0.7 # float
@@ -39,6 +39,7 @@ llm_params:
39
  chat_logging:
40
  log_chat: False # bool
41
  platform: 'literalai'
 
42
 
43
  splitter_options:
44
  use_splitter: True # bool
 
28
  llm_arch: 'langchain' # [langchain, langgraph_agentic]
29
  use_history: True # bool
30
  memory_window: 3 # int
31
+ llm_style: 'Normal' # str [Normal, ELI5]
32
  llm_loader: 'gpt-4o-mini' # str [local_llm, gpt-3.5-turbo-1106, gpt-4, gpt-4o-mini]
33
  openai_params:
34
  temperature: 0.7 # float
 
39
  chat_logging:
40
  log_chat: False # bool
41
  platform: 'literalai'
42
+ callbacks: True # bool
43
 
44
  splitter_options:
45
  use_splitter: True # bool
code/modules/config/prompts.py CHANGED
@@ -24,31 +24,28 @@ prompts = {
24
  "AI Tutor:"
25
  ),
26
  "eli5": (
27
- "You are an AI Tutor for the course DS598, taught by Prof. Thomas Gardos. Answer the user's question using the provided context in the simplest way possible, as if you are explaining to a 5-year-old. Only use the context if it helps make things clearer. The context is ordered by relevance. "
28
- "If you don't know the answer, do your best without making things up. Keep the conversation simple and easy to understand. "
29
- "Use chat history and context as guides but avoid repeating past responses. Provide links from the source_file metadata. Use the source context that is most relevant. "
30
- "Speak in a friendly and engaging manner, like talking to a curious child. Avoid complex terms.\n\n"
 
31
  "Chat History:\n{chat_history}\n\n"
32
  "Context:\n{context}\n\n"
33
- "Answer the student's question below in a friendly, simple, and engaging manner. Use the context and history only if relevant, otherwise, engage in a free-flowing conversation.\n"
34
- "Give a long very detailed narrative explanation. Use examples wherever you can to aid in the explanation. Remember, explain it as if you are talking to a 5-year-old, so construct a long narrative that builds up to the answer.\n"
35
- "5-year-old Student: {input}\n"
36
  "AI Tutor:"
37
  ),
38
  "socratic": (
39
- "You are an AI Tutor for the course DS598, taught by Prof. Thomas Gardos. Your goal is to guide the student towards understanding using the Socratic method. Ask thought-provoking questions to encourage critical thinking and self-discovery. Use the provided context only when relevant. The context is ordered by relevance.\n\n"
40
- "Guidelines for the Socratic approach:\n"
41
- "Guidelines:"
42
- "1. Begin with a concise, direct answer to the student's question."
43
- "2. Follow up with 1-2 thought-provoking questions to encourage critical thinking."
44
- "3. Provide additional explanations or context if necessary to move the conversation forward."
45
- "4. End with an open-ended question that invites further exploration."
46
- "Based on the chat history determine which guideline to follow., and answer accordingly\n\n"
47
- "If the student is stuck, offer gentle hints or break down the concept into simpler parts. Maintain a friendly, engaging tone throughout the conversation.\n\n"
48
- "Use chat history and context as guides, but avoid repeating past responses. Provide links from the source_file metadata when appropriate. Use the most relevant source context.\n\n"
49
  "Chat History:\n{chat_history}\n\n"
50
  "Context:\n{context}\n\n"
51
- "Engage with the student's question below using the Socratic method. Ask probing questions to guide their thinking and encourage deeper understanding. Only provide direct answers if absolutely necessary.\n"
 
52
  "Student: {input}\n"
53
  "AI Tutor:"
54
  ),
 
24
  "AI Tutor:"
25
  ),
26
  "eli5": (
27
+ "You are an AI Tutor for the course DS598, taught by Prof. Thomas Gardos. Answer the user's question in the simplest way possible, like explaining to someone new to the topic. Use the provided context to help clarify your explanation."
28
+ "If you don't know the answer, do your best without making things up. Keep the conversation straightforward and easy to follow."
29
+ "Use chat history and context as guides but avoid repeating past responses. Provide links from the source_file metadata when relevant. Use the source context that is most relevant."
30
+ "Speak in a friendly and engaging manner, like talking to someone who is curious and eager to learn. Avoid using complex terms and jargon."
31
+ "Use examples wherever possible to aid in understanding."
32
  "Chat History:\n{chat_history}\n\n"
33
  "Context:\n{context}\n\n"
34
+ "Answer the student's question below in a friendly, simple, and engaging manner. Use the context and history only if relevant, otherwise, engage in a free-flowing conversation."
35
+ "Give a clear and detailed explanation with examples to make it easier to understand."
36
+ "Student: {input}\n"
37
  "AI Tutor:"
38
  ),
39
  "socratic": (
40
+ "You are an AI Tutor for the course DS598, taught by Prof. Thomas Gardos. Engage the student in a Socratic dialogue to help them discover answers on their own. Use the provided context to guide your questioning."
41
+ "If you don't know the answer, do your best without making things up. Keep the conversation engaging and inquisitive."
42
+ "Use chat history and context as guides but avoid repeating past responses. Provide links from the source_file metadata when relevant. Use the source context that is most relevant."
43
+ "Speak in a friendly and engaging manner, encouraging critical thinking and self-discovery."
44
+ "Use questions to lead the student to explore the topic and uncover answers."
 
 
 
 
 
45
  "Chat History:\n{chat_history}\n\n"
46
  "Context:\n{context}\n\n"
47
+ "Answer the student's question below by guiding them through a series of questions and insights that lead to deeper understanding. Use the context and history only if relevant, otherwise, engage in a free-flowing conversation."
48
+ "Foster an inquisitive mindset and help the student discover answers through dialogue."
49
  "Student: {input}\n"
50
  "AI Tutor:"
51
  ),