Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -449,6 +449,60 @@ def _format_steps_as_numbered(steps: list) -> str:
|
|
| 449 |
return "\n".join(out)
|
| 450 |
|
| 451 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 452 |
def _filter_context_for_query(context: str, query: str) -> Tuple[str, Dict[str, Any]]:
|
| 453 |
STRICT_OVERLAP = 3
|
| 454 |
MAX_SENTENCES_STRICT = 4
|
|
@@ -980,25 +1034,29 @@ async def chat_with_ai(input_data: ChatInput):
|
|
| 980 |
|
| 981 |
if full_steps:
|
| 982 |
numbered_full = _ensure_numbering(full_steps)
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
| 992 |
-
|
| 993 |
-
|
| 994 |
-
|
| 995 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 996 |
)
|
| 997 |
-
|
| 998 |
-
|
| 999 |
-
numbered_full, wanted={"delete"}, exclude={"create", "update"}
|
| 1000 |
-
)
|
| 1001 |
-
|
| 1002 |
next_only = _resolve_next_steps(
|
| 1003 |
input_data.user_message,
|
| 1004 |
numbered_full,
|
|
|
|
| 449 |
return "\n".join(out)
|
| 450 |
|
| 451 |
|
| 452 |
+
# --- NEW: sentence-level action filter for mixed paragraphs ---
|
| 453 |
+
def _filter_sentences_by_actions(numbered_text: str,
|
| 454 |
+
wanted: set[str],
|
| 455 |
+
exclude: set[str]) -> str:
|
| 456 |
+
"""
|
| 457 |
+
Works on already-numbered text. Splits each line into sentences and
|
| 458 |
+
keeps only sentences that match wanted actions; drops sentences matching exclude actions.
|
| 459 |
+
Falls back gracefully if no wanted match is found.
|
| 460 |
+
"""
|
| 461 |
+
ACTION_SYNONYMS = {
|
| 462 |
+
"create": ("create", "creation", "add", "new", "generate", "setup", "set up", "register"),
|
| 463 |
+
"update": ("update", "modify", "change", "edit", "amend"),
|
| 464 |
+
"delete": ("delete", "remove", "cancel", "void"),
|
| 465 |
+
"navigate": ("navigate", "go to", "open"),
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
def _has_any(text: str, keys: set[str]) -> bool:
|
| 469 |
+
low = (text or "").lower()
|
| 470 |
+
for k in keys:
|
| 471 |
+
for syn in ACTION_SYNONYMS.get(k, (k,)):
|
| 472 |
+
if syn in low:
|
| 473 |
+
return True
|
| 474 |
+
return False
|
| 475 |
+
|
| 476 |
+
def _split_sentences(block: str) -> list:
|
| 477 |
+
# robust split on ., !, ? followed by space
|
| 478 |
+
import re
|
| 479 |
+
parts = [s.strip() for s in re.split(r"(?<=[.!?])\s+", block or "") if s.strip()]
|
| 480 |
+
return parts if parts else ([block.strip()] if block.strip() else [])
|
| 481 |
+
|
| 482 |
+
out_lines = []
|
| 483 |
+
for ln in (numbered_text or "").splitlines():
|
| 484 |
+
sent_keep = []
|
| 485 |
+
sentences = _split_sentences(ln)
|
| 486 |
+
for s in sentences:
|
| 487 |
+
if exclude and _has_any(s, exclude):
|
| 488 |
+
continue
|
| 489 |
+
if wanted:
|
| 490 |
+
if _has_any(s, wanted):
|
| 491 |
+
sent_keep.append(s)
|
| 492 |
+
else:
|
| 493 |
+
# no explicit wanted → keep unless excluded
|
| 494 |
+
sent_keep.append(s)
|
| 495 |
+
|
| 496 |
+
# If nothing matched wanted but line mentions wanted elsewhere, keep the whole line
|
| 497 |
+
if wanted and not sent_keep:
|
| 498 |
+
if _has_any(ln, wanted) and not _has_any(ln, exclude):
|
| 499 |
+
sent_keep = sentences
|
| 500 |
+
|
| 501 |
+
if sent_keep:
|
| 502 |
+
out_lines.append(" ".join(sent_keep))
|
| 503 |
+
|
| 504 |
+
return "\n".join(out_lines).strip() or (numbered_text or "").strip()
|
| 505 |
+
|
| 506 |
def _filter_context_for_query(context: str, query: str) -> Tuple[str, Dict[str, Any]]:
|
| 507 |
STRICT_OVERLAP = 3
|
| 508 |
MAX_SENTENCES_STRICT = 4
|
|
|
|
| 1034 |
|
| 1035 |
if full_steps:
|
| 1036 |
numbered_full = _ensure_numbering(full_steps)
|
| 1037 |
+
raw_actions = set((kb_results.get("actions") or []))
|
| 1038 |
+
msg_low = (input_data.user_message or "").lower()
|
| 1039 |
+
# Fallbacks if extractor missed it
|
| 1040 |
+
if not raw_actions and ("creation" in msg_low or "create" in msg_low or "set up" in msg_low or "setup" in msg_low):
|
| 1041 |
+
raw_actions = {"create"}
|
| 1042 |
+
elif not raw_actions and ("update" in msg_low or "modify" in msg_low or "edit" in msg_low or "change" in msg_low):
|
| 1043 |
+
raw_actions = {"update"}
|
| 1044 |
+
elif not raw_actions and ("delete" in msg_low or "remove" in msg_low or "cancel" in msg_low or "void" in msg_low):
|
| 1045 |
+
raw_actions = {"delete"}
|
| 1046 |
+
wanted, exclude = set(), set()
|
| 1047 |
+
if "create" in raw_actions and not ({"update", "delete"} & raw_actions):
|
| 1048 |
+
wanted, exclude = {"create"}, {"update", "delete"}
|
| 1049 |
+
elif "update" in raw_actions and not ({"create", "delete"} & raw_actions):
|
| 1050 |
+
wanted, exclude = {"update"}, {"create", "delete"}
|
| 1051 |
+
elif "delete" in raw_actions and not ({"create", "update"} & raw_actions):
|
| 1052 |
+
wanted, exclude = {"delete"}, {"create", "update"}
|
| 1053 |
+
if wanted or exclude:
|
| 1054 |
+
# Sentence-level filtering for mixed paragraphs
|
| 1055 |
+
numbered_full = _filter_sentences_by_actions(
|
| 1056 |
+
numbered_full, wanted=wanted, exclude=exclude
|
| 1057 |
)
|
| 1058 |
+
|
| 1059 |
+
|
|
|
|
|
|
|
|
|
|
| 1060 |
next_only = _resolve_next_steps(
|
| 1061 |
input_data.user_message,
|
| 1062 |
numbered_full,
|