geo/backend/app/schemas/scoring.py

204 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pydantic import BaseModel, Field
from typing import Optional
class CitationResult(BaseModel):
"""LLM查询品牌引用结果"""
cited: bool = Field(..., description="是否检测到品牌引用")
position: Optional[int] = Field(None, description="引用位置1-based")
citation_text: Optional[str] = Field(None, description="引用文本片段")
sentiment: str = Field(..., description="情感类型: positive/neutral/negative")
confidence: float = Field(..., ge=0.0, le=1.0, description="置信度 0.0-1.0")
class ScoringResult(BaseModel):
"""评分结果"""
mention_rate_score: float = Field(..., ge=0.0, le=100.0, description="提及率得分 0-100")
sov_score: float = Field(..., ge=0.0, le=100.0, description="SOV得分 0-100")
quality_score: float = Field(..., ge=0.0, le=100.0, description="引用质量得分 0-100")
overall_score: float = Field(..., ge=0.0, le=100.0, description="综合评分 0-100")
class Config:
json_schema_extra = {
"example": {
"mention_rate_score": 66.67,
"sov_score": 50.0,
"quality_score": 78.5,
"overall_score": 64.67
}
}
class BrandScoreResponse(BaseModel):
"""品牌评分响应"""
mention_rate_score: float = Field(..., ge=0.0, le=100.0, description="提及率得分 0-100")
sov_score: float = Field(..., ge=0.0, le=100.0, description="SOV得分 0-100")
quality_score: float = Field(..., ge=0.0, le=100.0, description="引用质量得分 0-100")
overall_score: float = Field(..., ge=0.0, le=100.0, description="综合评分 0-100")
# ============================================================
# V2 评分Schema
# ============================================================
class DimensionScoreResponse(BaseModel):
"""单个维度评分响应"""
name: str = Field(..., description="维度名称")
score: float = Field(..., ge=0.0, description="该维度得分")
max_score: float = Field(..., description="该维度满分")
percentage: float = Field(..., ge=0.0, le=100.0, description="得分率百分比")
detail: dict = Field(default_factory=dict, description="评分细节")
class BrandScoreV2Response(BaseModel):
"""品牌可见性评分V2响应"""
overall_score: float = Field(..., ge=0.0, le=100.0, description="综合评分 0-100")
health_level: str = Field(..., description="健康等级: excellent/good/pass/danger")
mention_rate: DimensionScoreResponse = Field(..., description="提及率维度 (25分)")
recommendation_rank: DimensionScoreResponse = Field(..., description="推荐排名维度 (25分)")
sentiment_score: DimensionScoreResponse = Field(..., description="情感倾向维度 (20分)")
citation_quality: DimensionScoreResponse = Field(..., description="引用质量维度 (15分)")
competitive_position: DimensionScoreResponse = Field(..., description="竞品对比维度 (15分)")
# V1兼容字段保留旧字段方便前端平滑迁移
mention_rate_score: float = Field(..., description="[V1兼容] 提及率得分 0-100")
sov_score: float = Field(..., description="[V1兼容] SOV得分 0-100")
quality_score: float = Field(..., description="[V1兼容] 引用质量得分 0-100")
class Config:
json_schema_extra = {
"example": {
"overall_score": 68.5,
"health_level": "good",
"mention_rate": {
"name": "提及率",
"score": 20.0,
"max_score": 25.0,
"percentage": 80.0,
"detail": {"mentioned_count": 8, "total_queries": 10, "rate": 0.8},
},
"recommendation_rank": {
"name": "推荐排名",
"score": 18.5,
"max_score": 25.0,
"percentage": 74.0,
"detail": {"avg_position": 2.5, "valid_count": 8},
},
"sentiment_score": {
"name": "情感倾向",
"score": 15.0,
"max_score": 20.0,
"percentage": 75.0,
"detail": {"positive": 5, "neutral": 3, "negative": 0},
},
"citation_quality": {
"name": "引用质量",
"score": 10.0,
"max_score": 15.0,
"percentage": 66.7,
"detail": {"cited_count": 8, "avg_depth_score": 0.667},
},
"competitive_position": {
"name": "竞品对比",
"score": 5.0,
"max_score": 15.0,
"percentage": 33.3,
"detail": {"brand_mentions": 8, "competitor_count": 3, "ahead_count": 1},
},
"mention_rate_score": 80.0,
"sov_score": 50.0,
"quality_score": 66.7,
}
}
class BrandScoreHistoryItem(BaseModel):
"""评分历史条目"""
date: str = Field(..., description="日期 YYYY-MM-DD")
mention_rate_score: float = Field(..., ge=0.0, le=100.0, description="提及率得分")
sov_score: float = Field(..., ge=0.0, le=100.0, description="SOV得分")
quality_score: float = Field(..., ge=0.0, le=100.0, description="引用质量得分")
overall_score: float = Field(..., ge=0.0, le=100.0, description="综合评分")
total_queries: int = Field(..., description="总查询次数")
cited_count: int = Field(..., description="被引用次数")
class BrandScoreHistoryResponse(BaseModel):
"""品牌评分历史响应"""
history: list[BrandScoreHistoryItem] = Field(default_factory=list)
total: int = Field(..., description="历史记录总数")
class PlatformStats(BaseModel):
"""平台统计"""
queries: int = Field(..., description="查询次数")
citations: int = Field(..., description="引用次数")
rate: float = Field(..., description="引用率")
class TrendItem(BaseModel):
"""趋势数据"""
date: str = Field(..., description="日期")
score: int = Field(..., description="评分/引用数")
class SentimentBreakdown(BaseModel):
"""情感分布"""
positive: int = Field(0, description="正面引用数")
neutral: int = Field(0, description="中性引用数")
negative: int = Field(0, description="负面引用数")
class CitationsStatsResponse(BaseModel):
"""引用统计响应"""
total_queries: int = Field(..., description="总查询次数")
total_citations: int = Field(..., description="总引用次数")
citation_rate: float = Field(..., description="引用率百分比")
platform_breakdown: dict[str, PlatformStats] = Field(
default_factory=dict, description="各平台统计"
)
sentiment_breakdown: SentimentBreakdown = Field(
..., description="情感分布"
)
trend: list[TrendItem] = Field(default_factory=list, description="趋势数据")
class DimensionCompareItem(BaseModel):
"""单维度对比项"""
name: str = Field(..., description="维度名称")
score: float = Field(..., description="得分")
max_score: float = Field(..., description="满分")
percentage: float = Field(..., description="得分率百分比")
trend: str = Field("stable", description="趋势: up/down/stable")
trend_value: float = Field(0.0, description="趋势变化值")
class CompareItem(BaseModel):
"""对比项"""
entity_id: str = Field(..., description="品牌或竞品ID")
entity_name: str = Field(..., description="品牌或竞品名称")
entity_type: str = Field(..., description="类型: brand 或 competitor")
mention_rate_score: float = Field(..., description="提及率得分")
sov_score: float = Field(..., description="SOV得分")
quality_score: float = Field(..., description="引用质量得分")
overall_score: float = Field(..., description="综合评分")
citation_count: int = Field(0, description="引用次数")
# V2 多维度对比
dimensions: list[DimensionCompareItem] = Field(
default_factory=list, description="五维度评分对比"
)
# 趋势
overall_trend: str = Field("stable", description="综合评分趋势: up/down/stable")
overall_trend_value: float = Field(0.0, description="综合评分变化值")
class CompareResponse(BaseModel):
"""竞品对比响应"""
brand_id: str = Field(..., description="品牌ID")
brand_name: str = Field(..., description="品牌名称")
items: list[CompareItem] = Field(default_factory=list, description="对比项列表(含品牌和竞品)")
# 雷达图数据
radar_data: list[dict] = Field(
default_factory=list, description="雷达图数据(各维度各品牌得分)"
)