Skip to main content

Data and model workflow toolkit for cleaning, clustering, generation, and evaluation

Project description

MySphinx Forge

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

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

当前输入支持 csvxlsxlsxxlsm。工具会尽量保留原始表结构,并在不同 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.pyHDBSCAN / 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
  • tests/:pytest 测试
  • data/:仓库内示例输入和历史生成产物

安装

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

从 PyPI 安装

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]'

安装后可以直接使用:

mysphinx-forge --help

在源码仓库中开发

基础开发环境:

uv sync --group dev

按需补装扩展能力:

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、精确 deduplicateclean-deduplicatesplit、OpenAI / HTTP 模式的 model-test
  • embeddings:语义去重
  • ml + embeddings:聚类
  • llm-local:本地模型 model-test
  • all:安装全部能力

从源码安装当前项目

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. 查看帮助

安装包后,直接运行:

mysphinx-forge --help

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

uv run python main.py --help

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

uv run python main.py ...

1.1 使用 mysphinx-forge.yaml

除了命令行参数,也可以在当前目录放一个 mysphinx-forge.yaml,或通过 --config <path> 显式指定配置文件。

仓库根目录已经提供了一份带完整注释的 mysphinx-forge.yaml,可以直接按需修改。

优先级规则:

  • CLI 显式参数
  • mysphinx-forge.yaml
  • 程序内置默认值

配置文件中的相对路径input_fileoutputsystem_prompt_filesft_instruction_fileembedding_model_pathtest_model_path 等)以执行时的当前工作目录为基准展开,与命令行参数行为一致。因此推荐从项目根目录运行工具,配置文件中的路径直接写相对于项目根目录的路径即可:

# configs/05_model_test.yaml
action: model-test
input_file: data/raw_deduplicated_split_test.xlsx   # 相对于运行时 cwd(项目根目录)
model-test:
  system_prompt_file: prompts/intent_system.md      # 同上
# 从项目根目录运行,路径正确展开
mysphinx-forge --config configs/05_model_test.yaml

配置文件支持三种层级:

  • 顶层公共参数
  • defaults 公共默认参数
  • 按 action 分节配置,例如 splitclustermodel-test

示例:

action: split
input_file: data/input.xlsx

defaults:
  target_column: text

split:
  split_mode: auto
  validation_ratio: 0.1
  test_ratio: 0.1
  split_random_seed: 42

命令行会覆盖配置文件,例如:

mysphinx-forge --config mysphinx-forge.yaml --validation-ratio 0.2

2. 准备数据

  • 输入文件必须是 csvxlsxlsxxlsm
  • Excel 输入会默认读取并合并所有 sheet
  • 默认目标列优先按以下顺序自动探测:
    • text
    • 用户问题
    • 客户问题
    • 用户输入
  • 如果你的文本列不是这些名字,请显式传 --target-column

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

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

models/m3e-base

如果模型不在这个位置,请传入:

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

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

复制模板并填写:

cp .env.example .env

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

常用命令

数据清洗

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

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

基础示例:

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

指定列名:

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

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

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

数据去重

deduplicate 支持两种模式:

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

精确去重:

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

语义去重:

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

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

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

指定近似索引:

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

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

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

先清洗再去重

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

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

先清洗再做语义去重:

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

导出 LLaMA-Factory SFT 数据

convert-sft 目前支持将表格转换为 alpaca 格式 JSON,可直接给 LLaMA-FactorySFT 训练。

关于命名:这里的 sft训练阶段(Supervised Fine-Tuning,监督微调),而非训练方法。alpacainstruction / input / output 结构正是 SFT 阶段的标准监督数据,无法用于 pt(纯文本预训练)或 dpo / rm(需要 chosen / rejected 偏好对)等其它阶段。

与训练方法无关:训练方法(LoRA / 全参数 / freeze)和数据格式是两个正交的维度。本命令产出的这份 alpaca JSON,无论你用 LoRA 还是全参数微调都通用,一个字都不用改——只需在 LLaMA-Factory 的训练配置里切换 finetuning_type 即可。

默认会自动探测:

  • 输入列:text / 用户问题 / 客户问题 / 用户输入
  • 输出列:category / label / intent / output / response / answer / target

基础示例:

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

默认输出:

data/input_deduplicated_split_train_alpaca.json

指定输出标签列:

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

覆盖默认 instructionsystem

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

instructioninput 字段的两种模式

默认模式(--sft-user-query-as-instruction,默认开启)

用户输入文本放入 instructioninput 字段留空:

{
  "instruction": "怎么买基金",
  "input": "",
  "output": "基金"
}

适合不需要 few-shot context 的分类或问答任务,格式简洁。

经典模式(--no-sft-user-query-as-instruction

用户输入放入 inputinstruction 为固定任务描述文本:

{
  "instruction": "请根据用户输入判断其category,只输出category。",
  "input": "怎么买基金",
  "output": "基金"
}

开启方式:

mysphinx-forge --action convert-sft --input-file data/input.xlsx --no-sft-user-query-as-instruction

也可以在 yaml 配置中指定:

convert-sft:
  sft_user_query_as_instruction: false

注意:如果同时传入了显式 --sft-instruction,则该固定文本始终作为 instructioninput 照常存放用户输入,--sft-user-query-as-instruction 不影响此情形。

说明:

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

文本聚类

cluster 默认使用 hdbscan,也支持固定簇数的 kmeans

基础示例:

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

使用 KMeans

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

调整 HDBSCAN 参数:

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

使用 LLM 生成簇标签:

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

基础示例:

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

如果输入是 Excel,多 sheet 会默认合并;其中名字精确等于 increment 的 sheet 会被视为增量数据:

  • increment 不参与 train / valid / test 比例切分
  • increment 会全量追加到 train 和 valid
  • increment 不会进入 test

显式分层切分:

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

按组切分,避免泄漏:

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

按时间切分:

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:对整张表的目标列做批量推理,并生成结果文件

本地模型单条测试:

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

批量测试本地模型:

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

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

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 接口批量测试:

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_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:

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

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

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

自动生成评估报告

当输入文件包含 预期结果 列时,批量测试完成后会自动:

  1. 在终端打印人类可读的评估汇总,包含每个类别的 TP / FP / FN / Precision / Recall / F1 明细,以及总体准确率、Macro F1、Weighted F1:
--------------------------------------------------------------------
类别              TP    FP    FN  Precision   Recall       F1  Support
--------------------------------------------------------------------
基金               3     1     1     0.7500   0.7500   0.7500        4
股票               3     1     1     0.7500   0.7500   0.7500        4
--------------------------------------------------------------------
准确率 0.7500(6/8)  |  Macro F1 0.7500  |  Weighted F1 0.7500
  1. 将同样的数据以 CSV 格式写入 *_model_tested_eval.csv,便于在 Excel 中进一步分析。CSV 格式为列=类别 / Macro / Weighted / Support,行=TP / FP / FN / Precision / Recall / F1:
,基金,股票,Macro,Weighted,Support
TP,3,3,,,
FP,1,1,,,
FN,1,1,,,
Precision,0.75000,0.75000,,,
Recall,0.75000,0.75000,,,
F1,0.75000,0.75000,0.75000,0.75000,8

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

输出文件规则

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

补充说明:

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

运行行为说明

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

环境变量与 .env

项目根目录提供了 .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_* 系列配置

开发与验证

常用命令:

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

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

uv sync --group dev

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

构建 wheel 并发布到 PyPI

本项目使用 setuptools 作为构建后端(见 pyproject.toml[build-system]),构建产物是纯 Python 包(py3-none-any),跨平台通用。

1. 更新版本号

PyPI 不允许覆盖已发布的同一版本,发新版前先在 pyproject.toml 中提升版本号:

[project]
version = "0.2.0"   # 改成新的版本号

2. 构建产物

uv build

构建完成后会在 dist/ 下生成两个文件:

  • mysphinx_forge-<version>-py3-none-any.whl(wheel)
  • mysphinx_forge-<version>.tar.gz(源码分发包 sdist)

3. 校验产物

uv pip install twine        # 首次需要安装
twine check dist/*

4. 配置凭证

~/.pypirc 中配置 PyPI / TestPyPI 的 API token(用户名固定为 __token__):

[pypi]
  username = __token__
  password = pypi-XXXXXXXX

[testpypi]
  username = __token__
  password = pypi-XXXXXXXX

token 在 https://pypi.org/manage/account/token/ 创建。请将该文件权限收紧:chmod 600 ~/.pypirc,并且不要提交到任何仓库。

5. 上传

# 建议先上传到 TestPyPI 验证
twine upload --repository testpypi dist/*

# 验证无误后正式上传到 PyPI
twine upload dist/*

也可以用 uv 直接发布(无需安装 twine):

uv publish --token pypi-XXXXXXXX

发布成功后即可通过 pip install mysphinx-forge 安装。

当前项目状态

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

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

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

使用场景

场景 1:收到一份原始 Excel,且已经有标签或答案列

适用条件:

  • 表里已经有输入列,例如 text用户问题
  • 同时也有监督列,例如 categorylabelintentoutputresponseanswertarget

推荐流程:

  1. 先清洗和去重,得到更干净的基础数据
mysphinx-forge --action clean-deduplicate --input-file data/raw.xlsx --target-column 用户问题 --dedupe-mode exact

这一步通常会生成:

data/raw_deduplicated.xlsx
  1. 再切分训练集、验证集、测试集
mysphinx-forge --action split --input-file data/raw_deduplicated.xlsx --split-mode auto --validation-ratio 0.1 --test-ratio 0.1

这一步会生成:

data/raw_deduplicated_split_train.xlsx
data/raw_deduplicated_split_valid.xlsx
data/raw_deduplicated_split_test.xlsx
  1. 如果你做的是传统分类训练,到这里通常已经可以直接使用这些切分文件

  2. 如果你做的是 LLaMA-Factory 一类的 SFT,再把切分后的文件转换成 alpaca 格式 JSON

mysphinx-forge --action convert-sft --input-file data/raw_deduplicated_split_train.xlsx --target-column 用户问题 --sft-output-column label
mysphinx-forge --action convert-sft --input-file data/raw_deduplicated_split_valid.xlsx --target-column 用户问题 --sft-output-column label

补充说明:

  • convert-sft 默认会自动探测输出列:categorylabelintentoutputresponseanswertarget
  • 如果输入是 Excel,多 sheet 会默认合并
  • 如果存在名字精确等于 increment 的 sheet,它在 split 时不会参与比例切分,而是会全量注入 trainvalid

场景 2:收到一份原始 Excel,但只有问题文本,没有标签

适用条件:

  • 表里只有输入文本
  • 还没有可直接用于监督训练的标签或标准答案

推荐流程:

  1. 先做清洗和去重,减少脏数据和重复样本
mysphinx-forge --action clean-deduplicate --input-file data/raw.xlsx --target-column 用户问题
  1. cluster 做主题聚类,辅助你理解数据结构和后续标注
mysphinx-forge --action cluster --input-file data/raw_deduplicated.xlsx --target-column 用户问题
  1. 或者用 model-test 批量生成候选标签、候选回复,再做人工抽检和回填
mysphinx-forge --action model-test --input-file data/raw_deduplicated.xlsx --target-column 用户问题 --model-test-mode openai --test-model-path gpt-4.1-mini
  1. 当表里补齐了监督列,例如 labeloutput,再执行 split
mysphinx-forge --action split --input-file data/raw_labeled.xlsx --split-mode auto
  1. 如果要做 SFT,最后再执行 convert-sft
mysphinx-forge --action convert-sft --input-file data/raw_labeled_split_train.xlsx --sft-output-column label

重要说明:

  • clustermodel-test 只能辅助整理和生成候选结果,不能替代人工确认的高质量监督标签
  • 如果原始表里没有输出列,就不能直接产出可靠的监督训练数据
  • model-test 当前默认的内置 system prompt 是金融二分类示例;如果你的任务不是这个场景,建议显式传 --system-prompt-file

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mysphinx_forge-0.2.0.tar.gz (90.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mysphinx_forge-0.2.0-py3-none-any.whl (68.3 kB view details)

Uploaded Python 3

File details

Details for the file mysphinx_forge-0.2.0.tar.gz.

File metadata

  • Download URL: mysphinx_forge-0.2.0.tar.gz
  • Upload date:
  • Size: 90.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for mysphinx_forge-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dbbaec81834814d9b5c72cd1f4047559a2494ed10365938fe7b4d1ddacf816a5
MD5 73214c5dec6d5ba46c052aba6acba4cb
BLAKE2b-256 524e7231a4117d6330e493753f47a839e5df982700fff1f1908b6a66709cfc6f

See more details on using hashes here.

File details

Details for the file mysphinx_forge-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mysphinx_forge-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 68.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for mysphinx_forge-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e234c61a07a14a2974a8b9141a0af594896e3fea07a6ee73701cfdf704fed18
MD5 8397ba8ca5e4006ed8496d5ec91b4f95
BLAKE2b-256 c4716a305e370b97991fcec53e246d39234d28e6749a909f4fb0cda666e1171f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page