srilakshu012456 commited on
Commit
416f7ae
·
verified ·
1 Parent(s): 4ba70dc

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +84 -56
main.py CHANGED
@@ -103,53 +103,60 @@ def _normalize_lines(text: str) -> List[str]:
103
  return [raw.strip()] if raw.strip() else []
104
 
105
  def _ensure_numbering(text: str) -> str:
106
- text = re.sub(r"[\u2060\u200B]", "", text or "")
107
- def strip_prefix_any(s: str) -> str:
108
-
109
- #Matches any leading list marker: numbers (1) or 1., 'Step N:', bullets -, *, •, circled numerals
110
- pattern = (
111
- r"^\s*(?:" # start, optional spaces, non-capturing group
112
- r"[\u2060\u200B]*" # optional zero-width characters
113
- r"(?:\d+\s*[.)]" # classic numbers like '1)' or '2.'
114
- r"|step\s*\d+:?" # 'Step 3:' (case-insensitive via IGNORECASE)
115
- r"|[\-\*\u2022]" # bullets '-', '*', '•'
116
- r"|[\u2460-\u2473])" # circled numerals
117
- r"\s*)" # trailing spaces, close outer group ← THIS ) WAS MISSING
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  )
119
- return re.sub(pattern, "", (s or "").strip(), flags=re.IGNORECASE)
 
 
 
 
120
 
121
- lines = [ln.strip() for ln in (text or "").splitlines() if ln and ln.strip()]
122
- if not lines:
123
- return text or ""
124
- merged: List[str] = []
125
- i = 0
126
- while i < len(lines):
127
- ln = lines[i]
128
- if re.fullmatch(r"\d+[.)]|[\u2460-\u2473]", ln) and (i + 1) < len(lines):
129
- merged.append(lines[i + 1].strip())
130
- i += 2
131
- else:
132
- merged.append(ln)
133
- i += 1
134
- para = " ".join(merged).strip()
135
- if not para:
136
- return ""
137
- para_clean = re.sub(r"(?:((?<=^)|(?<=\s))\d+[.)])\s+", "\n\n\n", para)
138
- para_clean = re.sub(r"(?:((?<=^)|(?<=\s))[\u2460-\u2473])\s+", "\n\n\n", para_clean)
139
- para_clean = re.sub(r"(?i)\bstep\s*\d+\s*:\s*", "\n\n\n", para_clean)
140
- segments = [seg.strip() for seg in para_clean.split("\n\n\n") if seg.strip()]
141
- if len(segments) < 2:
142
- tmp = [ln.strip() for ln in para.splitlines() if ln.strip()]
143
- segments = tmp if len(tmp) > 1 else [seg.strip() for seg in re.split(r"(?<=[.!?])\s+|;\s+", para) if seg.strip()]
144
- segments = [strip_prefix_any(seg) for seg in segments if seg.strip()]
145
  circled = {
146
- 1:"\u2460",2:"\u2461",3:"\u2462",4:"\u2463",5:"\u2464",6:"\u2465",7:"\u2466",8:"\u2467",9:"\u2468",10:"\u2469",
147
- 11:"\u246a",12:"\u246b",13:"\u246c",14:"\u246d",15:"\u246e",16:"\u246f",17:"\u2470",18:"\u2471",19:"\u2472",20:"\u2473",
 
 
148
  }
149
- out: List[str] = []
150
- for idx, seg in enumerate(segments, start=1):
151
- marker = circled.get(idx, f"{idx})")
152
- out.append(f"{marker} {seg}")
153
  return "\n".join(out)
154
 
155
  def _filter_error_lines_by_query(text: str, query: str, max_lines: int = 4) -> str:
@@ -597,19 +604,40 @@ async def chat_with_ai(input_data: ChatInput):
597
  # Prefer full SOP section when we have the best_doc
598
  escalation_line = None # SOP escalation candidate (if found)
599
  if best_doc:
600
- if detected_intent == "steps":
601
- # PATCH: prefer action-filtered steps first
602
- preferred_actions = kb_results.get("actions", []) or []
603
- full_steps = get_steps_text_by_action(best_doc, preferred_actions)
604
- if not full_steps:
605
- full_steps = get_best_steps_section_text(best_doc)
606
- if not full_steps:
607
- sec = (top_meta or {}).get("section")
608
- if sec: full_steps = get_section_text(best_doc, sec)
609
- if full_steps:
610
- context = _ensure_numbering(full_steps)
611
-
612
- elif detected_intent == "errors":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  full_errors = get_best_errors_section_text(best_doc)
614
  if full_errors:
615
  # Extract the error lines from the SOP
 
103
  return [raw.strip()] if raw.strip() else []
104
 
105
  def _ensure_numbering(text: str) -> str:
106
+ """
107
+ Robust step numbering:
108
+ - Split by natural delimiters (newline, end-of-sentence, semicolons, arrows, 'then', simple bullets).
109
+ - Strip any existing list markers (numbers, 'Step N:', bullets).
110
+ - Return ①..⑳ then 'N)' beyond 20.
111
+ """
112
+ import re
113
+ t = (text or "").replace("\u2060", "").replace("\u200B", "")
114
+
115
+ # 1) Split to segments by common step delimiters
116
+ parts = re.split(
117
+ r"(?:\r?\n|\r|\u2028|\u2029)" # newlines
118
+ r"|(?<=[.!?])\s+" # sentence end + space
119
+ r"|;\s+" # semicolons
120
+ r"|(?:\s*→\s*|\s*->\s*)" # arrows
121
+ r"|(?:\s*\bthen\b\s*)" # 'then'
122
+ r"|(?:^\s*[-*•]\s*)", # simple bullets
123
+ t,
124
+ flags=re.IGNORECASE
125
+ )
126
+
127
+ # 2) Clean segments & drop empties
128
+ cleaned = []
129
+ for seg in parts:
130
+ s = (seg or "").strip()
131
+ if not s:
132
+ continue
133
+ # Remove ANY leading list marker (1) / 2. / Step 3: / -, *, • / circled numerals
134
+ s = re.sub(
135
+ r"^\s*(?:"
136
+ r"(?:\d+\s*[.)])|" # 1) or 2.
137
+ r"(?i:step\s*\d+:?)|" # Step 3:
138
+ r"[-*•]|" # bullets
139
+ r"[\u2460-\u2473]" # circled numerals
140
+ r")\s*",
141
+ "",
142
+ s
143
  )
144
+ if s:
145
+ cleaned.append(s)
146
+
147
+ if not cleaned:
148
+ return (text or "").strip()
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  circled = {
151
+ 1:"\u2460",2:"\u2461",3:"\u2462",4:"\u2463",5:"\u2464",
152
+ 6:"\u2465",7:"\u2466",8:"\u2467",9:"\u2468",10:"\u2469",
153
+ 11:"\u246a",12:"\u246b",13:"\u246c",14:"\u246d",15:"\u246e",
154
+ 16:"\u246f",17:"\u2470",18:"\u2471",19:"\u2472",20:"\u2473",
155
  }
156
+ out = []
157
+ for i, s in enumerate(cleaned, 1):
158
+ marker = circled.get(i, f"{i})")
159
+ out.append(f"{marker} {s}")
160
  return "\n".join(out)
161
 
162
  def _filter_error_lines_by_query(text: str, query: str, max_lines: int = 4) -> str:
 
604
  # Prefer full SOP section when we have the best_doc
605
  escalation_line = None # SOP escalation candidate (if found)
606
  if best_doc:
607
+ if detected_intent == "steps":
608
+ # 1) Prefer action-matched steps first (update/reschedule/edit vs create)
609
+ preferred_actions = kb_results.get("actions", []) or []
610
+ full_steps = get_steps_text_by_action(best_doc, preferred_actions)
611
+
612
+ # 2) If nothing found, fallback BUT FILTER creation-only when user asked update
613
+ if not full_steps:
614
+ fallback = get_best_steps_section_text(best_doc)
615
+ if preferred_actions and ("update" in [a.lower() for a in preferred_actions]):
616
+ # Drop lines that look like pure creation verbs when user asked update
617
+ fallback_lines = [ln.strip() for ln in (fallback or "").splitlines() if ln.strip()]
618
+ keep = []
619
+ for ln in fallback_lines:
620
+ low = ln.lower()
621
+ is_creation_only = (
622
+ ("create" in low or "creation" in low or " add " in low or " new " in low or " book " in low or " schedule " in low)
623
+ and not any(x in low for x in ("update", "modify", "change", "edit", "amend", "reschedule", "re-schedule"))
624
+ )
625
+ if is_creation_only:
626
+ continue # skip creation-only line
627
+ keep.append(ln)
628
+ fallback = "\n".join(keep).strip()
629
+ full_steps = fallback if (fallback and fallback.strip()) else full_steps
630
+
631
+ if not full_steps:
632
+ sec = (top_meta or {}).get("section")
633
+ if sec:
634
+ full_steps = get_section_text(best_doc, sec)
635
+
636
+ if full_steps:
637
+ context = _ensure_numbering(full_steps)
638
+
639
+ elif detected_intent == "errors":
640
+
641
  full_errors = get_best_errors_section_text(best_doc)
642
  if full_errors:
643
  # Extract the error lines from the SOP