diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 151fb7299..236b28894 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -18,9 +18,7 @@ from domain.epc.property_overrides.main_heating_guard import main_heating_guard from domain.epc.property_overrides.property_type import PropertyType from domain.epc.property_overrides.property_type_guard import property_type_guard from domain.epc.property_overrides.roof_type import RoofType -from domain.epc.property_overrides.roof_party_ceiling_guard import ( - roof_party_ceiling_guard, -) +from domain.epc.property_overrides.roof_guard import roof_guard from domain.data_transformation.guarded_column_classifier import ( GuardedColumnClassifier, ) @@ -133,12 +131,13 @@ def _build_columns( "roof_type": lambda src: ClassifiableColumn( name="roof_type", source_column=src, - # A party ceiling ("another/same dwelling or premises above") has ~0 - # heat loss and must never be classified as an external roof; the - # deterministic guard resolves those markers and the LLM handles the - # rest (#1376). + # Deterministic roof guards resolve the markers they are certain of + # ahead of the LLM: a party ceiling ("another/same dwelling or + # premises above", ~0 heat loss, #1376) and a slope-following ceiling + # ("PitchedWithSlopingCeiling", rafter/slope-line insulation, never + # the loft ladder, ADR-0066). The LLM handles the rest. classifier=GuardedColumnClassifier( - guard=roof_party_ceiling_guard, + guard=roof_guard, fallback=ChatGptColumnClassifier(chat_gpt, RoofType, RoofType.UNKNOWN), ), repo=LandlordOverridesRepository[RoofType]( diff --git a/domain/epc/property_overrides/roof_guard.py b/domain/epc/property_overrides/roof_guard.py index e3203e950..a45732324 100644 --- a/domain/epc/property_overrides/roof_guard.py +++ b/domain/epc/property_overrides/roof_guard.py @@ -2,8 +2,24 @@ from __future__ import annotations from typing import Optional +from domain.epc.property_overrides.roof_party_ceiling_guard import ( + roof_party_ceiling_guard, +) +from domain.epc.property_overrides.roof_sloping_ceiling_guard import ( + roof_sloping_ceiling_guard, +) from domain.epc.property_overrides.roof_type import RoofType def roof_guard(description: str) -> Optional[RoofType]: - raise NotImplementedError + """The deterministic roof guard for the roof `GuardedColumnClassifier`. + + Composes the two roof guards that resolve a description with certainty, ahead + of the LLM fallback: a party ceiling (~0 heat loss, #1376) and a + slope-following ceiling (rafter/slope-line insulation, ADR-0066). The two + marker sets are disjoint, so precedence is immaterial; anything neither + recognises returns None and reaches the LLM classifier. + """ + return roof_party_ceiling_guard(description) or roof_sloping_ceiling_guard( + description + )