Key changes: - New: data_loader.py SQLite persistence with drop_sqlite_table - New: db_utils.py retry_on_lock decorator (3 retries, exponential backoff) - New: tool_registry.py with 27 MCP tools (filter_and_cluster, compute_scores, etc.) - New: tls_ref.py for TLS cipher/reference data - New: import_tlsdb.py management command - New: scripts/start_server.py for portable runtime - New: migrations 0003-0007 for SQLite table, display_id, llm fields - Changed: views.py unified pipeline worker, retry_run, display_id everywhere - Changed: models.py with display_id auto-assignment, run_type, sqlite_table, llm_thinking, tool_calls_json - Changed: urls.py added retry_run route - Changed: session_store.py robust JSON persistence - Changed: AGENTS.md v7 fix summary added - Changed: templates — globe rewrite (inertia/polar flip), auto.html (thinking/tool accordions), base.html (toast/config), all pages use display_id - Changed: run.bat PYTHONUTF8=1 - Deleted: entity_detector.py, entity_aggregator.py (replaced by filter_and_cluster clustering pipeline) - Test: 92/92 unit tests passing
天璇 (TianXuan) — TLS 流数据分析与实体画像系统
基于 Polars + scikit-learn + Three.js 的 TLS 流数据分析工具链。支持 CSV 批量导入、自动实体检测、多维聚合、聚类分析、特征提取、3D 地球流量可视化。提供 Django Web 操作界面和 MCP 协议接口,支持 32B 大语言模型编排分析流程。全离线运行,所有 JS 库/地图贴图/GeoIP 数据库均已内嵌。
目录
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