后端:
- traffic_timeline_view: 返回edges[{first_ts,last_ts}]替代windows
- datetime.strptime + .timestamp()保留微秒精度
前端:
- 完全移除窗口概念, edge._fs/_ls定义生命周期
- 时间桶索引(O(1)查找可见边)
- 生命周期<5s自动扩展±30s
- 5%软边缘淡入淡出
- 每帧仅检查当前时间桶±1的边(性能优化)
- 最大渲染500条(按count排序)
验证: 500条边, ~127K像素, 206活跃节点, 边持久可见
Co-Authored-By: Claude <noreply@anthropic.com>
天璇 (TianXuan) — TLS 流数据分析与实体画像系统
基于 Polars + scikit-learn + Three.js 的 TLS 流数据分析工具链。支持 CSV 批量导入、自动实体检测、多维聚合、聚类分析、特征提取、3D 地球流量可视化。提供 Django Web 操作界面和 MCP 协议接口,支持 32B 大语言模型编排分析流程。全离线运行,所有 JS 库/地图贴图/GeoIP 数据库均已内嵌。
TlsDB.csv — 参考表头名清单
TlsDB.csv 是 TLS 流量数据的参考表头名清单,包含常见的列名、含义和数据类型对照表。
此文件为参考对照表,非实际数据文件。
实际 CSV 文件的列名可能与表头名不同,分析工具会自动匹配。
目录
1. 系统概述
1.1 解决的问题
企业网络中 TLS 流量通常以 CSV 形式导出(每行一条流记录),数据量大、列名不统一、缺乏标签。本系统提供一条从原始 CSV 到实体画像的自动化分析流水线:
CSV 文件 → 上传/加载 → 自动检测实体列 → 按实体聚合特征
→ 实体级聚类 → 提取每簇区分特征 → Web 可视化 / MCP 接口
1.2 核心能力
| 模块 | 功能说明 |
|---|---|
| 数据加载 | 多文件合并、BOM 自动检测、跨文件 schema 容错、递归 **/*.csv、中文路径支持 |
| 实体检测 | 基于列名关键词 + 唯一值比率 + 数据类型的三维打分,自动推荐实体列(如 src_ip、sni、user) |
| 实体聚合 | 按实体分组计算流统计、目标多样性、TLS 特征、协议特征、时间模式、地理位置(经纬度) |
| IP 子网聚合 | 支持 /24 和 /28 子网掩码,同一子网下所有 IP 合并为一个实体节点 |
| 多列复合键 | 支持 (src_ip, dst_ip) 等多列组合作为实体标识 |
| 聚类分析 | HDBSCAN(自动确定簇数)/ KMeans,零样本自动降级,Silhouette / Davies-Bouldin 质量评估 |
| 特征提取 | Z-Score / ANOVA 方法计算每个聚类的区分性特征 |
| 3D 地球 | 基于 Three.js 的 TLS 流量弧线可视化,多数据源叠加,经纬线网格,国境线轮廓 |
| 地理可视化 | PCA 散点图 + Canvas 原生渲染(无外部 JS 依赖) |
| LLM 集成 | OpenAI 兼容 API、LLM 自动编排分析流程(profile → 实体 → 聚类 → 特征) |
| Web 界面 | CSV 上传拖拽、手动分步分析向导、LLM 自动分析、配置管理、运行记录查看 |
| MCP 协议 | 12 个 JSON-RPC 工具,供外部 LLM 编排调用 |
| 便携运行时 | 项目内置 Python 3.12 运行时(593MB),零系统依赖,run.bat 双击即用 |
1.3 技术栈
| 组件 | 技术选型 |
|---|---|
| 后端框架 | Django 4.2 (SQLite WAL) |
| 数据处理 | Polars 1.42.1 (LazyFrame 延迟计算 + streaming) |
| 机器学习 | scikit-learn (StandardScaler, HDBSCAN, KMeans, PCA) |
| MCP 协议 | Python MCP SDK (stdio 传输) |
| 前端 3D | Three.js (603KB, 离线) |
| 前端图表 | 纯 Canvas 2D API 原生绘制 |
| 配置 | Pydantic + YAML |
| LLM 接口 | OpenAI chat/completions 兼容 API |
| 运行时 | 嵌入式 Python 3.12 (Win7 兼容版 adang1345) |
2. 快速开始
2.1 用户模式(无需预装 Python)
1. 解压项目文件夹到任意目录
2. 双击 run.bat
3. 等待命令行显示 "Starting TianXuan..."
4. 浏览器自动打开 http://127.0.0.1:8000/
5. 点击「上传数据」→ 选择 CSV 文件 → 上传 → 等待预处理完成
6. 进入「手动分析」→ 选择数据集 → 配置参数 → 运行分析
7. 查看结果:聚类概览、簇详情、实体画像、地球分布图
2.2 开发者模式
# 初始化数据库
runtime\python\python.exe manage.py migrate
# 生成测试数据
runtime\python\python.exe scripts\gen_test_data.py --rows 1000
# 启动开发服务器
runtime\python\python.exe manage.py runserver
# 浏览器打开 http://127.0.0.1:8000/
2.3 脚本一览
| 脚本 | 功能 |
|---|---|
run.bat |
启动 Django Web 界面(:8000),自动打开浏览器 |
shell.bat |
打开 Django Shell(Python 交互式环境) |
2.4 一键分析管道
# 加载 CSV → 自动检测实体 → 聚合 → 聚类 → 特征提取 → 写入数据库
runtime\python\python.exe manage.py run_pipeline "data/input.csv"
# 指定聚类算法
runtime\python\python.exe manage.py run_pipeline "data/*.csv" --algo kmeans
# 手动指定实体列(跳过自动检测)
runtime\python\python.exe manage.py run_pipeline "data/*.csv" --entity-col src_ip
# 导出结果
runtime\python\python.exe manage.py run_pipeline "data/*.csv" --output ./results/
输出示例:
[1/5] 加载 CSV: data/test_flows.csv → 500 rows, 1 files, 0.2 MB
[2/5] 检测实体列 → 自动检测: src_ip (共 6 候选)
[3/5] 实体聚合 → 50 个实体, 18 维特征
[4/5] 聚类 (hdbscan) → 2 个簇, 噪声比 0.24, Silhouette: 0.2557
[5/5] 特征提取 → 30 个特征已保存到数据库
*** 分析完成! Run ID: #1
3. 用户指南
3.1 上传数据
- 点击导航栏「上传数据」
- 拖拽 CSV 文件到虚线区域,或点击选择文件
- 支持多文件上传,自动拼接相同 schema 的文件
- 支持
schema_strict=false模式(默认):不同列名的文件会自动合并,缺失列填 null - 支持
.zip压缩包自动解压 - 上传后自动在后台进行预处理(加载 → 检测实体列 → 聚合),完成后状态变为
ready - 进度条实时显示处理状态
数据格式要求:
- 每行一条 TLS 流记录
- 建议包含列:
src_ip、dst_ip、proto、bytes_sent、bytes_rev、duration、packets等 - 可选地理列:
latitude/lat/y和longitude/lon/lng/x(自动识别) - 可选时间列:
timestamp/ts/time(自动识别)
3.2 手动分析
3 步向导完成分析:
Step 1 - 选择数据集:从已预处理完成的数据集中选择一个(显示行数、已检测的实体列)
Step 2 - 配置参数:
- 聚类算法:HDBSCAN(自动确定簇数,推荐)/ KMeans(需预设 k 值)
- 最小簇大小(min_cluster_size):默认 5,数据不足时自动降级
Step 3 - 确认运行:回顾配置,点击「开始分析」。后台自动完成聚类 + 特征提取,完成后跳转到结果页。
3.3 LLM 自动分析
需要先在「配置」页面设置 LLM 的 base_url 和 API Key:
- 进入「LLM 分析」页面
- 选择一个已预处理的数据集
- 点击「开始自动分析」
- 后端 LLM 编排器会自动调用 profile → build_entity_profiles → run_clustering → extract_features
- 进度条实时显示当前步骤
3.4 查看结果
运行详情页
- 总流数、实体数、簇数 摘要卡片
- 簇列表:每个簇的大小、占比、Silhouette 分数
聚类概览页
- PCA 散点图:实体在二维主成分空间中的分布,颜色区分聚类
- 地理分布图:实体在地理坐标上的分布(需 CSV 包含经纬度列),支持缺失值
- 每个簇的详情卡片:Top 5 区分特征
簇详情页
- 特征表:每列的均值、标准差、中位数、区分度分数(Top 50)
- 实体列表:该簇包含的实体(Top 50),可点击查看详情
实体画像页
- 实体标识、所属簇
- 聚合特征值和相对簇均值的偏离(Z-score)
- 偏差显著的特征以颜色高亮(|Z| > 2)
3D 地球页
- Three.js 3D 地球,TLS 流量弧线连接源目 IP
- 弧线颜色标识 TLS 版本(TLSv1.3 蓝 / v1.2 粉 / 其他青)
- 鼠标拖拽旋转、滚轮缩放
- 经纬线网格 + 国境线轮廓
- 多数据源叠加复选框
- 脉冲光点动画(背面剔除)
4. 页面功能说明
| 页面 | 路由 | 功能 |
|---|---|---|
| 首页 | / |
最近运行记录概览 |
| 上传数据 | /upload/ |
拖拽上传 CSV,自动预处理 |
| 手动分析 | /analyze/manual/ |
3 步向导:选数据→设参数→运行 |
| LLM 分析 | /analyze/auto/ |
LLM 自动编排分析流程 |
| 运行记录 | /runs/ |
所有分析运行列表 |
| 运行详情 | /runs/<id>/ |
单次运行摘要 + 簇列表 |
| 聚类概览 | /clusters/<run_id>/ |
PCA 散点图 + 每簇区分特征 |
| 簇详情 | /clusters/<run_id>/<label>/ |
特征表 + 实体列表 |
| 实体画像 | /entities/<id>/ |
单实体特征 + 簇偏离 |
| 3D 地球 | /globe/ |
Three.js 流量弧线可视化 |
| 配置 | /config/ |
系统配置编辑 + LLM 测试 |
| 日志 | /logs/ |
运行日志查看 |
5. CLI 管道
# 完整管道(HDBSCAN 默认)
runtime\python\python.exe manage.py run_pipeline data/complex_test.csv
# 指定 KMeans
runtime\python\python.exe manage.py run_pipeline data/*.csv --algo kmeans
# 手动指定实体列
runtime\python\python.exe manage.py run_pipeline data/*.csv --entity-col src_ip
# 设置子网聚合掩码
runtime\python\python.exe manage.py run_pipeline data/*.csv --subnet-masks 24 28
6. MCP 工具文档
6.1 工具总览
系统通过 MCP (Model Context Protocol) 暴露 12 个工具,支持 LLM 以 JSON-RPC 方式编排调用。
| # | 工具名 | 功能 | 必需参数 |
|---|---|---|---|
| 1 | load_data |
加载 CSV 文件(支持 glob、递归、schema 容错) | csv_glob |
| 2 | profile_data |
数据集概要统计 + 相关性矩阵 | dataset_id |
| 3 | filter_data |
按条件过滤(12 操作符 + AND/OR) | dataset_id, filters |
| 4 | preprocess_data |
预处理(标准化/编码/填充) | dataset_id, columns |
| 5 | run_clustering |
执行聚类(HDBSCAN/KMeans,带质量评估) | dataset_id, cluster_columns |
| 6 | evaluate_clustering |
评估聚类质量(Silhouette/DB/CH) | cluster_result_id, dataset_id |
| 7 | extract_features |
提取各聚类区分特征(Z-Score/ANOVA) | dataset_id, cluster_result_id |
| 8 | export_results |
导出结果到磁盘(CSV/Parquet/JSON) | result_id, output_path |
| 9 | list_datasets |
列出所有活跃数据集 | 无 |
| 10 | drop_dataset |
删除数据集释放内存 | dataset_id |
| 11 | clone_dataset |
浅拷贝数据集(不复制数据) | dataset_id |
| 12 | build_entity_profiles |
自动检测实体列 + 聚合画像 | dataset_id |
6.2 响应约定
- 成功时返回 JSON 对象,含
truncated: false - 超过阈值时自动截断,设置
truncated: true+omitted_columns - 错误时返回
{ "error": "描述", "truncated": false } - 所有响应通过
TextContent包装返回
6.3 JSON-RPC 调用示例
→ {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"load_data","arguments":{"csv_glob":"data/*.csv"}}}
← {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"dataset_id\":\"ds_...\",\"row_count\":500}"}]}}
→ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"build_entity_profiles","arguments":{"dataset_id":"ds_...","auto_detect":true}}}
← {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"entity_dataset_id\":\"entity_...\",\"entity_count\":50,\"entity_column_used\":\"src_ip\"}"}]}}
7. 测试
# 运行全部测试
runtime\python\python.exe -m pytest tests -q
# 运行特定测试文件
runtime\python\python.exe -m pytest tests/test_entity.py -v
# 运行端到端测试
runtime\python\python.exe -m pytest tests/test_e2e.py -v
生成测试数据
# 简单数据
runtime\python\python.exe scripts\gen_test_data.py --rows 1000
# Globe 模式(IP 在真实 GeoIP 范围内,弧线可见)
runtime\python\python.exe scripts\gen_test_data.py --globe
# 复杂数据(5000 行 24 列含 55% 缺失)
runtime\python\python.exe scripts\gen_complex_test.py --rows 5000
列结构调查
# 统计各 CSV 文件的列名、类型、分布
runtime\python\python.exe scripts\column_survey.py --csv "data/*.csv"
8. 项目结构
tianxuan/
├── tianxuan/ # Django 项目配置
│ ├── settings.py # Django 配置(数据库、中间件)
│ ├── urls.py # 根路由
│ └── llm_orchestrator.py # LLM 编排后端(tool_calls 循环)
│
├── analysis/ # 核心分析模块(Django app)
│ ├── data_loader.py # CSV 加载、BOM 检测、schema 容错、递归 glob
│ ├── data_profiler.py # 数据集概要统计与相关性矩阵
│ ├── entity_detector.py # 实体列自动检测(关键词 + unique_ratio 打分)
│ ├── entity_aggregator.py # 实体聚合(流→实体画像),含 IP 子网聚合
│ ├── type_classifier.py # 值优先类型检测(MAC/端口/IPv4/URL/HEX/ENUM/LAT_LON)
│ ├── data_validator.py # 列校验(缺失率/异常值/IP有效性)
│ ├── geoip.py # GeoIP 经纬度查询
│ ├── session_store.py # 线程安全内存会话存储(Singleton + RLock)
│ ├── tool_registry.py # 12 个 MCP 工具定义 + 异步处理函数
│ ├── mcp_server.py # MCP stdio 服务器
│ ├── views.py # 所有 Django 视图
│ ├── urls.py # 16 条 URL 路由
│ ├── models.py # ORM 模型
│ └── management/commands/
│ ├── start_mcp.py # manage.py start_mcp
│ └── run_pipeline.py # manage.py run_pipeline(一键 CLI 管道)
│
├── config/
│ ├── config.yaml # 配置文件(自动生成,带注释)
│ └── loader.py # Pydantic 配置加载器
│
├── templates/tianxuan/ # 11 个页面模板
├── static/tianxuan/ # Three.js + 地球贴图 + 国境线
├── runtime/python/ # 便携 Python 3.12 运行时(593MB)
├── tests/ # 53 个测试 (pytest)
├── scripts/ # 工具脚本
├── docs/ # 文档
├── run.bat # 用户启动脚本(双击即用)
└── manage.py # Django 管理入口
9. 常见问题
Q1: 双击 run.bat 后浏览器没打开?
A: 手动打开浏览器访问 http://127.0.0.1:8000/。如果也无法访问,检查命令行是否有报错。
Q2: 压缩时提示 db.sqlite3-wal 被占用?
A: 有残留的 Python 进程持有 SQLite 连接。运行以下命令后重试:
Get-Process python -ErrorAction SilentlyContinue | Stop-Process -Force
Remove-Item db.sqlite3-wal, db.sqlite3-shm -Force -ErrorAction SilentlyContinue
Q3: 地图不显示?
A: CSV 需包含 lat/lon 列(列名含 lat/latitude/lon/longitude/lng 自动识别),缺失值不显示。页面会提示跳过的数量。
Q4: 上传 CSV 后显示 "处理失败"?
A: 在运行详情页查看错误消息。常见原因:
- CSV 编码不是 UTF-8
- 所有列都是非数值类型(无法聚类,返回 0 簇)
- 数据量太小(< 3 条实体记录,HDBSCAN 自动跳过)
Q5: 如何配置 LLM?
A: 导航到「配置」页面,填写 base_url 和 API Key,点击「测试连通性」验证。支持 OpenAI 兼容的任何 API。
Q6: 支持哪些 CSV 编码?
A: 自动检测 UTF-8 BOM、UTF-16LE BOM、UTF-16BE BOM。无 BOM 时默认 UTF-8。中文路径完全支持。
Q7: 不同 CSV 文件的列名不一致怎么办?
A: 默认 schema_strict=false,系统自动取所有文件的列名并集,缺失列填 null。如需严格模式,在配置中将 schema_strict 改为 true。
Q8: 项目太大,如何缩小?
Remove-Item -Recurse *.pyc, __pycache__ -Force
Remove-Item db.sqlite3-wal, db.sqlite3-shm -Force -ErrorAction SilentlyContinue
10. 增量更新(部署到离线机)
天璇支持增量更新,只需将变更代码打包成小 zip 包,复制到离线机双击 update.bat 即可完成更新,无需每次传输整个项目(1.5GB)。
10.1 首次部署
在离线机上第一次部署时,需要完成数据库迁移:
:: 确保数据库在 %APPDATA%/TianXuan/ 下
runtime\python\python.exe scripts\migrate_db_to_appdata.py
:: 初始化数据库表
runtime\python\python.exe manage.py migrate
:: 导入 TLS 引用数据
runtime\python\python.exe manage.py import_tlsdb
如果之前已在使用天璇,
migrate_db_to_appdata.py会自动将已有db.sqlite3复制到新位置。
10.2 开发机:构建更新包
在开发机上完成代码修改并提交后:
# 确保工作树干净(无未提交变更)
git status
# 构建增量更新包
python scripts/build_update.py
脚本会自动:
- 检测当前 git tag 与最近一次 tag 之间的文件变更
- 计算每个文件的 SHA256 校验和
- 打包为
tianxuan_update_<旧版本>-<新版本>.zip - 更新
VERSION文件 - 如果检测到依赖变更,会输出提示信息
输出示例:
==================================================
天璇 增量更新包构建工具
==================================================
当前 VERSION: v1.0.0
最新 git tag: v1.0
变更文件: 5 个修改/新增, 1 个删除
==================================================
✅ 增量更新包构建完成!
包: tianxuan_update_v1.0-v1.1.zip
大小: 0.05 MB
从: v1.0
到: v1.1
文件数: 5
删除: 1
==================================================
10.3 离线机:应用更新
在离线机上:
- 将
tianxuan_update_*.zip复制到天璇项目目录(与run.bat同目录) - 双击
update.bat(或拖拽 zip 到update.bat上) - 等待更新完成
- 关闭窗口,重新双击
run.bat启动新版本
更新脚本会自动:
- ✅ 验证更新包完整性(SHA256 校验)
- ✅ 备份当前配置(
config/config.yaml) - ✅ 删除废弃文件
- ✅ 覆盖更新文件
- ✅ 智能合并配置(保留你的设置,仅增加新配置项)
- ✅ 清理 Python 缓存
- ✅ 运行数据库迁移
- ✅ 更新版本号
10.4 回滚
如果更新后出现问题:
双击 rollback.bat
→ 输入 y 确认回滚
→ 等待恢复完成
→ 重新双击 run.bat 启动旧版本
回滚会从 %APPDATA%/TianXuan/backups/ 恢复最近一次备份。
10.5 依赖变更时的特殊处理
当 pyproject.toml 或 requirements.txt 变更时(即添加/更新了 Python 依赖),构建脚本会输出警告:
⚠️ 依赖已变更!请手动将 runtime/ 目录同步到离线机
此时需要额外步骤:
- 在开发机上将
runtime/目录完整压缩(约 645MB) - 复制到离线机,覆盖
runtime/目录 - 或者使用差异更新:仅覆盖变更的包目录(
runtime/python/Lib/site-packages/)
依赖变更是低频操作(通常只在添加新功能时需要),所以这不会影响日常的代码增量更新。
10.6 文件说明
| 文件 | 用途 | 需要 git 跟踪? |
|---|---|---|
VERSION |
记录当前版本号 | ✅ 是 |
scripts/build_update.py |
开发机:构建增量包 | ✅ 是 |
scripts/apply_update.py |
离线机:应用更新 | ✅ 是 |
scripts/merge_config.py |
合并用户配置与源码配置 | ✅ 是 |
scripts/migrate_db_to_appdata.py |
首次迁移数据库到 APPDATA | ✅ 是 |
scripts/version_utils.py |
版本工具函数 | ✅ 是 |
update.bat |
离线机双击入口 | ✅ 是 |
rollback.bat |
回滚入口 | ✅ 是 |
analysis/appdata.py |
APPDATA 路径共享模块 | ✅ 是 |
.update_cache/runtime_snapshot.json |
运行时依赖快照(自动生成) | ❌ 否 |
RUNTIME_CHANGED.txt |
依赖变更提示(自动生成) | ❌ 否 |
10.7 目录结构变化
更新系统将用户数据与项目代码分离:
项目目录(可安全覆盖) 用户数据目录(永不覆盖)
天璇/ %APPDATA%/TianXuan/
├── analysis/ ← 代码 ├── db.sqlite3 ← 数据库
├── config/config.yaml ← 配置 ├── data/uploads/ ← 上传的 CSV
├── runtime/ ← 运行时 ├── .session_store.json
├── templates/ ← 模板 └── backups/ ← 更新备份
├── static/ ← 静态资源
├── scripts/ ← 工具脚本
├── update.bat ← 更新入口
└── VERSION ← 版本号