Update app.py
Browse files
app.py
CHANGED
@@ -97,7 +97,7 @@ def analyze_query(query):
|
|
97 |
return int(number)
|
98 |
|
99 |
# Поиск цены
|
100 |
-
price_keywords = ["руб", "р.", "рублей", "рубля"]
|
101 |
price_match = re.findall(rf"(до|\s*)(\d+[\s]*[.,]?\d*)\s*(млн|тр|т\.р|тыс|тысруб|тыс\.руб|тр|т\.р.|тыр|тыр.|тыщ|тыш|тысяч|млнруб|млн\.руб|мн|М|миллионов|милионов|лямов|лимонов)?\s*({'|'.join(price_keywords)})\b", query)
|
102 |
if price_match:
|
103 |
operator = price_match[0][0]
|
@@ -128,10 +128,44 @@ def analyze_query(query):
|
|
128 |
filters["area_max"] = int(area_max_match[0][1])
|
129 |
|
130 |
return filters
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
|
132 |
|
133 |
# Поиск объектов недвижимости в CSV
|
134 |
-
def search_real_estate(dataframe, filters):
|
135 |
if not filters:
|
136 |
return []
|
137 |
|
@@ -163,6 +197,61 @@ def search_real_estate(dataframe, filters):
|
|
163 |
|
164 |
# Возвращаем все подходящие объекты
|
165 |
return dataframe[mask].to_dict(orient="records")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
|
168 |
# Функция для получения ответа от модели
|
@@ -200,13 +289,15 @@ def predict(message, history=None):
|
|
200 |
for result in filtered_results:
|
201 |
response += (
|
202 |
f"ID: {result.get('item_id', 'Не указано')}\n"
|
|
|
203 |
f"Адрес: {result.get('address', 'Не указано')}\n"
|
204 |
f"Цена: {result.get('price', 'Не указано')} руб.\n"
|
205 |
f"Площадь: {result.get('area', 'Не указано')} м²\n"
|
206 |
f"Метро: {result.get('metro', 'Не указано')}\n"
|
207 |
f"До метро: {result.get('met_range', 'Не указано')}\n"
|
208 |
f"Описание: {result.get('description', 'Не указано')}\n"
|
209 |
-
f"
|
|
|
210 |
f"---\n"
|
211 |
)
|
212 |
log_dialog(message, response)
|
|
|
97 |
return int(number)
|
98 |
|
99 |
# Поиск цены
|
100 |
+
"""price_keywords = ["руб", "р.", "рублей", "рубля"]
|
101 |
price_match = re.findall(rf"(до|\s*)(\d+[\s]*[.,]?\d*)\s*(млн|тр|т\.р|тыс|тысруб|тыс\.руб|тр|т\.р.|тыр|тыр.|тыщ|тыш|тысяч|млнруб|млн\.руб|мн|М|миллионов|милионов|лямов|лимонов)?\s*({'|'.join(price_keywords)})\b", query)
|
102 |
if price_match:
|
103 |
operator = price_match[0][0]
|
|
|
128 |
filters["area_max"] = int(area_max_match[0][1])
|
129 |
|
130 |
return filters
|
131 |
+
"""
|
132 |
+
|
133 |
+
# Поиск цены. из стримлит
|
134 |
+
price_keywords = ["руб", "р.", "рублей", "рубля"]
|
135 |
+
price_match = re.findall(rf"(до|<|>\s*)(\d+[\s]*[.,]?\d*)\s*(млн|тр|т\.р|тыс|тысруб|тыс\.руб|тр|т\.р.|тыр|тыр.|тыщ|тыш|тысяч|млнруб|млн\.руб|мн|М|миллионов|милионов|лямов|лимонов)?\s*({'|'.join(price_keywords)})\b", query)
|
136 |
+
if price_match:
|
137 |
+
operator = price_match[0][0]
|
138 |
+
raw_price = price_match[0][1] + (price_match[0][2] or "")
|
139 |
+
normalized_price = normalize_number(raw_price)
|
140 |
+
if normalized_price is not None:
|
141 |
+
if operator in ["до", "<"]:
|
142 |
+
filters["price_max"] = normalized_price
|
143 |
+
elif operator in ["от", ">"]:
|
144 |
+
filters["price_min"] = normalized_price
|
145 |
+
# Поиск площади
|
146 |
+
area_keywords = ["квм", "кв.м", "кв метров", "кв м", "кв.м.", "квадратов", "квадрата", "м2", "метров", "м²"]
|
147 |
+
# Сначала ищем диапазоны
|
148 |
+
area_range_match_1 = re.findall(rf"(\d+)\s*-\s*(\d+)\s*({'|'.join(area_keywords)})", query)
|
149 |
+
area_range_match_2 = re.findall(rf"(\d+)\s*[.\s]+\s*(\d+)\s*({'|'.join(area_keywords)})", query)
|
150 |
+
if area_range_match_1:
|
151 |
+
filters["area_min"] = int(area_range_match_1[0][0])
|
152 |
+
filters["area_max"] = int(area_range_match_1[0][1])
|
153 |
+
elif area_range_match_2:
|
154 |
+
filters["area_min"] = int(area_range_match_2[0][0])
|
155 |
+
filters["area_max"] = int(area_range_match_2[0][1])
|
156 |
+
else:
|
157 |
+
# Если не найдены диапазоны, ищем "от" или "до"
|
158 |
+
area_min_match = re.findall(rf"\b(от)\s*(\d+)\s*({'|'.join(area_keywords)})", query)
|
159 |
+
area_max_match = re.findall(rf"\b(до)\s*(\d+)\s*({'|'.join(area_keywords)})", query)
|
160 |
+
if area_min_match:
|
161 |
+
filters["area_min"] = int(area_min_match[0][1]) # Преобразуем число в целый тип
|
162 |
+
if area_max_match:
|
163 |
+
filters["area_max"] = int(area_max_match[0][1]) # Преобразуем число в целый тип
|
164 |
+
return filters
|
165 |
|
166 |
|
167 |
# Поиск объектов недвижимости в CSV
|
168 |
+
"""def search_real_estate(dataframe, filters):
|
169 |
if not filters:
|
170 |
return []
|
171 |
|
|
|
197 |
|
198 |
# Возвращаем все подходящие объекты
|
199 |
return dataframe[mask].to_dict(orient="records")
|
200 |
+
"""
|
201 |
+
# Поиск объектов недвижимости в CSV
|
202 |
+
def search_real_estate(dataframe, filters):
|
203 |
+
if not filters:
|
204 |
+
return []
|
205 |
+
mask = pd.Series([True] * len(dataframe))
|
206 |
+
# Фильтрация по типу недвижимости
|
207 |
+
if "type" in filters:
|
208 |
+
mask &= dataframe["type"].str.lower().isin(filters["type"])
|
209 |
+
|
210 |
+
# Фильтрация по виду сделки (Аренда/Продажа)
|
211 |
+
if "rent" in filters:
|
212 |
+
mask &= dataframe["RENT"].str.lower() == filters["rent"].lower()
|
213 |
+
|
214 |
+
# Фильтрация по цене
|
215 |
+
if "price_min" in filters and "price_max" in filters:
|
216 |
+
mask &= (dataframe["price"] >= filters["price_min"]) & (dataframe["price"] <= filters["price_max"])
|
217 |
+
elif "price_min" in filters:
|
218 |
+
mask &= dataframe["price"] >= filters["price_min"]
|
219 |
+
elif "price_max" in filters:
|
220 |
+
mask &= dataframe["price"] <= filters["price_max"]
|
221 |
+
# Фильтрация по площади
|
222 |
+
if "area_min" in filters and "area_max" in filters:
|
223 |
+
mask &= (dataframe["area"] >= filters["area_min"]) & (dataframe["area"] <= filters["area_max"])
|
224 |
+
elif "area_min" in filters:
|
225 |
+
mask &= dataframe["area"] >= filters["area_min"]
|
226 |
+
elif "area_max" in filters:
|
227 |
+
mask &= dataframe["area"] <= filters["area_max"]
|
228 |
+
results = dataframe[mask]
|
229 |
+
# Проверяем, есть ли результаты
|
230 |
+
if not results.empty:
|
231 |
+
return results.to_dict(orient="records") # Возвращаем список словарей
|
232 |
+
# Fallback: Если нет подходящих объектов, предлагаем все объекты данного типа
|
233 |
+
if "type" in filters:
|
234 |
+
fallback_mask = dataframe["type"].str.lower().isin(filters["type"])
|
235 |
+
fallback_results = dataframe[fallback_mask]
|
236 |
+
if not fallback_results.empty:
|
237 |
+
return {"fallback": True, "results": fallback_results.to_dict(orient="records")} # Возвращаем fallback-результаты
|
238 |
+
return [] # Возвращаем пустой список, если ничего не найдено
|
239 |
+
|
240 |
+
# Создание контекста для модели
|
241 |
+
def create_context(dataframe, filters):
|
242 |
+
if "type" in filters and "rent" in filters:
|
243 |
+
# Создаем контекст только для релевантных данных
|
244 |
+
relevant_data = dataframe[
|
245 |
+
(dataframe["type"].str.lower().isin(filters["type"])) &
|
246 |
+
(dataframe["RENT"].str.lower() == filters["rent"].lower())
|
247 |
+
]
|
248 |
+
else:
|
249 |
+
# Если параметры не указаны, используем весь датасет
|
250 |
+
relevant_data = dataframe
|
251 |
+
context = " ".join(relevant_data["description"].dropna().tolist()) + " " + \
|
252 |
+
" ".join(relevant_data["type"].dropna().tolist()) + " " + \
|
253 |
+
" ".join(relevant_data["address"].dropna().tolist())
|
254 |
+
return context
|
255 |
|
256 |
|
257 |
# Функция для получения ответа от модели
|
|
|
289 |
for result in filtered_results:
|
290 |
response += (
|
291 |
f"ID: {result.get('item_id', 'Не указано')}\n"
|
292 |
+
f"Тип: {result.get('type', 'Не указано')}\n"
|
293 |
f"Адрес: {result.get('address', 'Не указано')}\n"
|
294 |
f"Цена: {result.get('price', 'Не указано')} руб.\n"
|
295 |
f"Площадь: {result.get('area', 'Не указано')} м²\n"
|
296 |
f"Метро: {result.get('metro', 'Не указано')}\n"
|
297 |
f"До метро: {result.get('met_range', 'Не указано')}\n"
|
298 |
f"Описание: {result.get('description', 'Не указано')}\n"
|
299 |
+
f"Фото: {result.get('foto', 'Не указано')}\n"
|
300 |
+
f"Записаться на просмотр: {result.get('order', 'Не указано')}\n"
|
301 |
f"---\n"
|
302 |
)
|
303 |
log_dialog(message, response)
|