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="雷达图数据(各维度各品牌得分)" )