Ключевые особенности
| Язык | C# |
| Фреймворк | .NET 10 |
| Тип проекта | Приложение (Real Estate Api + Worker Host + GpuWorkerHost) |
| Статус | Proof of concept |
| Лицензия | GPL |
| Github | Laraue.Apps.RealEstate |
| Приложение | Crawled Apartments |
О рынке недвижимости
Рынок — это всегда битва двух сторон: одна хочет продать, другая — купить. Сделка обычно происходит, когда цена устраивает обе стороны. Но непосвященному человеку часто трудно определить, высокая ли цена, низкая, или это выгодное предложение. Профессионалы рынка обычно знают различные маркеры, которые позволяют им оценить цену и сравнить её с реальной стоимостью. Они видят хорошие и плохие предложения и понимают, где можно заработать. Обычный человек часто принимает неверные решения, которые приводят к финансовым потерям.
Проблема поиска для пользователя
Но как помочь обычному пользователю понять, выгодное это предложение или нет? Ещё недавно это было почти невозможно, потому что задачи нечетких оценок плохо решались компьютерами. Но с появлением ИИ теперь можно делегировать задачу оценки моделям. Фотографии объектов и их метаинформация могут многое рассказать о стоимости и о том, будет ли сделка выгодной.
Видение приложения
Приложение должно собирать объявления с сайтов недвижимости, анализировать все изображения и оценивать качество ремонта на этих фотографиях, чтобы вынести вердикт о том, является ли предложение выгодным. Затем оно должно возвращать агрегированные объявления, позволяя сравнивать их по уровню объявления или идеальности (соотношению ремонта, цены и местоположения).
Сервисы приложения
Необходимо реализовать несколько сервисов:
Сборщик объявлений
Сервис, который периодически запускается и собирает данные с агрегаторов объявлений. Логика проста:
- Запускать краулер каждые 4 часа. Краулер построен на библиотеке crawler и представляет собой задачу, которая запускает процесс обхода с определённой схемой.
- Попытаться сохранить результат в базу данных. Когда некоторые объявления не новые, это означает, что все элементы собраны, и задача должна ждать следующего выполнения. Эта логика работает, потому что краулер всегда запрашивает самые новые объявления. В системе может быть столько разных сайтов для краулеров, сколько необходимо. Каждый из них — отдельная задача.
Обработчик изображений
Сервис, который делает прогнозы для изображений собранных квартир.
- Запускать предсказатель каждую минуту. Взять следующую порцию непредсказанных изображений и отправить их последовательно в предсказатель. Класс запускает предсказание на локально размещенной модели Ollama qwen2.5, передавая байты изображения и используя промпт, который описывает, какие признаки на фото являются хорошими, а какие — плохими, а затем возвращает результат предсказания.
- Для каждого предсказанного изображения сохранить результат.
- Когда нет изображений для предсказания, ждать следующего выполнения задачи.
Каждое предсказание представлено следующим классом:
public record OllamaPredictionResult
{
public double RenovationRating { get; init; } // Значение от 0 до 1
public string[] Tags { get; init; } = []; // Что было найдено на изображении
public string Description { get; init; } = string.Empty; // Описание, почему выбранно именно такое значение рейтинга
}В конечном результате используется только одно свойство, но остальные помогают понять, как настроить промпт/модель для повышения точности распознавания.
Система ранжирования
Сервис получает результаты, когда они готовы, и выдает окончательную оценку для объявления. С этого момента элемент участвует в результате, возвращаемом из API. Работает по следующему потоку:
- Получить объявления, по которым предсказаны все изображения.
- Рассчитать идеальность. AdvertisementComputedFieldsCalculator устанавливает итоговую оценку идеальности, используя систему штрафов. Если рядом нет станции метро или она слишком далеко от центра, это плохо, и назначается штраф. Плохая оценка ремонта — тоже штраф. Чем больше штрафов, тем ниже идеальность.
- Рассчитать оценку ремонта. Ремонт — это просто средняя оценка по фотографиям. Квартиры со слишком малым количеством фотографий не включаются в рейтинг из-за высокой вероятности ошибки.
API системы
Сервис возвращает запрошенные элементы с различными фильтрами и сортировкой. Обычное API, ничего особо интересного.
Архитектура приложения
Объединить все описанные сервисы и получить следующее:
- ApiHost: хост, обслуживающий запросы фронтенда
- WorkerHost: хост, запускающий краулеры и расчет рейтинга
- GpuWorkerHost: хост, выполняющий задачу предсказания
Сложности
Основные решенные проблемы будут описаны в отдельных статьях:
- Как выбрать подходящую модель для задачи
- Как создать формулу системы ранжирования для проекта
- Как тестировать такую большую систему, чтобы убедиться, что она работает
Хронология
- Фев 2023 Попытки собрать набор данных и обучить модель с помощью TensorFlow.
- Окт 2023 Запуск первой версии приложения, использующей три обученные модели с ~22M параметров для получения прогнозов. Работает быстро, но имеет низкую точность. Очень сложно собрать большой и корректный набор данных.
- Сен 2025 Замена самостоятельно обученных моделей на открытые.
Реальные случаи использования
Иногда приложение используется мной и моими друзьями для наблюдения за ценами на рынке недвижимости. Оно работает не абсолютно правильно — например, прогнозы часто содержат ошибки. Но благодаря использованию усредненной системы ранжирования, это работает достаточно хорошо, чтобы ранжировать предложения от плохих до хороших.