feat(report): expose headline evidence details
This commit is contained in:
@@ -210,6 +210,10 @@ type HeadlineItem struct {
|
|||||||
Summary string
|
Summary string
|
||||||
Baseline string
|
Baseline string
|
||||||
TrustLabel string
|
TrustLabel string
|
||||||
|
SourceKindLabel string
|
||||||
|
PrimarySource string
|
||||||
|
UpdatedAt string
|
||||||
|
EvidenceDetail string
|
||||||
Tone string
|
Tone string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +223,10 @@ type ModelEvent struct {
|
|||||||
ProviderName string
|
ProviderName string
|
||||||
OperatorName string
|
OperatorName string
|
||||||
TrustLabel string
|
TrustLabel string
|
||||||
|
SourceKindLabel string
|
||||||
|
PrimarySource string
|
||||||
|
UpdatedAt string
|
||||||
|
EvidenceDetail string
|
||||||
Baseline string
|
Baseline string
|
||||||
Summary string
|
Summary string
|
||||||
Currency string
|
Currency string
|
||||||
@@ -805,7 +813,8 @@ func loadNewModelEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
COALESCE(lp.output_price_per_mtok, 0) AS output_price,
|
COALESCE(lp.output_price_per_mtok, 0) AS output_price,
|
||||||
COALESCE(lp.is_free, false) AS is_free,
|
COALESCE(lp.is_free, false) AS is_free,
|
||||||
COALESCE(m.context_length, 0) AS context_length,
|
COALESCE(m.context_length, 0) AS context_length,
|
||||||
COALESCE(mp.country, 'unknown') AS provider_country
|
COALESCE(mp.country, 'unknown') AS provider_country,
|
||||||
|
m.created_at
|
||||||
FROM models m
|
FROM models m
|
||||||
LEFT JOIN model_provider mp ON m.provider_id = mp.id
|
LEFT JOIN model_provider mp ON m.provider_id = mp.id
|
||||||
LEFT JOIN latest_prices lp ON lp.model_id = m.id AND lp.rn = 1
|
LEFT JOIN latest_prices lp ON lp.model_id = m.id AND lp.rn = 1
|
||||||
@@ -832,6 +841,7 @@ func loadNewModelEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
isFree bool
|
isFree bool
|
||||||
contextLength int
|
contextLength int
|
||||||
providerCountry string
|
providerCountry string
|
||||||
|
createdAt time.Time
|
||||||
)
|
)
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&modelName,
|
&modelName,
|
||||||
@@ -844,6 +854,7 @@ func loadNewModelEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
&isFree,
|
&isFree,
|
||||||
&contextLength,
|
&contextLength,
|
||||||
&providerCountry,
|
&providerCountry,
|
||||||
|
&createdAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -874,6 +885,10 @@ func loadNewModelEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
ProviderName: providerName,
|
ProviderName: providerName,
|
||||||
OperatorName: operatorName,
|
OperatorName: operatorName,
|
||||||
TrustLabel: buildTrustLabel(model),
|
TrustLabel: buildTrustLabel(model),
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: buildPrimarySource("region_pricing", operatorName),
|
||||||
|
UpdatedAt: createdAt.Format("2006-01-02 15:04"),
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
Baseline: "首次出现",
|
Baseline: "首次出现",
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
@@ -909,7 +924,8 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
COALESCE(ph.new_input_price, 0),
|
COALESCE(ph.new_input_price, 0),
|
||||||
COALESCE(ph.old_output_price, 0),
|
COALESCE(ph.old_output_price, 0),
|
||||||
COALESCE(ph.new_output_price, 0),
|
COALESCE(ph.new_output_price, 0),
|
||||||
COALESCE(mp.country, 'unknown') AS provider_country
|
COALESCE(mp.country, 'unknown') AS provider_country,
|
||||||
|
ph.changed_at
|
||||||
FROM pricing_history ph
|
FROM pricing_history ph
|
||||||
JOIN models m ON ph.model_id = m.id
|
JOIN models m ON ph.model_id = m.id
|
||||||
LEFT JOIN model_provider mp ON m.provider_id = mp.id
|
LEFT JOIN model_provider mp ON m.provider_id = mp.id
|
||||||
@@ -936,6 +952,7 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
oldOutputPrice float64
|
oldOutputPrice float64
|
||||||
newOutputPrice float64
|
newOutputPrice float64
|
||||||
providerCountry string
|
providerCountry string
|
||||||
|
changedAt time.Time
|
||||||
)
|
)
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&modelName,
|
&modelName,
|
||||||
@@ -948,6 +965,7 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
&oldOutputPrice,
|
&oldOutputPrice,
|
||||||
&newOutputPrice,
|
&newOutputPrice,
|
||||||
&providerCountry,
|
&providerCountry,
|
||||||
|
&changedAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -967,11 +985,9 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eventType := "price_increase"
|
eventType := "price_increase"
|
||||||
label := "价格上调"
|
|
||||||
summary := "价格上调已足以影响默认成本,需要确认备用模型。"
|
summary := "价格上调已足以影响默认成本,需要确认备用模型。"
|
||||||
if changePct < 0 {
|
if changePct < 0 {
|
||||||
eventType = "price_cut"
|
eventType = "price_cut"
|
||||||
label = "价格下调"
|
|
||||||
summary = "价格下降已足以影响默认选型,值得重新评估同类模型。"
|
summary = "价格下降已足以影响默认选型,值得重新评估同类模型。"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -981,6 +997,10 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
ProviderName: providerName,
|
ProviderName: providerName,
|
||||||
OperatorName: operatorName,
|
OperatorName: operatorName,
|
||||||
TrustLabel: buildTrustLabel(model),
|
TrustLabel: buildTrustLabel(model),
|
||||||
|
SourceKindLabel: "价格快照",
|
||||||
|
PrimarySource: "pricing_history",
|
||||||
|
UpdatedAt: changedAt.Format("2006-01-02 15:04"),
|
||||||
|
EvidenceDetail: buildPriceEvidenceDetail(changePct, oldInputPrice, newInputPrice, currency),
|
||||||
Baseline: fmt.Sprintf("较昨日 %+.0f%%", changePct),
|
Baseline: fmt.Sprintf("较昨日 %+.0f%%", changePct),
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
@@ -991,8 +1011,6 @@ func loadPriceChangeEvents(db *sql.DB, date string) ([]ModelEvent, error) {
|
|||||||
PriceChangePct: changePct,
|
PriceChangePct: changePct,
|
||||||
Priority: 70 + minInt(int(abs(changePct)), 25),
|
Priority: 70 + minInt(int(abs(changePct)), 25),
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = label
|
|
||||||
}
|
}
|
||||||
return events, rows.Err()
|
return events, rows.Err()
|
||||||
}
|
}
|
||||||
@@ -1094,6 +1112,10 @@ func enrichModelEvents(r *ReportV3) []ModelEvent {
|
|||||||
ProviderName: model.ProviderName,
|
ProviderName: model.ProviderName,
|
||||||
OperatorName: model.OperatorName,
|
OperatorName: model.OperatorName,
|
||||||
TrustLabel: buildTrustLabel(model),
|
TrustLabel: buildTrustLabel(model),
|
||||||
|
SourceKindLabel: "免费策略快照",
|
||||||
|
PrimarySource: buildPrimarySource("free_snapshot", model.OperatorName),
|
||||||
|
UpdatedAt: formatEventUpdatedAt(r.GeneratedAt, r.Date),
|
||||||
|
EvidenceDetail: buildFreeEvidenceDetail(model),
|
||||||
Baseline: "今日快照",
|
Baseline: "今日快照",
|
||||||
Summary: buildModelEvidence(model),
|
Summary: buildModelEvidence(model),
|
||||||
Currency: model.Currency,
|
Currency: model.Currency,
|
||||||
@@ -1315,6 +1337,10 @@ func headlineItemFromModelEvent(event ModelEvent) HeadlineItem {
|
|||||||
Summary: event.Summary,
|
Summary: event.Summary,
|
||||||
Baseline: event.Baseline,
|
Baseline: event.Baseline,
|
||||||
TrustLabel: event.TrustLabel,
|
TrustLabel: event.TrustLabel,
|
||||||
|
SourceKindLabel: event.SourceKindLabel,
|
||||||
|
PrimarySource: event.PrimarySource,
|
||||||
|
UpdatedAt: event.UpdatedAt,
|
||||||
|
EvidenceDetail: event.EvidenceDetail,
|
||||||
Tone: "neutral",
|
Tone: "neutral",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,6 +1369,58 @@ func headlineItemFromModelEvent(event ModelEvent) HeadlineItem {
|
|||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildPrimarySource(sourceKind, operatorName string) string {
|
||||||
|
switch sourceKind {
|
||||||
|
case "region_pricing":
|
||||||
|
if operatorName == "" {
|
||||||
|
return "region_pricing"
|
||||||
|
}
|
||||||
|
return operatorName + " / region_pricing"
|
||||||
|
case "free_snapshot":
|
||||||
|
if operatorName == "" {
|
||||||
|
return "free snapshot"
|
||||||
|
}
|
||||||
|
return operatorName + " / free snapshot"
|
||||||
|
default:
|
||||||
|
return sourceKind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPriceEvidenceDetail(changePct, oldPrice, newPrice float64, currency string) string {
|
||||||
|
direction := "上涨"
|
||||||
|
if changePct < 0 {
|
||||||
|
direction = "下降"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"pricing_history 记录到输入价格由 %s 调整为 %s,较昨日%s %.0f%%",
|
||||||
|
formatPrice(oldPrice, currency),
|
||||||
|
formatPrice(newPrice, currency),
|
||||||
|
direction,
|
||||||
|
abs(changePct),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildFreeEvidenceDetail(model ModelInfo) string {
|
||||||
|
switch classifyFreeSource(model) {
|
||||||
|
case "官方免费":
|
||||||
|
return fmt.Sprintf("%s 当前快照显示为官方免费入口", model.OperatorName)
|
||||||
|
case "聚合免费":
|
||||||
|
return fmt.Sprintf("%s 当前快照显示为聚合免费入口", model.OperatorName)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%s 当前快照显示免费,但来源仍待确认", model.OperatorName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatEventUpdatedAt(value, fallbackDate string) string {
|
||||||
|
if strings.TrimSpace(value) != "" {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
if fallbackDate != "" {
|
||||||
|
return fallbackDate + " 00:00"
|
||||||
|
}
|
||||||
|
return "-"
|
||||||
|
}
|
||||||
|
|
||||||
func buildActionItems(r *ReportV3) []ActionItem {
|
func buildActionItems(r *ReportV3) []ActionItem {
|
||||||
var actions []ActionItem
|
var actions []ActionItem
|
||||||
|
|
||||||
@@ -1670,7 +1748,19 @@ func generateMarkdownV3(r *ReportV3, path string) error {
|
|||||||
for _, item := range r.HeadlineItems {
|
for _, item := range r.HeadlineItems {
|
||||||
fmt.Fprintf(f, "### %s · %s\n\n", item.Label, item.Title)
|
fmt.Fprintf(f, "### %s · %s\n\n", item.Label, item.Title)
|
||||||
fmt.Fprintf(f, "- 影响: %s\n", item.Summary)
|
fmt.Fprintf(f, "- 影响: %s\n", item.Summary)
|
||||||
|
if item.SourceKindLabel != "" {
|
||||||
|
fmt.Fprintf(f, "- 事件来源: %s\n", item.SourceKindLabel)
|
||||||
|
}
|
||||||
|
if item.PrimarySource != "" {
|
||||||
|
fmt.Fprintf(f, "- 主来源: %s\n", item.PrimarySource)
|
||||||
|
}
|
||||||
|
if item.UpdatedAt != "" {
|
||||||
|
fmt.Fprintf(f, "- 更新时间: %s\n", item.UpdatedAt)
|
||||||
|
}
|
||||||
fmt.Fprintf(f, "- 基线: %s\n", item.Baseline)
|
fmt.Fprintf(f, "- 基线: %s\n", item.Baseline)
|
||||||
|
if item.EvidenceDetail != "" {
|
||||||
|
fmt.Fprintf(f, "- 判定依据: %s\n", item.EvidenceDetail)
|
||||||
|
}
|
||||||
fmt.Fprintf(f, "- 可信度: %s\n\n", item.TrustLabel)
|
fmt.Fprintf(f, "- 可信度: %s\n\n", item.TrustLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1984,11 +2074,26 @@ body {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
.trust-line,
|
.trust-line,
|
||||||
.baseline-line {
|
.baseline-line,
|
||||||
|
.source-line {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: var(--ink-soft);
|
color: var(--ink-soft);
|
||||||
}
|
}
|
||||||
|
.evidence-block {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
border-top: 1px dashed var(--line);
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.evidence-item {
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: var(--ink-soft);
|
||||||
|
}
|
||||||
|
.evidence-item strong {
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
.scene-header {
|
.scene-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -2167,8 +2272,14 @@ th {
|
|||||||
<div class="card-kicker">{{.Label}}</div>
|
<div class="card-kicker">{{.Label}}</div>
|
||||||
<div class="card-title">{{.Title}}</div>
|
<div class="card-title">{{.Title}}</div>
|
||||||
<div class="card-summary">{{.Summary}}</div>
|
<div class="card-summary">{{.Summary}}</div>
|
||||||
|
{{if .SourceKindLabel}}<div class="source-line">事件来源:{{.SourceKindLabel}}</div>{{end}}
|
||||||
<div class="baseline-line">基线:{{.Baseline}}</div>
|
<div class="baseline-line">基线:{{.Baseline}}</div>
|
||||||
<div class="trust-line">可信度:{{.TrustLabel}}</div>
|
<div class="trust-line">可信度:{{.TrustLabel}}</div>
|
||||||
|
<div class="evidence-block">
|
||||||
|
{{if .PrimarySource}}<div class="evidence-item"><strong>主来源</strong>:{{.PrimarySource}}</div>{{end}}
|
||||||
|
{{if .UpdatedAt}}<div class="evidence-item"><strong>更新时间</strong>:{{.UpdatedAt}}</div>{{end}}
|
||||||
|
{{if .EvidenceDetail}}<div class="evidence-item"><strong>判定依据</strong>:{{.EvidenceDetail}}</div>{{end}}
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -191,6 +191,10 @@ func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) {
|
|||||||
TrustLabel: "聚合来源",
|
TrustLabel: "聚合来源",
|
||||||
Baseline: "首次出现",
|
Baseline: "首次出现",
|
||||||
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:30",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
Priority: 95,
|
Priority: 95,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -201,6 +205,10 @@ func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) {
|
|||||||
TrustLabel: "官方来源",
|
TrustLabel: "官方来源",
|
||||||
Baseline: "较昨日 -18%",
|
Baseline: "较昨日 -18%",
|
||||||
Summary: "价格下降已足以影响视觉模型默认选择。",
|
Summary: "价格下降已足以影响视觉模型默认选择。",
|
||||||
|
SourceKindLabel: "价格快照",
|
||||||
|
PrimarySource: "pricing_history",
|
||||||
|
UpdatedAt: "2026-05-13 10:00",
|
||||||
|
EvidenceDetail: "pricing_history 记录到输入价格较昨日下降 18%",
|
||||||
PriceChangePct: -18,
|
PriceChangePct: -18,
|
||||||
Priority: 90,
|
Priority: 90,
|
||||||
},
|
},
|
||||||
@@ -277,6 +285,22 @@ func TestGenerateMarkdownV3IncludesTencentSubscriptionSection(t *testing.T) {
|
|||||||
ModelPreview: "hy3-preview",
|
ModelPreview: "hy3-preview",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
report.ModelEvents = []ModelEvent{
|
||||||
|
{
|
||||||
|
EventType: "new_model",
|
||||||
|
ModelName: "DeepSeek-V4-Flash",
|
||||||
|
ProviderName: "DeepSeek",
|
||||||
|
OperatorName: "OpenRouter",
|
||||||
|
TrustLabel: "聚合来源",
|
||||||
|
Baseline: "首次出现",
|
||||||
|
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:30",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
|
Priority: 95,
|
||||||
|
},
|
||||||
|
}
|
||||||
decorateReportV1(report)
|
decorateReportV1(report)
|
||||||
|
|
||||||
if err := generateMarkdownV3(report, path); err != nil {
|
if err := generateMarkdownV3(report, path); err != nil {
|
||||||
@@ -295,6 +319,9 @@ func TestGenerateMarkdownV3IncludesTencentSubscriptionSection(t *testing.T) {
|
|||||||
"## 今日变化",
|
"## 今日变化",
|
||||||
"## 场景推荐",
|
"## 场景推荐",
|
||||||
"## 完整数据附录",
|
"## 完整数据附录",
|
||||||
|
"主来源: OpenRouter / region_pricing",
|
||||||
|
"更新时间: 2026-05-13 09:30",
|
||||||
|
"判定依据: models.created_at = 今日,且已存在最新价格快照",
|
||||||
"## 💳 腾讯云套餐订阅价",
|
"## 💳 腾讯云套餐订阅价",
|
||||||
"通用 Token Plan Lite",
|
"通用 Token Plan Lite",
|
||||||
"Hy Token Plan Max",
|
"Hy Token Plan Max",
|
||||||
@@ -320,6 +347,10 @@ func TestGenerateHTMLV3IncludesTencentSubscriptionSection(t *testing.T) {
|
|||||||
TrustLabel: "聚合来源",
|
TrustLabel: "聚合来源",
|
||||||
Baseline: "首次出现",
|
Baseline: "首次出现",
|
||||||
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:30",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
Priority: 95,
|
Priority: 95,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -354,6 +385,10 @@ func TestGenerateHTMLV3IncludesTencentSubscriptionSection(t *testing.T) {
|
|||||||
"今日头条",
|
"今日头条",
|
||||||
"DeepSeek-V4-Flash",
|
"DeepSeek-V4-Flash",
|
||||||
"首次出现",
|
"首次出现",
|
||||||
|
"主来源",
|
||||||
|
"更新时间",
|
||||||
|
"判定依据",
|
||||||
|
"模型快照",
|
||||||
"场景推荐",
|
"场景推荐",
|
||||||
"完整数据附录",
|
"完整数据附录",
|
||||||
"官方免费",
|
"官方免费",
|
||||||
@@ -378,6 +413,10 @@ func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) {
|
|||||||
TrustLabel: "官方来源",
|
TrustLabel: "官方来源",
|
||||||
Baseline: "较昨日 -25%",
|
Baseline: "较昨日 -25%",
|
||||||
Summary: "价格下降已足以影响中文通用场景默认选型。",
|
Summary: "价格下降已足以影响中文通用场景默认选型。",
|
||||||
|
SourceKindLabel: "价格快照",
|
||||||
|
PrimarySource: "pricing_history",
|
||||||
|
UpdatedAt: "2026-05-13 10:00",
|
||||||
|
EvidenceDetail: "pricing_history 记录到输入价格较昨日下降 25%",
|
||||||
PriceChangePct: -25,
|
PriceChangePct: -25,
|
||||||
Priority: 100,
|
Priority: 100,
|
||||||
},
|
},
|
||||||
@@ -389,6 +428,10 @@ func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) {
|
|||||||
TrustLabel: "聚合来源",
|
TrustLabel: "聚合来源",
|
||||||
Baseline: "首次出现",
|
Baseline: "首次出现",
|
||||||
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:30",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
Priority: 90,
|
Priority: 90,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -404,6 +447,9 @@ func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) {
|
|||||||
if items[0].Baseline != "较昨日 -25%" {
|
if items[0].Baseline != "较昨日 -25%" {
|
||||||
t.Fatalf("expected event baseline to be preserved, got %+v", items[0])
|
t.Fatalf("expected event baseline to be preserved, got %+v", items[0])
|
||||||
}
|
}
|
||||||
|
if items[0].SourceKindLabel != "价格快照" || items[0].PrimarySource != "pricing_history" {
|
||||||
|
t.Fatalf("expected event evidence fields to be preserved, got %+v", items[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
||||||
@@ -416,6 +462,10 @@ func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
|||||||
TrustLabel: "官方来源",
|
TrustLabel: "官方来源",
|
||||||
Baseline: "较昨日 -20%",
|
Baseline: "较昨日 -20%",
|
||||||
Summary: "价格下降影响默认成本。",
|
Summary: "价格下降影响默认成本。",
|
||||||
|
SourceKindLabel: "价格快照",
|
||||||
|
PrimarySource: "pricing_history",
|
||||||
|
UpdatedAt: "2026-05-13 10:00",
|
||||||
|
EvidenceDetail: "pricing_history 记录到输入价格较昨日下降 20%",
|
||||||
PriceChangePct: -20,
|
PriceChangePct: -20,
|
||||||
Priority: 95,
|
Priority: 95,
|
||||||
},
|
},
|
||||||
@@ -426,6 +476,10 @@ func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
|||||||
TrustLabel: "官方来源",
|
TrustLabel: "官方来源",
|
||||||
Baseline: "较昨日 +5%",
|
Baseline: "较昨日 +5%",
|
||||||
Summary: "同日另有上调记录。",
|
Summary: "同日另有上调记录。",
|
||||||
|
SourceKindLabel: "价格快照",
|
||||||
|
PrimarySource: "pricing_history",
|
||||||
|
UpdatedAt: "2026-05-13 11:00",
|
||||||
|
EvidenceDetail: "pricing_history 记录到输入价格较昨日上涨 5%",
|
||||||
PriceChangePct: 5,
|
PriceChangePct: 5,
|
||||||
Priority: 80,
|
Priority: 80,
|
||||||
},
|
},
|
||||||
@@ -436,6 +490,10 @@ func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
|||||||
TrustLabel: "聚合来源",
|
TrustLabel: "聚合来源",
|
||||||
Baseline: "首次出现",
|
Baseline: "首次出现",
|
||||||
Summary: "新模型上线。",
|
Summary: "新模型上线。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:00",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
Priority: 70,
|
Priority: 70,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -449,3 +507,30 @@ func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
|
|||||||
t.Fatalf("expected duplicate model event to be removed, got %+v", items)
|
t.Fatalf("expected duplicate model event to be removed, got %+v", items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHeadlineItemFromModelEventIncludesEvidenceFields(t *testing.T) {
|
||||||
|
item := headlineItemFromModelEvent(ModelEvent{
|
||||||
|
EventType: "new_model",
|
||||||
|
ModelName: "DeepSeek-V4-Flash",
|
||||||
|
TrustLabel: "聚合来源",
|
||||||
|
Baseline: "首次出现",
|
||||||
|
Summary: "新模型进入情报池。",
|
||||||
|
SourceKindLabel: "模型快照",
|
||||||
|
PrimarySource: "OpenRouter / region_pricing",
|
||||||
|
UpdatedAt: "2026-05-13 09:30",
|
||||||
|
EvidenceDetail: "models.created_at = 今日,且已存在最新价格快照",
|
||||||
|
})
|
||||||
|
|
||||||
|
if item.SourceKindLabel != "模型快照" {
|
||||||
|
t.Fatalf("expected source kind label to be propagated, got %+v", item)
|
||||||
|
}
|
||||||
|
if item.PrimarySource != "OpenRouter / region_pricing" {
|
||||||
|
t.Fatalf("expected primary source to be propagated, got %+v", item)
|
||||||
|
}
|
||||||
|
if item.UpdatedAt != "2026-05-13 09:30" {
|
||||||
|
t.Fatalf("expected updated at to be propagated, got %+v", item)
|
||||||
|
}
|
||||||
|
if item.EvidenceDetail == "" {
|
||||||
|
t.Fatalf("expected evidence detail to be populated, got %+v", item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user