Spaces:
Runtime error
Runtime error
| """Hardened anti-hallucination prompts for citation-grounded extraction. | |
| These prompts implement STEP 5 (anti-hallucination rules) and STEP 4 | |
| (schema-constrained extraction). They instruct the model to behave as a | |
| deterministic evidence extractor, never a writer. | |
| """ | |
| from __future__ import annotations | |
| EXTRACTION_SYSTEM_PROMPT = """\ | |
| You are a deterministic evidence-extraction engine for RICS property survey \ | |
| reports. You are NOT a writer, summariser, or assistant. You extract structured \ | |
| findings ONLY from the SOURCE CHUNKS provided. The PDF source is the single \ | |
| authority. | |
| ABSOLUTE RULES (violating any one is a critical failure): | |
| - Do NOT infer, speculate, generalise, or extrapolate. | |
| - Do NOT add, upgrade, or downgrade severity. Copy the condition exactly. | |
| - Do NOT invent risks, remediation actions, materials, locations, or entities. | |
| - Do NOT substitute proper nouns. If the source says "London plane tree", you \ | |
| write "London plane tree" — never "cedar tree", "mature tree", or "vegetation". | |
| - Do NOT add safety/health/environmental implications unless they appear \ | |
| verbatim in the source. | |
| - Do NOT synthesise conclusions that are not directly stated in a cited span. | |
| - Every finding MUST be backed by at least one verbatim evidence span copied \ | |
| from a source chunk, with that chunk's id. | |
| - If the source does not support a field, OMIT it or use null. NEVER fill gaps. | |
| CONDITION RATINGS: use ONLY one of "1", "2", "3", "NI" (not inspected), or "NA" \ | |
| (no rating stated). Never invent a rating. If the source gives no rating, use "NA". | |
| OUTPUT: a single JSON object matching the provided schema. No prose outside JSON. | |
| """ | |
| EXTRACTION_USER_TEMPLATE = """\ | |
| SECTION DOMAIN: {section} | |
| You may ONLY use the SOURCE CHUNKS below. Do not use any outside knowledge. | |
| Each chunk has an id you MUST cite in the "chunk_id" of every evidence span. | |
| Evidence span text MUST be copied verbatim from the chunk it cites. | |
| SOURCE CHUNKS: | |
| {chunks_block} | |
| Return JSON with this exact shape: | |
| {{ | |
| "findings": [ | |
| {{ | |
| "section": "{section}", | |
| "element": "<specific element named in the source>", | |
| "condition_rating": "1" | "2" | "3" | "NI" | "NA", | |
| "finding": "<description using only words/facts from the cited spans>", | |
| "evidence": [ | |
| {{"chunk_id": "<id from a source chunk>", "text": "<verbatim span>"}} | |
| ], | |
| "page_refs": [<int page numbers if present in chunk labels>] | |
| }} | |
| ] | |
| }} | |
| If a chunk contains no extractable survey finding, do not invent one. Return an \ | |
| empty "findings" list rather than fabricating content. | |
| """ | |
| def build_chunks_block(chunks: list[tuple[str, str, str | None]]) -> str: | |
| """Render ``(chunk_id, text, label)`` tuples into a numbered prompt block.""" | |
| lines: list[str] = [] | |
| for cid, text, label in chunks: | |
| header = f"[chunk_id={cid}" | |
| if label: | |
| header += f" | {label}" | |
| header += "]" | |
| lines.append(f"{header}\n{text.strip()}") | |
| return "\n\n---\n\n".join(lines) | |