srilakshu012456 commited on
Commit
f4fe3d5
·
verified ·
1 Parent(s): 4bd1f48

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +49 -34
main.py CHANGED
@@ -16,6 +16,7 @@ from services.kb_creation import (
16
  hybrid_search_knowledge_base,
17
  get_section_text,
18
  get_best_steps_section_text,
 
19
  )
20
  from services.login import router as login_router
21
  from services.generate_ticket import get_valid_token, create_incident
@@ -123,12 +124,12 @@ def _as_numbered_steps(text: str) -> str:
123
  # ---------------- Clarifying message (ASCII-only) ----------------
124
  def _build_clarifying_message() -> str:
125
  return (
126
- "I couldn't find matching content in the KB yet. To help me narrow it down, please share:\n\n"
127
  "- Module/area (e.g., Picking, Receiving, Trailer Close)\n"
128
  "- Exact error message text/code (copy-paste)\n"
129
  "- IDs involved (Order#, Load ID, Shipment#)\n"
130
  "- Warehouse/site & environment (prod/test)\n"
131
- "- When it started and how many users are impacted\n\n"
132
  "You can also say 'create ticket' and I'll raise a ServiceNow incident now."
133
  )
134
 
@@ -207,6 +208,9 @@ STRICT_OVERLAP = 3
207
  MAX_SENTENCES_STRICT = 4
208
  MAX_SENTENCES_CONCISE = 3
209
 
 
 
 
210
  def _normalize_for_match(text: str) -> str:
211
  t = (text or "").lower()
212
  t = re.sub(r"[^\w\s]", " ", t)
@@ -214,7 +218,6 @@ def _normalize_for_match(text: str) -> str:
214
  return t
215
 
216
  def _split_sentences(ctx: str) -> List[str]:
217
- # Split on sentence boundaries, newlines, or ASCII bullets (-, *)
218
  raw_sents = re.split(r"(?<=[.!?])\s+|\n+|\-\s*|\*\s*", ctx or "")
219
  return [s.strip() for s in raw_sents if s and len(s.strip()) > 2]
220
 
@@ -262,7 +265,7 @@ def _extract_navigation_only(text: str, max_lines: int = 6) -> str:
262
  ERROR_STARTS = (
263
  "error", "resolution", "fix", "verify", "check",
264
  "permission", "access", "authorization", "authorisation",
265
- "role", "role mapping", "security profile", "escalation"
266
  )
267
 
268
  def _extract_errors_only(text: str, max_lines: int = 12) -> str:
@@ -376,31 +379,21 @@ async def chat_with_ai(input_data: ChatInput):
376
  "debug": {"intent": "create_ticket"},
377
  }
378
 
379
- # --- Generic opener ---
380
- if len(msg_norm.split()) <= 2 or any(p in msg_norm for p in ("issue", "problem", "help", "support")):
381
- return {
382
- "bot_response": _build_clarifying_message(),
383
- "status": "NO_KB_MATCH",
384
- "context_found": False,
385
- "ask_resolved": False,
386
- "suggest_incident": True,
387
- "followup": "Reply with the above details or say 'create ticket'.",
388
- "top_hits": [],
389
- "sources": [],
390
- "debug": {"intent": "generic_issue"},
391
- }
392
-
393
  # --- Status intent ---
394
  status_intent = _parse_ticket_status_intent(msg_norm)
395
  if status_intent:
396
  if status_intent.get("ask_number"):
 
397
  return {
398
- "bot_response": "Please share the Incident ID (e.g., INC0012345) to check the status.",
 
 
 
399
  "status": "PARTIAL",
400
  "context_found": False,
401
  "ask_resolved": False,
402
  "suggest_incident": False,
403
- "followup": "Provide the Incident ID and I'll fetch the status.",
404
  "show_status_form": True,
405
  "top_hits": [],
406
  "sources": [],
@@ -441,6 +434,21 @@ async def chat_with_ai(input_data: ChatInput):
441
  except Exception as e:
442
  raise HTTPException(status_code=500, detail=safe_str(e))
443
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  # --- Hybrid KB search ---
445
  kb_results = hybrid_search_knowledge_base(input_data.user_message, top_k=10, alpha=0.6, beta=0.4)
446
  documents = kb_results.get("documents", [])
@@ -474,20 +482,31 @@ async def chat_with_ai(input_data: ChatInput):
474
  best_doc = kb_results.get("best_doc")
475
  top_meta = (metadatas or [{}])[0] if metadatas else {}
476
 
477
- if detected_intent == "steps" and best_doc:
478
- full_steps = get_best_steps_section_text(best_doc)
479
- if not full_steps:
480
- sec = (top_meta or {}).get("section")
481
- if sec:
482
- full_steps = get_section_text(best_doc, sec)
483
- if full_steps:
484
- context = _as_numbered_steps(full_steps)
 
 
 
 
 
 
 
 
 
 
 
485
 
486
  # Intent shaping
487
  q = (input_data.user_message or "").lower()
488
  if detected_intent == "errors" or any(k in q for k in [
489
  "error", "issue", "fail", "not working", "resolution", "fix",
490
- "permission", "access", "authorization", "escalation", "role", "security profile"
491
  ]):
492
  context = _extract_errors_only(context, max_lines=12)
493
  elif any(k in q for k in ["navigate", "navigation", "menu", "screen"]):
@@ -505,11 +524,7 @@ async def chat_with_ai(input_data: ChatInput):
505
  and (best_distance is None or best_distance >= gate_distance_no_kb)
506
  ):
507
  second_try = (input_data.prev_status or "").upper() == "NO_KB_MATCH"
508
- clarify_text = (
509
- _build_clarifying_message()
510
- if not second_try
511
- else "I still don't find a relevant KB match for this scenario even after clarification."
512
- )
513
  return {
514
  "bot_response": clarify_text,
515
  "status": "NO_KB_MATCH",
 
16
  hybrid_search_knowledge_base,
17
  get_section_text,
18
  get_best_steps_section_text,
19
+ get_best_errors_section_text,
20
  )
21
  from services.login import router as login_router
22
  from services.generate_ticket import get_valid_token, create_incident
 
124
  # ---------------- Clarifying message (ASCII-only) ----------------
125
  def _build_clarifying_message() -> str:
126
  return (
127
+ "I couldn't find matching content in the KB yet. To help me narrow it down, please share:\n"
128
  "- Module/area (e.g., Picking, Receiving, Trailer Close)\n"
129
  "- Exact error message text/code (copy-paste)\n"
130
  "- IDs involved (Order#, Load ID, Shipment#)\n"
131
  "- Warehouse/site & environment (prod/test)\n"
132
+ "- When it started and how many users are impacted\n"
133
  "You can also say 'create ticket' and I'll raise a ServiceNow incident now."
134
  )
135
 
 
208
  MAX_SENTENCES_STRICT = 4
209
  MAX_SENTENCES_CONCISE = 3
210
 
211
+ PERM_QUERY_TERMS = ["permission", "permissions", "access", "access right", "authorization", "authorisation", "role", "role access", "security", "security profile", "privilege", "not allowed", "not authorized", "denied"]
212
+
213
+
214
  def _normalize_for_match(text: str) -> str:
215
  t = (text or "").lower()
216
  t = re.sub(r"[^\w\s]", " ", t)
 
218
  return t
219
 
220
  def _split_sentences(ctx: str) -> List[str]:
 
221
  raw_sents = re.split(r"(?<=[.!?])\s+|\n+|\-\s*|\*\s*", ctx or "")
222
  return [s.strip() for s in raw_sents if s and len(s.strip()) > 2]
223
 
 
265
  ERROR_STARTS = (
266
  "error", "resolution", "fix", "verify", "check",
267
  "permission", "access", "authorization", "authorisation",
268
+ "role", "role mapping", "security profile", "escalation", "not allowed", "not authorized", "denied"
269
  )
270
 
271
  def _extract_errors_only(text: str, max_lines: int = 12) -> str:
 
379
  "debug": {"intent": "create_ticket"},
380
  }
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  # --- Status intent ---
383
  status_intent = _parse_ticket_status_intent(msg_norm)
384
  if status_intent:
385
  if status_intent.get("ask_number"):
386
+ # Show clarifying bullets explicitly in bot_response (not only followup)
387
  return {
388
+ "bot_response": (
389
+ "To check a ticket status, please share the Incident ID (e.g., INC0012345).\n\n"
390
+ "You can paste the ID here or say 'cancel'."
391
+ ),
392
  "status": "PARTIAL",
393
  "context_found": False,
394
  "ask_resolved": False,
395
  "suggest_incident": False,
396
+ "followup": None,
397
  "show_status_form": True,
398
  "top_hits": [],
399
  "sources": [],
 
434
  except Exception as e:
435
  raise HTTPException(status_code=500, detail=safe_str(e))
436
 
437
+ # --- Generic opener ---
438
+ if len(msg_norm.split()) <= 2 or any(p in msg_norm for p in ("issue", "problem", "help", "support")):
439
+ # Return clarifying bullets directly in bot_response; followup is CTA only
440
+ return {
441
+ "bot_response": _build_clarifying_message(),
442
+ "status": "NO_KB_MATCH",
443
+ "context_found": False,
444
+ "ask_resolved": False,
445
+ "suggest_incident": True,
446
+ "followup": "Reply with the above details or say 'create ticket'.",
447
+ "top_hits": [],
448
+ "sources": [],
449
+ "debug": {"intent": "generic_issue"},
450
+ }
451
+
452
  # --- Hybrid KB search ---
453
  kb_results = hybrid_search_knowledge_base(input_data.user_message, top_k=10, alpha=0.6, beta=0.4)
454
  documents = kb_results.get("documents", [])
 
482
  best_doc = kb_results.get("best_doc")
483
  top_meta = (metadatas or [{}])[0] if metadatas else {}
484
 
485
+ # If the query is a permissions question, force error handling & prefer errors section from SOP
486
+ is_perm_query = any(t in msg_norm for t in PERM_QUERY_TERMS)
487
+ if is_perm_query:
488
+ detected_intent = "errors"
489
+
490
+ # Prefer full 'Process Steps' or 'Errors & Resolution' section from the best SOP
491
+ if best_doc:
492
+ if detected_intent == "steps":
493
+ full_steps = get_best_steps_section_text(best_doc)
494
+ if not full_steps:
495
+ sec = (top_meta or {}).get("section")
496
+ if sec:
497
+ full_steps = get_section_text(best_doc, sec)
498
+ if full_steps:
499
+ context = _as_numbered_steps(full_steps)
500
+ elif detected_intent == "errors":
501
+ full_errors = get_best_errors_section_text(best_doc)
502
+ if full_errors:
503
+ context = _extract_errors_only(full_errors, max_lines=12)
504
 
505
  # Intent shaping
506
  q = (input_data.user_message or "").lower()
507
  if detected_intent == "errors" or any(k in q for k in [
508
  "error", "issue", "fail", "not working", "resolution", "fix",
509
+ "permission", "access", "authorization", "escalation", "role", "security profile", "not allowed", "not authorized", "denied"
510
  ]):
511
  context = _extract_errors_only(context, max_lines=12)
512
  elif any(k in q for k in ["navigate", "navigation", "menu", "screen"]):
 
524
  and (best_distance is None or best_distance >= gate_distance_no_kb)
525
  ):
526
  second_try = (input_data.prev_status or "").upper() == "NO_KB_MATCH"
527
+ clarify_text = _build_clarifying_message()
 
 
 
 
528
  return {
529
  "bot_response": clarify_text,
530
  "status": "NO_KB_MATCH",