# 清理计划 ## 第一步:删掉我加的所有垃圾 > 前置条件:确认 `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` 中没有 `
` 元素——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`,将两个分析逻辑作为回调注入。 **新设计**: ```python 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图标所有页面 | 访问首页 `/` → 检查 `` 存在 | `favicon.ico` 或 `favicon.svg` 在 `` 中存在 | | 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.md` - `tianxiu-v5.md` - `tianxiu-v6.md` - `globe-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 — 提交清理 ```bash git add -A git status # 确认只删了垃圾、没误伤原始文件 git commit -m "cleanup: 删除v6引入的垃圾文件/恢复原始文件/统一views.py后台工作者" ```