Agent Impact Modeling and Integration

Summary

The implementation of backend endpoints and frontend UI components to calculate and visualize the influence of specific real estate agents on property valuations. This process involved updating the residual-modeling inference engine to support agent-specific performance metrics and integrating these capabilities into the sokrates-website valuation (Verðmat) interface.

Details

The Agent Impact feature allows users to see how a specific real estate agent’s historical performance (spread and speed) might adjust a property’s baseline valuation. This was executed as a coordinated update across the backend modeling service and the frontend consumer application.

Backend Implementation (residual-modeling)

The backend work focused on correcting data retrieval logic and exposing new calculation primitives via FastAPI.

  • Inference Logic: In src/residual_modeling/modeling/inference.py, the _lookup_agent_spread function was refactored to correctly JOIN the agent_statistics table with the agents table, resolving a bug where it previously attempted to query a non-existent agent_name column.
  • Core Helpers: New shared helpers were extracted to support both standard predictions and agent impact assessments:
    • compute_base_price: Executes the L1 (Structural), L2 (Spatial), and L3 (Temporal) modeling layers to return a BasePriceResult.
    • compute_agent_impact: Calculates the multiplicative spread, applies inflation to nominal ISK, and generates a 93% Confidence Interval (CI).
  • Hardcoded Market Constants: For comparison purposes, market averages were established as module-level constants: _MARKET_AVG_SPREAD = 0.2034 and _MARKET_AVG_DOM = 38.1 (Days on Market).
  • API Endpoints:
    • GET /api/agents?q=<search>: A LIKE-based autocomplete search for agents, ordered by transaction count.
    • POST /api/agent-impact: Accepts a fastanumer (property ID) and agent_id to return an AgentImpactResponse containing base/adjusted prices and delta metrics.
  • Unified Layer Model: The PredictResponse was updated to include a unified layers array containing five items: Structural, Spatial, Temporal, Agent, and Presentation. Each layer includes contribution_isk, r2 (training R² values), and an is_active flag.

Frontend Integration (sokrates-website)

The frontend implementation in src/app/[locale]/verdmat/page.tsx introduced a new “Fasteignasali” (Real Estate Agent) mode to the valuation tool.

  • UI Components:
    • TabToggle: A custom toggle using Framer Motion (layoutId) to switch between “Verðmat” (Decomposition) and “Fasteignasali” (Agent) modes.
    • AgentSearchInput: A debounced search component for selecting agents from the backend registry.
    • AgentSalesPitch: A comprehensive results view featuring an odometer-animated adjusted price, a spread badge, and an agent scorecard.
    • ComparisonBar: Animated horizontal bars comparing the selected agent’s spread and Days on Market against the market averages.
  • Data Transformation: The frontend converts raw backend metrics, such as speed deciles (1-10), into human-readable Icelandic percentile text (e.g., “Top 10% in speed”).
  • Design Language: The implementation follows the “Icelandic Archive” aesthetic, prioritizing surface hierarchy (using surface-container and surface-container-low) over borders, gradients, or shadows. The primary color (#f2ca50) is used for emphasis on active states and “better than average” indicators.

Technical Decisions

  • Data Payload: _lookup_agent_spread was modified to return a full dictionary of statistics (median spread, transaction count, speed decile, DOM) rather than just a float, ensuring the API can provide full context without redundant queries.
  • Backward Compatibility: The base_layers field in the API response was retained temporarily to support existing frontend versions while transitioning to the unified layers array.
  • Type Safety: The agent_id was standardized as a number across the stack, and TypeScript types were updated to reflect the new AgentImpactResponse and LayerInfo structures.