323 lines
13 KiB
Python
323 lines
13 KiB
Python
"""
|
||
Pydantic схемы для API Embedding сервиса.
|
||
"""
|
||
|
||
from pydantic import BaseModel, Field
|
||
|
||
# =============================================================================
|
||
# Запросы
|
||
# =============================================================================
|
||
|
||
|
||
class ScoreRequest(BaseModel):
|
||
"""Запрос на расчет скора."""
|
||
|
||
text: str = Field(..., min_length=1, description="Текст поста для оценки")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {"example": {"text": "Это пример текста поста для оценки скоринга"}}
|
||
}
|
||
|
||
|
||
class ExampleRequest(BaseModel):
|
||
"""Запрос на добавление примера."""
|
||
|
||
text: str = Field(..., min_length=1, description="Текст примера")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {"example": {"text": "Это пример опубликованного/отклоненного поста"}}
|
||
}
|
||
|
||
|
||
class SimilarRequest(BaseModel):
|
||
"""Запрос на поиск похожих постов."""
|
||
|
||
text: str = Field(..., min_length=1, description="Текст для поиска похожих")
|
||
threshold: float = Field(
|
||
default=0.9, ge=0.0, le=1.0, description="Минимальный порог similarity"
|
||
)
|
||
hours: int = Field(default=24, ge=1, le=168, description="Количество часов для фильтрации")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"text": "Текст поста для поиска похожих",
|
||
"threshold": 0.9,
|
||
"hours": 24,
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class SubmittedRequest(BaseModel):
|
||
"""Запрос на добавление submitted-поста."""
|
||
|
||
text: str = Field(..., min_length=1, description="Текст поста")
|
||
post_id: int | None = None
|
||
rag_score: float | None = None
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"text": "Текст submitted-поста",
|
||
"post_id": 12345,
|
||
"rag_score": 0.85,
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
# =============================================================================
|
||
# Ответы
|
||
# =============================================================================
|
||
|
||
|
||
class ScoreMetadata(BaseModel):
|
||
"""Метаданные результата скоринга."""
|
||
|
||
positive_examples: int = Field(..., description="Количество положительных примеров")
|
||
negative_examples: int = Field(..., description="Количество отрицательных примеров")
|
||
model: str = Field(..., description="Название модели")
|
||
timestamp: int = Field(..., description="Время расчета (unix timestamp)")
|
||
|
||
|
||
class ScoreResponse(BaseModel):
|
||
"""Ответ с результатом скоринга."""
|
||
|
||
rag_score: float = Field(..., ge=0.0, le=1.0, description="Основной скор (neg/pos формула)")
|
||
rag_confidence: float = Field(..., ge=0.0, le=1.0, description="Уверенность в оценке")
|
||
rag_score_pos_only: float = Field(
|
||
..., ge=0.0, le=1.0, description="Скор только по положительным примерам"
|
||
)
|
||
meta: ScoreMetadata = Field(..., description="Метаданные")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"rag_score": 0.7523,
|
||
"rag_confidence": 0.85,
|
||
"rag_score_pos_only": 0.6891,
|
||
"meta": {
|
||
"positive_examples": 500,
|
||
"negative_examples": 350,
|
||
"model": "sentence-transformers/all-MiniLM-L12-v2",
|
||
"timestamp": 1706270000,
|
||
},
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class ExampleResponse(BaseModel):
|
||
"""Ответ на добавление примера."""
|
||
|
||
success: bool = Field(..., description="Успешность добавления")
|
||
message: str = Field(..., description="Сообщение о результате")
|
||
positive_count: int = Field(..., description="Текущее количество положительных примеров")
|
||
negative_count: int = Field(..., description="Текущее количество отрицательных примеров")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"success": True,
|
||
"message": "Положительный пример добавлен",
|
||
"positive_count": 501,
|
||
"negative_count": 350,
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class SimilarPostItem(BaseModel):
|
||
"""Элемент похожего поста."""
|
||
|
||
similarity: float = Field(..., description="Косинусное сходство")
|
||
created_at: int = Field(..., description="Unix timestamp создания")
|
||
post_id: int | None = None
|
||
text: str = Field(..., description="Текст поста")
|
||
rag_score: float | None = None
|
||
|
||
|
||
class SimilarResponse(BaseModel):
|
||
"""Ответ с похожими постами."""
|
||
|
||
similar_count: int = Field(..., description="Количество найденных похожих постов")
|
||
similar_posts: list[SimilarPostItem] = Field(..., description="Список похожих постов")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"similar_count": 2,
|
||
"similar_posts": [
|
||
{
|
||
"similarity": 0.95,
|
||
"created_at": 1706270000,
|
||
"post_id": 123,
|
||
"text": "Похожий пост",
|
||
"rag_score": 0.85,
|
||
}
|
||
],
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class SubmittedResponse(BaseModel):
|
||
"""Ответ на добавление submitted-поста."""
|
||
|
||
success: bool = Field(..., description="Успешность добавления")
|
||
message: str = Field(..., description="Сообщение о результате")
|
||
submitted_count: int = Field(..., description="Текущее количество submitted-постов")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"success": True,
|
||
"message": "Submitted-пост добавлен",
|
||
"submitted_count": 42,
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class VectorStoreStats(BaseModel):
|
||
"""Статистика хранилища векторов."""
|
||
|
||
positive_count: int = Field(..., description="Количество положительных примеров")
|
||
negative_count: int = Field(..., description="Количество отрицательных примеров")
|
||
total_count: int = Field(..., description="Общее количество примеров")
|
||
submitted_count: int = Field(default=0, description="Количество submitted-постов")
|
||
vector_dim: int = Field(..., description="Размерность векторов")
|
||
max_examples: int = Field(..., description="Максимальное количество примеров")
|
||
max_submitted: int = Field(default=5000, description="Максимальное количество submitted-постов")
|
||
|
||
|
||
class StatsResponse(BaseModel):
|
||
"""Ответ со статистикой сервиса."""
|
||
|
||
model_name: str = Field(..., description="Название модели")
|
||
model_loaded: bool = Field(..., description="Загружена ли модель")
|
||
device: str | None = Field(None, description="Устройство (cpu/cuda)")
|
||
vector_store: VectorStoreStats = Field(..., description="Статистика хранилища векторов")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"model_name": "sentence-transformers/all-MiniLM-L12-v2",
|
||
"model_loaded": True,
|
||
"device": "cpu",
|
||
"vector_store": {
|
||
"positive_count": 500,
|
||
"negative_count": 350,
|
||
"total_count": 850,
|
||
"vector_dim": 384,
|
||
"max_examples": 10000,
|
||
},
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class WarmupResponse(BaseModel):
|
||
"""Ответ на прогрев модели."""
|
||
|
||
success: bool = Field(..., description="Успешность загрузки")
|
||
model_loaded: bool = Field(..., description="Загружена ли модель")
|
||
message: str = Field(..., description="Сообщение о результате")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"success": True,
|
||
"model_loaded": True,
|
||
"message": "Модель успешно загружена",
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class ErrorResponse(BaseModel):
|
||
"""Ответ с ошибкой."""
|
||
|
||
detail: str = Field(..., description="Описание ошибки")
|
||
error_type: str = Field(..., description="Тип ошибки")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {
|
||
"detail": "Недостаточно примеров для расчета скора",
|
||
"error_type": "InsufficientExamplesError",
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
class HealthResponse(BaseModel):
|
||
"""Ответ проверки здоровья сервиса."""
|
||
|
||
status: str = Field(..., description="Статус сервиса")
|
||
model_loaded: bool = Field(..., description="Загружена ли модель")
|
||
version: str = Field(..., description="Версия сервиса")
|
||
|
||
model_config = {
|
||
"json_schema_extra": {
|
||
"example": {"status": "healthy", "model_loaded": True, "version": "0.1.0"}
|
||
}
|
||
}
|
||
|
||
|
||
class ScoringParamsResponse(BaseModel):
|
||
"""Ответ с текущими параметрами формулы расчета score."""
|
||
|
||
score_multiplier: float = Field(
|
||
...,
|
||
description=(
|
||
"Множитель для масштабирования разницы в скорах. "
|
||
"Используется в формуле: score = (diff * score_multiplier + 1) / 2, "
|
||
"где diff = avg_pos - avg_neg (разница средних сходств топ-k примеров). "
|
||
"Чем больше значение, тем сильнее влияние разницы между положительными и отрицательными примерами на итоговый score. "
|
||
"Рекомендуемое значение: 5.0"
|
||
),
|
||
)
|
||
k: int = Field(
|
||
...,
|
||
description=(
|
||
"Количество ближайших примеров для расчета среднего сходства. "
|
||
"Алгоритм берет топ-k самых похожих примеров из каждого типа (положительные/отрицательные) "
|
||
"и вычисляет среднее косинусное сходство. "
|
||
"Меньшее значение k делает алгоритм более чувствительным к различиям, но может быть менее стабильным. "
|
||
"Рекомендуемое значение: 3"
|
||
),
|
||
)
|
||
|
||
model_config = {"json_schema_extra": {"example": {"score_multiplier": 5.0, "k": 3}}}
|
||
|
||
|
||
class UpdateScoringParamsRequest(BaseModel):
|
||
"""Запрос на обновление параметров формулы расчета score."""
|
||
|
||
score_multiplier: float | None = Field(
|
||
None,
|
||
gt=0,
|
||
description=(
|
||
"Множитель для масштабирования разницы в скорах. "
|
||
"Используется в формуле: score = (diff * score_multiplier + 1) / 2, "
|
||
"где diff = avg_pos - avg_neg (разница средних сходств топ-k примеров). "
|
||
"Чем больше значение, тем сильнее влияние разницы между положительными и отрицательными примерами на итоговый score. "
|
||
"Должен быть > 0. Рекомендуемое значение: 5.0"
|
||
),
|
||
)
|
||
k: int | None = Field(
|
||
None,
|
||
ge=1,
|
||
description=(
|
||
"Количество ближайших примеров для расчета среднего сходства. "
|
||
"Алгоритм берет топ-k самых похожих примеров из каждого типа (положительные/отрицательные) "
|
||
"и вычисляет среднее косинусное сходство. "
|
||
"Меньшее значение k делает алгоритм более чувствительным к различиям, но может быть менее стабильным. "
|
||
"Должно быть >= 1. Рекомендуемое значение: 3"
|
||
),
|
||
)
|
||
|
||
model_config = {"json_schema_extra": {"example": {"score_multiplier": 5.0, "k": 3}}}
|