Metadata-Version: 2.4
Name: mysphinx-forge
Version: 0.1.6
Summary: Data and model workflow toolkit for cleaning, clustering, generation, and evaluation
Keywords: data-cleaning,deduplication,clustering,nlp,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Environment :: Console
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: pandas>=2.2.3
Requires-Dist: tqdm>=4.67.1
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: xlrd>=2.0.1
Provides-Extra: ml
Requires-Dist: numpy>=2.2.0; extra == "ml"
Requires-Dist: scikit-learn>=1.7.0; extra == "ml"
Provides-Extra: embeddings
Requires-Dist: faiss-cpu>=1.11.0; extra == "embeddings"
Requires-Dist: sentence-transformers>=5.1.0; extra == "embeddings"
Provides-Extra: llm-local
Requires-Dist: torch>=2.8.0; extra == "llm-local"
Requires-Dist: transformers>=4.55.0; extra == "llm-local"
Provides-Extra: all
Requires-Dist: numpy>=2.2.0; extra == "all"
Requires-Dist: scikit-learn>=1.7.0; extra == "all"
Requires-Dist: faiss-cpu>=1.11.0; extra == "all"
Requires-Dist: sentence-transformers>=5.1.0; extra == "all"
Requires-Dist: torch>=2.8.0; extra == "all"
Requires-Dist: transformers>=4.55.0; extra == "all"

# MySphinx Forge

`MySphinx Forge` 是一个面向表格文本数据的 Python CLI 工具，重点解决语料预处理和模型验证这两类工作：

- 数据清洗
- 精确去重与语义去重
- 清洗后再去重的流水线处理
- 文本聚类与聚类报告生成
- 训练集 / 验证集 / 测试集切分
- 本地模型、OpenAI 兼容接口、通用 HTTP 接口的批量模型测试

当前输入支持 `csv`、`xls`、`xlsx`、`xlsm`。工具会尽量保留原始表结构，并在不同 action 下补充日志、元数据、聚类报表或模型测试结果。

## 适用场景

- 清理客服问答、FAQ、标注语料、指令数据
- 在训练前做空值剔除、去重和数据集切分
- 对文本数据做主题聚类，快速查看簇分布
- 用本地模型或远程模型接口对整张表做批量推理和结果比对

## 功能概览

| Action | 用途 | 默认输出 |
| --- | --- | --- |
| `clean` | 删除空白、纯符号、纯表情、纯乱码行 | `*_cleaned.*` |
| `deduplicate` | 按精确或语义方式去重 | `*_deduplicated.*` |
| `clean-deduplicate` | 先清洗，再去重 | `*_deduplicated.*` |
| `cluster` | 文本聚类，并导出汇总、投影和 HTML 报告 | `*_clustered.*` |
| `split` | 切分 train / valid / test | `*_split_train.*` 等 |
| `model-test` | 批量执行模型推理或单条烟雾测试 | `*_model_tested.*` 或终端输出 |
| `convert-sft` | 转换表格数据为 LLaMA-Factory 可用的 SFT 数据 | `*_alpaca.json` |

## 项目结构

- `main.py`：仓库内运行入口，实际调用 `mysphinx_forge.cli:main`
- `mysphinx_forge/`：核心实现
  - `cleaning.py`：清洗规则和统计
  - `deduplication.py`：精确去重
  - `semantic_deduplication.py`：基于 embedding + FAISS 的语义去重
  - `clustering.py`：`HDBSCAN` / `KMeans` 聚类
  - `cluster_reporting.py`：聚类分析表和 HTML 可视化报告
  - `model_testing.py`：本地模型 / OpenAI 兼容接口 / HTTP 接口测试
  - `splitting.py`：随机、分层、分组、时间切分
  - `sft_dataset.py`：表格到 LLaMA-Factory SFT `alpaca` 格式转换
  - `file_io.py`：CSV / Excel 读取与结果写出
  - `cli.py`：命令行参数、阶段编排、日志与元数据写出
- `models/`：本地 embedding 模型或本地生成模型目录，示例见 [models/README.md](models/README.md)
- `tests/`：pytest 测试
- `data/`：仓库内示例输入和历史生成产物

## 安装

项目要求 Python `3.12+`，并使用 `uv` 管理环境。

### 从 PyPI 安装

```bash
uv pip install mysphinx-forge
uv pip install 'mysphinx-forge[embeddings]'
uv pip install 'mysphinx-forge[ml,embeddings]'
uv pip install 'mysphinx-forge[llm-local]'
uv pip install 'mysphinx-forge[all]'
```

安装后可以直接使用：

```bash
mysphinx-forge --help
```

### 在源码仓库中开发

基础开发环境：

```bash
uv sync --group dev
```

按需补装扩展能力：

```bash
uv sync --extra embeddings --group dev
uv sync --extra ml --extra embeddings --group dev
uv sync --extra llm-local --group dev
uv sync --extra all --group dev
```

能力与依赖对应关系：

- 基础依赖：`clean`、精确 `deduplicate`、`clean-deduplicate`、`split`、OpenAI / HTTP 模式的 `model-test`
- `embeddings`：语义去重
- `ml + embeddings`：聚类
- `llm-local`：本地模型 `model-test`
- `all`：安装全部能力

### 从源码安装当前项目

```bash
uv pip install -e .
uv pip install -e '.[embeddings]'
uv pip install -e '.[ml,embeddings]'
uv pip install -e '.[llm-local]'
uv pip install -e '.[all]'
```

## 快速开始

### 1. 查看帮助

安装包后，直接运行：

```bash
mysphinx-forge --help
```

如果你是在源码仓库里、本地还没有安装命令行入口，也可以运行：

```bash
uv run python main.py --help
```

下文命令默认都以已安装的 CLI 为准；在源码仓库中，它们等价于：

```bash
uv run python main.py ...
```

### 2. 准备数据

- 输入文件必须是 `csv`、`xls`、`xlsx`、`xlsm`
- 默认目标列优先按以下顺序自动探测：
  - `text`
  - `用户问题`
  - `客户问题`
  - `用户输入`
- 如果你的文本列不是这些名字，请显式传 `--target-column`

### 3. 如需语义能力，先准备模型

语义去重和聚类默认使用本地 embedding 模型路径：

```bash
models/m3e-base
```

如果模型不在这个位置，请传入：

```bash
--embedding-model-path <你的模型目录>
```

### 4. 如需远程接口能力，准备环境变量

复制模板并填写：

```bash
cp .env.example .env
```

当前已支持的环境变量见下文“环境变量与 `.env`”。

## 常用命令

### 数据清洗

`clean` 会删除目标列中的以下行：

- 空白行
- 纯符号 / 纯标点行
- 纯表情行
- 纯乱码行

基础示例：

```bash
mysphinx-forge --action clean --input-file data/input.xlsx
```

指定列名：

```bash
mysphinx-forge --action clean --input-file data/input.xlsx --target-column 用户问题
```

对大 CSV 使用流式分块处理：

```bash
mysphinx-forge --action clean --input-file data/input.csv --chunk-size 20000
```

### 数据去重

`deduplicate` 支持两种模式：

- `exact`：标准化空白和大小写后做精确匹配
- `semantic`：基于 embedding 相似度做语义去重

精确去重：

```bash
mysphinx-forge --action deduplicate --input-file data/input.xlsx
```

语义去重：

```bash
mysphinx-forge --action deduplicate --input-file data/input.xlsx --dedupe-mode semantic
```

调整语义阈值和模型路径：

```bash
mysphinx-forge --action deduplicate --input-file data/input.xlsx --dedupe-mode semantic --semantic-threshold 0.9 --embedding-model-path models/m3e-base
```

指定近似索引：

```bash
mysphinx-forge --action deduplicate --input-file data/input.xlsx --dedupe-mode semantic --semantic-index-type hnsw --semantic-hnsw-m 32
```

如果输入表中有分类列，希望在语义命中明细里一起导出，可指定：

```bash
mysphinx-forge --action deduplicate --input-file data/input.xlsx --dedupe-mode semantic --category-column label
```

### 先清洗再去重

当你希望先移除明显脏数据，再做去重时，使用 `clean-deduplicate`：

```bash
mysphinx-forge --action clean-deduplicate --input-file data/input.xlsx
```

先清洗再做语义去重：

```bash
mysphinx-forge --action clean-deduplicate --input-file data/input.xlsx --dedupe-mode semantic
```

### 导出 LLaMA-Factory SFT 数据

`convert-sft` 目前支持将表格转换为 `alpaca` 格式 JSON，可直接给 `LLaMA-Factory` 做 `SFT` 训练。

默认会自动探测：

- 输入列：`text` / `用户问题` / `客户问题` / `用户输入`
- 输出列：`category` / `label` / `intent` / `output` / `response` / `answer` / `target`

基础示例：

```bash
mysphinx-forge --action convert-sft --input-file data/input_deduplicated_split_train.xlsx
```

默认输出：

```bash
data/input_deduplicated_split_train_alpaca.json
```

指定输出标签列：

```bash
mysphinx-forge --action convert-sft --input-file data/input.xlsx --sft-output-column label
```

覆盖默认 `instruction` 和 `system`：

```bash
mysphinx-forge --action convert-sft --input-file data/input.xlsx --sft-output-column category --sft-instruction "请判断用户问题所属分类，只输出分类标签。" --sft-system-prompt "你是一个证券问答分类助手。"
```

说明：

- 当前仅实现 `alpaca` 格式
- 空输入行和空输出行会自动跳过
- 会同时生成日志文件和 `*.meta.json` 元数据文件

### 文本聚类

`cluster` 默认使用 `hdbscan`，也支持固定簇数的 `kmeans`。

基础示例：

```bash
mysphinx-forge --action cluster --input-file data/input_deduplicated.xlsx
```

使用 `KMeans`：

```bash
mysphinx-forge --action cluster --input-file data/input_deduplicated.xlsx --cluster-mode kmeans --num-clusters 12
```

调整 `HDBSCAN` 参数：

```bash
mysphinx-forge --action cluster --input-file data/input_deduplicated.xlsx --min-cluster-size 8 --cluster-selection-epsilon 0.05
```

使用 LLM 生成簇标签：

```bash
OPENAI_API_KEY=... mysphinx-forge --action cluster --input-file data/input_deduplicated.xlsx --cluster-label-mode llm
```

聚类会同时产出结果表、簇汇总、投影数据、分析表和 HTML 报告，详见“输出文件规则”。

### 数据集切分

`split` 支持以下模式：

- `auto`：优先按 `category` / `label` / `intent` 分层，否则退化为随机切分
- `random`
- `stratified`
- `group`
- `time`

基础示例：

```bash
mysphinx-forge --action split --input-file data/input_deduplicated.xlsx
```

显式分层切分：

```bash
mysphinx-forge --action split --input-file data/input_deduplicated.xlsx --split-mode stratified --stratify-column category
```

按组切分，避免泄漏：

```bash
mysphinx-forge --action split --input-file data/input_deduplicated.xlsx --split-mode group --group-column session_id
```

按时间切分：

```bash
mysphinx-forge --action split --input-file data/input_deduplicated.xlsx --split-mode time --time-column created_at --time-order asc
```

### 模型测试

`model-test` 有两种使用方式：

- 不传 `--input-file`：执行单条烟雾测试，输入内容使用代码内置的固定样例
- 传 `--input-file`：对整张表的目标列做批量推理，并生成结果文件

本地模型单条测试：

```bash
mysphinx-forge --action model-test --test-model-path models/your-chat-model
```

批量测试本地模型：

```bash
mysphinx-forge --action model-test --input-file data/input_deduplicated.xlsx --test-model-path models/your-chat-model
```

使用 OpenAI 兼容接口批量测试：

```bash
OPENAI_API_KEY=... mysphinx-forge --action model-test --input-file data/input_deduplicated.xlsx --model-test-mode openai --test-model-path gpt-4.1-mini --model-test-api-base https://api.openai.com/v1
```

使用通用 HTTP POST 接口批量测试：

```bash
HTTP_API_KEY=... mysphinx-forge --action model-test --input-file data/input_deduplicated.xlsx --model-test-mode http --test-model-path custom-http-model --model-test-api-base https://example.test/infer
```

请求体字段名与默认协议不一致时：

```bash
HTTP_API_KEY=... mysphinx-forge --action model-test --input-file data/input_deduplicated.xlsx --model-test-mode http --test-model-path custom-http-model --model-test-api-base https://example.test/infer --http-request-field-map '{"user_input":"prompt","system_prompt":"system","max_new_tokens":"max_tokens"}' --http-extra-body '{"tenant":"forge","stream":false}'
```

通过文件覆盖默认 system prompt：

```bash
mysphinx-forge --action model-test --input-file data/input_deduplicated.xlsx --test-model-path models/your-chat-model --system-prompt-file prompts/system.txt
```

批量模型测试的结果文件会追加：

- `模型结果`
- `模型调用时间`
- `匹配预期`：仅当输入文件包含 `预期结果` 列时生成

本地批量测试会按可见 GPU 数自动分配 worker；没有 GPU 时自动退化为单 worker CPU 模式。

## 输出文件规则

| Action | 主要输出 | 附加输出 |
| --- | --- | --- |
| `clean` | `*_cleaned.*` | `*.meta.json`、`mysphinx-forge.log` |
| `deduplicate` | `*_deduplicated.*` | 语义模式额外生成 `*_matches.csv`；同时写 `*.meta.json`、`mysphinx-forge.log` |
| `clean-deduplicate` | `*_deduplicated.*` | 语义模式额外生成 `*_matches.csv`；同时写 `*.meta.json`、`mysphinx-forge.log` |
| `cluster` | `*_clustered.*` | `*_clusters.csv`、`*_projection.csv`、`*_analysis.csv`、`*_report.html`、`*.meta.json`、`mysphinx-forge.log` |
| `split` | `*_split_train.*`、`*_split_valid.*`、`*_split_test.*` | `*_split.meta.json`、`mysphinx-forge.log` |
| `model-test` 文件模式 | `*_model_tested.*` | `mysphinx-forge.log` |
| `model-test` 单条模式 | 终端输出 | 当前工作目录下的 `mysphinx-forge.log` |

补充说明：

- 日志文件统一写到输出目录下的 `mysphinx-forge.log`
- `clean`、`deduplicate`、`clean-deduplicate`、`cluster`、`split` 会写结构化 `.meta.json`
- 当前 `model-test` 文件模式不会生成 `.meta.json`
- 语义去重的 `*_matches.csv` 会记录重复行命中的代表行、相似度，以及可选的分类列对比信息

## 运行行为说明

- `csv` 在 `clean`、`deduplicate`、`clean-deduplicate` 下支持分块流式处理，`--chunk-size` 仅对 `csv` 生效
- `Excel` 文件会整表读入内存
- 终端会显示多阶段 `tqdm` 进度条
- CLI 启动时会自动尝试加载当前工作目录和项目根目录中的 `.env` 文件，且不会覆盖已有环境变量

## 环境变量与 `.env`

项目根目录提供了 [.env.example](.env.example)。

常用变量：

- `OPENAI_API_KEY`
- `OPENAI_BASE_URL`
- `HTTP_API_KEY`
- `HTTP_API_KEY_HEADER`
- `HTTP_API_KEY_PREFIX`
- `HTTP_API_BASE_URL`
- `HTTP_REQUEST_FIELD_MAP`
- `HTTP_EXTRA_BODY`

用途说明：

- `cluster --cluster-label-mode llm` 使用 `OPENAI_API_KEY` / `OPENAI_BASE_URL`
- `model-test --model-test-mode openai` 使用 `OPENAI_API_KEY` / `OPENAI_BASE_URL`
- `model-test --model-test-mode http` 使用 `HTTP_*` 系列配置

## 开发与验证

常用命令：

```bash
uv run pytest
uv run python -m compileall .
uv build
```

如果你只是想本地运行当前仓库，通常只需要：

```bash
uv sync --group dev
```

如果要做语义去重或聚类，再补装对应 extra 即可。

## 当前项目状态

当前仓库已经不是单一脚本，而是一个有明确包结构、CLI 入口和测试覆盖的工具型项目。更适合把它理解为：

- 一个围绕表格文本数据处理的命令行工具
- 一个可以逐步扩展更多训练 / 评估流水线能力的 Python 包

如果你要继续扩展这个项目，建议优先在 `mysphinx_forge/` 下新增模块，而不是继续把逻辑堆到 `main.py`。
