后端-数据库-v4模型缺少negative_penalty列导致评分写入失败
问题现象
- 日报
docs/day/2026-7-14-day.md显示 "AI 评分文章数: 0",但当天采集了 617 篇网页新闻 + 136 篇公众号文章 = 753 篇新文章 - AI 分析耗时仅 3 秒(正常评分 700+ 篇至少需几分钟),说明评分逻辑几乎未执行
- 查看
log/daily_crawl.log发现:
sqlalchemy.exc.OperationalError: (asyncmy.errors.OperationalError) (1364, "Field 'negative_penalty' doesn't have a default value")
[SQL: INSERT INTO recommendation_scores (news_type, news_id, final_score, score_reason, scored_at) VALUES (...)]
核心问题
- 数据库
recommendation_scores表保留了 v2 规则引擎 时代的negative_penalty列(float NOT NULL无默认值) - v4 LLM 综合评分模型(
modules/ai-recommendation/models.py)简化后未定义该字段 - SQLAlchemy 生成的 INSERT 语句不包含
negative_penalty→ MySQL 拒绝写入 - 异常被
daily_crawl.py的run_ai_recommendation()顶层except捕获,scored = 0
数据库实际列(v2 遗留): | 列名 | 类型 | NULL | 默认 | 状态 | |------|------|------|------|------| | negative_penalty | float | NO | 无 | 缺失(引发错误) | | llm_score | float | YES | NULL | 可省略 | | topic_score | float | YES | NULL | 遗留 | | depth_score | float | YES | NULL | 遗留 | | utility_score | float | YES | NULL | 遗留 | | source_score | float | YES | NULL | 遗留 | | topic_label | varchar(50) | YES | NULL | 遗留 |
解决方法
1. 修复模型定义
在 modules/ai-recommendation/models.py 的 RecommendationScore 类中添加:
negative_penalty: Mapped[float] = mapped_column(Float, default=0.0, server_default="0", comment="负例惩罚值")
2. 部署到服务器
git add modules/ai-recommendation/models.py
git commit -m "fix(ai-recommendation): add negative_penalty field to fix INSERT error"
git push origin main
ssh news "cd /www/news && git pull origin main && systemctl restart news-backend"
3. 重新触发评分
ssh news "curl -s -X POST 'http://localhost:8000/api/ai-recommendation/score-articles' \
-H 'Content-Type: application/json' -d '{\"date\": \"2026-07-14\"}'"
下次防错措施
快速定位
# 查看评分是否异常(score=0 但文章数 > 0)
ssh news "cat /www/news/docs/day/$(date +%Y-%-m-%-d)-day.md | grep -A1 'AI 评分'"
# 查看评分阶段日志
ssh news "grep -A10 '阶段四' /www/news/log/daily_crawl.log | tail -15"
模型变更检查清单
- 修改 Python 模型后,对比 MySQL 表结构 — 不可仅依赖
extend_existing=True - 服务器端执行:
ssh news "mysql -u root -p\$DB_PASS -D news -e 'DESC recommendation_scores'"
- 确认 Python 模型中所有
NOT NULL无默认值的列都有对应的字段定义
巡检脚本
#!/bin/bash
# 检查今天日报中的 AI 评分是否为 0
TODAY=$(date +%Y-%-m-%-d)
FILE="/www/news/docs/day/${TODAY}-day.md"
COUNT=$(grep "AI 评分文章数" "$FILE" | grep -oP '\d+')
ARTICLES=$(($(grep "网页新文章数" "$FILE" | grep -oP '\d+') + $(grep "公众号新文章数" "$FILE" | grep -oP '\d+')))
if [ "$COUNT" -eq 0 ] && [ "$ARTICLES" -gt 0 ]; then
echo "告警: 今天采集了 ${ARTICLES} 篇文章但 AI 评分为 0"
exit 1
fi
echo "正常: AI 评分 ${COUNT} 篇 / ${ARTICLES} 篇"