Kalpokoch commited on
Commit
d2159e2
·
verified ·
1 Parent(s): 27e4dfd

Update app/app.py

Browse files
Files changed (1) hide show
  1. app/app.py +27 -5
app/app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import os
2
  import json
3
  import asyncio
@@ -100,6 +101,20 @@ class Feedback(BaseModel):
100
  feedback: str
101
  comment: str | None = None
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  # -----------------------------
104
  # ✅ Endpoints
105
  # -----------------------------
@@ -170,13 +185,23 @@ async def chat(query: Query, request: Request):
170
  "answer": "Sorry, I could not find a relevant policy to answer that question. Please try rephrasing."
171
  }
172
 
 
 
 
 
 
 
 
 
 
 
173
  scores = [f"{result['relevance_score']:.4f}" for result in search_results]
174
  adapter.info(f"Found {len(search_results)} relevant chunks with scores: {scores}")
175
 
176
  # 2. Prepare Context
177
  context_chunks = [result['text'] for result in search_results[:TOP_K_CONTEXT]]
178
  context = "\n---\n".join(context_chunks)
179
-
180
  # 3. Build Prompt with Separator Instruction
181
  prompt = f"""<|system|>
182
  You are a precise and factual assistant for NEEPCO's Delegation of Powers (DoP) policy.
@@ -187,6 +212,7 @@ Your task is to answer the user's question based ONLY on the provided context.
187
  </s>
188
  <|user|>
189
  ### Relevant Context:
 
190
  ```
191
  {context}
192
  ```
@@ -212,14 +238,10 @@ Your task is to answer the user's question based ONLY on the provided context.
212
  # Check if the model used the pipe separator, indicating a list.
213
  if '|' in raw_answer:
214
  adapter.info("Pipe separator found. Formatting response as a bulleted list.")
215
- # Split the string into a list of items
216
  items = raw_answer.split('|')
217
- # Clean up each item and format it as a bullet point
218
  cleaned_items = [f"* {item.strip()}" for item in items if item.strip()]
219
- # Join them back together with newlines
220
  answer = "\n".join(cleaned_items)
221
  else:
222
- # If no separator, use the answer as is.
223
  answer = raw_answer
224
 
225
  except asyncio.TimeoutError:
 
1
+ //app.py
2
  import os
3
  import json
4
  import asyncio
 
101
  feedback: str
102
  comment: str | None = None
103
 
104
+ # -----------------------------
105
+ # ✅ Helper for metadata-based filtering
106
+ # -----------------------------
107
+ def is_personnel_related(metadata: dict) -> bool:
108
+ # Keywords indicating personnel or HR related policy sections
109
+ personnel_keywords = [
110
+ "ii", "personnel", "recruitment", "resignation", "hr", "promotion",
111
+ "employee", "staff", "service", "termination", "transfer"
112
+ ]
113
+ section = str(metadata.get("section", "")).lower()
114
+ title = str(metadata.get("title", "")).lower()
115
+ # Return True if any keyword is found in section or title
116
+ return any(kw in section for kw in personnel_keywords) or any(kw in title for kw in personnel_keywords)
117
+
118
  # -----------------------------
119
  # ✅ Endpoints
120
  # -----------------------------
 
185
  "answer": "Sorry, I could not find a relevant policy to answer that question. Please try rephrasing."
186
  }
187
 
188
+ # Post-search metadata-based filtering for personnel/HR queries
189
+ if any(keyword in question_lower for keyword in ["personnel", "hr", "recruitment", "resignation",
190
+ "promotion", "employee", "termination", "transfer"]):
191
+ filtered_results = [res for res in search_results if is_personnel_related(res.get('metadata', {}))]
192
+ if filtered_results:
193
+ adapter.info(f"Filtered {len(search_results) - len(filtered_results)} irrelevant chunks for personnel query.")
194
+ search_results = filtered_results
195
+ else:
196
+ adapter.info("No personnel-related chunks found after filtering; using unfiltered results.")
197
+
198
  scores = [f"{result['relevance_score']:.4f}" for result in search_results]
199
  adapter.info(f"Found {len(search_results)} relevant chunks with scores: {scores}")
200
 
201
  # 2. Prepare Context
202
  context_chunks = [result['text'] for result in search_results[:TOP_K_CONTEXT]]
203
  context = "\n---\n".join(context_chunks)
204
+
205
  # 3. Build Prompt with Separator Instruction
206
  prompt = f"""<|system|>
207
  You are a precise and factual assistant for NEEPCO's Delegation of Powers (DoP) policy.
 
212
  </s>
213
  <|user|>
214
  ### Relevant Context:
215
+
216
  ```
217
  {context}
218
  ```
 
238
  # Check if the model used the pipe separator, indicating a list.
239
  if '|' in raw_answer:
240
  adapter.info("Pipe separator found. Formatting response as a bulleted list.")
 
241
  items = raw_answer.split('|')
 
242
  cleaned_items = [f"* {item.strip()}" for item in items if item.strip()]
 
243
  answer = "\n".join(cleaned_items)
244
  else:
 
245
  answer = raw_answer
246
 
247
  except asyncio.TimeoutError: