#!/usr/bin/env python3 # Author: Simon-Pierre Boucher — contact@spboucher.ai # """Step 2 — Embed descriptions and compute the 20 cosine-similarity features. Inputs : data/processed/houses.parquet Outputs: data/processed/embeddings_maisons.npy (17,087 x 384, cached) data/processed/sim_matrix_maisons.npy (17,087 x 20) data/processed/hedonic_maison_results.csv (analysis dataset) Pass --force to re-encode the embeddings even if a valid cache exists. """ import sys from pathlib import Path import numpy as np import pandas as pd sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from src import config from src.embeddings import (add_similarity_columns, encode_references, load_or_encode_remarks, similarity_features) from src.references import SIM_COLS def main(force=False): df = pd.read_parquet(config.HOUSES_PARQUET) print(f"{len(df):,} houses loaded") print("Encoding 20 reference descriptions ...") _, ref_embeddings = encode_references() print("Encoding listing descriptions (cache: data/processed) ...") prop_embeddings, from_cache = load_or_encode_remarks( df["remarks"], force=force ) print(f" embeddings {prop_embeddings.shape} " f"({'loaded from cache' if from_cache else 'freshly encoded'})") sim_matrix = similarity_features(prop_embeddings, ref_embeddings) np.save(config.SIM_MATRIX_NPY, sim_matrix) add_similarity_columns(df, sim_matrix) export_cols = ["id", "price", "log_price", "bedrooms", "bathrooms", "half_baths", "parking", "stories", "land_size", "remarks_length"] + SIM_COLS df[export_cols].to_csv(config.ANALYSIS_CSV, index=False) print(f" -> {config.SIM_MATRIX_NPY}") print(f" -> {config.ANALYSIS_CSV}") if __name__ == "__main__": main(force="--force" in sys.argv)