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