HR-ATS-Portal/backend/job_assist/decorators.py

41 lines
1.4 KiB
Python

"""Parse and normalize the field-assist model response.
Pure module: no FastAPI imports and no HTTPException.
"""
from __future__ import annotations
import re
from job_assist.prompt import LIST_FIELDS, SINGLE_LINE_FIELDS
MAX_SUGGESTION_CHARS = 6000
# Leading bullet/number markers the model may emit despite the prompt.
_BULLET = re.compile(r"^\s*(?:[-*•·]+|\d+[.)])\s+")
def parse_assist_response(data, field) -> str:
"""The suggestion string, normalized to the field's shape. Raises RuntimeError."""
if not isinstance(data, dict):
raise RuntimeError("assist response is not an object")
suggestion = data.get("suggestion")
if not isinstance(suggestion, str) or not suggestion.strip():
raise RuntimeError("assist response has no suggestion")
text = suggestion.replace("\r\n", "\n").replace("\r", "\n").strip()
if field in SINGLE_LINE_FIELDS:
text = " ".join(text.split())
elif field in LIST_FIELDS:
# The form splits these on newline (Jobs.jsx splitLines), so strip any
# bullet markers and keep one item per line.
lines = [_BULLET.sub("", line).strip() for line in text.split("\n")]
text = "\n".join(line for line in lines if line)
if not text:
raise RuntimeError("assist response emptied after normalization")
else:
text = re.sub(r"\n{3,}", "\n\n", text)
return text[:MAX_SUGGESTION_CHARS].strip()