Nischal Subedi commited on
Commit
4c5479b
·
1 Parent(s): bb08c16

added Open AI api key features

Browse files
Files changed (2) hide show
  1. app.py +173 -67
  2. requirements.txt +2 -2
app.py CHANGED
@@ -26,7 +26,6 @@ class RAGSystem:
26
  self.prompt_template = PromptTemplate(
27
  input_variables=["query", "context", "state", "statutes"],
28
  template="""You are a legal assistant specializing in tenant rights and landlord-tenant laws. Your goal is to provide accurate, detailed, and helpful answers that are explicitly grounded in the statutes provided in the context. Only use general knowledge to supplement the answer if the context lacks sufficient detail to fully answer the question, and clearly indicate when you are doing so.
29
-
30
  Instructions:
31
  - Use the context information and the provided statutes as the primary source to answer the question.
32
  - Explicitly cite the relevant statute(s) (e.g., (AS § 34.03.220(a)(2))) in your answer to ground your response in the legal text.
@@ -35,17 +34,12 @@ Instructions:
35
  - Provide detailed answers with practical examples or scenarios when possible.
36
  - Use bullet points or numbered lists for clarity when applicable.
37
  - Maintain a professional and neutral tone.
38
- - Do not include a "Sources" section in the answer.
39
-
40
  Question: {query}
41
  State: {state}
42
-
43
  Statutes found in context:
44
  {statutes}
45
-
46
  Context information:
47
  {context}
48
-
49
  Answer:"""
50
  )
51
 
@@ -88,7 +82,6 @@ Answer:"""
88
  if not state:
89
  return {
90
  "answer": "Please select a state to proceed with your query.",
91
- "sources": [],
92
  "context_used": "N/A",
93
  "statutes_found": "N/A"
94
  }
@@ -96,7 +89,6 @@ Answer:"""
96
  if not openai_api_key:
97
  return {
98
  "answer": "Please provide an OpenAI API key to proceed.",
99
- "sources": [],
100
  "context_used": "N/A",
101
  "statutes_found": "N/A"
102
  }
@@ -108,7 +100,6 @@ Answer:"""
108
  except Exception as e:
109
  return {
110
  "answer": f"Failed to initialize LLM with the provided API key: {str(e)}",
111
- "sources": [],
112
  "context_used": "N/A",
113
  "statutes_found": "N/A"
114
  }
@@ -118,37 +109,24 @@ Answer:"""
118
  logging.info("Vector database query successful")
119
  except Exception as e:
120
  logging.error(f"Vector database query failed: {str(e)}")
121
- return {
122
- "answer": "An error occurred while querying the database. Please try again.",
123
- "sources": [],
124
- "context_used": "N/A",
125
- "statutes_found": "N/A"
126
  }
 
127
 
128
  context_parts = []
129
- sources = []
130
 
131
- if results["document_results"]["documents"]:
132
  for i, doc in enumerate(results["document_results"]["documents"][0]):
133
  metadata = results["document_results"]["metadatas"][0][i]
134
  context_parts.append(f"[{metadata['state']} - Chunk {metadata.get('chunk_id', 'N/A')}] {doc}")
135
- sources.append({
136
- "text": doc[:100] + "..." if len(doc) > 100 else doc,
137
- "state": metadata["state"],
138
- "chunk_id": str(metadata.get("chunk_id", "N/A")),
139
- "source_file": metadata.get("source", "Unknown")
140
- })
141
 
142
- if results["state_results"]["documents"]:
143
  for i, doc in enumerate(results["state_results"]["documents"][0]):
144
  metadata = results["state_results"]["metadatas"][0][i]
145
  context_parts.append(f"[{metadata['state']} - Summary] {doc}")
146
- sources.append({
147
- "text": doc[:100] + "..." if len(doc) > 100 else doc,
148
- "state": metadata["state"],
149
- "type": metadata.get("type", "summary"),
150
- "source_file": "state_summary"
151
- })
152
 
153
  context = "\n\n---\n\n".join(context_parts) if context_parts else "No relevant context found."
154
 
@@ -156,7 +134,6 @@ Answer:"""
156
  logging.info("No relevant context found for query")
157
  return {
158
  "answer": "I don't have sufficient information in my database to answer this question accurately. However, I can provide some general information about tenant rights.",
159
- "sources": [],
160
  "context_used": context,
161
  "statutes_found": "N/A"
162
  }
@@ -176,14 +153,12 @@ Answer:"""
176
  logging.error(f"LLM processing failed: {str(e)}")
177
  return {
178
  "answer": "An error occurred while generating the answer. Please try again.",
179
- "sources": sources,
180
  "context_used": context,
181
  "statutes_found": statutes
182
  }
183
 
184
  return {
185
  "answer": answer['text'].strip(),
186
- "sources": sources,
187
  "context_used": context,
188
  "statutes_found": statutes
189
  }
@@ -209,40 +184,193 @@ Answer:"""
209
  def gradio_interface(self) -> gr.Interface:
210
  def query_interface(api_key: str, query: str, state: str) -> str:
211
  if not api_key:
212
- return "Please provide an OpenAI API key to proceed."
213
  if not state:
214
- return "Please select a state to proceed with your query."
215
  result = self.process_query(query, state=state, openai_api_key=api_key)
216
- return f"**Answer:**\n{result['answer']}\n\n**Statutes Found:**\n{result['statutes_found']}"
217
 
218
  states = self.get_states()
219
 
220
  example_queries = [
221
- ["sk-abc123", "What is the rent due date law?", "California"],
222
- ["sk-abc123", "What are the rules for security deposit returns?", "New York"],
223
- ["sk-abc123", "Can a landlord enter without notice?", "Texas"],
224
- ["sk-abc123", "What are the eviction notice requirements?", "Florida"],
225
- ["sk-abc123", "Are there rent control laws?", "Oregon"]
226
  ]
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  interface = gr.Interface(
229
  fn=query_interface,
230
  inputs=[
231
  gr.Textbox(
232
  label="Enter your OpenAI API Key",
233
  type="password",
234
- placeholder="e.g., sk-abc123"
 
235
  ),
236
  gr.Textbox(
237
  label="Enter your question about Landlord-Tenant laws",
238
  placeholder="e.g., What are the eviction rules?",
239
- lines=2
 
240
  ),
241
  gr.Dropdown(
242
  label="Select a state (required)",
243
  choices=states,
244
  value=None,
245
- allow_custom_value=False
 
246
  )
247
  ],
248
  outputs=gr.Markdown(
@@ -252,30 +380,8 @@ Answer:"""
252
  title="🏠 Landlord-Tenant Rights Bot",
253
  description="Ask questions about tenant rights and landlord-tenant laws based on state-specific legal documents. Provide your OpenAI API key, select a state, and enter your question below. You can get an API key from [OpenAI](https://platform.openai.com/api-keys).",
254
  examples=example_queries,
255
- theme=gr.themes.Soft(),
256
- css="""
257
- .output-markdown {
258
- background-color: #f8f9fa;
259
- padding: 20px;
260
- border-radius: 10px;
261
- border: 1px solid #e0e0e0;
262
- font-size: 16px;
263
- line-height: 1.6;
264
- }
265
- .gr-button-primary {
266
- background-color: #4a90e2;
267
- border: none;
268
- padding: 10px 20px;
269
- font-weight: bold;
270
- }
271
- .gr-button-primary:hover {
272
- background-color: #357abd;
273
- }
274
- .gr-form {
275
- max-width: 800px;
276
- margin: 0 auto;
277
- }
278
- """
279
  )
280
  return interface
281
 
 
26
  self.prompt_template = PromptTemplate(
27
  input_variables=["query", "context", "state", "statutes"],
28
  template="""You are a legal assistant specializing in tenant rights and landlord-tenant laws. Your goal is to provide accurate, detailed, and helpful answers that are explicitly grounded in the statutes provided in the context. Only use general knowledge to supplement the answer if the context lacks sufficient detail to fully answer the question, and clearly indicate when you are doing so.
 
29
  Instructions:
30
  - Use the context information and the provided statutes as the primary source to answer the question.
31
  - Explicitly cite the relevant statute(s) (e.g., (AS § 34.03.220(a)(2))) in your answer to ground your response in the legal text.
 
34
  - Provide detailed answers with practical examples or scenarios when possible.
35
  - Use bullet points or numbered lists for clarity when applicable.
36
  - Maintain a professional and neutral tone.
 
 
37
  Question: {query}
38
  State: {state}
 
39
  Statutes found in context:
40
  {statutes}
 
41
  Context information:
42
  {context}
 
43
  Answer:"""
44
  )
45
 
 
82
  if not state:
83
  return {
84
  "answer": "Please select a state to proceed with your query.",
 
85
  "context_used": "N/A",
86
  "statutes_found": "N/A"
87
  }
 
89
  if not openai_api_key:
90
  return {
91
  "answer": "Please provide an OpenAI API key to proceed.",
 
92
  "context_used": "N/A",
93
  "statutes_found": "N/A"
94
  }
 
100
  except Exception as e:
101
  return {
102
  "answer": f"Failed to initialize LLM with the provided API key: {str(e)}",
 
103
  "context_used": "N/A",
104
  "statutes_found": "N/A"
105
  }
 
109
  logging.info("Vector database query successful")
110
  except Exception as e:
111
  logging.error(f"Vector database query failed: {str(e)}")
112
+ # Safeguard: Fallback to empty results if vector DB query fails
113
+ results = {
114
+ "document_results": {"documents": [[]], "metadatas": [[]]},
115
+ "state_results": {"documents": [[]], "metadatas": [[]]}
 
116
  }
117
+ logging.info("Applied safeguard: Using empty results due to vector DB failure")
118
 
119
  context_parts = []
 
120
 
121
+ if results["document_results"]["documents"] and results["document_results"]["documents"][0]:
122
  for i, doc in enumerate(results["document_results"]["documents"][0]):
123
  metadata = results["document_results"]["metadatas"][0][i]
124
  context_parts.append(f"[{metadata['state']} - Chunk {metadata.get('chunk_id', 'N/A')}] {doc}")
 
 
 
 
 
 
125
 
126
+ if results["state_results"]["documents"] and results["state_results"]["documents"][0]:
127
  for i, doc in enumerate(results["state_results"]["documents"][0]):
128
  metadata = results["state_results"]["metadatas"][0][i]
129
  context_parts.append(f"[{metadata['state']} - Summary] {doc}")
 
 
 
 
 
 
130
 
131
  context = "\n\n---\n\n".join(context_parts) if context_parts else "No relevant context found."
132
 
 
134
  logging.info("No relevant context found for query")
135
  return {
136
  "answer": "I don't have sufficient information in my database to answer this question accurately. However, I can provide some general information about tenant rights.",
 
137
  "context_used": context,
138
  "statutes_found": "N/A"
139
  }
 
153
  logging.error(f"LLM processing failed: {str(e)}")
154
  return {
155
  "answer": "An error occurred while generating the answer. Please try again.",
 
156
  "context_used": context,
157
  "statutes_found": statutes
158
  }
159
 
160
  return {
161
  "answer": answer['text'].strip(),
 
162
  "context_used": context,
163
  "statutes_found": statutes
164
  }
 
184
  def gradio_interface(self) -> gr.Interface:
185
  def query_interface(api_key: str, query: str, state: str) -> str:
186
  if not api_key:
187
+ return "⚠️ **Error:** Please provide an OpenAI API key to proceed."
188
  if not state:
189
+ return "⚠️ **Error:** Please select a state to proceed with your query."
190
  result = self.process_query(query, state=state, openai_api_key=api_key)
191
+ return f"### Answer:\n{result['answer']}\n\n### Statutes Found:\n{result['statutes_found']}"
192
 
193
  states = self.get_states()
194
 
195
  example_queries = [
196
+ ["What is the rent due date law?", "California"],
197
+ ["What are the rules for security deposit returns?", "New York"],
198
+ ["Can a landlord enter without notice?", "Texas"],
199
+ ["What are the eviction notice requirements?", "Florida"],
200
+ ["Are there rent control laws?", "Oregon"]
201
  ]
202
 
203
+ # Custom CSS for a modern, readable, and responsive UI
204
+ custom_css = """
205
+ /* General container styling */
206
+ .gr-form {
207
+ max-width: 900px;
208
+ margin: 0 auto;
209
+ padding: 20px;
210
+ background-color: #ffffff;
211
+ border-radius: 15px;
212
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
213
+ }
214
+
215
+ /* Title and description */
216
+ .gr-title {
217
+ font-size: 2.2em;
218
+ font-weight: bold;
219
+ color: #2c3e50;
220
+ text-align: center;
221
+ margin-bottom: 10px;
222
+ }
223
+ .gr-description {
224
+ font-size: 1.1em;
225
+ color: #7f8c8d;
226
+ text-align: center;
227
+ margin-bottom: 30px;
228
+ }
229
+
230
+ /* Input fields */
231
+ .gr-textbox, .gr-dropdown {
232
+ border: 1px solid #dcdcdc !important;
233
+ border-radius: 8px !important;
234
+ padding: 12px !important;
235
+ font-size: 1em !important;
236
+ transition: border-color 0.3s ease;
237
+ }
238
+ .gr-textbox:focus, .gr-dropdown:focus {
239
+ border-color: #3498db !important;
240
+ box-shadow: 0 0 5px rgba(52, 152, 219, 0.3) !important;
241
+ }
242
+ .gr-textbox label, .gr-dropdown label {
243
+ font-weight: 600;
244
+ color: #34495e;
245
+ margin-bottom: 8px;
246
+ }
247
+
248
+ /* Buttons */
249
+ .gr-button-primary {
250
+ background-color: #3498db !important;
251
+ border: none !important;
252
+ padding: 12px 30px !important;
253
+ font-weight: bold !important;
254
+ font-size: 1em !important;
255
+ border-radius: 8px !important;
256
+ transition: background-color 0.3s ease, transform 0.1s ease;
257
+ }
258
+ .gr-button-primary:hover {
259
+ background-color: #2980b9 !important;
260
+ transform: translateY(-2px);
261
+ }
262
+ .gr-button-secondary {
263
+ background-color: #95a5a6 !important;
264
+ border: none !important;
265
+ padding: 12px 30px !important;
266
+ font-weight: bold !important;
267
+ font-size: 1em !important;
268
+ border-radius: 8px !important;
269
+ transition: background-color 0.3s ease;
270
+ }
271
+ .gr-button-secondary:hover {
272
+ background-color: #7f8c8d !important;
273
+ }
274
+
275
+ /* Output area */
276
+ .output-markdown {
277
+ background-color: #f9f9f9 !important;
278
+ color: #2c3e50 !important; /* Dark text for readability */
279
+ padding: 25px !important;
280
+ border-radius: 10px !important;
281
+ border: 1px solid #e0e0e0 !important;
282
+ font-size: 1.1em !important;
283
+ line-height: 1.8 !important;
284
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
285
+ }
286
+
287
+ /* Examples section */
288
+ .gr-examples {
289
+ background-color: #ecf0f1;
290
+ padding: 15px;
291
+ border-radius: 10px;
292
+ margin-top: 20px;
293
+ }
294
+ .gr-examples table {
295
+ background-color: transparent !important;
296
+ }
297
+
298
+ /* Dark mode */
299
+ @media (prefers-color-scheme: dark) {
300
+ .gr-form {
301
+ background-color: #2c3e50;
302
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
303
+ }
304
+ .gr-title {
305
+ color: #ecf0f1;
306
+ }
307
+ .gr-description {
308
+ color: #bdc3c7;
309
+ }
310
+ .gr-textbox, .gr-dropdown {
311
+ background-color: #34495e !important;
312
+ color: #ecf0f1 !important;
313
+ border-color: #7f8c8d !important;
314
+ }
315
+ .gr-textbox label, .gr-dropdown label {
316
+ color: #ecf0f1;
317
+ }
318
+ .output-markdown {
319
+ background-color: #34495e !important;
320
+ color: #ecf0f1 !important;
321
+ border-color: #7f8c8d !important;
322
+ }
323
+ .gr-examples {
324
+ background-color: #3e5367;
325
+ }
326
+ }
327
+
328
+ /* Responsive design */
329
+ @media (max-width: 600px) {
330
+ .gr-form {
331
+ padding: 15px;
332
+ }
333
+ .gr-title {
334
+ font-size: 1.8em;
335
+ }
336
+ .gr-description {
337
+ font-size: 1em;
338
+ }
339
+ .gr-textbox, .gr-dropdown {
340
+ font-size: 0.9em !important;
341
+ }
342
+ .gr-button-primary, .gr-button-secondary {
343
+ padding: 10px 20px !important;
344
+ font-size: 0.9em !important;
345
+ }
346
+ .output-markdown {
347
+ font-size: 1em !important;
348
+ padding: 15px !important;
349
+ }
350
+ }
351
+ """
352
+
353
  interface = gr.Interface(
354
  fn=query_interface,
355
  inputs=[
356
  gr.Textbox(
357
  label="Enter your OpenAI API Key",
358
  type="password",
359
+ placeholder="e.g., sk-abc123",
360
+ elem_classes="input-field"
361
  ),
362
  gr.Textbox(
363
  label="Enter your question about Landlord-Tenant laws",
364
  placeholder="e.g., What are the eviction rules?",
365
+ lines=3,
366
+ elem_classes="input-field"
367
  ),
368
  gr.Dropdown(
369
  label="Select a state (required)",
370
  choices=states,
371
  value=None,
372
+ allow_custom_value=False,
373
+ elem_classes="input-field"
374
  )
375
  ],
376
  outputs=gr.Markdown(
 
380
  title="🏠 Landlord-Tenant Rights Bot",
381
  description="Ask questions about tenant rights and landlord-tenant laws based on state-specific legal documents. Provide your OpenAI API key, select a state, and enter your question below. You can get an API key from [OpenAI](https://platform.openai.com/api-keys).",
382
  examples=example_queries,
383
+ theme=gr.themes.Default(),
384
+ css=custom_css
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  )
386
  return interface
387
 
requirements.txt CHANGED
@@ -1,7 +1,6 @@
1
  gradio==4.44.0
2
  langchain==0.3.1
3
- langchain-openai==0.2.0
4
- openai==1.40.0
5
  chromadb==0.5.5
6
  sentence-transformers==3.0.1
7
  torch==2.2.2
@@ -12,3 +11,4 @@ pandas==2.2.2
12
  huggingface_hub==0.23.4
13
  pymupdf==1.24.9
14
  langchain_community
 
 
1
  gradio==4.44.0
2
  langchain==0.3.1
3
+ langchain-openai==0.2.0
 
4
  chromadb==0.5.5
5
  sentence-transformers==3.0.1
6
  torch==2.2.2
 
11
  huggingface_hub==0.23.4
12
  pymupdf==1.24.9
13
  langchain_community
14
+