-
Notifications
You must be signed in to change notification settings - Fork 150
No.41 SDPO实现与复现 #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ZiyiTsang
wants to merge
274
commits into
redai-studio:main
Choose a base branch
from
ZiyiTsang:sdpo
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
No.41 SDPO实现与复现 #237
Changes from 250 commits
Commits
Show all changes
274 commits
Select commit
Hold shift + click to select a range
52fe76a
fix(megatron): restore cuda patch target in validate_args
Yangruipis d20dd64
chore(data): remove unused prompt helpers
dirtyDan0 cbd1895
fix(data): avoid prompt mutation in reads
dirtyDan0 95d39be
fix(megatron): wait for previous eval on final training step
NINGBENZHE eb89a0d
feat(megatron): upgrade to Megatron-Bridge mainline
Yangruipis 338324b
feat(models): add Qwen3.6-35B-A3B support with MoE expert detection
Yangruipis 1bb19f4
feat(metrics): report reward dict fields
dirtyDan0 aef19c6
fix(deepeyes): collapse duplicate image_pad tokens before load_mm_data
Yangruipis 79b764c
fix(megatron): GDN torch.compile + Qwen3.6 unsplit forward
Yangruipis 0d0dcfe
fix(qwen3.6): fp16 support and related fixes
Yangruipis 2a24010
feat(genrm): support shared-GPU colocate with rollout
Yangruipis cf776b4
fix(device): avoid gloo dist backend on CPU-only Ray driver
Yangruipis 8407f9d
feat(glm5): support glm5 model and parameterize env variables
NINGBENZHE 710d50f
chore(docker): switch torch_memory_saver to redai-infra fork
NINGBENZHE 851c2ac
refactor(scripts): separate MODEL_DIR/DATA_DIR/EXP_DIR
Yangruipis 6ffee26
chore(deepeyes): remove duplicate rollout gpus-per-engine arg in deep…
dirtyDan0 d9089f7
fix(deepeyes): preserve multimodal sample state
dirtyDan0 7359829
feat(async): auto-enable true-on-policy mode and skip actor_fwd
NINGBENZHE e9639a1
fix: resume bug if num_rollout changed
Yangruipis 8442731
fix(slime-sync): port 8 upstream slime fixes
li126com a17e9b9
fix: add qwen3.6 async image example and rollout healthcheck retry fo…
Yangruipis a5af22e
feat(data): add custom-prompt-path and image-resize-scale-factor
yxyOo 8fa57a4
feat(training): add hybrid training mode
yxyOo d9be1bc
feat: add eval for multimodal
liujia-cc 73d78e0
feat(visualize): add rollout result viewer (web + TUI)
Yangruipis 430c1f4
fix(scripts): split MODEL_DIR/EXP_DIR/DATA_DIR init
Yangruipis 56b1773
fix(CE): restore openr1 script to fix CE error
liujia-cc 213863e
chore(deepeyes): align datasets with main script
dirtyDan0 f77758c
docs(hybrid): add bilingual hybrid training guide
yxyOo c695ce5
feat(megatron): dump provider config as json
Yangruipis 62a0e0a
docs(readme): document hybrid execution mode
yxyOo 3b1f339
perf(megatron): warm HF ckpt page cache before bridge load
Yangruipis c632ba9
feat(megatron): wire VPP training
Yangruipis 61d77bf
fix(deepeyes): repair rollout recovery paths
dirtyDan0 3c5967e
feat(kimi-k2.6): add INT4 QAT training support
NINGBENZHE b690511
fix(megatron): idempotent grad/param sync setup
yxyOo 852ddf6
Low Precision Training Support
21758b1
fix(megatron): skip IPC route for hybrid weight sync
ec92a90
docs: add Kimi K2.6 to model tables and Skills section
NINGBENZHE 4bf681f
fix(sglang): backport mamba pool sizing #24244
Yangruipis 62a92e8
fix: ci tests
Yangruipis 555ea80
docs: add projects built upon Relax
Yangruipis 45c1677
fix(gitleaks): tighten secret allowlists
Yangruipis 09fa804
fix(scripts,ci): clean up dir vars and narrow gitleaks scope
Yangruipis 52f6d6a
feat(perf): replace FLOPS calculation with verl-style FlopsCounter an…
NINGBENZHE d9441d8
feat(weight-update,scripts): add Qwen3.5-397B support and unify bridg…
NINGBENZHE 69a696c
fix(megatron): use global_param_name and tqdm progress bar
Yangruipis c19d9ef
fix(R3): shape mismatch when cp > 1
liujia-cc 2ee5140
fix(weight-sync): use node_id to detect colocated rollout engines
yxyOo 2323ceb
perf(megatron-loss): scale logits per-chunk to avoid OOM
Yangruipis 1079893
fix(misc): tui bug
Yangruipis ac55f1c
fix(flops): handle CPU peak detection
Yangruipis 69f910a
[NPU] Support qwen3-4B dapo full async mode on Ascend NPU (#36)
meiqingsui a650d4a
fix(args): validate rollout batch sizing
Yangruipis d925047
Revert "Merge branch fix/wuhuan/tiny_bugs into dev"
Yangruipis 1857260
fix: fix resume start step from 0, beacase of start_rollout_id is not…
NINGBENZHE ab679a1
feat(agentic): add agentic rollout
dirtyDan0 b9450a3
feat(metrics): add multimodal and agent rollout metrics
Yangruipis 98e9855
fix(sft): use self.healthy for actor handle to preserve Base._healthy…
Yangruipis d16c25e
chore(rollout): align generation runtime behavior
dirtyDan0 2890680
fix(sft): use self.healthy for actor handle to preserve Base._healthy…
370414e
chore(scripts): cap OMP/MKL/BLAS threads in Ray runtime env
xiaoliang0601 e5c7f62
feat: support per-sample apply_chat_template_kwargs
NINGBENZHE d463d0d
feat(sft): support OpenAI-style tool_calls + tool role in chat data
Yangruipis bc7d5e6
perf(stream-dataloader): NCCL-stream multimodal inputs
yxyOo 04642a6
fix(stream-dataloader): broadcast multimodal inputs over CP before TP/PP
yxyOo 5547eca
fix(entrypoint): avoid suiciding self when cleaning old ray jobs
Yangruipis 3a3b80e
fix: test failed for python3.10
Yangruipis aa05058
fix(test): kill ray workers for each testcase
Yangruipis 638866e
feat(models): support dots.mocr training (#42)
Yangruipis 7af7bf9
feat(rollout): support async over-sampling in fully-async mode
NINGBENZHE 68ae62a
fix(rollout): handle abort with eos
dirtyDan0 adde31a
feat(weight-conversion): add Qwen3 VL MoE converter
Yangruipis 5da77c6
docs(readme): update community links and add docker badge
Yangruipis f8455a2
fix(ray): spread scheduling and stale-job cleanup
NINGBENZHE bb05453
fix: enable logprob maxtoken and adjust param to increase gpu utils
liujia-cc ed5d8e7
chore(scripts): tune qwen35-9b hybrid-async config
yxyOo 5e8876b
chore(scripts): tune qwen35-9b hybrid-async config
yxyOo 49812ff
feat(rollout): support reasoning and tool call parsers
dirtyDan0 26a450a
fix(registry): override StrEnum.__str__ for Python 3.10 colocate dete…
yeqinghe609 9a191dd
fix(args): validate rollout batch sizing
Yangruipis 1c7eaae
Revert "Merge branch fix/wuhuan/tiny_bugs into dev"
Yangruipis 511ac02
perf(dataloader): skip GPU round-trips for trivial parallel groups
yxyOo 7ececdf
fix(sft): exit on data errors and bound TQ wait
Yangruipis d3e99bf
chore(rollout): align generation runtime behavior
Yangruipis 5cc260c
feat: add npu ci
NINGBENZHE eeffd0e
feat(model): add qwen3.5-27B example
Yangruipis 2845de6
fix(tools): auto-disable MTP in bridge convert
yxyOo 0090a5f
feat(mtp): add qwen35 mtp 8gpu script (mtp rollout + train)
li126com 77d9e59
feat(algorithm): integrate CISPO algorithm
fxsc03 380e7c7
fix: batch size of sft bench
Yangruipis 5c0bb0d
feat(megatron): fully-async dynamic-batch streaming for PP/DP
NINGBENZHE 7521df2
ci(gitleaks): scan tracked files
Yangruipis d0f9449
fix(rollout): guard context before append
dirtyDan0 93144fa
transferqueue lazy import
GUOGUOPOT d32fa9b
fix(requirements): fixed pyarrow version at 14.0.2 to match numpy<2
yuanlehome cb43be3
feat(sft): chunked logits & fused grouped gemm
xiaoliang0601 5ad58f2
fix(scripts,ci): clean up dir vars and narrow gitleaks scope
Yangruipis 70b4bac
Revert "Merge branch fix/tfq_lazy_import into dev"
Yangruipis e9ea9ee
fix(tools): force contiguous tensors in bridge HF export
Yangruipis b06b31b
fix(controller): hint tq upgrade on missing sampler
Yangruipis f860ad3
feat(skills): add GitHub sync workflow
Yangruipis fe564fe
fix(rollout): set SGLANG TP imbalance check via ENABLE
yxyOo bbdaaf7
fix(test): test cases stale state
Yangruipis 7ad441c
fix(test): github unittests
Yangruipis b620106
fix(wandb): add wandb init (#55)
grootZ 20b3925
feat(klx):add klx XPU training support for Qwen3-4B, Qwen3.5-9B and Q…
yeqinghe609 242e2b8
feat(npu): add NPU training support for Qwen3-4B and Qwen3.5-9B in fu…
hbamboo 1cabd3e
fix(megatron-fp16): avoid assert crash & double grad scaling under fp…
jamesruio fa7d16c
docs: fix stale branch name in raw GitHub link (#59)
YowatariChiaki f2cfef5
fix(rollout): SGLang PD bootstrap TP size inference (#61)
anranxia 11d0215
fix(agentic): surface agent subprocess errors in driver log
Yangruipis 9843b12
feat(megatron): split rollout mini batches
NINGBENZHE 89701fc
fix(entrypoint,tools): harden multinode worker join & expose GPUs in …
Yangruipis b19dd12
fix(genrm): prevent colocate OOM and unblock judge concurrency
yxyOo 6b5d68a
feat: adopt qs_inject shim for tensorboard SummaryWriter
Yangruipis 3026fbb
feat(deepeyes-v2-agentic): DeepEyes V2 example on the agentic stack
Yangruipis 9405dfe
feat: support partial_rollout with dynamic_global_batch_size
liujia-cc 68ce1eb
fix(rollout): pass image config to agentic
dirtyDan0 f366bc6
fix: fix CE gbs not set
NINGBENZHE 10a9b6d
feat(genrm): two-phase colocate GenRM via defer + swap
Yangruipis a70015b
feat(sft): support & reproduce redaccel cot compression
xiaoliang0601 f18b76a
feat(router): add sticky-session routing
flyinglandlord 0a3632a
fix(wandb): initialize tracking after Serve
Yangruipis 654d7b6
fix(test): CI collection and add GitHub sync gate (#62)
Yangruipis bf72f18
fix(sglang-nonfp8): catch broad Exception for fp8 ue8m0 imports to su…
yeqinghe609 371ada5
fix(klx-scripts): Update qwen3/qwen3.5 training scripts for klx (#60)
fenta 72e92cf
fix(megatron): sync conditional vision branch
NINGBENZHE a8cb7cd
docs(scripts): remove misleading comments in convert_torch_dist_to_hf…
xiaoliang0601 7df195e
feat(opd): add core distillation plumbing
kkyyxhll be657fe
fix(deepeyes-v2): eliminate rollout hang and cancel storms
Yangruipis 853cb02
fix(controller): reset sglang router on global restart
Yangruipis 1ea3325
fix(megatron): resolve PP≥2 NCCL P2P deadlock with same-peer / SPMD skew
Yangruipis 83e9093
fix(sglang): pin genRM moe_dense_tp_size to avoid corrupt weights
yuanlehome 89499c2
feat(megatron): support dynamic_context_parallel
liujia-cc fe53a02
docs(dynamic-cp): add feature guide
Yangruipis cb1d51a
fix: docker build error for documents
Yangruipis 5bb3f7e
docs(sync-github): base-locate via cherry-pick tails on both sides
Yangruipis 9f8ecee
feat(npu): add Qwen3.5-35B-A3B training scripts and NPU infrastructur…
hbamboo ddfedcd
fix: async reward computation streamed prompt groups (#65)
mununumu 8b23346
docs(deepeyes-v2): add adaptation pitfalls guide
Yangruipis 7a0d52f
feat(opd): add core distillation plumbing
fxsc03 cd0b760
support qwen3.6 multimodal qat
GUOGUOPOT 4f2a97b
refactor(warmup): extend HF page-cache warmup to genrm and teacher
Yangruipis 7f5ac76
fix(rollout): throttle data-system wait log
Yangruipis a19a39e
refactor(utils): merge relax.tools into relax.utils
Yangruipis 1c247ef
feat(sglang): upgrade to v0.5.12.post1-cu129
yuanlehome 197cef2
chore: uncommit kimi 2-layer smoke launcher and sglang upgrade-plan d…
yuanlehome 3598a26
feat(quant-cast): add streaming FP8 export
Yangruipis 5855d64
fix(distributed): use version parse for pg_options name
3de9a89
fix(sft): multimodal data process
GUOGUOPOT f0cdde4
fix(multimodal): eager-decode images to survive fd close on flaky NFS
xiaoliang0601 fac6ba0
fix(sft): preserve Qwen tool-call thinking
Yangruipis 143e72e
fix(examples): correct CISPO script paths and disable KL loss (#72)
fxsc03 f061244
fix(deps): pin FastAPI for Ray Serve (#74)
Yangruipis a8f8802
fix(opd): fix opd scripts (#70)
kkyyxhll b055f8d
docs(installation): update official image (#75)
Yangruipis 1094df9
feat(models): qwen3-0.6B.sh (#79)
Baiiiii126 05fc68f
chore(opd): update Math OPD training recipe (#84)
kkyyxhll cbf09f0
fix(training): handle unknown GPU metrics (#80)
Dayuxiaoshui 3a123d5
fix(streaming): per-window quota to fix DP-imbalance deadlock
NINGBENZHE b7194e7
feat(arguments): check TransferQueue version for fully-async
NINGBENZHE 13c5075
feat(model): support lora training for dense model
GUOGUOPOT 3b1db0f
feat(rollout): support multi-record exports
dirtyDan0 42dda50
fix(peft): clearer error when Megatron-Bridge lacks PEFT
Yangruipis c422eba
feat(ppo): add PPO algorithm end-to-end
Yangruipis 3f3f606
feat(sft): support 128K Qwen3.5 397B training
Yangruipis 73a8b87
fix(megatron): tolerate missing MTP export keys
NINGBENZHE 787b80f
fix(megatron): correct GDN context-parallel all-gather grads & guards
NINGBENZHE 8a2d2e0
fix(ci): isolate Megatron-free tests
Yangruipis 42f53f8
fix(convert): reconcile HF export index and supplement missing MTP (#…
circleLZY 022ff82
【No.11】test(data): add unit tests for seqlen_balancing partitions (#90)
Saddss d0c79ab
test(data): cover multimodal prompt length filtering (#103)
xiaoh1024 b65b2ac
【No.16】feat(data): configurable media-encoding thread pool via --enco…
Saddss cfebed8
test(training): cover GRPO return and KL utils (#128)
Dayuxiaoshui e8eefc9
【No.10】 test(rewards): add DAPO math utils coverage (#94)
howtomakeaname 5260b36
feat(rewards): format-aware reward router with registry and fallback …
DreamEnding 5ebed6c
feat(klx): add qwen35-35B-vl, qwen36-35B support and performance opti…
grootZ 87e1452
feat(rewards): run sync custom rewards in worker pool (#181)
sidneychang d310482
feat(rollout): Optimize multi-turn Rollout request scheduling (#127)
overloadedHenry c83741d
perf(megatron): backport upstream frozen-weight DGRAD fold to the ima…
guanzheh b25f8fd
test(multimodal): cover image preprocessing utilities (#107)
MaybeIcanShow ef60b8f
fix(megatron): make FP16 optimizer settings configurable (#146)
huxy1225-cloud 278c1e0
feat(sdpo): add SDPO-lite training path
ZiyiTsang 30b74af
feat(megatron): add selective CPU offload as an alternative to torch_…
yeqinghe609 64b68e5
feat(examples): integrate nemo-gym agentic environments (#179)
Yangruipis 864857f
feat(sdpo): add Relax-SDPO training path
ZiyiTsang 0e06348
fix(genrm): stabilize GenRM colocate init and offload
NINGBENZHE 4c52f6a
feat: migrate ark feature and fix to dev
li126com 3bb8a1f
fix(checkpoint): alias renamed transfer_queue enum
yxyOo 25ac0ac
fix(sft): support dynamic CP evaluation
Yangruipis 4761069
feat(mopd): 9B recipe + data-prep/reward fixes
fxsc03 fbe4046
fix(sglang): detect dead engines when flushing cache
li126com 18968fb
fix(sft): support inline image URL inputs
Yangruipis 1591881
fix(rollout): retry get() like post() so a transient router disconnec…
yuanlehome 9431128
fix(deps): pin fastapi==0.136.0 to fix agentic 422
yuanlehome fd77086
feat(utils): centralize environment variable access
li126com 89cf658
fix(dcs): keep training alive when a scale-out rollout engine dies
RexFlux 4954568
feat(training): add Qwen3.5-35B-A3B VPP script
yuanlehome b9fb758
feat(example): add mini-swe-agent example
yxyOo 6f79010
fix(sglang): support DP-aware router workers
yuanlehome 719309b
feat(service): affinitize baseline roles to stable worker-group via c…
RexFlux e9a4870
fix(opd): fix opd scripts (#70)
NINGBENZHE 22c64e9
fix(ci): skip optional backend test deps
NINGBENZHE 8893612
test(megatron): guard unavailable backend import
ZiyiTsang e63049c
【No.017】Replace DeepEyes processor file override with dynamic registr…
A-Words f5ba4ab
test(sdpo): refine SDPO validation baseline
ZiyiTsang 6cc82d2
feat(sdpo): add EMA teacher weight updates
ZiyiTsang 69c4e37
fix(sdpo): finalize EMA teacher publishing
ZiyiTsang 6954be4
fix(sdpo): complete teacher publish flow
ZiyiTsang 8d200e9
merge: finalize SDPO EMA teacher path
ZiyiTsang 902ebb0
merge: sync upstream main
ZiyiTsang 4152ed6
refactor(opd): reuse feedback and generic loss
ZiyiTsang 8cda947
Merge remote-tracking branch 'upstream/main' into sdpo
ZiyiTsang 0982fa7
feat(klx): add qwen35-9B-vl script (#249)
yeqinghe609 4c2f8b9
feat(rl): implement REINFORCE++ variants with global normalization (#…
zheself 82b7117
fix(sdpo): derive project root in settings
ZiyiTsang e9cd530
Merge remote-tracking branch 'upstream/main' into sdpo
ZiyiTsang efff599
feat(opd): add SDPO feedback plumbing
ZiyiTsang 19d687a
docs: add Relax-SDPO README
ZiyiTsang 0d0f08c
fix(opd): align SDPO with upstream math
ZiyiTsang becf6a4
refactor(opd): gate OPD sample mask into loss masks instead of denomi…
ZiyiTsang 812fe06
docs(sdpo): polish SDPO example README for new users
ZiyiTsang 85355d8
feat(sdpo): switch example launchers to EMA teacher and auto-enable t…
ZiyiTsang ac7670d
chore(sdpo): simplify launcher context config and drop cuda-graph dis…
ZiyiTsang abaf55d
refactor(sdpo): unify env config in env.yaml
ZiyiTsang 47329b1
feat(sdpo): implement METH distillation decision matrix
ZiyiTsang 5ad1497
refactor(sdpo): default example launchers to static teacher update
ZiyiTsang 8986ec7
# 🐛 fix
ZiyiTsang 439486b
feat(sdpo): upgrade all launchers to 4-GPU TP=4 colocate
ZiyiTsang 857b3fe
refactor(sdpo): revert megatron internals to PR base
ZiyiTsang d31dc3b
refactor(sdpo): strip EMA teacher path and redundant validation
ZiyiTsang 9d26fd9
chore(sdpo): remove REVIEWER_RESPONSE.md from PR branch
ZiyiTsang df8f29d
fix(sdpo): repair eval data args in launchers
ZiyiTsang 3c5b995
chore(sdpo): tune launchers (env source, rollout/eval scaling)
ZiyiTsang f93473f
Merge remote-tracking branch 'upstream/main' into sdpo
ZiyiTsang ff7d1f2
fix(sdpo): keep configs/env.yaml tracked, align .gitignore with upstream
ZiyiTsang 9da912b
style: apply pre-commit formatting fixes from upstream merge
ZiyiTsang 3201cb9
chore: drop unnecessary copyright header from tensor_backper.py and t…
ZiyiTsang 5a83435
fix(examples): pairwise tooluse reward scoring
ZiyiTsang 75c74fc
refactor(opd): per-algorithm feedback strategies
ZiyiTsang 139cd93
refactor(opd): unify feedback strategies
ZiyiTsang 1026a77
Merge remote-tracking branch 'upstream/main' into sdpo
ZiyiTsang edf2d80
fix(ci): stub sglang modules in opd teacher colocate arguments tests
ZiyiTsang 4c2864e
refactor(opd): drop dead code and ghost test attrs
ZiyiTsang 8f4b9a2
feat(sdpo): unify 4xgpu launchers and params
ZiyiTsang f8054a1
refactor(opd): drop redundant state.feedback alias
ZiyiTsang adcefb8
revert(opd): keep existing recipes unchanged
ZiyiTsang 155c4e0
feat(opd): add --opd-feedback-kwargs binding
ZiyiTsang 0d50b1f
style(sdpo): fix pre-commit formatting violations
ZiyiTsang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Copyright (c) 2026 Relax Authors. All Rights Reserved. | ||
|
|
||
| """Minimal static-teacher SDPO examples for Relax.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,261 @@ | ||
| # Copyright (c) 2026 Relax Authors. All Rights Reserved. | ||
|
|
||
| """Prepare the reference SDPO SciKnowEval and ToolAlpaca data for Relax.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import argparse | ||
| import json | ||
| import logging | ||
| import random | ||
| from pathlib import Path | ||
| from typing import Any, Iterable | ||
|
|
||
|
|
||
| logger = logging.getLogger(__name__) | ||
| TARGET_DOMAINS = frozenset({"Chemistry", "Physics", "Biology", "Materials"}) | ||
|
|
||
|
|
||
| def _read_jsonl(path: Path) -> list[dict[str, Any]]: | ||
| with path.open(encoding="utf-8") as handle: | ||
| return [json.loads(line) for line in handle if line.strip()] | ||
|
|
||
|
|
||
| def _read_rows(path: Path) -> list[dict[str, Any]]: | ||
| if path.suffix.lower() in {".jsonl", ".json"}: | ||
| if path.suffix.lower() == ".jsonl": | ||
| return _read_jsonl(path) | ||
| text = path.read_text(encoding="utf-8").strip() | ||
| try: | ||
| value = json.loads(text) | ||
| except json.JSONDecodeError: | ||
| return _read_jsonl(path) | ||
| return value if isinstance(value, list) else [value] | ||
| if path.suffix.lower() == ".parquet": | ||
| import pyarrow.parquet as parquet | ||
|
|
||
| return parquet.read_table(path).to_pylist() | ||
| raise ValueError(f"Unsupported input format: {path}") | ||
|
|
||
|
|
||
| def _canonical_domain(value: Any) -> str: | ||
| normalized = str(value or "").strip().casefold() | ||
| if normalized == "material": | ||
| return "Materials" | ||
| return normalized.capitalize() | ||
|
|
||
|
|
||
| def _json_text(value: Any) -> str: | ||
| if isinstance(value, str): | ||
| return value | ||
| return json.dumps(value, ensure_ascii=False, sort_keys=True) | ||
|
|
||
|
|
||
| def _normalize_sciknoweval_row( | ||
| row: dict[str, Any], | ||
| *, | ||
| source_split: str, | ||
| domain: str | None, | ||
| ) -> dict[str, Any] | None: | ||
| if row.get("dataset") == "sciknoweval" and isinstance(row.get("prompt"), str) and "answer" in row: | ||
| normalized_domain = _canonical_domain(domain) | ||
| if normalized_domain not in {"Chemistry", "Physics", "Biology", "Materials"}: | ||
| return None | ||
| prompt = str(row["prompt"]).strip() | ||
| system = str(row.get("system") or "").strip() | ||
| if system: | ||
| prompt = f"{system}\n\n{prompt}" | ||
| answer = row.get("answer", "") | ||
| metadata = { | ||
| "data_source": "sciknoweval", | ||
| "source_split": source_split, | ||
| "domain": normalized_domain, | ||
| "task_type": str(row.get("kind", "mcq")), | ||
| "answer_key": answer, | ||
| "source_index": row.get("idx"), | ||
| } | ||
| return {"prompt": prompt, "label": _json_text(answer), "metadata": metadata} | ||
|
|
||
| details = row.get("details") or {} | ||
| if not isinstance(details, dict) or str(details.get("level", "")).upper() != "L3": | ||
| return None | ||
|
|
||
| source_domain = _canonical_domain(row.get("domain")) | ||
| if source_domain not in TARGET_DOMAINS: | ||
| return None | ||
|
|
||
| choices = row.get("choices") or {} | ||
| choice_lines = [ | ||
| f"{label}: {text}" for label, text in zip(choices.get("label") or [], choices.get("text") or [], strict=False) | ||
| ] | ||
| prompt_value = row.get("prompt", {}) | ||
| prompt_default = prompt_value.get("default", "") if isinstance(prompt_value, dict) else prompt_value | ||
| question = str(row.get("question") or prompt_default).strip() | ||
| prompt = question | ||
| if choice_lines: | ||
| prompt = f"{question}\n\n" + "\n".join(choice_lines) | ||
| prompt += "\n\nReason carefully and provide the final answer." | ||
|
|
||
| normalized_domain = source_domain | ||
| answer = row.get("answerKey") or row.get("answer", "") | ||
| metadata = { | ||
| "data_source": "sciknoweval", | ||
| "source_split": source_split, | ||
| "domain": normalized_domain, | ||
| "task_type": str(row.get("type", "unknown")), | ||
| "answer_key": answer, | ||
| } | ||
| return {"prompt": prompt, "label": _json_text(answer), "metadata": metadata} | ||
|
|
||
|
|
||
| def _normalize_tool_row(row: dict[str, Any], *, source_split: str, dataset: str) -> dict[str, Any] | None: | ||
| if row.get("dataset") == "tooluse" and isinstance(row.get("prompt"), str) and "answer" in row: | ||
| answer = row.get("answer", "") | ||
| try: | ||
| golden_answer = json.loads(answer) if isinstance(answer, str) else answer | ||
| except json.JSONDecodeError: | ||
| golden_answer = answer | ||
| prompt = str(row.get("prompt", "")).strip() | ||
| metadata = { | ||
| "data_source": "tooluse", | ||
| "source_split": source_split, | ||
| "task_type": str(row.get("kind", "tooluse")), | ||
| "golden_answer": golden_answer, | ||
| "source_index": row.get("idx"), | ||
| } | ||
| return {"prompt": prompt, "label": _json_text(answer), "metadata": metadata} | ||
|
|
||
| if dataset != "toolalpaca" or "golden_answer" not in row: | ||
| return None | ||
|
|
||
| name = str(row.get("name", "")).strip() | ||
| description = str(row.get("description", "")).strip() | ||
| documentation = str(row.get("nl_documentation", "")).strip() | ||
| instruction = str(row.get("instruction", row.get("prompt", ""))).strip() | ||
| prompt = ( | ||
| "You are given an API specification and a user request. Select the correct tool and " | ||
| "emit the tool call using exactly:\n" | ||
| "Action: <tool name>\nAction Input: <JSON object>\n\n" | ||
| f"Tool name: {name}\n" | ||
| f"Tool description: {description}\n" | ||
| f"Tool documentation:\n{documentation}\n\n" | ||
| f"User request:\n{instruction}" | ||
| ) | ||
| golden_answer = row.get("golden_answer") or [] | ||
| metadata = { | ||
| "data_source": "toolalpaca", | ||
| "source_split": source_split, | ||
| "task_type": "tool_call", | ||
| "golden_answer": golden_answer, | ||
| } | ||
| return {"prompt": prompt, "label": _json_text(golden_answer), "metadata": metadata} | ||
|
|
||
|
|
||
| def _normalize_relax_row(row: dict[str, Any], *, source_split: str) -> dict[str, Any] | None: | ||
| if not isinstance(row.get("prompt"), str) or "label" not in row: | ||
| return None | ||
| metadata = row.get("metadata") | ||
| if not isinstance(metadata, dict): | ||
| metadata = {} | ||
| metadata = dict(metadata) | ||
| metadata.setdefault("source_split", source_split) | ||
| return {"prompt": row["prompt"], "label": row["label"], "metadata": metadata} | ||
|
|
||
|
|
||
| def normalize_rows( | ||
| dataset: str, | ||
| rows: Iterable[dict[str, Any]], | ||
| *, | ||
| source_split: str, | ||
| domain: str | None = None, | ||
| ) -> list[dict[str, Any]]: | ||
| """Convert one supported source schema into Relax's prompt-data schema.""" | ||
| if dataset not in {"sciknoweval", "toolalpaca", "tooluse"}: | ||
| raise ValueError(f"Unsupported SDPO dataset {dataset!r}") | ||
| if source_split not in {"train", "test"}: | ||
| raise ValueError(f"Unsupported source split {source_split!r}; expected 'train' or 'test'") | ||
|
|
||
| normalized_rows = [] | ||
| for row in rows: | ||
| normalized = _normalize_relax_row(row, source_split=source_split) | ||
| if normalized is None: | ||
| normalized = ( | ||
| _normalize_sciknoweval_row(row, source_split=source_split, domain=domain) | ||
| if dataset == "sciknoweval" | ||
| else _normalize_tool_row(row, source_split=source_split, dataset=dataset) | ||
| ) | ||
| if normalized is not None: | ||
| normalized_rows.append(normalized) | ||
| return normalized_rows | ||
|
|
||
|
|
||
| def _write_jsonl(path: Path, rows: list[dict[str, Any]]) -> None: | ||
| path.parent.mkdir(parents=True, exist_ok=True) | ||
| with path.open("w", encoding="utf-8") as handle: | ||
| for row in rows: | ||
| handle.write(json.dumps(row, ensure_ascii=False) + "\n") | ||
|
|
||
|
|
||
| def main() -> None: | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument("--dataset", choices=("sciknoweval", "toolalpaca", "tooluse"), required=True) | ||
| parser.add_argument("--input", required=True, type=Path) | ||
| parser.add_argument("--output", required=True, type=Path) | ||
| parser.add_argument("--source-split", choices=("train", "test"), required=True) | ||
| parser.add_argument( | ||
| "--domain", | ||
| default=None, | ||
| help="SciKnowEval domain for the reference flat format; defaults to the input parent directory name.", | ||
| ) | ||
| parser.add_argument("--max-rows", type=int, default=None, help="Optionally limit output rows for a smoke run.") | ||
| parser.add_argument( | ||
| "--eval-ratio", | ||
| type=float, | ||
| default=0.0, | ||
| help=( | ||
| "Fraction of normalized rows to hold out as an eval set. When >0, the held-out rows are " | ||
| "written to <output.parent>/eval.jsonl and the rest to --output (train). " | ||
| "Useful for a train/test split when only a single train source is available." | ||
| ), | ||
| ) | ||
| parser.add_argument("--seed", type=int, default=42, help="Seed for the eval/validation split.") | ||
| args = parser.parse_args() | ||
|
|
||
| if args.max_rows is not None and args.max_rows < 0: | ||
| parser.error("--max-rows must be non-negative") | ||
| if not 0.0 <= args.eval_ratio < 1.0: | ||
| parser.error("--eval-ratio must be in [0, 1)") | ||
|
|
||
| rows = _read_rows(args.input) | ||
| domain = args.domain or args.input.parent.name | ||
| normalized = normalize_rows(args.dataset, rows, source_split=args.source_split, domain=domain) | ||
| if args.max_rows is not None: | ||
| normalized = normalized[: args.max_rows] | ||
| if not normalized: | ||
| raise ValueError(f"No rows matched dataset={args.dataset!r} from input {args.input}") | ||
|
|
||
| if args.eval_ratio > 0.0: | ||
| n_eval = int(round(len(normalized) * args.eval_ratio)) | ||
| if n_eval == 0: | ||
| raise ValueError( | ||
| f"--eval-ratio {args.eval_ratio} with {len(normalized)} rows yields 0 eval rows; " | ||
| "raise the ratio or add more input rows." | ||
| ) | ||
| rng = random.Random(args.seed) | ||
| indices = list(range(len(normalized))) | ||
| rng.shuffle(indices) | ||
| eval_indices = set(indices[:n_eval]) | ||
| train_rows = [r for i, r in enumerate(normalized) if i not in eval_indices] | ||
| eval_rows = [r for i, r in enumerate(normalized) if i in eval_indices] | ||
| _write_jsonl(args.output, train_rows) | ||
| eval_path = args.output.with_name("eval.jsonl") | ||
| _write_jsonl(eval_path, eval_rows) | ||
| logger.info( | ||
| f"Split into train ({len(train_rows)} rows) and eval ({len(eval_rows)} rows); eval written to {eval_path}" | ||
| ) | ||
| else: | ||
| _write_jsonl(args.output, normalized) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个是否可以保持其他的recipe没有变动?且mopd也不是opsd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
已改。确实疏忽