feat(report): improve daily intelligence UX and price tracking
Some checks failed
CI / go-test (push) Has been cancelled
CI / scripts-regression (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / docker-build (push) Has been cancelled

This commit is contained in:
phamnazage-jpg
2026-05-27 17:23:08 +08:00
parent f274621013
commit f5b373caf4
29 changed files with 4257 additions and 801 deletions

View File

@@ -7,8 +7,10 @@
- 基础地址:`http://<host>:<port>`
- 默认端口:`8080`
- 返回格式:成功接口统一返回 `{ "data": ... }`
- 失败格式:当前直接返回纯文本错误信息,不是统一 JSON 错误结构
- 鉴权:当前仓库未内建认证、鉴权与限流;公网暴露前应由网关或反向代理补齐
- 失败格式:失败接口统一返回 `{ "error": { "code": "...", "message": "..." } }`
- 访问控制:`/health` 仅允许本机或私网访问;`/api/*` 对外访问默认要求 `Authorization: Bearer <token>` 或 Basic Auth详见下文
- 限流:`/api/*` 默认按来源 IP 做窗口限流;可通过 `API_RATE_LIMIT_PER_WINDOW``API_RATE_LIMIT_WINDOW_SEC` 调整
## `GET /health`
@@ -24,18 +26,30 @@
### 失败
- `503 database not configured`:未配置 `DATABASE_URL`
- `503 database unavailable`:数据库 Ping 失败
```json
{
"error": {
"code": "database_not_configured",
"message": "database not configured"
}
}
```
- `503 database_not_configured`:未配置 `DATABASE_URL`
- `503 database_unavailable`:数据库 Ping 失败
### 示例
```bash
curl -fsS http://127.0.0.1:8080/health
```
### 访问控制
- 仅允许本机或私网请求;外部地址返回 `403 health_endpoint_internal_only`
## `GET /api/v1/models`
返回模型列表,数据来源于 `models``model_provider``region_pricing` 当前最新价格快照
返回模型列表,数据来源于 `models``model_provider``region_pricing`当同一模型存在多条价格记录时API 按“`global` 区域优先、`official` > `reseller` > `free_tier`、再按 `effective_date`/`id` 倒序”的规则选取主价格
### 返回体
@@ -84,8 +98,10 @@ curl -fsS http://127.0.0.1:8080/health
### 失败
- `503 database not configured`
- `500 query failed`
- `503 database_not_configured`
- `500 query_failed`
- `401 auth_required`
- `429 rate_limited`
## `GET /api/v1/subscription-plans`
@@ -122,8 +138,10 @@ curl -fsS http://127.0.0.1:8080/health
### 失败
- `503 database not configured`
- `500 query failed`
- `503 database_not_configured`
- `500 query_failed`
- `401 auth_required`
- `429 rate_limited`
## `GET /api/v1/reports/latest`
@@ -155,9 +173,12 @@ curl -fsS http://127.0.0.1:8080/health
### 失败
- `503 database not configured`
- `404 latest report not found`
- `500 query failed`
- `503 database_not_configured`
- `404 latest_report_not_found`
- `500 query_failed`
- `401 auth_required`
- `429 rate_limited`
## `GET /api/v1/reports/latest/markdown`
@@ -170,8 +191,10 @@ curl -fsS http://127.0.0.1:8080/health
### 失败
- `404 latest report not found`:数据库中没有符合条件的正式日报
- `404 report artifact not found`:元数据存在,但落盘文件缺失
- `404 latest_report_not_found`:数据库中没有符合条件的正式日报
- `404 report_artifact_not_found`:元数据存在,但落盘文件缺失
- `401 auth_required`
- `429 rate_limited`
## `GET /api/v1/reports/latest/html`
@@ -184,22 +207,24 @@ curl -fsS http://127.0.0.1:8080/health
### 失败
- `404 latest report not found`
- `404 report artifact not found`
- `404 latest_report_not_found`
- `404 report_artifact_not_found`
- `401 auth_required`
- `429 rate_limited`
## 冒烟检查命令
```bash
curl -fsS http://127.0.0.1:8080/health
curl -fsS http://127.0.0.1:8080/api/v1/models | jq '.data | length'
curl -fsS http://127.0.0.1:8080/api/v1/subscription-plans | jq '.data | length'
curl -fsS http://127.0.0.1:8080/api/v1/reports/latest | jq '.data.reportDate'
curl -fsS http://127.0.0.1:8080/api/v1/reports/latest/html > /tmp/latest_report.html
curl -fsS -H "Authorization: Bearer $API_AUTH_TOKEN" http://127.0.0.1:8080/api/v1/models | jq '.data | length'
curl -fsS -H "Authorization: Bearer $API_AUTH_TOKEN" http://127.0.0.1:8080/api/v1/subscription-plans | jq '.data | length'
curl -fsS -H "Authorization: Bearer $API_AUTH_TOKEN" http://127.0.0.1:8080/api/v1/reports/latest | jq '.data.reportDate'
curl -fsS -H "Authorization: Bearer $API_AUTH_TOKEN" http://127.0.0.1:8080/api/v1/reports/latest/html > /tmp/latest_report.html
```
## 生产暴露建议
- Nginx / 网关上补齐访问控制、速率限制和超时配置
- `/health` 仅暴露给负载均衡器监控系统
-公网暴露时至少配置 `API_AUTH_TOKEN``API_BASIC_AUTH_USER` / `API_BASIC_AUTH_PASS`
- `/health` 仅暴露给负载均衡器监控系统或私网来源
- 如果前端与 API 同域部署,优先由 Nginx 转发 `/api/``/health`
-果需要公网访问,建议至少加一层 Basic Auth、OIDC 或内网入口限制
-需更强控制,继续在 Nginx / 网关上补齐 CIDR 白名单、OIDC、WAF 与更细粒度限流

View File

@@ -18,13 +18,18 @@
| 变量名 | 必填 | 使用方 | 默认值 | 说明 |
|--------|------|--------|--------|------|
| `DATABASE_URL` | 是 | API Server、迁移、采集、日报、备份恢复、验收脚本 | 无 | PostgreSQL 连接串,缺失时多数核心脚本会直接失败 |
| `OPENROUTER_API_KEY` | 条件必填 | `fetch_openrouter.go``run_real_pipeline.sh``run_daily.sh` | 无 | 真实采集所需;只查看历史数据或仅跑前端时可不配 |
| `OPENROUTER_API_KEY` | 条件必填 | `fetch_openrouter.go``run_real_pipeline.sh``run_daily.sh``run_intraday_price_watch.sh` | 无 | 真实采集所需;只查看历史数据或仅跑前端时可不配 |
| `PORT` | 否 | `cmd/server/main.go` | `8080` | API Server 监听端口 |
| `API_AUTH_TOKEN` | 条件必填 | `cmd/server/main.go`、API smoke / 外部调用 | 空 | 对外访问 `/api/*` 时推荐使用的 Bearer token外部请求未携带合法 token 或 Basic Auth 时返回 `401` |
| `API_BASIC_AUTH_USER` | 条件必填 | `cmd/server/main.go` | 空 | 对外访问 `/api/*` 的 Basic Auth 用户名;与 `API_BASIC_AUTH_PASS` 配套使用 |
| `API_BASIC_AUTH_PASS` | 条件必填 | `cmd/server/main.go` | 空 | 对外访问 `/api/*` 的 Basic Auth 密码 |
| `API_RATE_LIMIT_PER_WINDOW` | 否 | `cmd/server/main.go` | `60` | `/api/*` 按来源 IP 的窗口限流阈值;设为 `0` 表示关闭内建限流 |
| `API_RATE_LIMIT_WINDOW_SEC` | 否 | `cmd/server/main.go` | `60` | `/api/*` 限流窗口长度(秒) |
| `FEISHU_WEBHOOK` | 否 | `run_daily.sh``feishu_alert.sh` | 空 | 正式日报失败时发送飞书告警 |
| `REPORT_OUTPUT_DIR` | 否 | `generate_daily_report.go` | `reports/daily` | 日报主产物输出目录 |
| `REPORT_DATE` | 否 | `generate_daily_report.go``rebuild_historical_report.sh` | 当天日期 | 指定日报生成日期,格式 `YYYY-MM-DD` |
| `REPORT_DATE` | 否 | `generate_daily_report.go``rebuild_historical_report.sh``run_intraday_price_watch.sh` | 当天日期 | 指定日报或日内价格追踪的日期,格式 `YYYY-MM-DD` |
| `REPORT_RUN_KIND` | 否 | `generate_daily_report.go` | `manual` | 运行语义,如 `scheduled` / `manual` / `historical_rebuild` |
| `REPORT_TRIGGER_SOURCE` | 否 | `generate_daily_report.go` | `cli` | 触发来源,如 `cron` / `pipeline` / `rebuild_script` |
| `REPORT_TRIGGER_SOURCE` | 否 | `generate_daily_report.go``materialize_daily_signals.go` | `cli` | 触发来源,如 `cron` / `pipeline` / `intraday` / `rebuild_script` |
| `REPORT_IS_OFFICIAL_DAILY` | 否 | `generate_daily_report.go` | `false` | 是否属于正式日报产出 |
| `REPORT_RUNTIME_AUDIT` | 否 | `generate_daily_report.go` | 空 | 来源级运行审计摘要,通常由流水线脚本注入 |
| `PHASE6_PORT` | 否 | `verify_phase6.sh` | 自动挑选 `18080-18120` | Phase 6 验收时临时启动 API Server 的端口 |
@@ -33,6 +38,8 @@
| `LIGHTHOUSE_FCP_THRESHOLD_MS` | 否 | `verify_lighthouse.sh` | `2000` | 首次内容绘制门槛 |
| `VERIFY_DB_NAME` | 否 | `verify_common.sh` | `llm_intelligence` | SQL 型验收脚本默认连接的数据库名 |
## 推荐的生产注入方式
### API Server
@@ -40,9 +47,12 @@
```bash
export DATABASE_URL="postgres://app_user:***@db:5432/llm_intelligence?sslmode=disable"
export PORT="8080"
export API_AUTH_TOKEN="replace-with-long-random-token"
# 或者export API_BASIC_AUTH_USER="review" && export API_BASIC_AUTH_PASS="replace-with-password"
./server
```
### 正式日报调度
```bash
@@ -60,6 +70,19 @@ export OPENROUTER_API_KEY="***"
bash scripts/run_real_pipeline.sh
```
### 日内价格追踪
```bash
export DATABASE_URL="postgres://app_user:***@db:5432/llm_intelligence?sslmode=disable"
export OPENROUTER_API_KEY="***"
bash scripts/run_intraday_price_watch.sh
```
说明:
- 该入口只刷新价格 importer 与 `daily_signal_snapshot`
- 不生成正式 HTML / Markdown 日报
- 推荐先按每 4 小时一次调度,再根据外部源稳定性决定是否收紧到每 2 小时
## 日报运行语义
项目用以下字段区分正式日报、手工复跑和历史补跑:
@@ -104,6 +127,11 @@ PORT="8080" \
go run ./cmd/server
```
说明:
- `/health` 仅允许本机或私网来源访问
- `/api/*` 对外访问默认要求 Bearer token 或 Basic Auth
- 本机与私网来源可直接访问,便于同机前端、验收脚本和内网反代联调
### 仅生成指定日期日报
```bash

View File

@@ -43,7 +43,7 @@
### 应用与产物
- `go test ./...` 通过(覆盖 `cmd/server``internal/...`
- `go test ./...` 通过(覆盖 package 形式的 Go 代码,如 `cmd/server``internal/...`;其中 API 错误结构与模型主价格排序规则需由这些 package tests 兜底
- `bash scripts/test_importers.sh` 通过(覆盖 scripts 层 importer targeted go test matrix
- `bash scripts/importer_smoke_gate_test.sh` 通过
- `bash scripts/pipeline_runtime_alignment_test.sh` 通过
@@ -51,12 +51,15 @@
- `cd frontend && npm run test -- --run` 通过
- `cd frontend && npm run build` 通过
- `go build ./cmd/server` 通过
- 已确认发布结论不是仅凭 `go test ./...` 得出,而是同时包含 scripts 与 gate 层验证
### 调度与日报
- 正式调度命令已确定:`bash scripts/run_daily.sh`
- 手工复跑命令已确定:`bash scripts/run_real_pipeline.sh`
- 历史补跑命令已确定:`bash scripts/rebuild_historical_report.sh YYYY-MM-DD`
- 日内价格追踪命令已确定:`bash scripts/run_intraday_price_watch.sh`
- `OPENROUTER_API_KEY` 已在正式调度环境可用
- `FEISHU_WEBHOOK` 已配置或明确不上告警
@@ -136,6 +139,8 @@ bash scripts/run_real_pipeline.sh
```cron
0 8 * * * cd /path/to/llm-intelligence && bash scripts/run_daily.sh >> /tmp/llm_hub_cron.log 2>&1
```
# 日内价格追踪(推荐)
0 */4 * * * cd /path/to/llm-intelligence && bash scripts/run_intraday_price_watch.sh >> /tmp/llm_hub_intraday.log 2>&1
### 7. 线上冒烟

View File

@@ -0,0 +1,60 @@
# 日内价格追踪方案2026-05-27
## 目标
让“日内大降价 / 大涨价 / 泄露 / 活动窗口”不必等到第二天正式日报才出现。
## 当前限制
- 正式链路 `scripts/run_daily.sh` 按天运行一次。
- `daily_signal_snapshot` 也是按日物化。
- 像“小米大模型大降价”这样的日内事件,即使价格页已经变化,也可能错过当天头条和一句话结论。
## 最小可落地方案
新增脚本:`scripts/run_intraday_price_watch.sh`
它复用当前 `run_intel_pipeline.sh` 的“采集 / 导入 / 物化”链路,但刻意不生成正式日报,不写 `daily_report`,也不污染 `latest_report` 语义。
### 执行内容
- `fetch_openrouter.go -strict-real`
- `fetch_multi_source.go --sources moonshot,deepseek,openai`
- 官方导入脚本(套餐 + 价格 importer
- `materialize_daily_signals.go`
### 不执行
- `generate_daily_report.go`
- `track_report_state` / `daily_report`
- 正式 HTML / Markdown 日报归档
## 推荐调度频率
推荐两档:
1. 保守版:每 4 小时一次
- `0 */4 * * * bash scripts/run_intraday_price_watch.sh`
2. 激进版:每 2 小时一次
- `0 */2 * * * bash scripts/run_intraday_price_watch.sh`
先从每 4 小时开始,观察外部文档源稳定性和数据库写入压力。
## 结果用途
- 更快写入 `pricing_history`
- 更快刷新 `daily_signal_snapshot`
- 为前端查询页/日内快讯卡提供更及时的信号
- 第二天正式日报能直接消费更完整的价格变化记录
## 与正式日报的边界
- `run_daily.sh`:正式日级产物,决定 `latest_report`
- `run_intraday_price_watch.sh`:日内信号刷新,不生成正式日报
- `run_real_pipeline.sh`:人工真实复跑,验证全链路
## 下一步建议
1. 把前端查询页增加“最近一次价格追踪时间”提示
2.`materialize_daily_signals.go` 增加 `trigger_source=intraday` 的文档说明
3. 如果日内事件仍不够敏感,再考虑引入独立 `intraday_signal_snapshot`