Spaces:
Runtime error
Runtime error
File size: 3,416 Bytes
aad7814 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | """Extract raw note lines from uploaded field-notes files."""
from __future__ import annotations
import io
import re
from pathlib import Path
from backend.core.note_bullets import explode_note_lines
def _classify_notes_tier(text: str) -> tuple[int, float, str]:
"""Lightweight tier guess from note content (no LLM required)."""
if len(text) < 200:
return 0, 0.0, ""
lower = text.lower()
l3 = sum(
1
for kw in (
"roof structure",
"dpc",
"damp proof",
"chimney",
"services",
"drainage",
"ground floor",
"timber decay",
"asbestos",
)
if kw in lower
)
l1 = sum(1 for kw in ("condition only", "no advice", "traffic light") if kw in lower)
explicit = re.search(r"level\s*([123])", lower)
if explicit:
lvl = int(explicit.group(1))
return lvl, 0.55, f"Mention of Level {lvl} in notes text."
if l3 >= 3:
return 3, 0.45, "Notes contain multiple Level 3-style inspection topics."
if l1 >= 1 and l3 == 0:
return 1, 0.35, "Notes suggest a condition-only (Level 1) style."
if l3 >= 1:
return 2, 0.32, "Notes contain some detailed inspection topics (possible Level 2/3)."
return 0, 0.0, ""
def extract_lines_from_bytes(data: bytes, suffix: str) -> list[str]:
"""Parse docx/pdf/txt bytes into non-empty lines."""
suffix = suffix.lower()
lines: list[str] = []
if suffix == ".docx":
from docx import Document as DocxDocument
doc = DocxDocument(io.BytesIO(data))
for para in doc.paragraphs:
text = para.text.strip()
if text:
lines.append(text)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
text = cell.text.strip()
if text and text not in lines:
lines.append(text)
elif suffix == ".pdf":
import pypdf
reader = pypdf.PdfReader(io.BytesIO(data))
for page in reader.pages:
page_text = page.extract_text() or ""
for line in page_text.splitlines():
line = line.strip()
if line:
lines.append(line)
else:
text = data.decode("utf-8", errors="replace")
lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
return explode_note_lines(lines)
def extract_notes_from_upload(data: bytes, filename: str) -> dict:
"""Full /extract-notes response payload."""
suffix = Path(filename or "").suffix.lower()
if suffix not in {".docx", ".pdf", ".txt"}:
raise ValueError("Unsupported file type. Upload a .docx, .pdf, or .txt notes file.")
lines = extract_lines_from_bytes(data, suffix)
joined = "\n".join(lines)
predicted_level, confidence, rationale = _classify_notes_tier(joined)
if confidence and confidence < 0.30:
predicted_level = 0
rationale = (
f"{rationale} (confidence {confidence:.0%} below threshold — treating as tier-unknown.)"
).strip()
return {
"filename": filename or "unknown",
"lines": lines,
"line_count": len(lines),
"predicted_survey_level": predicted_level,
"confidence": confidence,
"rationale": rationale,
}
|