根据产品规划设计完成技术设计和实施分解:
1. docs/TECH_ARCHITECTURE.md(新,587行)
- 分层架构图(接入层/网关/服务/数据/基础设施)
- 技术栈选型(Python + SQLite + FastAPI)
- 核心模块设计:
* AI审核服务(49元版)
* 反扎堆检测
* 数据溯源
* 订单管理
- 数据架构与目录结构
- 安全设计(脱敏/权限/审计)
- 性能指标
- 11项技术决策记录
2. docs/IMPLEMENTATION_PLAN.md(新,432行)
- 5大开发任务(30天)
- T1: AI审核服务(10天,P0核心)
- T2: 反扎堆检测(5天,P0)
- T3: 数据溯源(5天,P1)
- T4: 订单管理(5天,P1)
- T5: 集成测试(5天,P0)
- 详细周计划(4周)
- 每个Task的DoD
- 风险与应对
3. docs/plans/ 新增3份详细计划:
- T1-1-crowd-db-setup.md (扎堆数据库,3个子任务)
- T1-2-audit-skill-and-parser.md (Skill+解析器)
- T1-4-to-1-10-audit-completion.md (T1.4-1.8完整代码)
4. docs/NAVIGATION.md 更新
- 添加新文档索引
每个实施计划都包含:
- TDD流程(写测试→失败→实现→通过→提交)
- 完整可复制代码
- 精确文件路径
- 验证命令和预期输出
- 提交步骤
技术决策:
- 选用SQLite(本地优先,零配置)
- FastAPI作为Web框架
- 扎堆数据库手动维护(合规考虑)
- 数据溯源JSON文件存储(Git友好)
13 KiB
T1.1 准备扎堆数据库结构 - 详细实施
For Hermes: Use subagent-driven-development skill to implement this plan task-by-task.
Goal: 建立大厂AI推荐数据库的目录结构和初始数据
Architecture: JSON文件存储,按省份组织,手动维护
Tech Stack: Python 3.10+, JSON
Task 1.1.1: 创建数据目录结构
Objective: 创建 crowd_db 目录及相关子目录
Files:
- Create:
data/crowd_db/.gitkeep - Create:
data/crowd_db/README.md
Step 1: 创建目录
cd /home/long/project/gaokao-volunteer-system
mkdir -p data/crowd_db
touch data/crowd_db/.gitkeep
Step 2: 创建README说明文件
Create file: data/crowd_db/README.md
# 大厂AI推荐数据库 (Crowd Detection Database)
## 用途
存储大厂AI(千问/元宝/百度/豆包)的高频推荐院校,
用于反扎堆检测功能。
## 数据格式
按省份组织,每个JSON文件包含该省的推荐数据:
```json
{
"province": "湖南",
"last_updated": "2026-06-15",
"data_year": 2025,
"score_ranges": [
{
"range": [560, 580],
"recommendations": [
{
"name": "长沙理工大学",
"major": "会计学",
"frequency": 4,
"platforms": ["千问", "元宝", "百度", "豆包"],
"predicted_increase": 18,
"alternatives": [
{ "name": "湖南工商大学", "major": "会计学", "score": 95 },
{ "name": "湖北经济学院", "major": "财务管理", "score": 92 }
]
}
]
}
]
}
```
字段说明
| 字段 | 说明 |
|---|---|
range |
分数区间 [min, max] |
frequency |
4个大厂AI中有几个推荐(0-4) |
platforms |
具体推荐了哪些AI |
predicted_increase |
预测2026年分数线上涨分 |
alternatives |
替代院校推荐 |
数据来源
- 手动整理大厂AI公开推荐
- 高考季后期的实际数据
- 不爬虫、不抓取(合规考虑)
更新频率
每周更新一次,高考季(6-7月)每周两次
文件命名
hunan.json- 湖南省zhejiang.json- 浙江省national.json- 全国通用
**Step 3: 验证**
```bash
ls -la data/crowd_db/
cat data/crowd_db/README.md | head -5
Expected:
- 看到 .gitkeep 和 README.md 文件
- README.md 内容正确
Step 4: 提交
cd /home/long/project/gaokao-volunteer-system
git add data/crowd_db/
git commit -m "feat: 创建大厂AI推荐数据库目录结构"
Task 1.1.2: 创建湖南省初始数据
Objective: 创建 hunan.json 初始数据
Files:
- Create:
data/crowd_db/hunan.json
Step 1: 创建初始JSON
Create file: data/crowd_db/hunan.json
{
"province": "湖南",
"last_updated": "2026-06-15",
"data_year": 2025,
"score_ranges": [
{
"range": [560, 580],
"recommendations": [
{
"name": "长沙理工大学",
"major": "会计学",
"frequency": 4,
"platforms": ["千问", "元宝", "百度", "豆包"],
"predicted_increase": 18,
"alternatives": [
{ "name": "湖南工商大学", "major": "会计学", "score": 95 },
{ "name": "湖北经济学院", "major": "财务管理", "score": 92 }
]
},
{
"name": "江西财经大学",
"major": "会计学",
"frequency": 3,
"platforms": ["千问", "元宝", "百度"],
"predicted_increase": 12,
"alternatives": [
{ "name": "湖南工商大学", "major": "会计学", "score": 95 },
{ "name": "重庆工商大学", "major": "会计学", "score": 90 }
]
}
]
},
{
"range": [580, 600],
"recommendations": [
{
"name": "湖南师范大学",
"major": "会计学",
"frequency": 4,
"platforms": ["千问", "元宝", "百度", "豆包"],
"predicted_increase": 15,
"alternatives": [
{ "name": "湘潭大学", "major": "会计学", "score": 96 },
{ "name": "长沙理工大学", "major": "会计学", "score": 93 }
]
}
]
}
]
}
Step 2: 验证JSON格式
python3 -c "import json; data = json.load(open('data/crowd_db/hunan.json')); print(f'省份: {data[\"province\"]}, 分数段数: {len(data[\"score_ranges\"])}')"
Expected:
省份: 湖南, 分数段数: 2
Step 3: 提交
git add data/crowd_db/hunan.json
git commit -m "feat: 添加湖南省大厂AI推荐数据初始版本"
Task 1.1.3: 实现数据加载器
Objective: 实现 crowd_db JSON 数据加载和查询
Files:
- Create:
data/crowd_db/loader.py - Test:
data/crowd_db/tests/test_loader.py
Step 1: 写测试
Create file: data/crowd_db/tests/test_loader.py
"""数据加载器测试"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
from data.crowd_db.loader import CrowdDBLoader, CrowdRecommendation
def test_load_hunan_data():
"""测试加载湖南数据"""
loader = CrowdDBLoader()
data = loader.load_province("湖南")
assert data is not None
assert data["province"] == "湖南"
assert len(data["score_ranges"]) > 0
def test_find_recommendations_in_range():
"""测试查询分数段内的推荐"""
loader = CrowdDBLoader()
recs = loader.find_recommendations("湖南", score=575)
assert isinstance(recs, list)
# 578分应该在 560-580 范围内
if recs:
assert all(r["frequency"] > 0 for r in recs)
def test_find_recommendations_by_school():
"""测试按院校名查询推荐"""
loader = CrowdDBLoader()
rec = loader.find_recommendation_by_school("湖南", "长沙理工大学")
assert rec is not None
assert rec["name"] == "长沙理工大学"
def test_load_nonexistent_province():
"""测试加载不存在的省份"""
loader = CrowdDBLoader()
data = loader.load_province("不存在的省")
assert data is None
def test_crowd_recommendation_dataclass():
"""测试数据类"""
rec = CrowdRecommendation(
name="测试大学",
major="测试专业",
frequency=4,
platforms=["千问", "元宝", "百度", "豆包"],
predicted_increase=15,
alternatives=[]
)
assert rec.frequency == 4
assert rec.risk_level == "high" # frequency=4 应该是高风险
Step 2: 运行测试确认失败
cd /home/long/project/gaokao-volunteer-system
python3 -m pytest data/crowd_db/tests/test_loader.py -v
Expected: FAIL — module not found
Step 3: 创建init**.py**
mkdir -p data/crowd_db/tests
touch data/crowd_db/__init__.py
touch data/crowd_db/tests/__init__.py
Step 4: 实现loader
Create file: data/crowd_db/loader.py
"""
大厂AI推荐数据库加载器
用于反扎堆检测功能,加载和查询大厂AI的高频推荐院校。
"""
import json
import os
from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any
@dataclass
class CrowdRecommendation:
"""扎堆推荐数据"""
name: str # 院校名称
major: str # 专业
frequency: int # 推荐频次(0-4)
platforms: List[str] # 推荐平台列表
predicted_increase: int # 预测分数上涨
alternatives: List[Dict[str, Any]] = field(default_factory=list)
@property
def risk_level(self) -> str:
"""根据频次计算风险等级"""
if self.frequency >= 4:
return "high"
elif self.frequency >= 2:
return "medium"
else:
return "low"
class CrowdDBLoader:
"""
大厂AI推荐数据库加载器
数据存储在 data/crowd_db/{province}.json 文件中
"""
# 数据目录路径(相对项目根目录)
DATA_DIR = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
"data", "crowd_db"
)
def __init__(self, data_dir: Optional[str] = None):
"""初始化加载器
Args:
data_dir: 数据目录路径,默认使用 DATA_DIR
"""
self.data_dir = data_dir or self.DATA_DIR
self._cache: Dict[str, dict] = {}
def load_province(self, province: str) -> Optional[dict]:
"""加载指定省份的推荐数据
Args:
province: 省份名称(如"湖南")
Returns:
省份数据字典,未找到返回 None
"""
if province in self._cache:
return self._cache[province]
file_path = os.path.join(self.data_dir, f"{province}.json")
if not os.path.exists(file_path):
return None
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
self._cache[province] = data
return data
except (json.JSONDecodeError, IOError):
return None
def find_recommendations(self, province: str, score: int) -> List[Dict[str, Any]]:
"""查询指定分数段内的所有推荐
Args:
province: 省份名称
score: 用户分数
Returns:
推荐列表
"""
data = self.load_province(province)
if not data:
return []
results = []
for score_range in data.get("score_ranges", []):
min_score, max_score = score_range["range"]
if min_score <= score <= max_score:
results.extend(score_range.get("recommendations", []))
return results
def find_recommendation_by_school(
self,
province: str,
school_name: str
) -> Optional[Dict[str, Any]]:
"""按院校名查询推荐信息
Args:
province: 省份名称
school_name: 院校名称(支持模糊匹配)
Returns:
推荐信息,未找到返回 None
"""
data = self.load_province(province)
if not data:
return None
for score_range in data.get("score_ranges", []):
for rec in score_range.get("recommendations", []):
if school_name in rec["name"] or rec["name"] in school_name:
return rec
return None
# 命令行测试
if __name__ == "__main__":
loader = CrowdDBLoader()
# 测试加载湖南数据
data = loader.load_province("湖南")
if data:
print(f"✅ 加载湖南数据: {len(data.get('score_ranges', []))} 个分数段")
else:
print("❌ 加载湖南数据失败")
# 测试分数查询
recs = loader.find_recommendations("湖南", score=575)
print(f"📊 575分在湖南的扎堆院校: {len(recs)} 个")
for rec in recs:
print(f" - {rec['name']} {rec['major']} (频次:{rec['frequency']}, +{rec['predicted_increase']}分)")
Step 5: 再次运行测试
cd /home/long/project/gaokao-volunteer-system
python3 -m pytest data/crowd_db/tests/test_loader.py -v
Expected: PASS — 5 tests pass
Step 6: 提交
git add data/crowd_db/
git commit -m "feat(crowd_db): 实现数据加载器 - T1.1.3"
Task 1.1.4: 端到端验证
Objective: 完整运行验证流程
Step 1: 运行所有测试
cd /home/long/project/gaokao-volunteer-system
python3 -m pytest data/crowd_db/tests/ -v
Expected: All tests pass
Step 2: 运行loader CLI验证
cd /home/long/project/gaokao-volunteer-system
python3 -m data.crowd_db.loader
Expected:
✅ 加载湖南数据: 2 个分数段
📊 575分在湖南的扎堆院校: 2 个
- 长沙理工大学 会计学 (频次:4, +18分)
- 江西财经大学 会计学 (频次:3, +12分)
Step 3: 推送到三个仓库
cd /home/long/project/gaokao-volunteer-system
git push gitea main
git push origin main
git push tksea main
总结
完成清单
- Task 1.1.1: 创建数据目录结构
- Task 1.1.2: 创建湖南省初始数据
- Task 1.1.3: 实现数据加载器
- Task 1.1.4: 端到端验证
产出
| 文件 | 说明 |
|---|---|
data/crowd_db/.gitkeep |
目录占位 |
data/crowd_db/README.md |
数据说明 |
data/crowd_db/hunan.json |
湖南初始数据 |
data/crowd_db/loader.py |
数据加载器 |
data/crowd_db/tests/test_loader.py |
测试 |
验证
- 5个测试全部通过
- CLI运行正常
- 3个仓库同步
下一步: T1.2 创建审核服务Skill