dtflow 0.5.6__tar.gz → 0.5.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. {dtflow-0.5.6 → dtflow-0.5.8}/.gitignore +3 -0
  2. {dtflow-0.5.6 → dtflow-0.5.8}/PKG-INFO +47 -4
  3. {dtflow-0.5.6 → dtflow-0.5.8}/README.md +46 -1
  4. dtflow-0.5.8/dtflow/SKILL.md +245 -0
  5. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/__init__.py +1 -1
  6. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/__main__.py +70 -55
  7. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/clean.py +204 -8
  8. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/commands.py +16 -10
  9. dtflow-0.5.8/dtflow/cli/skill.py +72 -0
  10. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/stats.py +247 -40
  11. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/validate.py +52 -19
  12. dtflow-0.5.8/dtflow/parallel.py +115 -0
  13. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/schema.py +99 -13
  14. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/tokenizers.py +104 -21
  15. {dtflow-0.5.6 → dtflow-0.5.8}/pyproject.toml +0 -4
  16. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_cli_clean.py +239 -1
  17. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_cli_stats.py +150 -0
  18. dtflow-0.5.8/tests/test_parallel.py +153 -0
  19. dtflow-0.5.6/dtflow/mcp/__init__.py +0 -29
  20. dtflow-0.5.6/dtflow/mcp/__main__.py +0 -18
  21. dtflow-0.5.6/dtflow/mcp/cli.py +0 -388
  22. dtflow-0.5.6/dtflow/mcp/docs.py +0 -416
  23. dtflow-0.5.6/dtflow/mcp/server.py +0 -153
  24. {dtflow-0.5.6 → dtflow-0.5.8}/CHANGELOG.md +0 -0
  25. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/__init__.py +0 -0
  26. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/common.py +0 -0
  27. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/io_ops.py +0 -0
  28. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/lineage.py +0 -0
  29. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/pipeline.py +0 -0
  30. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/sample.py +0 -0
  31. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/cli/transform.py +0 -0
  32. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/converters.py +0 -0
  33. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/core.py +0 -0
  34. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/framework.py +0 -0
  35. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/lineage.py +0 -0
  36. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/pipeline.py +0 -0
  37. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/presets.py +0 -0
  38. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/storage/__init__.py +0 -0
  39. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/storage/io.py +0 -0
  40. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/streaming.py +0 -0
  41. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/utils/__init__.py +0 -0
  42. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/utils/display.py +0 -0
  43. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/utils/field_path.py +0 -0
  44. {dtflow-0.5.6 → dtflow-0.5.8}/dtflow/utils/helpers.py +0 -0
  45. {dtflow-0.5.6 → dtflow-0.5.8}/tests/README.md +0 -0
  46. {dtflow-0.5.6 → dtflow-0.5.8}/tests/benchmark_io.py +0 -0
  47. {dtflow-0.5.6 → dtflow-0.5.8}/tests/benchmark_sharegpt.py +0 -0
  48. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_cli_benchmark.py +0 -0
  49. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_cli_sample.py +0 -0
  50. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_cli_transform.py +0 -0
  51. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_converters.py +0 -0
  52. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_field_path.py +0 -0
  53. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_framework.py +0 -0
  54. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_io.py +0 -0
  55. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_lineage.py +0 -0
  56. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_pipeline.py +0 -0
  57. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_schema.py +0 -0
  58. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_streaming.py +0 -0
  59. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_tokenizers.py +0 -0
  60. {dtflow-0.5.6 → dtflow-0.5.8}/tests/test_transformer.py +0 -0
@@ -49,6 +49,9 @@ data/
49
49
  *.csv
50
50
  *.parquet
51
51
 
52
+ # Claude Code
53
+ .claude/settings.local.json
54
+
52
55
  # OS
53
56
  .DS_Store
54
57
  Thumbs.db
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dtflow
3
- Version: 0.5.6
3
+ Version: 0.5.8
4
4
  Summary: A flexible data transformation tool for ML training formats (SFT, RLHF, Pretrain)
5
5
  Project-URL: Homepage, https://github.com/yourusername/DataTransformer
6
6
  Project-URL: Documentation, https://github.com/yourusername/DataTransformer#readme
@@ -69,8 +69,6 @@ Requires-Dist: tokenizers>=0.15.0; extra == 'full'
69
69
  Requires-Dist: toolong>=1.5.0; extra == 'full'
70
70
  Provides-Extra: logs
71
71
  Requires-Dist: toolong>=1.5.0; extra == 'logs'
72
- Provides-Extra: mcp
73
- Requires-Dist: mcp>=1.0.0; extra == 'mcp'
74
72
  Provides-Extra: similarity
75
73
  Requires-Dist: datasketch>=1.5.0; extra == 'similarity'
76
74
  Requires-Dist: scikit-learn>=0.24.0; extra == 'similarity'
@@ -99,6 +97,17 @@ pip install transformers # Token 统计(HuggingFace 模型)
99
97
  pip install datasets # HuggingFace Dataset 转换
100
98
  ```
101
99
 
100
+ ## 🤖 Claude Code 集成
101
+
102
+ dtflow 内置了 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) skill:
103
+
104
+ ```bash
105
+ dt install-skill # 安装 skill
106
+ dt skill-status # 查看状态
107
+ ```
108
+
109
+ 安装后在 Claude Code 中输入 `/dtflow`,Claude 将掌握 dtflow 的完整用法,可直接协助你完成数据处理任务。
110
+
102
111
  ## 快速开始
103
112
 
104
113
  ```python
@@ -443,6 +452,7 @@ dt run pipeline.yaml --input=new_data.jsonl --output=result.jsonl
443
452
  dt token-stats data.jsonl --field=messages --model=gpt-4
444
453
  dt token-stats data.jsonl --field=messages[-1].content # 统计最后一条消息
445
454
  dt token-stats data.jsonl --field=text --detailed
455
+ dt token-stats data.jsonl --workers=4 # 多进程加速(数据量大时自动启用)
446
456
 
447
457
  # 数据对比
448
458
  dt diff v1/train.jsonl v2/train.jsonl
@@ -471,13 +481,22 @@ dt dedupe data.jsonl --key=text --similar=0.8 # 相似度去重
471
481
  dt concat a.jsonl b.jsonl -o merged.jsonl
472
482
 
473
483
  # 数据统计
474
- dt stats data.jsonl
484
+ dt stats data.jsonl # 快速模式
485
+ dt stats data.jsonl --full # 完整模式(含值分布)
486
+ dt stats data.jsonl --full --field=category # 指定字段统计
487
+ dt stats data.jsonl --full --expand=tags # 展开 list 字段统计元素分布
488
+ dt stats data.jsonl --full --expand='messages[*].role' # 展开嵌套 list 字段
489
+
490
+ # Claude Code Skill 安装
491
+ dt install-skill # 安装到 ~/.claude/skills/
492
+ dt skill-status # 查看安装状态
475
493
 
476
494
  # 数据验证
477
495
  dt validate data.jsonl --preset=openai_chat # 使用预设 schema 验证
478
496
  dt validate data.jsonl --preset=alpaca --verbose # 详细输出
479
497
  dt validate data.jsonl --preset=sharegpt --filter-invalid -o valid.jsonl # 过滤出有效数据
480
498
  dt validate data.jsonl --preset=dpo --max-errors=100 # 限制错误输出数量
499
+ dt validate data.jsonl --preset=openai_chat --workers=4 # 多进程加速
481
500
  ```
482
501
 
483
502
  ### 字段路径语法
@@ -506,6 +525,18 @@ CLI 命令中的字段参数支持嵌套路径语法,可访问深层嵌套的
506
525
  | `token-stats` | `--field=` | `--field=messages[-1].content` |
507
526
  | `diff` | `--key=` | `--key=meta.uuid` |
508
527
 
528
+ `--where` 支持的操作符:
529
+
530
+ | 操作符 | 含义 | 示例 |
531
+ |--------|------|------|
532
+ | `=` | 等于 | `--where="category=tech"` |
533
+ | `!=` | 不等于 | `--where="source!=wiki"` |
534
+ | `~=` | 包含 | `--where="content~=机器学习"` |
535
+ | `>` | 大于 | `--where="score>0.8"` |
536
+ | `>=` | 大于等于 | `--where="messages.#>=2"` |
537
+ | `<` | 小于 | `--where="length<1000"` |
538
+ | `<=` | 小于等于 | `--where="turns<=10"` |
539
+
509
540
  示例数据:
510
541
  ```json
511
542
  {"meta": {"source": "wiki"}, "messages": [{"role": "user", "content": "hi"}, {"role": "assistant", "content": "hello"}]}
@@ -603,6 +634,18 @@ dt history processed.jsonl
603
634
  dt history processed.jsonl --json # JSON 格式输出
604
635
  ```
605
636
 
637
+ ### 日志查看
638
+
639
+ dtflow 内置了 [toolong](https://github.com/Textualize/toolong) 日志查看器:
640
+
641
+ ```bash
642
+ pip install dtflow[logs] # 安装日志工具
643
+
644
+ tl app.log # 交互式 TUI 查看
645
+ tl --tail app.log # 实时跟踪(类似 tail -f)
646
+ dt logs # 查看使用说明
647
+ ```
648
+
606
649
  ### 大文件流式处理
607
650
 
608
651
  专为超大文件设计的流式处理接口,内存占用 O(1),支持 JSONL、CSV、Parquet、Arrow 格式:
@@ -13,6 +13,17 @@ pip install transformers # Token 统计(HuggingFace 模型)
13
13
  pip install datasets # HuggingFace Dataset 转换
14
14
  ```
15
15
 
16
+ ## 🤖 Claude Code 集成
17
+
18
+ dtflow 内置了 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) skill:
19
+
20
+ ```bash
21
+ dt install-skill # 安装 skill
22
+ dt skill-status # 查看状态
23
+ ```
24
+
25
+ 安装后在 Claude Code 中输入 `/dtflow`,Claude 将掌握 dtflow 的完整用法,可直接协助你完成数据处理任务。
26
+
16
27
  ## 快速开始
17
28
 
18
29
  ```python
@@ -357,6 +368,7 @@ dt run pipeline.yaml --input=new_data.jsonl --output=result.jsonl
357
368
  dt token-stats data.jsonl --field=messages --model=gpt-4
358
369
  dt token-stats data.jsonl --field=messages[-1].content # 统计最后一条消息
359
370
  dt token-stats data.jsonl --field=text --detailed
371
+ dt token-stats data.jsonl --workers=4 # 多进程加速(数据量大时自动启用)
360
372
 
361
373
  # 数据对比
362
374
  dt diff v1/train.jsonl v2/train.jsonl
@@ -385,13 +397,22 @@ dt dedupe data.jsonl --key=text --similar=0.8 # 相似度去重
385
397
  dt concat a.jsonl b.jsonl -o merged.jsonl
386
398
 
387
399
  # 数据统计
388
- dt stats data.jsonl
400
+ dt stats data.jsonl # 快速模式
401
+ dt stats data.jsonl --full # 完整模式(含值分布)
402
+ dt stats data.jsonl --full --field=category # 指定字段统计
403
+ dt stats data.jsonl --full --expand=tags # 展开 list 字段统计元素分布
404
+ dt stats data.jsonl --full --expand='messages[*].role' # 展开嵌套 list 字段
405
+
406
+ # Claude Code Skill 安装
407
+ dt install-skill # 安装到 ~/.claude/skills/
408
+ dt skill-status # 查看安装状态
389
409
 
390
410
  # 数据验证
391
411
  dt validate data.jsonl --preset=openai_chat # 使用预设 schema 验证
392
412
  dt validate data.jsonl --preset=alpaca --verbose # 详细输出
393
413
  dt validate data.jsonl --preset=sharegpt --filter-invalid -o valid.jsonl # 过滤出有效数据
394
414
  dt validate data.jsonl --preset=dpo --max-errors=100 # 限制错误输出数量
415
+ dt validate data.jsonl --preset=openai_chat --workers=4 # 多进程加速
395
416
  ```
396
417
 
397
418
  ### 字段路径语法
@@ -420,6 +441,18 @@ CLI 命令中的字段参数支持嵌套路径语法,可访问深层嵌套的
420
441
  | `token-stats` | `--field=` | `--field=messages[-1].content` |
421
442
  | `diff` | `--key=` | `--key=meta.uuid` |
422
443
 
444
+ `--where` 支持的操作符:
445
+
446
+ | 操作符 | 含义 | 示例 |
447
+ |--------|------|------|
448
+ | `=` | 等于 | `--where="category=tech"` |
449
+ | `!=` | 不等于 | `--where="source!=wiki"` |
450
+ | `~=` | 包含 | `--where="content~=机器学习"` |
451
+ | `>` | 大于 | `--where="score>0.8"` |
452
+ | `>=` | 大于等于 | `--where="messages.#>=2"` |
453
+ | `<` | 小于 | `--where="length<1000"` |
454
+ | `<=` | 小于等于 | `--where="turns<=10"` |
455
+
423
456
  示例数据:
424
457
  ```json
425
458
  {"meta": {"source": "wiki"}, "messages": [{"role": "user", "content": "hi"}, {"role": "assistant", "content": "hello"}]}
@@ -517,6 +550,18 @@ dt history processed.jsonl
517
550
  dt history processed.jsonl --json # JSON 格式输出
518
551
  ```
519
552
 
553
+ ### 日志查看
554
+
555
+ dtflow 内置了 [toolong](https://github.com/Textualize/toolong) 日志查看器:
556
+
557
+ ```bash
558
+ pip install dtflow[logs] # 安装日志工具
559
+
560
+ tl app.log # 交互式 TUI 查看
561
+ tl --tail app.log # 实时跟踪(类似 tail -f)
562
+ dt logs # 查看使用说明
563
+ ```
564
+
520
565
  ### 大文件流式处理
521
566
 
522
567
  专为超大文件设计的流式处理接口,内存占用 O(1),支持 JSONL、CSV、Parquet、Arrow 格式:
@@ -0,0 +1,245 @@
1
+ ---
2
+ name: dtflow
3
+ description: >
4
+ 当用户需要处理 JSONL/CSV/Parquet/JSON/Arrow 数据文件时使用此 skill。
5
+ 提供 CLI 工具 `dt` 和 Python API `DataTransformer`。
6
+ 适用场景:(1) 查看数据:dt sample/head/tail 采样预览,dt stats 统计字段分布;
7
+ (2) 数据清洗:dt clean 支持 --drop-empty/--min-len/--max-len 过滤行,--keep/--drop/--rename/--promote/--add-field/--fill/--reorder 操作字段;
8
+ (3) 去重:dt dedupe 精确去重或 --similar 相似度去重;
9
+ (4) 格式转换:dt transform 预设模板(openai_chat/alpaca/sharegpt/dpo)或自定义配置;
10
+ (5) Schema 验证:dt validate --preset 验证数据格式;
11
+ (6) ML 训练框架导出:export_for("llama-factory"/"swift"/"axolotl") 一键生成训练配置;
12
+ (7) 大文件流式处理:load_stream() O(1) 内存处理 100GB+ 文件。
13
+ 注意:此工具专注数据文件的结构化处理,不涉及 LLM 调用(LLM 调用请用 flexllm)。
14
+ ---
15
+
16
+ # dtflow - 机器学习训练数据格式转换工具
17
+
18
+ ## 设计理念
19
+
20
+ - **函数式优于类继承**:直接用 lambda/函数做转换,不需要 OOP 抽象
21
+ - **KISS 原则**:一个 `DataTransformer` 类搞定所有操作
22
+ - **链式 API**:`dt.filter(...).to(...).save(...)`
23
+
24
+ ## Python API
25
+
26
+ ```python
27
+ from dtflow import DataTransformer
28
+
29
+ # 加载数据(支持 JSONL/JSON/CSV/Parquet/Arrow,使用 Polars 引擎)
30
+ dt = DataTransformer.load("data.jsonl")
31
+
32
+ # 链式操作
33
+ (dt.filter(lambda x: x.score > 0.8)
34
+ .to(lambda x: {"q": x.question, "a": x.answer})
35
+ .dedupe("text")
36
+ .save("output.jsonl"))
37
+ ```
38
+
39
+ ### 数据过滤
40
+
41
+ ```python
42
+ dt.filter(lambda x: x.score > 0.8)
43
+ dt.filter(lambda x: x.language == "zh")
44
+ ```
45
+
46
+ ### 数据验证
47
+
48
+ ```python
49
+ # 简单验证
50
+ errors = dt.validate(lambda x: len(x.messages) >= 2)
51
+
52
+ # Schema 验证
53
+ from dtflow import Schema, Field, openai_chat_schema
54
+
55
+ result = dt.validate_schema(openai_chat_schema) # 预设 Schema
56
+ valid_dt = dt.validate_schema(schema, filter_invalid=True) # 过滤无效数据
57
+ ```
58
+
59
+ **预设 Schema**:`openai_chat_schema`、`alpaca_schema`、`sharegpt_schema`、`dpo_schema`
60
+
61
+ ### 数据转换
62
+
63
+ ```python
64
+ # 自定义转换
65
+ dt.to(lambda x: {"question": x.q, "answer": x.a})
66
+
67
+ # 使用预设模板
68
+ dt.to(preset="openai_chat", user_field="q", assistant_field="a")
69
+ ```
70
+
71
+ **预设模板**:`openai_chat`、`alpaca`、`sharegpt`、`dpo_pair`、`simple_qa`
72
+
73
+ ### Token 统计
74
+
75
+ ```python
76
+ from dtflow import count_tokens, token_counter, token_filter, token_stats
77
+
78
+ count = count_tokens("Hello world", model="gpt-4")
79
+ dt.transform(token_counter("text")).save("with_tokens.jsonl")
80
+ dt.filter(token_filter("text", max_tokens=2048))
81
+
82
+ # Messages Token 统计(多轮对话)
83
+ from dtflow import messages_token_counter, messages_token_filter
84
+ dt.transform(messages_token_counter(model="gpt-4", detailed=True))
85
+ dt.filter(messages_token_filter(min_turns=2, max_turns=10))
86
+ ```
87
+
88
+ ### 格式转换器
89
+
90
+ ```python
91
+ from dtflow import (
92
+ to_hf_dataset, from_hf_dataset, # HuggingFace Dataset
93
+ to_openai_batch, from_openai_batch, # OpenAI Batch API
94
+ to_llama_factory, to_llama_factory_sharegpt, # LLaMA-Factory
95
+ to_swift_messages, to_swift_query_response, # ms-swift
96
+ messages_to_text, # messages 转纯文本
97
+ )
98
+ ```
99
+
100
+ ### 训练框架导出
101
+
102
+ ```python
103
+ # 检查兼容性
104
+ result = dt.check_compatibility("llama-factory")
105
+
106
+ # 一键导出
107
+ files = dt.export_for("llama-factory", "./output/") # 生成 data.json + dataset_info.json + train_args.yaml
108
+ files = dt.export_for("swift", "./output/") # 生成 data.jsonl + train_swift.sh
109
+ files = dt.export_for("axolotl", "./output/") # 生成 data.jsonl + config.yaml
110
+ ```
111
+
112
+ ### 大文件流式处理
113
+
114
+ ```python
115
+ from dtflow import load_stream, load_sharded
116
+
117
+ # O(1) 内存,100GB 文件也能处理
118
+ (load_stream("huge.jsonl")
119
+ .filter(lambda x: x["score"] > 0.5)
120
+ .save("output.jsonl"))
121
+
122
+ # 分片文件加载
123
+ (load_sharded("data/train_*.parquet")
124
+ .filter(lambda x: len(x["text"]) > 10)
125
+ .save("merged.jsonl"))
126
+
127
+ # 分片保存
128
+ load_stream("huge.jsonl").save_sharded("output/", shard_size=100000)
129
+ ```
130
+
131
+ ### 其他操作
132
+
133
+ ```python
134
+ dt.sample(100) # 随机采样
135
+ dt.head(10) / dt.tail(10) # 取前/后 N 条
136
+ train, test = dt.split(ratio=0.8) # 分割
137
+ dt.shuffle(seed=42) # 打乱
138
+ dt.stats() # 统计
139
+ ```
140
+
141
+ ## CLI 命令
142
+
143
+ ```bash
144
+ # 统计(推荐首先使用)
145
+ dt stats data.jsonl # 基本统计(文件大小、条数、字段)
146
+ dt stats data.jsonl --full # 完整模式:值分布、唯一值、非空率
147
+ dt stats data.jsonl --full -n 20 # 显示 Top 20 值分布
148
+ dt stats data.jsonl --field=meta.source # 只统计指定字段(支持嵌套路径,可多次使用)
149
+ dt stats data.jsonl --expand=tags # 展开 list 字段统计(可多次使用)
150
+
151
+ # Token 统计
152
+ dt token-stats data.jsonl # 默认统计 messages 字段
153
+ dt token-stats data.jsonl -f text # 指定统计字段
154
+ dt token-stats data.jsonl -m qwen2.5 # 指定分词器 (cl100k_base/qwen2.5/llama3)
155
+ dt token-stats data.jsonl --detailed # 显示详细统计
156
+ dt token-stats data.jsonl -w 4 # 多进程加速(数据量>=1000时自动启用)
157
+
158
+ # 采样(支持字段路径语法)
159
+ dt sample data.jsonl 100 # 随机采样 100 条
160
+ dt sample data.jsonl 100 -t head # 取前 100 条 (head/tail/random)
161
+ dt sample data.jsonl 1000 --by=category # 分层采样
162
+ dt sample data.jsonl 1000 --by=category --uniform # 均匀分层采样
163
+ dt sample data.jsonl --where="messages.#>=2" # 条件筛选
164
+ dt sample data.jsonl 10 -f input,output # 只显示指定字段
165
+ dt sample data.jsonl 10 --raw # 输出原始 JSON(不截断)
166
+ dt sample data.jsonl 100 --seed=42 -o out.jsonl # 固定随机种子并保存
167
+
168
+ # 去重
169
+ dt dedupe data.jsonl --key=text # 精确去重
170
+ dt dedupe data.jsonl --key=meta.id # 按嵌套字段去重
171
+ dt dedupe data.jsonl --key=text --similar=0.8 # 相似度去重
172
+ dt dedupe data.jsonl --key=text -o deduped.jsonl # 指定输出文件
173
+
174
+ # 清洗
175
+ dt clean data.jsonl --drop-empty=text,answer # 删除空值记录
176
+ dt clean data.jsonl --min-len=text:10 # 最小长度过滤
177
+ dt clean data.jsonl --max-len=text:2000 # 最大长度过滤
178
+ dt clean data.jsonl --min-len=messages.#:2 # 最少 2 条消息
179
+ dt clean data.jsonl --keep=question,answer # 只保留指定字段
180
+ dt clean data.jsonl --drop=metadata # 删除指定字段
181
+ dt clean data.jsonl --rename=question:instruction,answer:output # 重命名字段
182
+ dt clean data.jsonl --promote=meta.label # 提升嵌套字段到顶层
183
+ dt clean data.jsonl --promote=meta.label:tag # 提升并自定义名称
184
+ dt clean data.jsonl --add-field=source:web # 添加常量字段
185
+ dt clean data.jsonl --fill=label:unknown # 填充空值/缺失字段
186
+ dt clean data.jsonl --reorder=id,text,label # 控制字段输出顺序
187
+ dt clean data.jsonl --strip # 去除字符串首尾空白
188
+ dt clean data.jsonl --promote=meta.label --drop=meta --fill=label:unknown # 组合使用
189
+
190
+ # 验证
191
+ dt validate data.jsonl --preset=openai_chat # 预设: openai_chat/alpaca/dpo/sharegpt
192
+ dt validate data.jsonl -p alpaca -f -o valid.jsonl # 过滤无效数据并保存
193
+ dt validate data.jsonl -p openai_chat -v # 显示详细信息
194
+ dt validate data.jsonl -p openai_chat --max-errors=50 # 最多显示 50 条错误
195
+ dt validate data.jsonl -p openai_chat -w 4 # 多进程加速
196
+
197
+ # 转换
198
+ dt transform data.jsonl --preset=openai_chat
199
+ dt transform data.jsonl # 交互式生成配置文件
200
+
201
+ # 合并与对比
202
+ dt concat a.jsonl b.jsonl -o merged.jsonl # 合并文件
203
+ dt concat a.jsonl b.jsonl -o merged.jsonl --strict # 严格模式(字段必须一致)
204
+ dt diff a.jsonl b.jsonl --key=id # 对比差异
205
+ dt diff a.jsonl b.jsonl --key=id -o report.md # 输出对比报告
206
+
207
+ # 查看数据
208
+ dt head data.jsonl 10 # 前 10 条
209
+ dt head data.jsonl 10 -f input,output # 只显示指定字段
210
+ dt head data.jsonl 10 --raw # 输出完整 JSON(不截断)
211
+ dt tail data.jsonl 10 # 后 10 条
212
+
213
+ # 其他
214
+ dt run pipeline.yaml # Pipeline 执行
215
+ dt history processed.jsonl # 数据血缘
216
+ dt install-skill # 安装 Claude Code skill
217
+ ```
218
+
219
+ ## 字段路径语法
220
+
221
+ | 语法 | 含义 | 示例 |
222
+ |------|------|------|
223
+ | `a.b.c` | 嵌套字段 | `meta.source` |
224
+ | `a[0].b` | 数组索引 | `messages[0].role` |
225
+ | `a[-1].b` | 负索引 | `messages[-1].content` |
226
+ | `a.#` | 数组长度 | `messages.#` |
227
+ | `a[*].b` | 展开所有元素 | `messages[*].role` |
228
+
229
+ ## Pipeline 配置
230
+
231
+ ```yaml
232
+ # pipeline.yaml
233
+ version: "1.0"
234
+ seed: 42
235
+ input: raw_data.jsonl
236
+ output: processed.jsonl
237
+
238
+ steps:
239
+ - type: filter
240
+ condition: "score > 0.5"
241
+ - type: transform
242
+ preset: openai_chat
243
+ - type: dedupe
244
+ key: text
245
+ ```
@@ -60,7 +60,7 @@ from .tokenizers import (
60
60
  token_stats,
61
61
  )
62
62
 
63
- __version__ = "0.5.6"
63
+ __version__ = "0.5.8"
64
64
 
65
65
  __all__ = [
66
66
  # core
@@ -6,21 +6,21 @@ Usage:
6
6
  dt --install-completion # 安装 shell 自动补全
7
7
 
8
8
  Commands:
9
- sample 从数据文件中采样
10
- head 显示文件的前 N 条数据
11
- tail 显示文件的后 N 条数据
12
- transform 转换数据格式(核心命令)
13
- stats 显示数据文件的统计信息
14
- token-stats Token 统计
15
- diff 数据集对比
16
- dedupe 数据去重
17
- concat 拼接多个数据文件
18
- clean 数据清洗
19
- run 执行 Pipeline 配置文件
20
- history 显示数据血缘历史
21
- validate 使用 Schema 验证数据格式
22
- mcp MCP 服务管理(install/uninstall/status)
23
- logs 日志查看工具使用说明
9
+ sample 从数据文件中采样
10
+ head 显示文件的前 N 条数据
11
+ tail 显示文件的后 N 条数据
12
+ transform 转换数据格式(核心命令)
13
+ stats 显示数据文件的统计信息
14
+ token-stats Token 统计
15
+ diff 数据集对比
16
+ dedupe 数据去重
17
+ concat 拼接多个数据文件
18
+ clean 数据清洗
19
+ run 执行 Pipeline 配置文件
20
+ history 显示数据血缘历史
21
+ validate 使用 Schema 验证数据格式
22
+ logs 日志查看工具使用说明
23
+ install-skill 安装 dtflow skill 到 Claude Code
24
24
  """
25
25
 
26
26
  import os
@@ -35,12 +35,15 @@ from .cli.commands import dedupe as _dedupe
35
35
  from .cli.commands import diff as _diff
36
36
  from .cli.commands import head as _head
37
37
  from .cli.commands import history as _history
38
+ from .cli.commands import install_skill as _install_skill
38
39
  from .cli.commands import run as _run
39
40
  from .cli.commands import sample as _sample
41
+ from .cli.commands import skill_status as _skill_status
40
42
  from .cli.commands import stats as _stats
41
43
  from .cli.commands import tail as _tail
42
44
  from .cli.commands import token_stats as _token_stats
43
45
  from .cli.commands import transform as _transform
46
+ from .cli.commands import uninstall_skill as _uninstall_skill
44
47
  from .cli.commands import validate as _validate
45
48
 
46
49
  # 创建主应用
@@ -161,11 +164,34 @@ def clean(
161
164
  max_len: Optional[str] = typer.Option(None, "--max-len", help="最大长度过滤 (字段:长度)"),
162
165
  keep: Optional[str] = typer.Option(None, "--keep", help="只保留指定字段"),
163
166
  drop: Optional[str] = typer.Option(None, "--drop", help="删除指定字段"),
167
+ rename: Optional[str] = typer.Option(None, "--rename", help="重命名字段 (old:new,old2:new2)"),
168
+ promote: Optional[str] = typer.Option(
169
+ None, "--promote", help="提升嵌套字段到顶层 (meta.label 或 meta.label:tag)"
170
+ ),
171
+ add_field: Optional[str] = typer.Option(None, "--add-field", help="添加常量字段 (key:value)"),
172
+ fill: Optional[str] = typer.Option(None, "--fill", help="填充空值 (field:default_value)"),
173
+ reorder: Optional[str] = typer.Option(
174
+ None, "--reorder", help="控制字段顺序 (field1,field2,...)"
175
+ ),
164
176
  strip: bool = typer.Option(False, "--strip", help="去除字符串首尾空白"),
165
177
  output: Optional[str] = typer.Option(None, "--output", "-o", help="输出文件路径"),
166
178
  ):
167
179
  """数据清洗"""
168
- _clean(filename, drop_empty, min_len, max_len, keep, drop, strip, output)
180
+ _clean(
181
+ filename,
182
+ drop_empty,
183
+ min_len,
184
+ max_len,
185
+ keep,
186
+ drop,
187
+ rename,
188
+ promote,
189
+ add_field,
190
+ fill,
191
+ reorder,
192
+ strip,
193
+ output,
194
+ )
169
195
 
170
196
 
171
197
  # ============ 数据统计命令 ============
@@ -176,9 +202,15 @@ def stats(
176
202
  filename: str = typer.Argument(..., help="输入文件路径"),
177
203
  top: int = typer.Option(10, "--top", "-n", help="显示 Top N 值"),
178
204
  full: bool = typer.Option(False, "--full", "-f", help="完整模式:统计值分布、唯一值等详细信息"),
205
+ field: Optional[List[str]] = typer.Option(
206
+ None, "--field", help="指定统计字段(可多次使用),支持嵌套路径"
207
+ ),
208
+ expand: Optional[List[str]] = typer.Option(
209
+ None, "--expand", help="展开 list 字段统计(可多次使用)"
210
+ ),
179
211
  ):
180
212
  """显示数据文件的统计信息"""
181
- _stats(filename, top, full)
213
+ _stats(filename, top, full, field, expand)
182
214
 
183
215
 
184
216
  @app.command("token-stats")
@@ -189,9 +221,12 @@ def token_stats(
189
221
  "cl100k_base", "--model", "-m", help="分词器: cl100k_base (默认), qwen2.5, llama3, gpt-4 等"
190
222
  ),
191
223
  detailed: bool = typer.Option(False, "--detailed", "-d", help="显示详细统计"),
224
+ workers: Optional[int] = typer.Option(
225
+ None, "--workers", "-w", help="并行进程数 (默认自动, 1 禁用并行)"
226
+ ),
192
227
  ):
193
228
  """统计数据集的 Token 信息"""
194
- _token_stats(filename, field, model, detailed)
229
+ _token_stats(filename, field, model, detailed, workers)
195
230
 
196
231
 
197
232
  @app.command()
@@ -227,9 +262,12 @@ def validate(
227
262
  filter: bool = typer.Option(False, "--filter", "-f", help="过滤无效数据并保存"),
228
263
  max_errors: int = typer.Option(20, "--max-errors", help="最多显示的错误数量"),
229
264
  verbose: bool = typer.Option(False, "--verbose", "-v", help="显示详细信息"),
265
+ workers: Optional[int] = typer.Option(
266
+ None, "--workers", "-w", help="并行进程数 (默认自动, 1 禁用并行)"
267
+ ),
230
268
  ):
231
269
  """使用预设 Schema 验证数据格式"""
232
- _validate(filename, preset, output, filter, max_errors, verbose)
270
+ _validate(filename, preset, output, filter, max_errors, verbose, workers)
233
271
 
234
272
 
235
273
  # ============ 工具命令 ============
@@ -263,48 +301,25 @@ dtflow 内置了 toolong 日志查看器,安装后可直接使用 tl 命令:
263
301
  print(help_text)
264
302
 
265
303
 
266
- # ============ MCP 子命令 ============
267
-
268
- mcp_app = typer.Typer(help="MCP 服务管理")
269
- app.add_typer(mcp_app, name="mcp")
270
-
271
-
272
- @mcp_app.command()
273
- def install(
274
- name: str = typer.Option("datatron", "--name", "-n", help="MCP 服务名称"),
275
- target: str = typer.Option("code", "--target", "-t", help="安装目标: desktop/code/all"),
276
- ):
277
- """安装 Datatron MCP 服务"""
278
- from .mcp.cli import MCPCommands
279
-
280
- MCPCommands().install(name, target)
281
-
282
-
283
- @mcp_app.command()
284
- def uninstall(
285
- name: str = typer.Option("datatron", "--name", "-n", help="MCP 服务名称"),
286
- target: str = typer.Option("all", "--target", "-t", help="移除目标: desktop/code/all"),
287
- ):
288
- """移除 Datatron MCP 服务"""
289
- from .mcp.cli import MCPCommands
290
-
291
- MCPCommands().uninstall(name, target)
304
+ # ============ Skill 命令 ============
292
305
 
293
306
 
294
- @mcp_app.command()
295
- def status():
296
- """查看 MCP 服务安装状态"""
297
- from .mcp.cli import MCPCommands
307
+ @app.command("install-skill")
308
+ def install_skill():
309
+ """安装 dtflow skill 到 Claude Code"""
310
+ _install_skill()
298
311
 
299
- MCPCommands().status()
300
312
 
313
+ @app.command("uninstall-skill")
314
+ def uninstall_skill():
315
+ """卸载 dtflow skill"""
316
+ _uninstall_skill()
301
317
 
302
- @mcp_app.command()
303
- def test():
304
- """测试 MCP 服务是否正常"""
305
- from .mcp.cli import MCPCommands
306
318
 
307
- MCPCommands().test()
319
+ @app.command("skill-status")
320
+ def skill_status():
321
+ """查看 skill 安装状态"""
322
+ _skill_status()
308
323
 
309
324
 
310
325
  def _show_completion_hint():