Files
llm-intelligence/scripts/generate_daily_report_test.go

452 lines
12 KiB
Go
Raw Normal View History

//go:build llm_script
package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
func sampleReportForV1() *ReportV3 {
return &ReportV3{
Date: "2026-05-13",
GeneratedAt: "2026-05-13T09:30:00+08:00",
TotalModels: 504,
AllModels: []ModelInfo{
{
Name: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
ProviderCountry:"CN",
ContextLength: 262144,
InputPrice: 0.30,
OutputPrice: 1.20,
Currency: "USD",
OperatorName: "OpenRouter",
OperatorType: "reseller",
Region: "global",
SceneTags: []SceneTag{SceneCode, SceneReasoning},
},
{
Name: "glm-5",
ProviderName: "Zhipu",
ProviderCountry:"CN",
ContextLength: 131072,
InputPrice: 0,
OutputPrice: 0,
Currency: "CNY",
IsFree: true,
OperatorName: "Zhipu",
OperatorType: "official",
Region: "cn",
SceneTags: []SceneTag{SceneWriting, SceneChat},
},
{
Name: "claude-3.7-sonnet",
ProviderName: "Anthropic",
ProviderCountry:"US",
ContextLength: 200000,
InputPrice: 3.0,
OutputPrice: 15.0,
Currency: "USD",
OperatorName: "Anthropic",
OperatorType: "official",
Region: "global",
SceneTags: []SceneTag{SceneWriting, SceneChat},
},
{
Name: "qwen-vl-max",
ProviderName: "Alibaba",
ProviderCountry:"CN",
ContextLength: 65536,
InputPrice: 0.8,
OutputPrice: 2.4,
Currency: "CNY",
OperatorName: "DashScope",
OperatorType: "cloud",
Region: "cn",
SceneTags: []SceneTag{SceneVision},
},
},
FreeModels: []ModelInfo{
{
Name: "glm-5",
ProviderName: "Zhipu",
ProviderCountry:"CN",
ContextLength: 131072,
Currency: "CNY",
IsFree: true,
OperatorName: "Zhipu",
OperatorType: "official",
Region: "cn",
SceneTags: []SceneTag{SceneWriting, SceneChat},
},
{
Name: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
ProviderCountry:"CN",
ContextLength: 262144,
Currency: "USD",
IsFree: true,
OperatorName: "OpenRouter",
OperatorType: "reseller",
Region: "global",
SceneTags: []SceneTag{SceneCode, SceneReasoning},
},
{
Name: "mystery-free-model",
ProviderName: "Unknown",
ProviderCountry:"unknown",
ContextLength: 65536,
Currency: "USD",
IsFree: true,
OperatorName: "Unknown Gateway",
OperatorType: "self_hosted_gateway",
Region: "global",
SceneTags: []SceneTag{SceneChat},
},
},
FreeTop20: []ModelInfo{
{
Name: "glm-5",
ProviderName: "Zhipu",
ProviderCountry:"CN",
ContextLength: 131072,
Currency: "CNY",
IsFree: true,
OperatorName: "Zhipu",
OperatorType: "official",
Region: "cn",
},
},
IntlTop5: []ModelInfo{
{
Name: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
ProviderCountry:"CN",
ContextLength: 262144,
InputPrice: 0.30,
OutputPrice: 1.20,
Currency: "USD",
OperatorName: "OpenRouter",
OperatorType: "reseller",
Region: "global",
SceneTags: []SceneTag{SceneCode, SceneReasoning},
},
},
DomesticTop10: []ModelInfo{
{
Name: "qwen-vl-max",
ProviderName: "Alibaba",
ProviderCountry:"CN",
ContextLength: 65536,
InputPrice: 0.8,
OutputPrice: 2.4,
Currency: "CNY",
OperatorName: "DashScope",
OperatorType: "cloud",
Region: "cn",
SceneTags: []SceneTag{SceneVision},
},
},
DailySignals: DailySignals{
NewModels: 2,
PriceChanges: 1,
OfficialFree: 1,
AggregatorFree:1,
UnknownFree: 1,
},
}
}
func TestBuildFreeSourceBreakdown(t *testing.T) {
report := sampleReportForV1()
breakdown := buildFreeSourceBreakdown(report.FreeModels)
if len(breakdown) != 3 {
t.Fatalf("expected 3 free source groups, got %d", len(breakdown))
}
if breakdown[0].Label != "官方免费" || breakdown[0].Count != 1 {
t.Fatalf("unexpected official free breakdown: %+v", breakdown[0])
}
if breakdown[1].Label != "聚合免费" || breakdown[1].Count != 1 {
t.Fatalf("unexpected aggregator free breakdown: %+v", breakdown[1])
}
if breakdown[2].Label != "待确认" || breakdown[2].Count != 1 {
t.Fatalf("unexpected unknown free breakdown: %+v", breakdown[2])
}
}
func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) {
report := sampleReportForV1()
report.ModelEvents = []ModelEvent{
{
EventType: "new_model",
ModelName: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
OperatorName: "OpenRouter",
TrustLabel: "聚合来源",
Baseline: "首次出现",
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
Priority: 95,
},
{
EventType: "price_cut",
ModelName: "qwen-vl-max",
ProviderName: "Alibaba",
OperatorName: "DashScope",
TrustLabel: "官方来源",
Baseline: "较昨日 -18%",
Summary: "价格下降已足以影响视觉模型默认选择。",
PriceChangePct: -18,
Priority: 90,
},
}
decorateReportV1(report)
if report.PageMode != "hot" {
t.Fatalf("expected hot page mode, got %q", report.PageMode)
}
if !strings.Contains(report.HeroSummary, "2 个新模型") {
t.Fatalf("hero summary missing new model signal: %s", report.HeroSummary)
}
if len(report.ActionItems) != 3 {
t.Fatalf("expected 3 action items, got %d", len(report.ActionItems))
}
if len(report.HeadlineItems) == 0 {
t.Fatalf("expected headline items to be built")
}
if report.ActionItems[0].Evidence == "" {
t.Fatalf("expected action item evidence to be populated")
}
if !strings.Contains(report.HeadlineItems[0].Title, "DeepSeek-V4-Flash") {
t.Fatalf("expected first headline to come from model events, got %+v", report.HeadlineItems[0])
}
}
func TestDecorateReportV1BuildsCalmDaySummary(t *testing.T) {
report := sampleReportForV1()
report.DailySignals = DailySignals{}
decorateReportV1(report)
if report.PageMode != "calm" {
t.Fatalf("expected calm page mode, got %q", report.PageMode)
}
if !strings.Contains(report.HeroSummary, "稳定") {
t.Fatalf("expected calm day summary to emphasize stability, got %s", report.HeroSummary)
}
}
func TestGenerateMarkdownV3IncludesTencentSubscriptionSection(t *testing.T) {
path := filepath.Join(t.TempDir(), "daily_report.md")
report := sampleReportForV1()
report.QualitySummary = DataQualitySummary{
Total: 502,
Fresh: 490,
CNY: 126,
USD: 376,
}
report.TencentSubscriptionPlans = []SubscriptionPlanInfo{
{
PlanName: "通用 Token Plan Lite",
PlanFamily: "token_plan",
Tier: "Lite",
Currency: "CNY",
ListPrice: 39,
QuotaValue: 35000000,
QuotaUnit: "tokens/month",
ContextWindow: 0,
ModelCount: 10,
ModelPreview: "tc-code-latest, glm-5, glm-5.1",
},
{
PlanName: "Hy Token Plan Max",
PlanFamily: "token_plan",
Tier: "Max",
Currency: "CNY",
ListPrice: 468,
QuotaValue: 650000000,
QuotaUnit: "tokens/month",
ContextWindow: 262144,
ModelCount: 1,
ModelPreview: "hy3-preview",
},
}
decorateReportV1(report)
if err := generateMarkdownV3(report, path); err != nil {
t.Fatalf("generateMarkdownV3 returned error: %v", err)
}
body, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read markdown output: %v", err)
}
content := string(body)
for _, want := range []string{
"## 今日结论",
"## 今日行动建议",
"## 今日变化",
"## 场景推荐",
"## 完整数据附录",
"## 💳 腾讯云套餐订阅价",
"通用 Token Plan Lite",
"Hy Token Plan Max",
"¥39.00/月",
"3500万 Tokens/月",
"256K",
} {
if !strings.Contains(content, want) {
t.Fatalf("markdown missing %q\n%s", want, content)
}
}
}
func TestGenerateHTMLV3IncludesTencentSubscriptionSection(t *testing.T) {
path := filepath.Join(t.TempDir(), "daily_report.html")
report := sampleReportForV1()
report.ModelEvents = []ModelEvent{
{
EventType: "new_model",
ModelName: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
OperatorName: "OpenRouter",
TrustLabel: "聚合来源",
Baseline: "首次出现",
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
Priority: 95,
},
}
report.TencentSubscriptionPlans = []SubscriptionPlanInfo{
{
PlanName: "通用 Token Plan Lite",
PlanFamily: "token_plan",
Tier: "Lite",
Currency: "CNY",
ListPrice: 39,
QuotaValue: 35000000,
QuotaUnit: "tokens/month",
ModelCount: 10,
ModelPreview: "tc-code-latest, glm-5, glm-5.1",
},
}
decorateReportV1(report)
if err := generateHTMLV3(report, path); err != nil {
t.Fatalf("generateHTMLV3 returned error: %v", err)
}
body, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read html output: %v", err)
}
content := string(body)
for _, want := range []string{
"今日一句话结论",
"三条行动建议",
"今日头条",
"DeepSeek-V4-Flash",
"首次出现",
"场景推荐",
"完整数据附录",
"官方免费",
"聚合免费",
"待确认",
"💳 腾讯云套餐订阅价",
} {
if !strings.Contains(content, want) {
t.Fatalf("html missing %q\n%s", want, content)
}
}
}
func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) {
report := sampleReportForV1()
report.ModelEvents = []ModelEvent{
{
EventType: "price_cut",
ModelName: "glm-5",
ProviderName: "Zhipu",
OperatorName: "Zhipu",
TrustLabel: "官方来源",
Baseline: "较昨日 -25%",
Summary: "价格下降已足以影响中文通用场景默认选型。",
PriceChangePct: -25,
Priority: 100,
},
{
EventType: "new_model",
ModelName: "DeepSeek-V4-Flash",
ProviderName: "DeepSeek",
OperatorName: "OpenRouter",
TrustLabel: "聚合来源",
Baseline: "首次出现",
Summary: "新模型进入情报池,值得重新评估低成本编码默认选择。",
Priority: 90,
},
}
items := buildHeadlineItems(report)
if len(items) < 2 {
t.Fatalf("expected at least 2 headline items, got %d", len(items))
}
if !strings.Contains(items[0].Title, "glm-5") {
t.Fatalf("expected price_cut event to rank first, got %+v", items[0])
}
if items[0].Baseline != "较昨日 -25%" {
t.Fatalf("expected event baseline to be preserved, got %+v", items[0])
}
}
func TestBuildHeadlineItemsDeduplicatesSameModel(t *testing.T) {
report := sampleReportForV1()
report.ModelEvents = []ModelEvent{
{
EventType: "price_cut",
ModelName: "OpenAI: GPT-4o",
ProviderName: "OpenAI",
TrustLabel: "官方来源",
Baseline: "较昨日 -20%",
Summary: "价格下降影响默认成本。",
PriceChangePct: -20,
Priority: 95,
},
{
EventType: "price_increase",
ModelName: "OpenAI: GPT-4o",
ProviderName: "OpenAI",
TrustLabel: "官方来源",
Baseline: "较昨日 +5%",
Summary: "同日另有上调记录。",
PriceChangePct: 5,
Priority: 80,
},
{
EventType: "new_model",
ModelName: "Claude Opus 4.7",
ProviderName: "Anthropic",
TrustLabel: "聚合来源",
Baseline: "首次出现",
Summary: "新模型上线。",
Priority: 70,
},
}
items := buildHeadlineItems(report)
if len(items) != 2 {
t.Fatalf("expected 2 deduplicated headline items, got %d", len(items))
}
if strings.Contains(items[1].Title, "GPT-4o") {
t.Fatalf("expected duplicate model event to be removed, got %+v", items)
}
}