Spaces:
Sleeping
Sleeping
Commit
·
a9ab2f8
1
Parent(s):
9ca349e
Add reindex endpoints for updating entity embeddings
Browse files- Added POST /reindex endpoint for single entity reindexing
- Added POST /reindex-batch endpoint for batch reindexing
- Updated root endpoint to show new reindex endpoints
- Improved documentation with clear use cases for create vs update operations
main.py
CHANGED
|
@@ -195,8 +195,10 @@ async def root():
|
|
| 195 |
"description": "Генерирует эмбеддинги. Хранение на стороне Go Backend + pgvector.",
|
| 196 |
"endpoints": {
|
| 197 |
"POST /embed": "Эмбеддинг из готового текста",
|
| 198 |
-
"POST /prepare-and-embed": "Подготовка полей + эмбеддинг (
|
| 199 |
-
"POST /
|
|
|
|
|
|
|
| 200 |
"GET /health": "Проверка здоровья",
|
| 201 |
"GET /model-info": "Информация о модели для pgvector"
|
| 202 |
},
|
|
@@ -380,3 +382,107 @@ LIMIT 10;
|
|
| 380 |
""".strip()
|
| 381 |
}
|
| 382 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
"description": "Генерирует эмбеддинги. Хранение на стороне Go Backend + pgvector.",
|
| 196 |
"endpoints": {
|
| 197 |
"POST /embed": "Эмбеддинг из готового текста",
|
| 198 |
+
"POST /prepare-and-embed": "Подготовка полей + эмбеддинг (создание)",
|
| 199 |
+
"POST /reindex": "Переиндексация объекта (обновление)",
|
| 200 |
+
"POST /batch": "Пакетная обработка (создание)",
|
| 201 |
+
"POST /reindex-batch": "Пакетная переиндексация (обновление)",
|
| 202 |
"GET /health": "Проверка здоровья",
|
| 203 |
"GET /model-info": "Информация о модели для pgvector"
|
| 204 |
},
|
|
|
|
| 382 |
""".strip()
|
| 383 |
}
|
| 384 |
}
|
| 385 |
+
|
| 386 |
+
|
| 387 |
+
# ============== Reindex Endpoint ==============
|
| 388 |
+
|
| 389 |
+
class ReindexRequest(BaseModel):
|
| 390 |
+
"""
|
| 391 |
+
Запрос на переиндексацию объекта.
|
| 392 |
+
|
| 393 |
+
Используется когда пользователь обновил лида/объект и нужно
|
| 394 |
+
пересоздать эмбеддинг.
|
| 395 |
+
"""
|
| 396 |
+
entity_id: str = Field(..., description="ID объекта для переиндексации")
|
| 397 |
+
entity_type: str = Field(default="lead", description="Тип: 'lead' или 'property'")
|
| 398 |
+
title: str = Field(default="", description="Название")
|
| 399 |
+
description: str = Field(default="", description="Описание")
|
| 400 |
+
requirement: Optional[Dict[str, Any]] = Field(default=None, description="Требования (JSON)")
|
| 401 |
+
price: Optional[float] = Field(default=None, description="Цена")
|
| 402 |
+
district: Optional[str] = Field(default=None, description="Район")
|
| 403 |
+
rooms: Optional[int] = Field(default=None, description="Количество комнат")
|
| 404 |
+
area: Optional[float] = Field(default=None, description="Площадь")
|
| 405 |
+
address: Optional[str] = Field(default=None, description="Адрес")
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
class ReindexResponse(BaseModel):
|
| 409 |
+
"""Ответ на переиндексацию."""
|
| 410 |
+
entity_id: str
|
| 411 |
+
entity_type: str
|
| 412 |
+
embedding: List[float]
|
| 413 |
+
dimensions: int
|
| 414 |
+
prepared_text: str
|
| 415 |
+
message: str = Field(default="Reindex successful. Update embedding in your database.")
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
@app.post("/reindex", response_model=ReindexResponse)
|
| 419 |
+
async def reindex_entity(request: ReindexRequest):
|
| 420 |
+
"""
|
| 421 |
+
Переиндексация объекта (лида или недвижимости).
|
| 422 |
+
|
| 423 |
+
⭐ Используйте когда пользователь ОБНОВИЛ данные объекта.
|
| 424 |
+
|
| 425 |
+
Сценарий:
|
| 426 |
+
1. Пользователь создал лида → POST /prepare-and-embed → сохранили embedding
|
| 427 |
+
2. Пользователь ИЗМЕНИЛ лида → POST /reindex → получили новый embedding
|
| 428 |
+
3. Go Backend обновляет embedding в PostgreSQL
|
| 429 |
+
|
| 430 |
+
Пример запроса:
|
| 431 |
+
```json
|
| 432 |
+
{
|
| 433 |
+
"entity_id": "lead-123",
|
| 434 |
+
"entity_type": "lead",
|
| 435 |
+
"title": "Обновлённый заголовок",
|
| 436 |
+
"description": "Новое описание",
|
| 437 |
+
"price": 12000000,
|
| 438 |
+
"district": "Арбат",
|
| 439 |
+
"rooms": 4
|
| 440 |
+
}
|
| 441 |
+
```
|
| 442 |
+
|
| 443 |
+
Go Backend должен выполнить:
|
| 444 |
+
```sql
|
| 445 |
+
UPDATE leads SET embedding = $1, updated_at = NOW() WHERE lead_id = $2
|
| 446 |
+
```
|
| 447 |
+
"""
|
| 448 |
+
if model is None:
|
| 449 |
+
raise HTTPException(status_code=503, detail="Model not loaded")
|
| 450 |
+
|
| 451 |
+
prepared = prepare_text(
|
| 452 |
+
title=request.title,
|
| 453 |
+
description=request.description,
|
| 454 |
+
requirement=request.requirement,
|
| 455 |
+
price=request.price,
|
| 456 |
+
district=request.district,
|
| 457 |
+
rooms=request.rooms,
|
| 458 |
+
area=request.area,
|
| 459 |
+
address=request.address
|
| 460 |
+
)
|
| 461 |
+
|
| 462 |
+
if not prepared:
|
| 463 |
+
raise HTTPException(status_code=400, detail="All fields are empty - nothing to reindex")
|
| 464 |
+
|
| 465 |
+
embedding = model.encode(prepared, convert_to_numpy=True)
|
| 466 |
+
|
| 467 |
+
return ReindexResponse(
|
| 468 |
+
entity_id=request.entity_id,
|
| 469 |
+
entity_type=request.entity_type,
|
| 470 |
+
embedding=embedding.tolist(),
|
| 471 |
+
dimensions=len(embedding),
|
| 472 |
+
prepared_text=prepared,
|
| 473 |
+
message=f"Reindex successful for {request.entity_type} '{request.entity_id}'. Update embedding in your database."
|
| 474 |
+
)
|
| 475 |
+
|
| 476 |
+
|
| 477 |
+
@app.post("/reindex-batch", response_model=BatchResponse)
|
| 478 |
+
async def reindex_batch(request: BatchRequest):
|
| 479 |
+
"""
|
| 480 |
+
Пакетная переиндексация нескольких объектов.
|
| 481 |
+
|
| 482 |
+
Используйте когда нужно переиндексировать много объектов после
|
| 483 |
+
массового обновления или изменения модели.
|
| 484 |
+
|
| 485 |
+
В��утренне вызывает тот же batch_process, но с понятным названием.
|
| 486 |
+
"""
|
| 487 |
+
return await batch_process(request)
|
| 488 |
+
|