SPB Git forge

spb/vrai-prix

Public

Vrai-Prix — l'évaluation du vrai prix des propriétés résidentielles au Québec.

60commits 1branches 0releases
12.3 MBsize
maindefault branch
17 days agolast push
TypeScript 90.2% JavaScript 3.5% Python 3.4% CSS 1.9% HTML 0.6%
8.0 KB · 48 lines typescript
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2/** Sortie modèle de référence (fixture) : tests hors réseau et fournisseur factice (`FakeProvider`). Module PUR. */3import type { ModelOutput } from "./schema";4import type { AnalyzeInput, AnalyzeResult, PropertyVisionModel } from "./provider";56const A = <T,>(value: T, confidence = 0.9, source: ModelOutput["property"]["building_type"]["source"] = "photo", evidence: string[] = ["photo_01"]) => ({ value, confidence, source, evidence });7const Q = (value: number | null, unit: string, confidence = 0.7, method: string | null = "visual estimate", source: ModelOutput["property"]["building_type"]["source"] = "ai_estimated") => ({ value, unit, confidence, source, method, evidence: value == null ? [] : ["photo_02"] });8const M = (value: string | null, status: ModelOutput["mechanical"]["heat_source"]["status"] = "inferred", confidence = 0.6) => ({ value, status, confidence, evidence: value ? ["photo_09"] : [] });910export function sampleOutput(): ModelOutput {11  return {12    property: { building_type: A("detached", 0.95), year_built: A(1998, 0.9, "listing", ["listing"]), stories: A(2, 0.9), gross_floor_area_sqft: A(2470, 0.99, "listing", ["listing"]), bedrooms: A(4, 0.95, "listing", ["listing"]), bathrooms: A(2, 0.9, "listing", ["listing"]), powder_rooms: A(1, 0.9, "listing", ["listing"]), dwelling_units: A(1, 0.95) },13    geometry: { footprint_sqft: A(null, 0.2, "unknown", []), roof_area_sqft: A(null, 0.1, "unknown", []), exterior_wall_area_sqft: A(null, 0.1, "unknown", []), perimeter_ft: A(null, 0.1, "unknown", []), roof_pitch_rise_per_12: A(6, 0.6) },14    construction: { foundation: A("poured_concrete", 0.88, "photo", ["photo_14"]), structural_system: A("wood_frame", 0.92, "assumed", []), floor_system: A(null, 0.2, "unknown", []), wall_system: A("2x6", 0.4, "assumed", []), roof_system_type: A("asphalt_shingle", 0.91), roof_geometry: A("gable", 0.9), insulation_level: A(null, 0.2, "unknown", []), building_envelope: A("brick and vinyl", 0.9) },15    exterior: {16      primary_siding: A("brick", 0.94, "photo", ["photo_01", "photo_03"]), secondary_siding: A("vinyl", 0.9, "photo", ["photo_03"]), siding_shares: { brick_pct: 60, vinyl_pct: 40, fiber_cement_pct: 0, wood_pct: 0, stone_pct: 0, stucco_pct: 0, metal_pct: 0, other_pct: 0 },17      windows_type: A("pvc", 0.7), window_count_estimate: Q(18, "unit", 0.65), exterior_doors_count: Q(2, "unit", 0.8), roof_covering: A("asphalt_shingle", 0.91), gutters: A(true, 0.8), balconies_count: Q(0, "unit", 0.7), decks_count: Q(1, "unit", 0.8), exterior_stairs: A("concrete steps", 0.7),18    },19    interior: { flooring_types: [{ material: "hardwood", share_pct: 60, evidence: ["photo_05"] }, { material: "ceramic_tile", share_pct: 40, evidence: ["photo_06"] }], wall_finish: A("painted drywall", 0.9), ceiling_finish: A("flat painted", 0.8), trim_quality: A("standard", 0.6), door_quality: A("standard", 0.6), stair_quality: A("superior", 0.6), fireplace: A("gas", 0.7), built_ins: A(false, 0.6), ceiling_height_ft: A(9, 0.6) },20    kitchens: [{ location: "main floor", quality: "superior", cabinet_type: "painted_mdf", countertop: "quartz", island: true, estimated_cabinet_linear_ft: 34, estimated_countertop_sqft: 68, estimated_backsplash_sqft: 40, condition: "renovated", confidence: 0.82, evidence: ["photo_18", "photo_19"] }],21    bathrooms: [{ type: "full", quality: "standard", tub: "alcove", shower: "combined", double_vanity: false, tile_extent: "tub surround", fixtures_quality: "standard", estimated_area_sqft: 45, estimated_tile_sqft: 60, condition: "good", confidence: 0.75, evidence: ["photo_20"] }, { type: "powder", quality: "standard", tub: null, shower: null, double_vanity: false, tile_extent: null, fixtures_quality: "standard", estimated_area_sqft: 20, estimated_tile_sqft: 20, condition: "good", confidence: 0.7, evidence: ["photo_21"] }],22    mechanical: { heat_source: M("electricity", "listing", 0.9), heat_distribution: M("forced_air", "inferred", 0.6), heat_pump: M("central", "observed", 0.8), air_conditioning: M("central", "inferred", 0.7), air_exchanger: M("unknown", "unknown", 0.2), water_heater: M("electric tank", "observed", 0.7), fireplace: M("gas", "observed", 0.7), boiler: M("none", "inferred", 0.5), furnace: M("electric", "inferred", 0.5) },23    electrical: { panel_type: M("breaker", "observed", 0.7), panel_capacity_amps: A(200, 0.31, "ai_estimated", ["photo_24"]), service_type: M("underground", "unknown", 0.2), visible_age: M(null, "unknown", 0.1), ev_charger: M("absent", "inferred", 0.5), generator: M("absent", "inferred", 0.6), lighting_quality: M("standard", "observed", 0.6), smart_home: M(null, "unknown", 0.1) },24    plumbing: { water_supply: M("municipal", "listing", 0.9), waste_system: M("municipal", "listing", 0.9), visible_pipe_type: M("pex", "observed", 0.5), fixtures_quality: M("standard", "observed", 0.6), laundry: M("basement", "observed", 0.7) },25    basement: { state: A("finished", 0.85, "photo", ["photo_22"]), estimated_finished_pct: A(90, 0.7), quality: A("standard", 0.6), ceiling_type: A("drywall", 0.6), flooring: A("vinyl_plank", 0.6), bathroom: A(false, 0.5), bedrooms: A(1, 0.5) },26    garage: { type: A("attached", 0.9), spaces: A(2, 0.85), area_estimate_sqft: A(480, 0.5, "ai_estimated"), finished: A(false, 0.5), heated: A(null, 0.2, "unknown", []), door_count: A(1, 0.9) },27    exterior_improvements: { deck_sqft: Q(200, "pi2", 0.6), patio_sqft: Q(null, "pi2", 0.2, null, "unknown"), pool: A("none", 0.8), spa: A(false, 0.7), shed: A(true, 0.7), fence_linear_ft: Q(120, "pi_lin", 0.5), driveway_type: A("asphalt", 0.9), driveway_sqft: Q(600, "pi2", 0.6), landscaping_quality: A("standard", 0.6), retaining_wall: A(false, 0.6), outdoor_kitchen: A(false, 0.8) },28    quality: { exterior_quality: "superior", interior_quality: "superior", kitchen_quality: "superior", bathroom_quality: "standard", mechanical_quality: "standard", overall_quality: "superior", confidence: 0.8 },29    condition: { roof: "average", windows: "good", exterior: "good", interior: "very_good", kitchen: "renovated", bathrooms: "good", basement: "excellent", mechanical: "good", electrical: "good", structure: "good", site: "good", confidence: 0.75 },30    estimated_effective_age: { chronological_age: 28, effective_age: 17, economic_life: 60, confidence: 0.72, reasoning_summary: ["kitchen renovated", "windows appear newer", "roof appears mid-life"] },31    renovations: [{ component: "kitchen", renovation_likelihood: 0.91, estimated_renovation_age_range: [3, 8], evidence: ["photo_18"] }],32    estimated_quantities: { window_count: Q(18, "unit", 0.65), kitchen_cabinets_linear_ft: Q(34, "pi_lin", 0.7), countertop_sqft: Q(68, "pi2", 0.7), backsplash_sqft: Q(40, "pi2", 0.6), bathroom_tile_sqft: Q(80, "pi2", 0.5), deck_sqft: Q(200, "pi2", 0.6), driveway_sqft: Q(600, "pi2", 0.6), fence_linear_ft: Q(120, "pi_lin", 0.5), garage_area_sqft: Q(480, "pi2", 0.5), finished_basement_pct: Q(90, "pct", 0.7), interior_door_count: Q(12, "unit", 0.55) },33    assemblies: [{ assembly_code: "KIT-SUPERIOR", quantity: 34, unit: "pi_lin", confidence: 0.7, evidence: ["photo_18"] }, { assembly_code: "ROOF-ASPHALT-ARCH", quantity: 1650, unit: "pi2", confidence: 0.65, evidence: ["photo_01"] }, { assembly_code: "EXT-DECK-TREATED", quantity: 200, unit: "pi2", confidence: 0.6, evidence: ["photo_11"] }],34    uncertainties: ["listing says metal roof; photos show asphalt shingles"],35    privacy: { people_visible: false, documents_visible: false, licence_plates_visible: false },36    confidence: { overall: 0.86, construction: 0.85, exterior: 0.9, interior: 0.82, mechanical: 0.6, quantities: 0.66 },37  };38}3940/** Fournisseur factice (tests, développement sans clé) : renvoie la fixture sans appel réseau. */41export class FakeProvider implements PropertyVisionModel {42  readonly model = "fake-vision-model";43  async analyze(input: AnalyzeInput): Promise<AnalyzeResult> {44    void input;45    return { output: sampleOutput(), usage: { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, estimatedCostUsd: 0, latencyMs: 1, attempts: 1 }, model: this.model, promptVersion: "v1", issues: [] };46  }47}48