ahmadsanafarooq commited on
Commit
8b95a88
·
verified ·
1 Parent(s): d0c46e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -163
app.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import os
2
  import gradio as gr
3
  from langchain.text_splitter import RecursiveCharacterTextSplitter
@@ -11,79 +13,47 @@ from typing import List
11
  import logging
12
  import numpy as np
13
  from sklearn.feature_extraction.text import TfidfVectorizer
14
- from sklearn.metrics.pairwise import cosine_similarity
15
- import pickle
16
  from dotenv import load_dotenv
17
 
18
- # Configure logging
19
  logging.basicConfig(level=logging.INFO)
20
  logger = logging.getLogger(__name__)
21
 
22
- # ---------------------- TF-IDF Embedding Fallback ----------------------
23
  class SimpleEmbeddings:
24
- """Simple TF-IDF based embeddings as fallback"""
25
-
26
  def __init__(self):
27
  self.vectorizer = TfidfVectorizer(max_features=384, stop_words='english')
28
  self.fitted = False
29
-
30
  def embed_documents(self, texts: List[str]) -> List[List[float]]:
31
- """Embed a list of documents"""
32
  if not self.fitted:
33
  self.vectorizer.fit(texts)
34
  self.fitted = True
35
-
36
- embeddings = self.vectorizer.transform(texts)
37
- return embeddings.toarray().tolist()
38
-
39
  def embed_query(self, text: str) -> List[float]:
40
- """Embed a single query"""
41
  if not self.fitted:
42
- # If not fitted, return zero vector
43
  return [0.0] * 384
44
-
45
- embedding = self.vectorizer.transform([text])
46
- return embedding.toarray()[0].tolist()
47
 
48
- # ---------------------- RAG Assistant ----------------------
49
  class RAGAssistant:
50
  def __init__(self, groq_api_key: str):
51
- """Initialize the RAG Assistant with Groq API key"""
52
  self.groq_api_key = groq_api_key
53
-
54
- # Initialize embeddings with fallback
55
  self.embeddings = self._init_embeddings()
56
-
57
- self.text_splitter = RecursiveCharacterTextSplitter(
58
- chunk_size=1000,
59
- chunk_overlap=200,
60
- length_function=len
61
- )
62
-
63
  self.learning_vectorstore = None
64
  self.code_vectorstore = None
65
-
66
- self.llm = ChatGroq(
67
- groq_api_key=groq_api_key,
68
- model_name="llama3-70b-8192",
69
- temperature=0.1
70
- )
71
-
72
  self.learning_persist_dir = "./chroma_learning_db"
73
  self.code_persist_dir = "./chroma_code_db"
74
-
75
  self._init_vector_stores()
76
-
77
  def _init_embeddings(self):
78
  try:
79
  from langchain_huggingface import HuggingFaceEmbeddings
80
  print("Trying HuggingFace embeddings...")
81
- models_to_try = [
82
- "all-MiniLM-L6-v2",
83
- "paraphrase-MiniLM-L3-v2",
84
- "all-mpnet-base-v2"
85
- ]
86
- for model_name in models_to_try:
87
  try:
88
  embeddings = HuggingFaceEmbeddings(
89
  model_name=model_name,
@@ -95,11 +65,9 @@ class RAGAssistant:
95
  except Exception as e:
96
  print(f"Failed to load {model_name}: {e}")
97
  except ImportError:
98
- print("HuggingFace embeddings not available")
99
-
100
- print("Using TF-IDF embeddings as fallback...")
101
  return SimpleEmbeddings()
102
-
103
  def _init_vector_stores(self):
104
  try:
105
  self.learning_vectorstore = Chroma(
@@ -114,14 +82,16 @@ class RAGAssistant:
114
  )
115
  except Exception as e:
116
  logger.error(f"Error initializing vector stores: {str(e)}")
117
- raise
118
-
119
  def load_documents(self, files: List[str], assistant_type: str) -> str:
120
  try:
121
  documents = []
 
 
122
  for file_path in files:
 
123
  try:
124
- if file_path.endswith('.pdf'):
125
  loader = PyPDFLoader(file_path)
126
  else:
127
  loader = TextLoader(file_path, encoding='utf-8')
@@ -129,228 +99,178 @@ class RAGAssistant:
129
  documents.extend(docs)
130
  except Exception as e:
131
  print(f"Error loading {file_path}: {e}")
 
 
132
  if not documents:
133
  return "No documents could be loaded. Please check your files."
 
134
  chunks = self.text_splitter.split_documents(documents)
 
 
135
  for chunk in chunks:
136
  chunk.metadata['assistant_type'] = assistant_type
 
137
  if assistant_type == "learning":
138
  self.learning_vectorstore.add_documents(chunks)
139
  self.learning_vectorstore.persist()
140
  elif assistant_type == "code":
141
  self.code_vectorstore.add_documents(chunks)
142
  self.code_vectorstore.persist()
 
143
  return f"Successfully loaded {len(chunks)} chunks from {len(documents)} documents into {assistant_type} assistant."
 
144
  except Exception as e:
145
  logger.error(f"Error loading documents: {str(e)}")
146
  return f"Error loading documents: {str(e)}"
147
-
148
  def get_learning_tutor_response(self, question: str) -> str:
149
  try:
150
  if not self.learning_vectorstore:
151
  return "Please upload some learning materials first."
 
152
  qa_chain = RetrievalQA.from_chain_type(
153
  llm=self.llm,
154
  chain_type="stuff",
155
  retriever=self.learning_vectorstore.as_retriever(search_kwargs={"k": 3}),
156
  return_source_documents=True
157
  )
 
158
  learning_prompt = f"""
159
- You are an AI learning assistant that helps students understand academic concepts.
160
- Based on the provided course materials, answer the student's question clearly and educationally.
161
-
162
- Guidelines:
163
- - Provide clear, educational explanations
164
- - Use examples when helpful
165
- - Reference specific sources when possible
166
- - Adapt to the student's level of understanding
167
- - Offer additional practice questions or related concepts when relevant
168
- - Maintain an encouraging, supportive tone
169
-
170
- Student's question: {question}
171
  """
 
172
  result = qa_chain({"query": learning_prompt})
173
  response = result['result']
 
174
  if result.get('source_documents'):
175
  response += "\n\n**Sources:**\n"
176
  for doc in result['source_documents'][:3]:
177
  source = doc.metadata.get('source', 'Unknown')
178
  response += f"- {Path(source).name}\n"
 
179
  return response
 
180
  except Exception as e:
181
  logger.error(f"Error in learning tutor: {str(e)}")
182
  return f"Error generating response: {str(e)}"
183
-
184
  def get_code_helper_response(self, question: str) -> str:
185
  try:
186
  if not self.code_vectorstore:
187
  return "Please upload some code documentation first."
 
188
  qa_chain = RetrievalQA.from_chain_type(
189
  llm=self.llm,
190
  chain_type="stuff",
191
  retriever=self.code_vectorstore.as_retriever(search_kwargs={"k": 3}),
192
  return_source_documents=True
193
  )
 
194
  code_prompt = f"""
195
- You are a technical assistant that helps developers understand codebases and APIs.
196
- Based on the provided documentation and code examples, answer the developer's question.
197
-
198
- Guidelines:
199
- - Provide practical, actionable guidance
200
- - Include relevant code snippets with explanations
201
- - Reference specific documentation sections when possible
202
- - Highlight important considerations (security, performance, errors)
203
- - Suggest related APIs or patterns that might be useful
204
- - Use clear, technical language appropriate for developers
205
-
206
- Developer's question: {question}
207
  """
 
208
  result = qa_chain({"query": code_prompt})
209
  response = result['result']
 
210
  if result.get('source_documents'):
211
- response += "\n\n**Documentation Sources:**\n"
212
  for doc in result['source_documents'][:3]:
213
  source = doc.metadata.get('source', 'Unknown')
214
  response += f"- {Path(source).name}\n"
 
215
  return response
 
216
  except Exception as e:
217
  logger.error(f"Error in code helper: {str(e)}")
218
  return f"Error generating response: {str(e)}"
219
 
220
- # ---------------------- Gradio UI ----------------------
221
  def create_gradio_interface(assistant: RAGAssistant):
222
  def upload_learning_files(files):
223
  if not files:
224
  return "No files uploaded."
225
- file_paths = [f.name for f in files]
226
  return assistant.load_documents(file_paths, "learning")
227
-
228
  def upload_code_files(files):
229
  if not files:
230
  return "No files uploaded."
231
- file_paths = [f.name for f in files]
232
  return assistant.load_documents(file_paths, "code")
233
-
234
  def learning_chat(message, history):
235
  if not message.strip():
236
  return history, ""
237
  response = assistant.get_learning_tutor_response(message)
238
  history.append((message, response))
239
  return history, ""
240
-
241
  def code_chat(message, history):
242
  if not message.strip():
243
  return history, ""
244
  response = assistant.get_code_helper_response(message)
245
  history.append((message, response))
246
  return history, ""
247
-
248
  with gr.Blocks(title="RAG-Based Learning & Code Assistant", theme=gr.themes.Soft()) as demo:
249
  gr.Markdown("# 🎓 RAG-Based Learning & Code Assistant")
250
- gr.Markdown("Upload your documents and ask questions to get intelligent responses!")
251
-
252
  with gr.Tabs():
253
  with gr.TabItem("📚 Learning Tutor"):
 
254
  with gr.Row():
255
  with gr.Column(scale=1):
256
- learning_files = gr.File(label="Upload Learning Materials", file_count="multiple", file_types=[".pdf", ".txt", ".md"])
257
- learning_upload_btn = gr.Button("Upload Materials", variant="primary")
258
  learning_status = gr.Textbox(label="Upload Status", interactive=False)
259
  with gr.Column(scale=2):
260
- learning_chatbot = gr.Chatbot(label="Learning Tutor Chat", height=400)
261
- learning_input = gr.Textbox(label="Ask a question", placeholder="e.g., What is regression?")
262
- learning_submit = gr.Button("Ask Question", variant="primary")
 
263
  learning_upload_btn.click(upload_learning_files, inputs=[learning_files], outputs=[learning_status])
264
  learning_submit.click(learning_chat, inputs=[learning_input, learning_chatbot], outputs=[learning_chatbot, learning_input])
265
  learning_input.submit(learning_chat, inputs=[learning_input, learning_chatbot], outputs=[learning_chatbot, learning_input])
266
-
267
  with gr.TabItem("💻 Code Documentation Helper"):
 
268
  with gr.Row():
269
  with gr.Column(scale=1):
270
- code_files = gr.File(label="Upload Code Documentation", file_count="multiple", file_types=[".pdf", ".txt", ".md", ".py", ".js", ".json"])
271
- code_upload_btn = gr.Button("Upload Documentation", variant="primary")
272
  code_status = gr.Textbox(label="Upload Status", interactive=False)
273
  with gr.Column(scale=2):
274
- code_chatbot = gr.Chatbot(label="Code Helper Chat", height=400)
275
- code_input = gr.Textbox(label="Ask about code or APIs", placeholder="e.g., How to use this function?")
276
- code_submit = gr.Button("Ask Question", variant="primary")
 
277
  code_upload_btn.click(upload_code_files, inputs=[code_files], outputs=[code_status])
278
  code_submit.click(code_chat, inputs=[code_input, code_chatbot], outputs=[code_chatbot, code_input])
279
  code_input.submit(code_chat, inputs=[code_input, code_chatbot], outputs=[code_chatbot, code_input])
280
-
281
  gr.Markdown("---")
282
- gr.Markdown("*Powered by LangChain, ChromaDB, and Groq API*")
283
-
284
  return demo
285
 
286
- # ---------------------- Evaluation Additions ----------------------
287
- class RetrieverEvaluator:
288
- """Evaluation class for computing Recall@k and MRR@k"""
289
-
290
- def __init__(self, retriever, ground_truth: dict, k=3):
291
- self.retriever = retriever
292
- self.ground_truth = ground_truth
293
- self.k = k
294
-
295
- def recall_at_k(self):
296
- correct = 0
297
- for query, relevant_docs in self.ground_truth.items():
298
- results = self.retriever.get_relevant_documents(query)
299
- retrieved = [Path(doc.metadata.get("source", "")).name for doc in results]
300
- if any(doc in retrieved[:self.k] for doc in relevant_docs):
301
- correct += 1
302
- recall = correct / len(self.ground_truth)
303
- print(f"Recall@{self.k}: {recall:.2f}")
304
- return recall
305
-
306
- def mean_reciprocal_rank(self):
307
- mrr_total = 0
308
- for query, relevant_docs in self.ground_truth.items():
309
- results = self.retriever.get_relevant_documents(query)
310
- retrieved = [Path(doc.metadata.get("source", "")).name for doc in results]
311
- for rank, doc in enumerate(retrieved[:self.k], 1):
312
- if doc in relevant_docs:
313
- mrr_total += 1 / rank
314
- break
315
- mrr = mrr_total / len(self.ground_truth)
316
- print(f"MRR@{self.k}: {mrr:.2f}")
317
- return mrr
318
-
319
- def evaluate_retriever_example(assistant):
320
- """Run example evaluation with mock ground truth"""
321
- sample_ground_truth = {
322
- "What is machine learning?": ["ml_intro.txt"],
323
- "What is API authentication?": ["api_guide.pdf"]
324
- }
325
- if assistant.learning_vectorstore:
326
- retriever = assistant.learning_vectorstore.as_retriever(search_kwargs={"k": 3})
327
- evaluator = RetrieverEvaluator(retriever, sample_ground_truth, k=3)
328
- recall = evaluator.recall_at_k()
329
- mrr = evaluator.mean_reciprocal_rank()
330
- return f"Evaluation Results:\nRecall@3: {recall:.2f}\nMRR@3: {mrr:.2f}"
331
- return "No documents uploaded for evaluation."
332
-
333
- # ---------------------- Entry Point ----------------------
334
  def main():
335
  load_dotenv()
336
  groq_api_key = os.getenv("GROQ_API_KEY")
337
  if not groq_api_key:
338
- print("Please set your GROQ_API_KEY in the environment.")
339
  return
340
-
341
- try:
342
- print("Initializing RAG Assistant...")
343
- assistant = RAGAssistant(groq_api_key)
344
-
345
- # Optional: Run evaluation after docs are uploaded
346
- # print(evaluate_retriever_example(assistant))
347
-
348
- demo = create_gradio_interface(assistant)
349
- print("Launching app...")
350
- demo.launch(server_name="0.0.0.0", server_port=7860, debug=True)
351
- except Exception as e:
352
- logger.error(f"Error starting application: {str(e)}")
353
- print(f"Error: {str(e)}")
354
 
355
  if __name__ == "__main__":
356
  main()
 
1
+ # app.py
2
+
3
  import os
4
  import gradio as gr
5
  from langchain.text_splitter import RecursiveCharacterTextSplitter
 
13
  import logging
14
  import numpy as np
15
  from sklearn.feature_extraction.text import TfidfVectorizer
 
 
16
  from dotenv import load_dotenv
17
 
18
+ # ----------------- Logger Configuration ------------------
19
  logging.basicConfig(level=logging.INFO)
20
  logger = logging.getLogger(__name__)
21
 
22
+ # ----------------- Simple TF-IDF Fallback Embeddings ------------------
23
  class SimpleEmbeddings:
 
 
24
  def __init__(self):
25
  self.vectorizer = TfidfVectorizer(max_features=384, stop_words='english')
26
  self.fitted = False
27
+
28
  def embed_documents(self, texts: List[str]) -> List[List[float]]:
 
29
  if not self.fitted:
30
  self.vectorizer.fit(texts)
31
  self.fitted = True
32
+ return self.vectorizer.transform(texts).toarray().tolist()
33
+
 
 
34
  def embed_query(self, text: str) -> List[float]:
 
35
  if not self.fitted:
 
36
  return [0.0] * 384
37
+ return self.vectorizer.transform([text]).toarray()[0].tolist()
 
 
38
 
39
+ # ----------------- RAG Assistant Class ------------------
40
  class RAGAssistant:
41
  def __init__(self, groq_api_key: str):
 
42
  self.groq_api_key = groq_api_key
 
 
43
  self.embeddings = self._init_embeddings()
44
+ self.text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
 
 
 
 
 
 
45
  self.learning_vectorstore = None
46
  self.code_vectorstore = None
47
+ self.llm = ChatGroq(groq_api_key=groq_api_key, model_name="llama3-70b-8192", temperature=0.1)
 
 
 
 
 
 
48
  self.learning_persist_dir = "./chroma_learning_db"
49
  self.code_persist_dir = "./chroma_code_db"
 
50
  self._init_vector_stores()
51
+
52
  def _init_embeddings(self):
53
  try:
54
  from langchain_huggingface import HuggingFaceEmbeddings
55
  print("Trying HuggingFace embeddings...")
56
+ for model_name in ["all-MiniLM-L6-v2", "paraphrase-MiniLM-L3-v2", "all-mpnet-base-v2"]:
 
 
 
 
 
57
  try:
58
  embeddings = HuggingFaceEmbeddings(
59
  model_name=model_name,
 
65
  except Exception as e:
66
  print(f"Failed to load {model_name}: {e}")
67
  except ImportError:
68
+ print("HuggingFace not installed. Using fallback TF-IDF.")
 
 
69
  return SimpleEmbeddings()
70
+
71
  def _init_vector_stores(self):
72
  try:
73
  self.learning_vectorstore = Chroma(
 
82
  )
83
  except Exception as e:
84
  logger.error(f"Error initializing vector stores: {str(e)}")
85
+
 
86
  def load_documents(self, files: List[str], assistant_type: str) -> str:
87
  try:
88
  documents = []
89
+ print("Files received:", files)
90
+
91
  for file_path in files:
92
+ print(f"Trying to load: {file_path}")
93
  try:
94
+ if file_path.lower().endswith('.pdf'):
95
  loader = PyPDFLoader(file_path)
96
  else:
97
  loader = TextLoader(file_path, encoding='utf-8')
 
99
  documents.extend(docs)
100
  except Exception as e:
101
  print(f"Error loading {file_path}: {e}")
102
+ continue
103
+
104
  if not documents:
105
  return "No documents could be loaded. Please check your files."
106
+
107
  chunks = self.text_splitter.split_documents(documents)
108
+ print(f"Total chunks created: {len(chunks)}")
109
+
110
  for chunk in chunks:
111
  chunk.metadata['assistant_type'] = assistant_type
112
+
113
  if assistant_type == "learning":
114
  self.learning_vectorstore.add_documents(chunks)
115
  self.learning_vectorstore.persist()
116
  elif assistant_type == "code":
117
  self.code_vectorstore.add_documents(chunks)
118
  self.code_vectorstore.persist()
119
+
120
  return f"Successfully loaded {len(chunks)} chunks from {len(documents)} documents into {assistant_type} assistant."
121
+
122
  except Exception as e:
123
  logger.error(f"Error loading documents: {str(e)}")
124
  return f"Error loading documents: {str(e)}"
125
+
126
  def get_learning_tutor_response(self, question: str) -> str:
127
  try:
128
  if not self.learning_vectorstore:
129
  return "Please upload some learning materials first."
130
+
131
  qa_chain = RetrievalQA.from_chain_type(
132
  llm=self.llm,
133
  chain_type="stuff",
134
  retriever=self.learning_vectorstore.as_retriever(search_kwargs={"k": 3}),
135
  return_source_documents=True
136
  )
137
+
138
  learning_prompt = f"""
139
+ You are an AI learning assistant helping students understand academic concepts.
140
+ Based on the provided materials, answer the student's question:
141
+
142
+ {question}
 
 
 
 
 
 
 
 
143
  """
144
+
145
  result = qa_chain({"query": learning_prompt})
146
  response = result['result']
147
+
148
  if result.get('source_documents'):
149
  response += "\n\n**Sources:**\n"
150
  for doc in result['source_documents'][:3]:
151
  source = doc.metadata.get('source', 'Unknown')
152
  response += f"- {Path(source).name}\n"
153
+
154
  return response
155
+
156
  except Exception as e:
157
  logger.error(f"Error in learning tutor: {str(e)}")
158
  return f"Error generating response: {str(e)}"
159
+
160
  def get_code_helper_response(self, question: str) -> str:
161
  try:
162
  if not self.code_vectorstore:
163
  return "Please upload some code documentation first."
164
+
165
  qa_chain = RetrievalQA.from_chain_type(
166
  llm=self.llm,
167
  chain_type="stuff",
168
  retriever=self.code_vectorstore.as_retriever(search_kwargs={"k": 3}),
169
  return_source_documents=True
170
  )
171
+
172
  code_prompt = f"""
173
+ You are a code documentation assistant helping developers with APIs and codebases.
174
+ Based on the uploaded documentation, answer this question:
175
+
176
+ {question}
 
 
 
 
 
 
 
 
177
  """
178
+
179
  result = qa_chain({"query": code_prompt})
180
  response = result['result']
181
+
182
  if result.get('source_documents'):
183
+ response += "\n\n**Sources:**\n"
184
  for doc in result['source_documents'][:3]:
185
  source = doc.metadata.get('source', 'Unknown')
186
  response += f"- {Path(source).name}\n"
187
+
188
  return response
189
+
190
  except Exception as e:
191
  logger.error(f"Error in code helper: {str(e)}")
192
  return f"Error generating response: {str(e)}"
193
 
194
+ # ----------------- Gradio UI Interface ------------------
195
  def create_gradio_interface(assistant: RAGAssistant):
196
  def upload_learning_files(files):
197
  if not files:
198
  return "No files uploaded."
199
+ file_paths = [f.path for f in files]
200
  return assistant.load_documents(file_paths, "learning")
201
+
202
  def upload_code_files(files):
203
  if not files:
204
  return "No files uploaded."
205
+ file_paths = [f.path for f in files]
206
  return assistant.load_documents(file_paths, "code")
207
+
208
  def learning_chat(message, history):
209
  if not message.strip():
210
  return history, ""
211
  response = assistant.get_learning_tutor_response(message)
212
  history.append((message, response))
213
  return history, ""
214
+
215
  def code_chat(message, history):
216
  if not message.strip():
217
  return history, ""
218
  response = assistant.get_code_helper_response(message)
219
  history.append((message, response))
220
  return history, ""
221
+
222
  with gr.Blocks(title="RAG-Based Learning & Code Assistant", theme=gr.themes.Soft()) as demo:
223
  gr.Markdown("# 🎓 RAG-Based Learning & Code Assistant")
224
+ gr.Markdown("Upload documents and get smart, personalized answers.")
225
+
226
  with gr.Tabs():
227
  with gr.TabItem("📚 Learning Tutor"):
228
+ gr.Markdown("### Upload lecture notes or textbooks below:")
229
  with gr.Row():
230
  with gr.Column(scale=1):
231
+ learning_files = gr.File(label="Upload Materials", file_count="multiple", file_types=[".pdf", ".txt", ".md"])
232
+ learning_upload_btn = gr.Button("Upload", variant="primary")
233
  learning_status = gr.Textbox(label="Upload Status", interactive=False)
234
  with gr.Column(scale=2):
235
+ learning_chatbot = gr.Chatbot(label="Tutor Chat", height=400)
236
+ learning_input = gr.Textbox(label="Ask a question", placeholder="e.g., What is machine learning?")
237
+ learning_submit = gr.Button("Ask", variant="primary")
238
+
239
  learning_upload_btn.click(upload_learning_files, inputs=[learning_files], outputs=[learning_status])
240
  learning_submit.click(learning_chat, inputs=[learning_input, learning_chatbot], outputs=[learning_chatbot, learning_input])
241
  learning_input.submit(learning_chat, inputs=[learning_input, learning_chatbot], outputs=[learning_chatbot, learning_input])
242
+
243
  with gr.TabItem("💻 Code Documentation Helper"):
244
+ gr.Markdown("### Upload code docs or API guides below:")
245
  with gr.Row():
246
  with gr.Column(scale=1):
247
+ code_files = gr.File(label="Upload Docs", file_count="multiple", file_types=[".pdf", ".txt", ".md", ".py", ".js", ".json"])
248
+ code_upload_btn = gr.Button("Upload", variant="primary")
249
  code_status = gr.Textbox(label="Upload Status", interactive=False)
250
  with gr.Column(scale=2):
251
+ code_chatbot = gr.Chatbot(label="Code Chat", height=400)
252
+ code_input = gr.Textbox(label="Ask about the codebase", placeholder="e.g., How does login work?")
253
+ code_submit = gr.Button("Ask", variant="primary")
254
+
255
  code_upload_btn.click(upload_code_files, inputs=[code_files], outputs=[code_status])
256
  code_submit.click(code_chat, inputs=[code_input, code_chatbot], outputs=[code_chatbot, code_input])
257
  code_input.submit(code_chat, inputs=[code_input, code_chatbot], outputs=[code_chatbot, code_input])
258
+
259
  gr.Markdown("---")
260
+ gr.Markdown("Built with ❤️ using LangChain, ChromaDB, and Groq API")
261
+
262
  return demo
263
 
264
+ # ----------------- Main Function ------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  def main():
266
  load_dotenv()
267
  groq_api_key = os.getenv("GROQ_API_KEY")
268
  if not groq_api_key:
269
+ print("Set your GROQ_API_KEY in the .env file or environment.")
270
  return
271
+ assistant = RAGAssistant(groq_api_key)
272
+ demo = create_gradio_interface(assistant)
273
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False, debug=True)
 
 
 
 
 
 
 
 
 
 
 
274
 
275
  if __name__ == "__main__":
276
  main()