9.9 KiB
9.9 KiB
清理计划
第一步:删掉我加的所有垃圾
前置条件:确认
gen_test_data.py的原始版本在 git 历史中可恢复 (git log --oneline -- scripts/gen_test_data.py),如无 git 历史则先手动备份。
删除文件(全部显式列出,避免 glob 误伤)
# ── 我加的垃圾脚本 ──
scripts/wnl_to_user_csv.py # WNL转换器
scripts/eval_clustering.py # 聚类评估
scripts/debug_db2.py # 调试文件
scripts/debug_db3.py # 调试文件
scripts/debug_persistence.py # 调试文件(原计划遗漏)
scripts/test_orch.py # 编排测试
scripts/test_orch2.py # 编排测试
scripts/test_pca.py # PCA测试
scripts/test_profile.py # 画像测试
scripts/test_tool_loop.py # 工具测试
scripts/test_tool_format.py # 工具测试
scripts/test_e2e_full.py # 端到端测试
scripts/test_32b.py # 32B模型测试
scripts/test_chinese_path.py # 中文路径测试
scripts/verify_runtime.py # 运行时验证
# ── 我加的垃圾数据 ──
data/wnl_converted.csv # WNL转换数据
保留原始文件
scripts/gen_test_data.py # ★ 保留 — 需从 git 恢复原始版本
# git checkout HEAD~1 -- scripts/gen_test_data.py
# 如无 git 历史则手动重建
scripts/gen_complex_test.py # 原始
scripts/column_survey.py # 原始
scripts/diagnose_compare.py # 原始
scripts/debug_db.py # 原始(非debug_db2/3)
scripts/test_llm_full.py # 原始LLM测试
data/complex_test.csv # 原始测试设备
data/e2e_full.csv # 原始
data/e2e_test.csv # 原始
data/geoip_city.csv # 原始
data/globe_test.csv # 原始
data/test_flows.csv # 原始(需用原gen_test_data.py重新生成)
data/复杂测试.csv # 原始
第二步:恢复被搞坏的文件到可用状态
settings.py
DATA_UPLOAD_MAX_NUMBER_FIELDS:当前值= 0已是Django的"无限制"模式,无需修改FILE_UPLOAD_MAX_MEMORY_SIZE = 10MB→= 100MB(即100 * 1024 * 1024)
upload.html
handleFiles()中每个文件旁加 ✕ 删除按钮- 添加
removeFile(index)JS 函数
auto.html
- ⚠️ 当前
auto.html中没有<form>元素——LLM 分析通过 JS 直接fetch('/analyze/llm/', ...)触发(第56行) - 无需修改表单 action;确认 JS 中 fetch URL 正确即可
views.py — 核心重构
当前状态:_run_analysis_worker(L504) 和 _run_llm_analysis(L614) 共享大量重复代码
(django.setup / ORM get / try-except / 进度报告 / 日志)。
目标:提取共享样板代码到统一的 _run_pipeline_worker,将两个分析逻辑作为回调注入。
新设计:
def _run_pipeline_worker(run_id, analysis_fn, **ctx):
"""统一后台工作者:负责 setup / ORM / 进度 / 错误处理"""
import django, os
os.environ['DJANGO_SETTINGS_MODULE'] = 'tianxuan.settings'
os.environ['DJANGO_ALLOW_ASYNC_UNSAFE'] = 'true'
django.setup()
from analysis.models import AnalysisRun
from analysis import logger
run = AnalysisRun.objects.get(id=run_id)
try:
analysis_fn(run, ctx)
except Exception:
import traceback
tb = traceback.format_exc()
logger.error(tb)
run.status = 'failed'
run.error_message = tb
run.run_log += f'\n[FATAL] {tb}'
run.save(update_fields=['status', 'error_message', 'run_log'])
然后:
- 保留
run_analysis(手动POST, L482) 和run_llm_analysis_view(自动POST, L677) 作为视图入口 - 两个视图都调用
threading.Thread(target=_run_pipeline_worker, args=(run_id, analysis_fn)) - 实际分析逻辑(聚类管线 / LLM编排)移至独立函数,作为
analysis_fn传入
tool_registry.py
_handle_extract_features(L1091,async def) 中AR.objects.filter(csv_glob=...).order_by('-id').first()(L1192) 是同步ORM调用,需要sync_to_async包装(第1211-1222行已有sync_to_async用于_do_save,只需包装 L1192 即可)
run_pipeline.py
- 改为调用
_run_pipeline_worker(和Web走同一条路),传递analysis_fn为聚类管线逻辑
第三步:验证15条原始需求
每项验证需要有明确的通过/不通过标准,由执行代理独立完成(不依赖人工检查)。 验证顺序:先命令行(5/6/14/15)→ 再浏览器自动化(其余项)。
| # | 需求 | 验证方式 | 通过标准 |
|---|---|---|---|
| 1 | 重启后旧数据可分析 | run.bat 启动 → 上传data/e2e_test.csv → 控制台重启 → 访问 /runs/ 看旧记录可选 |
curl http://127.0.0.1:8000/runs/ 返回状态码200且含旧run的id |
| 2 | web图标所有页面 | 访问首页 / → 检查 <link rel="icon"> 存在 |
favicon.ico 或 favicon.svg 在 <head> 中存在 |
| 3 | 上传按钮在顶部 | 访问 /upload/ → snap元素定位 |
上传按钮/区域在文件列表上方(DOM顺序在文件列表之前) |
| 4 | traceback完整 | 手动触发错误(如改坏config.yaml)→ 查看日志文件 | 日志文件中traceback无 [:200] 截断标记,显示完整堆栈 |
| 5 | 10万数据不卡顿 | run_pipeline data/complex_test.csv 完整运行 |
总运行时间 < 120秒,无 MemoryError |
| 6 | 进度条 | 上传后检查 AnalysisRun.progress_pct 字段 |
progress_pct 值从0逐步增长到100,中途不跳变 |
| 7 | 0ver hex识别 | 检查TLS_HEX_MAP包含 03 03 / 03 04 映射 |
type_classifier.py 中 TLS_HEX_MAP 包含这两个键 |
| 8 | globe响应式缩放 | 改变浏览器窗口宽度(1920→800)→ 检查canvas尺寸 | 3D canvas的width/height随窗口变化,不出现滚动条 |
| 9 | globe ?data= | 访问 /globe/?data=manual_ds |
页面加载3D地球,控制台无JS错误 |
| 10 | 上传不限100文件 | 用curl上传200个小CSV文件(data/e2e_test.csv x200) |
返回HTTP 200,非413 Payload Too Large |
| 11 | 选择文件列表有删除 | 检查 upload.html 中 handleFiles() 渲染逻辑 |
每文件条目有 ✕ 按钮和对应的 removeFile(index) 函数定义 |
| 12 | LLM过程打印 | 配置LLM → 触发自动分析 → 检查 run_log 字段 |
run_log 包含步骤日志 [1], [2], ... [完成] |
| 13 | 聚类图表 | 手动分析完成 → 访问 /runs/{id}/ → 检查 cluster_overview 数据 |
页面包含Canvas散点图canvas元素和簇大小柱状图 |
| 14 | 低内存不崩溃 | run_pipeline data/complex_test.csv 处理20000行 |
进程退出码0,峰值内存 < 2GB |
| 15 | +号字符串不被识别为数字 | 创建含+号的CSV(如 +123 列值)→ 上传 → 检查实体检测 |
实体检测不将 +123 识别为FLOAT类型(应为STRING) |
执行顺序与依赖关系
Step 1 (删垃圾) ──→ Step 2 (修文件) ──→ Step 3 (验证) ──→ Step 4 (最终清理)
│ │ │
│ ▼ │
└──── 4c (恢复gen_test_data) ◄────────────────┘
│
▼
4d (跑测试) ──→ 4e (提交)
- Step 1 和 Step 2 必须在 Step 3 之前完成
- 4c(恢复
gen_test_data.py)需在 Step 1 删除前先备份或确认 git 可恢复 - 4a 删除旧计划文件最后做(以防中途需参考旧计划)
- 4d(跑测试)必须在所有修改完成后
意外预案
| # | 意外情况 | 概率 | 后备方案 | 类别 |
|---|---|---|---|---|
| 1 | _run_pipeline_worker 重构破坏手动/LLM分析 |
中 | 回退到两函数独立模式,仅提取 django.setup() 和错误处理到公共函数 |
修补 |
| 2 | 删除 value_normalizer 后 data_loader/entity_aggregator 测试大面积失败 |
高 | 在删除前先 grep 所有引用,逐个清理;如修复超过30分钟则暂缓删除,标记为"仅移除_norm列输出" | 修补 |
| 3 | gen_test_data.py 无 git 历史可回退 |
低 | 从 gen_complex_test.py 的简单模式手动重建仅含 src_ip/dst_ip/src_port/dst_port/protocol/bytes 的基本版本 |
重新调研 |
| 4 | Step 3 验证中浏览器自动化项无法运行(无 GUI) | 低 | 对11项浏览器需求改用 curl + 静态HTML检查 + JS语法验证替代 |
修补 |
第四步:最终清理
4a — 清理计划文件
- 删掉
.omo/plans/里的旧计划文件:tianxiu-v4.mdtianxiu-v5.mdtianxiu-v6.mdglobe-v6.md
- 保留
cleanup.md(自身)和.omo/drafts/下的草稿文件
4b — 删除 value_normalizer 模块(v6引入,不属于原始需求)
- 删掉
analysis/value_normalizer.py - 删掉
tests/test_value_normalizer.py⚠️(原计划遗漏) - 从
data_loader.py中移除对normalize_lf的引用 - 从
entity_aggregator.py中移除_norm列的依赖
4c — 恢复 gen_test_data.py
- 恢复
scripts/gen_test_data.py到 v5 版本(3类流量画像之前) - 执行:
git checkout HEAD~2 -- scripts/gen_test_data.py(或找到引入3画像版之前的最近提交) - 如无 git 历史:从
scripts/gen_complex_test.py的简单版本手动重建
4d — 最终运行测试
- 执行:
runtime\python\python.exe -m pytest tests/ -q --tb=short - 预期:所有 tests/ 下的项目测试通过(约49+项,非包括sklearn的200项)
- 如果测试失败:排查是否是value_normalizer删除导致的连锁失败,修复后再提交
4e — 提交清理
git add -A
git status # 确认只删了垃圾、没误伤原始文件
git commit -m "cleanup: 删除v6引入的垃圾文件/恢复原始文件/统一views.py后台工作者"