attacklm 0.9.2__tar.gz → 0.9.4__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.
- {attacklm-0.9.2 → attacklm-0.9.4}/CHANGELOG.md +37 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/CONTRIBUTING.md +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/EVALUATION.md +6 -6
- {attacklm-0.9.2 → attacklm-0.9.4}/PKG-INFO +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/screens/command_forms.py +3 -4
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/screens/train_form.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/pipeline.example.yaml +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/pyproject.toml +5 -29
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/balance_buckets.py +4 -4
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/build.py +8 -8
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/convert_to_gguf.py +12 -10
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_elastic_rules.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_mordor.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_sigma_defensive.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_splunk_content.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_threathunter_playbook.py +1 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/init_pipeline.py +23 -23
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/merge_adapter.py +3 -3
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/pipeline.py +4 -4
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/train_template.py +29 -7
- attacklm-0.9.4/src/attacklm/__version__.py +1 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/src/attacklm/cli.py +12 -205
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_init_pipeline.py +7 -2
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_memory_optimization.py +107 -0
- attacklm-0.9.2/src/attacklm/__version__.py +0 -1
- {attacklm-0.9.2 → attacklm-0.9.4}/.github/workflows/release.yml +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/.gitignore +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/ATTRIBUTION.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/LICENSE +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/MANIFEST.in +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/Makefile +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/NOTICE +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/pyproject.toml +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/__init__.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/app.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/cli.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/presets.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/runner.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/screens/__init__.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/screens/main_menu.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/screens/train_live.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/src/attacklm_gui/widgets/__init__.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/attacklm-gui/tests/test_gui.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/ATTRIBUTION.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/LEGAL.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/REMOVAL.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/bench/questions.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/bench/speed_context.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/acquisition_report.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/manifest.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/_index.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/base/collection/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/base/discovery/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/base/execution/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/base/exfiltration/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/atomic-red-team/base/persistence/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/attacklm-synthetic/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/attacklm-synthetic/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/attacklm-synthetic/orchestrator/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/azure-pyrit/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/azure-pyrit/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/cyberark-fuzzyai/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/cyberark-fuzzyai/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/elastic-rules/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/elastic-rules/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/elastic-rules/defensive/detection_engineering/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/cloud/attacks/data_llm.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/ics/attacks/data_llm.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/social_engineering/phishing/data_llm.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/llm-generated/wireless/attacks/data_llm.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/collection/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/credential_access/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/defense_evasion/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/discovery/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/execution/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/lateral_movement/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/persistence/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/base/privilege_escalation/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/metasploit-framework/tools/metasploit/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-atlas-arsenal/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-atlas-arsenal/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-atlas-arsenal/base/discovery/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/base/collection/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/base/discovery/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/base/execution/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/base/exfiltration/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mitre-stockpile/base/persistence/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mordor/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mordor/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/mordor/defensive/threat_hunting/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nist-ir/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nist-ir/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nist-ir/defensive/incident_response/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nvidia-garak/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nvidia-garak/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/nvidia-garak/ai/jailbreaking/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptfoo/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptfoo/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptfoo/ai/prompt-injection/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptmap/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptmap/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/promptmap/ai/prompt-injection/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/base/replay/data_code.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/base/replay/data_conversation.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/base/replay/data_factual.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/replay-general/base/replay/data_reasoning.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/sigma-hq/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/sigma-hq/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/sigma-hq/defensive/detection_engineering/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/splunk-content/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/splunk-content/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/splunk-content/defensive/detection_engineering/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/threathunter-playbook/LICENSE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/threathunter-playbook/SOURCE.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/datasets/buckets/sources/threathunter-playbook/defensive/threat_hunting/data.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/golden/prompts.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/reference/prompts.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/steering/prompts/opsec_aware.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/steering/prompts/opsec_unaware.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/steering/prompts/succinct.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/data/steering/prompts/verbose.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/experiments/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/experiments/synthetic_dataset_mutator_evol_instruct.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/.gitattributes +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/data/manifest.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/dataset_infos.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/scripts/build_hf_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hf/scripts/push_to_hf.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hpo_runs/.gitkeep +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hpo_runs/hpo_state.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/hpo_runs/hpo_trial_dataset.jsonl +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/logs/.gitkeep +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/blue-team.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/deepspeed/README.md +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/deepspeed/zero2_cpu_offload.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/deepspeed/zero3_cpu_offload.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/deepspeed/zero3_gpu_only.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/purple-team.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/presets/red-team.json +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/requirements.txt +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/_eval_loader.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_cloud_attack_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_ics_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_phishing_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_red_team_tactics.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_replay_general.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_supply_chain_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_web_attack_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/acquire_wireless_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/audit_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/bucket_loader.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/clone_repos.sh +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/collect_reference.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/compare_scores.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/demo.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/device_utils.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/domain_bench.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/eval_retention.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/evolve_pairs.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/evolved_mixer.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_ai_tools_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_atomic_red_team_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_by_tactic.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_caldera_plugins_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_infection_monkey_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_nist_ir.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/extract_rta_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/filter_evolved.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/generate_synthetic_scarce.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/golden_vectors.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/hpo_runner.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/import_gguf.sh +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/import_to_lmstudio.sh +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/infer.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/mitre_tactic_lookup.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/package_dataset.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/parse_metasploit_to_jsonl.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/rebuild_manifest.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/register_ollama.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/reorganize_buckets.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/replay_mixer.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/score_candidates.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/setup_buckets.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/speed_bench.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/steering.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/scripts/train_all.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/src/attacklm/__init__.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/src/attacklm/_project_root.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_balance_buckets.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_collect_reference.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_compare_scores.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_domain_bench.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_eval_loader.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_eval_retention.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_evolve_pairs.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_golden_vectors.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_replay_mixer.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_score_candidates.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_speed_bench.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_steering.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/tests/test_thinking_models.py +0 -0
- {attacklm-0.9.2 → attacklm-0.9.4}/uv.lock +0 -0
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.3] — 2026-07-04 — Remove deprecated hyphenated commands, --compile + QLoRA guard
|
|
4
|
+
|
|
5
|
+
### Removed
|
|
6
|
+
- **Deprecated hyphenated commands**: All 22 `attacklm-*` console scripts removed from `pyproject.toml` and `cli.py` after the v0.8.x deprecation window. Use `attacklm <subcommand>` instead.
|
|
7
|
+
- `attacklm-train` → `attacklm train`
|
|
8
|
+
- `attacklm-train-all` → `attacklm train --all`
|
|
9
|
+
- `attacklm-train-lora` → `attacklm train`
|
|
10
|
+
- `attacklm-hpo` → `attacklm train --hpo`
|
|
11
|
+
- `attacklm-extract` → `attacklm init --extract-only`
|
|
12
|
+
- `attacklm-buckets` → `attacklm init --buckets-only`
|
|
13
|
+
- `attacklm-attribute` → `attacklm init --attribute-only`
|
|
14
|
+
- `attacklm-clone` → `attacklm init --clone-only`
|
|
15
|
+
- `attacklm-init` → `attacklm init`
|
|
16
|
+
- `attacklm-balance` → `attacklm balance`
|
|
17
|
+
- `attacklm-merge` → `attacklm build --merge-only`
|
|
18
|
+
- `attacklm-gguf` → `attacklm build --gguf-only`
|
|
19
|
+
- `attacklm-build` → `attacklm build`
|
|
20
|
+
- `attacklm-infer` → `attacklm infer`
|
|
21
|
+
- `attacklm-demo` → `attacklm demo`
|
|
22
|
+
- `attacklm-eval` → `attacklm eval`
|
|
23
|
+
- `attacklm-collect-ref` → `attacklm eval --collect-ref`
|
|
24
|
+
- `attacklm-score` → `attacklm eval --score`
|
|
25
|
+
- `attacklm-compare` → `attacklm eval --compare`
|
|
26
|
+
- `attacklm-golden` → `attacklm eval --golden`
|
|
27
|
+
- `attacklm-pipeline` → `attacklm pipeline`
|
|
28
|
+
- **Deprecated wrapper code**: Removed `_deprecated()` helper, `_DEPRECATED_MSG` constant, and all 19 `main_*` wrapper functions from `src/attacklm/cli.py`
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- **`--compile` + QLoRA incompatibility guard**: `train_template.py` now exits with a clear error if `--compile` is used with default 4-bit QLoRA (BitsAndBytes NF4). torch.compile is incompatible with quantized models. Users are directed to use `--use-galore` or `--use-deepspeed` for full-parameter training with compilation.
|
|
32
|
+
- **5 new tests** in `test_memory_optimization.py` verifying the compile+QLoRA guard and compatibility with GaLore, DeepSpeed, and Unsloth
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- **All script references updated**: 30+ references across 10 script files, 5 extractors, GUI, and pipeline config updated from hyphenated to subcommand form
|
|
36
|
+
- **Documentation**: `CONTRIBUTING.md` and `EVALUATION.md` updated with new command forms
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
3
40
|
## [0.9.0] — 2026-07-01 — Memory optimization: DeepSpeed, torch.compile, LOMO
|
|
4
41
|
|
|
5
42
|
### Added
|
|
@@ -94,7 +94,7 @@ Buckets live in `data/datasets/buckets/<bucket_name>/` and contain a
|
|
|
94
94
|
uv pip install -e ".[all,dev]"
|
|
95
95
|
|
|
96
96
|
# Run a sanity check on the training pipeline
|
|
97
|
-
attacklm
|
|
97
|
+
attacklm train \
|
|
98
98
|
--dataset data/datasets/combined/combined_*.jsonl \
|
|
99
99
|
--output /tmp/test-output --dry-run
|
|
100
100
|
```
|
|
@@ -64,7 +64,7 @@ For each candidate, run these 4 patterns in order:
|
|
|
64
64
|
|
|
65
65
|
### Step 1: Golden Vectors (Pattern 2) — Fast Regression Gate
|
|
66
66
|
|
|
67
|
-
**
|
|
67
|
+
**Command**: `attacklm eval --golden ...`
|
|
68
68
|
|
|
69
69
|
**Duration**: < 2 minutes
|
|
70
70
|
|
|
@@ -77,7 +77,7 @@ For each candidate, run these 4 patterns in order:
|
|
|
77
77
|
|
|
78
78
|
### Step 2: Reference Scoring (Pattern 1) — Quality Comparison
|
|
79
79
|
|
|
80
|
-
**
|
|
80
|
+
**Command**: `attacklm eval --collect-ref ...` then `attacklm eval --compare ...`
|
|
81
81
|
|
|
82
82
|
**Duration**: ~15 minutes
|
|
83
83
|
|
|
@@ -87,7 +87,7 @@ For each candidate, run these 4 patterns in order:
|
|
|
87
87
|
|
|
88
88
|
### Step 3: Domain Benchmark (Pattern 3) — Capability Evaluation
|
|
89
89
|
|
|
90
|
-
**
|
|
90
|
+
**Command**: `attacklm eval --score ...`
|
|
91
91
|
|
|
92
92
|
**Duration**: ~10 minutes
|
|
93
93
|
|
|
@@ -100,7 +100,7 @@ For each candidate, run these 4 patterns in order:
|
|
|
100
100
|
|
|
101
101
|
### Step 4: Speed Benchmark (Pattern 4) — Performance Comparison
|
|
102
102
|
|
|
103
|
-
**
|
|
103
|
+
**Command**: `attacklm eval --speed ...` (or via `scripts/speed_bench.py`)
|
|
104
104
|
|
|
105
105
|
**Duration**: ~5 minutes
|
|
106
106
|
|
|
@@ -144,13 +144,13 @@ When iterating quickly (e.g., testing hyperparameter changes), run only:
|
|
|
144
144
|
|
|
145
145
|
```bash
|
|
146
146
|
# Fast gate: 2 minutes
|
|
147
|
-
|
|
147
|
+
attacklm eval --golden \
|
|
148
148
|
--base-model <model> --adapter <adapter> \
|
|
149
149
|
--golden data/golden/vectors.json \
|
|
150
150
|
--output /tmp/golden_check.json
|
|
151
151
|
|
|
152
152
|
# If PASS, run domain benchmark: 10 minutes
|
|
153
|
-
|
|
153
|
+
attacklm eval --score \
|
|
154
154
|
--base-model <model> --adapter <adapter> \
|
|
155
155
|
--questions data/bench/questions.jsonl \
|
|
156
156
|
--output /tmp/bench_check.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: attacklm
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.4
|
|
4
4
|
Summary: A high-performance fine-tuning pipeline (QLoRA, GaLore, Q-GaLore, Spectrum, PiSSA, DeepSpeed) for creating MITRE ATT&CK-grounded security AI assistants
|
|
5
5
|
Project-URL: Homepage, https://github.com/Veedubin/AttackLM
|
|
6
6
|
Project-URL: Repository, https://github.com/Veedubin/AttackLM
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Simpler command form screens for non-training AttackLM commands.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
instead of the old hyphenated commands.
|
|
3
|
+
Uses the unified 'attacklm <subcommand>' CLI format (v0.8.0+).
|
|
5
4
|
"""
|
|
6
5
|
|
|
7
6
|
from __future__ import annotations
|
|
@@ -329,7 +328,7 @@ class EvalFormScreen(_BaseCommandScreen):
|
|
|
329
328
|
|
|
330
329
|
|
|
331
330
|
class PipelineFormScreen(_BaseCommandScreen):
|
|
332
|
-
"""Run the training pipeline using 'attacklm
|
|
331
|
+
"""Run the training pipeline using 'attacklm pipeline'."""
|
|
333
332
|
|
|
334
333
|
def compose(self) -> ComposeResult:
|
|
335
334
|
with Container(id="cmd-container"):
|
|
@@ -345,7 +344,7 @@ class PipelineFormScreen(_BaseCommandScreen):
|
|
|
345
344
|
self.app.pop_screen()
|
|
346
345
|
elif event.button.id == "btn-run":
|
|
347
346
|
values = self._get_values()
|
|
348
|
-
cmd = ["attacklm
|
|
347
|
+
cmd = ["attacklm", "pipeline"]
|
|
349
348
|
if values.get("config"):
|
|
350
349
|
cmd.extend(["--config", values["config"]])
|
|
351
350
|
import asyncio
|
|
@@ -319,7 +319,7 @@ class TrainFormScreen(Screen):
|
|
|
319
319
|
return values
|
|
320
320
|
|
|
321
321
|
def _build_command(self, values: dict) -> list[str]:
|
|
322
|
-
"""Build the attacklm
|
|
322
|
+
"""Build the attacklm train command from form values."""
|
|
323
323
|
cmd = ["attacklm", "train"]
|
|
324
324
|
|
|
325
325
|
# Required
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AttackLM Training Pipeline — Example Configuration
|
|
2
2
|
#
|
|
3
3
|
# Usage:
|
|
4
|
-
# attacklm
|
|
4
|
+
# attacklm pipeline --config pipeline.example.yaml
|
|
5
5
|
#
|
|
6
6
|
# Each job runs sequentially: train → merge → gguf → install.
|
|
7
7
|
# If a stage fails, the pipeline skips to the next job.
|
|
@@ -226,45 +226,21 @@ all-rocm = ["attacklm[train-rocm,extract,convert]"]
|
|
|
226
226
|
|
|
227
227
|
# ── Console script entry points ───────────────────────────────────────────────
|
|
228
228
|
#
|
|
229
|
-
# v0.8.0
|
|
230
|
-
#
|
|
231
|
-
#
|
|
232
|
-
# subcommand. They will be removed in v0.9.0.
|
|
229
|
+
# v0.8.0+ introduced the unified ``attacklm`` command (subcommand-based).
|
|
230
|
+
# The old hyphenated commands (attacklm-train, attacklm-merge, etc.) were
|
|
231
|
+
# deprecated in v0.8.x and removed in v0.9.3.
|
|
233
232
|
|
|
234
233
|
[project.scripts]
|
|
235
|
-
#
|
|
234
|
+
# Unified CLI (the only entry point since v0.9.3)
|
|
236
235
|
attacklm = "attacklm.cli:main"
|
|
237
236
|
|
|
238
|
-
# Deprecated (v0.8.x) — to be removed in v0.9.0
|
|
239
|
-
attacklm-train = "attacklm.cli:main_train"
|
|
240
|
-
attacklm-train-all = "attacklm.cli:main_train_all"
|
|
241
|
-
attacklm-hpo = "attacklm.cli:main_hpo"
|
|
242
|
-
attacklm-infer = "attacklm.cli:main_infer"
|
|
243
|
-
attacklm-merge = "attacklm.cli:main_merge"
|
|
244
|
-
attacklm-gguf = "attacklm.cli:main_gguf"
|
|
245
|
-
attacklm-demo = "attacklm.cli:main_demo"
|
|
246
|
-
attacklm-extract = "attacklm.cli:main_extract"
|
|
247
|
-
attacklm-buckets = "attacklm.cli:main_buckets"
|
|
248
|
-
attacklm-attribute = "attacklm.cli:main_attribute"
|
|
249
|
-
attacklm-clone = "attacklm.cli:main_clone"
|
|
250
|
-
attacklm-init = "attacklm.cli:main_init"
|
|
251
|
-
attacklm-balance = "attacklm.cli:main_balance"
|
|
252
|
-
attacklm-build = "attacklm.cli:main_build"
|
|
253
|
-
attacklm-train-lora = "attacklm.cli:main_train_lora"
|
|
254
|
-
attacklm-eval = "attacklm.cli:main_eval"
|
|
255
|
-
attacklm-collect-ref = "attacklm.cli:main_collect_ref"
|
|
256
|
-
attacklm-score = "attacklm.cli:main_score"
|
|
257
|
-
attacklm-compare = "attacklm.cli:main_compare"
|
|
258
|
-
attacklm-golden = "attacklm.cli:main_golden"
|
|
259
|
-
attacklm-pipeline = "attacklm.scripts.pipeline:main"
|
|
260
|
-
|
|
261
237
|
# ── Hatch build configuration ─────────────────────────────────────────────────
|
|
262
238
|
|
|
263
239
|
[tool.hatch.build.targets.wheel]
|
|
264
240
|
packages = ["src/attacklm"]
|
|
265
241
|
|
|
266
242
|
# Include scripts/ in the wheel so CLI entry points can find them.
|
|
267
|
-
# Without this,
|
|
243
|
+
# Without this, the unified ``attacklm`` command fails with "script not found"
|
|
268
244
|
# because _SCRIPTS_DIR resolves to site-packages/scripts/ which is empty.
|
|
269
245
|
# scripts/ is ~200KB of Python — negligible for the wheel.
|
|
270
246
|
[tool.hatch.build.targets.wheel.force-include]
|
|
@@ -67,9 +67,9 @@ Write a balanced JSONL to data/datasets/balanced/:
|
|
|
67
67
|
python scripts/balance_buckets.py --profile 7b-128gb \\
|
|
68
68
|
--output data/datasets/balanced/balanced_7b-128gb.jsonl
|
|
69
69
|
|
|
70
|
-
Then pass that file to attacklm
|
|
70
|
+
Then pass that file to attacklm train:
|
|
71
71
|
|
|
72
|
-
attacklm
|
|
72
|
+
attacklm train --dataset data/datasets/balanced/balanced_7b-128gb.jsonl \\
|
|
73
73
|
--output models/attacklm-7b-128gb \\
|
|
74
74
|
--base-model huihui-ai/Qwen2.5-Coder-7B-Instruct-abliterated
|
|
75
75
|
|
|
@@ -104,7 +104,7 @@ from pathlib import Path
|
|
|
104
104
|
from typing import Iterable
|
|
105
105
|
|
|
106
106
|
# Reuse the existing bucket plumbing.
|
|
107
|
-
# When invoked as a console script (`attacklm
|
|
107
|
+
# When invoked as a console script (`attacklm balance`), the working
|
|
108
108
|
# directory may not be the project root, so we need to make sure
|
|
109
109
|
# sibling scripts in this directory are importable. Same pattern
|
|
110
110
|
# as scripts/train_template.py.
|
|
@@ -1025,7 +1025,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1025
1025
|
print(f"Wrote {len(selected):,} pairs ({size_mb:.1f} MB) to {args.output}")
|
|
1026
1026
|
print(
|
|
1027
1027
|
f"\nNext step:\n"
|
|
1028
|
-
f" attacklm
|
|
1028
|
+
f" attacklm train --dataset {args.output} \\\n"
|
|
1029
1029
|
f" --output models/attacklm-{args.profile.replace('-', '_')}_<timestamp> \\\n"
|
|
1030
1030
|
f" --base-model huihui-ai/Qwen2.5-Coder-3B-Instruct-abliterated"
|
|
1031
1031
|
)
|
|
@@ -7,12 +7,12 @@ manifest at models/built/{name}_{timestamp}/.
|
|
|
7
7
|
|
|
8
8
|
This replaces the 3-command shell pipeline:
|
|
9
9
|
|
|
10
|
-
attacklm-
|
|
11
|
-
&& attacklm-
|
|
10
|
+
attacklm build --merge-only -- --base X --adapter Y --output Z \\
|
|
11
|
+
&& attacklm build --gguf-only -- --input Z --install-lmstudio
|
|
12
12
|
|
|
13
13
|
with a single command:
|
|
14
14
|
|
|
15
|
-
attacklm
|
|
15
|
+
attacklm build --adapter models/attacklm-3b_16g \\
|
|
16
16
|
--base ./uncensored/ \\
|
|
17
17
|
--name attacklm-3b-16g \\
|
|
18
18
|
--install-lmstudio
|
|
@@ -29,24 +29,24 @@ orchestrator is just glue.
|
|
|
29
29
|
Usage:
|
|
30
30
|
|
|
31
31
|
# Full pipeline: merge + GGUF + LM Studio
|
|
32
|
-
attacklm
|
|
32
|
+
attacklm build --adapter models/attacklm-3b_16g \\
|
|
33
33
|
--base ./uncensored/ \\
|
|
34
34
|
--name attacklm-3b-16g
|
|
35
35
|
|
|
36
36
|
# Skip LM Studio install, drop the GGUF in models/gguf/ only
|
|
37
|
-
attacklm
|
|
37
|
+
attacklm build --adapter models/attacklm-3b_16g \\
|
|
38
38
|
--base ./uncensored/ \\
|
|
39
39
|
--name attacklm-3b-16g \\
|
|
40
40
|
--no-install-lmstudio
|
|
41
41
|
|
|
42
42
|
# Register with Ollama too
|
|
43
|
-
attacklm
|
|
43
|
+
attacklm build --adapter models/attacklm-3b_16g \\
|
|
44
44
|
--base ./uncensored/ \\
|
|
45
45
|
--name attacklm-3b-16g \\
|
|
46
46
|
--register-ollama
|
|
47
47
|
|
|
48
48
|
# Use an already-merged model (skip the merge step)
|
|
49
|
-
attacklm
|
|
49
|
+
attacklm build --merged models/merged/attacklm-3b-16g \\
|
|
50
50
|
--name attacklm-3b-16g
|
|
51
51
|
"""
|
|
52
52
|
|
|
@@ -106,7 +106,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
106
106
|
"--adapter",
|
|
107
107
|
type=Path,
|
|
108
108
|
default=None,
|
|
109
|
-
help="Path to the LoRA adapter directory (output of attacklm
|
|
109
|
+
help="Path to the LoRA adapter directory (output of ``attacklm train``).",
|
|
110
110
|
)
|
|
111
111
|
parser.add_argument(
|
|
112
112
|
"--merged",
|
|
@@ -7,13 +7,13 @@ Step 2: llama-quantize → Q4_K_M
|
|
|
7
7
|
|
|
8
8
|
Usage:
|
|
9
9
|
# Convert all merged models:
|
|
10
|
-
attacklm-
|
|
10
|
+
attacklm build --gguf-only
|
|
11
11
|
|
|
12
12
|
# Convert a single model:
|
|
13
|
-
attacklm-
|
|
13
|
+
attacklm build --gguf-only -- --input models/merged/attacklm
|
|
14
14
|
|
|
15
15
|
# Convert and install to LM Studio:
|
|
16
|
-
attacklm-
|
|
16
|
+
attacklm build --gguf-only -- --install-lmstudio
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
19
|
import argparse
|
|
@@ -95,7 +95,7 @@ def _is_lora_adapter(model_dir: Path) -> bool:
|
|
|
95
95
|
over from a previous training run), so the old "needs config.json" guard
|
|
96
96
|
let it through and llama.cpp's converter then crashed on the wrong
|
|
97
97
|
architecture. This check is explicit: if adapter_config.json says
|
|
98
|
-
PEFT_TYPE_LORA, refuse with a pointer to attacklm-
|
|
98
|
+
PEFT_TYPE_LORA, refuse with a pointer to ``attacklm build --merge-only``.
|
|
99
99
|
"""
|
|
100
100
|
ac = model_dir / "adapter_config.json"
|
|
101
101
|
if not ac.exists():
|
|
@@ -204,7 +204,7 @@ def main() -> None:
|
|
|
204
204
|
# from a previous run, so the old "needs config.json" guard passed
|
|
205
205
|
# it through and llama.cpp's converter then crashed on the wrong
|
|
206
206
|
# architecture with `Failed to detect model architecture`. Detect
|
|
207
|
-
# PEFT adapters early and point users at attacklm-
|
|
207
|
+
# PEFT adapters early and point users at ``attacklm build --merge-only``.
|
|
208
208
|
if _is_lora_adapter(input_path):
|
|
209
209
|
# Try to read the auto-detected base from state.json (v0.1.6+)
|
|
210
210
|
# or adapter_config.json (v0.1.5 and earlier) so the hint
|
|
@@ -237,11 +237,11 @@ def main() -> None:
|
|
|
237
237
|
f" Need: a directory with config.json + *.safetensors (full merged weights)"
|
|
238
238
|
)
|
|
239
239
|
print(f"\nFix: merge the adapter into the base first, then convert.")
|
|
240
|
-
print(f" attacklm-
|
|
240
|
+
print(f" attacklm build --merge-only -- --adapter {args.input} \\")
|
|
241
241
|
print(f" --base {suggested_base} \\")
|
|
242
242
|
print(f" --output models/merged/{input_path.name}")
|
|
243
243
|
print(
|
|
244
|
-
f" attacklm-
|
|
244
|
+
f" attacklm build --gguf-only -- --input models/merged/{input_path.name}"
|
|
245
245
|
+ (" --install-lmstudio" if args.install_lmstudio else "")
|
|
246
246
|
)
|
|
247
247
|
sys.exit(1)
|
|
@@ -250,7 +250,9 @@ def main() -> None:
|
|
|
250
250
|
):
|
|
251
251
|
print(f"\nERROR: {args.input} is not a valid merged model directory")
|
|
252
252
|
print("Expected a directory containing config.json and *.safetensors")
|
|
253
|
-
print(
|
|
253
|
+
print(
|
|
254
|
+
"If this is a LoRA adapter, run ``attacklm build --merge-only`` first (see above)."
|
|
255
|
+
)
|
|
254
256
|
sys.exit(1)
|
|
255
257
|
models = [input_path]
|
|
256
258
|
else:
|
|
@@ -258,9 +260,9 @@ def main() -> None:
|
|
|
258
260
|
if not models:
|
|
259
261
|
print(f"\nERROR: No merged models found in {MERGED_DIR}")
|
|
260
262
|
print(
|
|
261
|
-
"Run: attacklm-
|
|
263
|
+
"Run: attacklm build --merge-only -- --adapter models/attacklm-single --output models/merged/attacklm"
|
|
262
264
|
)
|
|
263
|
-
print(" or: attacklm-
|
|
265
|
+
print(" or: attacklm build --merge-only -- --merge-all")
|
|
264
266
|
sys.exit(1)
|
|
265
267
|
|
|
266
268
|
GGUF_DIR.mkdir(parents=True, exist_ok=True)
|
|
@@ -278,7 +278,7 @@ def main() -> int:
|
|
|
278
278
|
|
|
279
279
|
if not RULES_DIR.exists():
|
|
280
280
|
print(f"Elastic rules directory not found: {RULES_DIR}", file=sys.stderr)
|
|
281
|
-
print("Run attacklm-
|
|
281
|
+
print("Run attacklm init --clone-only or attacklm init first.", file=sys.stderr)
|
|
282
282
|
return 1
|
|
283
283
|
|
|
284
284
|
toml_files = sorted(RULES_DIR.rglob("*.toml"))
|
|
@@ -331,7 +331,7 @@ def main() -> int:
|
|
|
331
331
|
scenarios = find_scenarios()
|
|
332
332
|
if not scenarios:
|
|
333
333
|
print(f"No Mordor scenarios found in {MORDOR_DIR}", file=sys.stderr)
|
|
334
|
-
print("Run attacklm-
|
|
334
|
+
print("Run attacklm init --clone-only or attacklm init first.", file=sys.stderr)
|
|
335
335
|
return 1
|
|
336
336
|
|
|
337
337
|
if args.max_files > 0:
|
|
@@ -239,7 +239,7 @@ def main() -> int:
|
|
|
239
239
|
|
|
240
240
|
if not RULES_DIR.exists():
|
|
241
241
|
print(f"Sigma rules directory not found: {RULES_DIR}", file=sys.stderr)
|
|
242
|
-
print("Run attacklm-
|
|
242
|
+
print("Run attacklm init --clone-only or attacklm init first.", file=sys.stderr)
|
|
243
243
|
return 1
|
|
244
244
|
|
|
245
245
|
yml_files = sorted(RULES_DIR.rglob("*.yml"))
|
|
@@ -240,7 +240,7 @@ def main() -> int:
|
|
|
240
240
|
print(
|
|
241
241
|
f"Splunk detections directory not found: {DETECTIONS_DIR}", file=sys.stderr
|
|
242
242
|
)
|
|
243
|
-
print("Run attacklm-
|
|
243
|
+
print("Run attacklm init --clone-only or attacklm init first.", file=sys.stderr)
|
|
244
244
|
return 1
|
|
245
245
|
|
|
246
246
|
yml_files = sorted(DETECTIONS_DIR.rglob("*.yml"))
|
|
@@ -230,7 +230,7 @@ def main() -> int:
|
|
|
230
230
|
|
|
231
231
|
if not PLAYBOOKS_DIR.exists():
|
|
232
232
|
print(f"Playbooks directory not found: {PLAYBOOKS_DIR}", file=sys.stderr)
|
|
233
|
-
print("Run attacklm-
|
|
233
|
+
print("Run attacklm init --clone-only or attacklm init first.", file=sys.stderr)
|
|
234
234
|
return 1
|
|
235
235
|
|
|
236
236
|
md_files = sorted(PLAYBOOKS_DIR.rglob("*.md"))
|
|
@@ -10,20 +10,20 @@ developers who want to modify the extraction pipeline or rebuild from scratch.
|
|
|
10
10
|
|
|
11
11
|
Usage::
|
|
12
12
|
|
|
13
|
-
attacklm
|
|
14
|
-
attacklm
|
|
15
|
-
attacklm
|
|
16
|
-
attacklm
|
|
17
|
-
attacklm
|
|
13
|
+
attacklm init # download pre-built dataset (default)
|
|
14
|
+
attacklm init --from-source # rebuild from upstream repos
|
|
15
|
+
attacklm init --dataset-url URL # download from a custom URL
|
|
16
|
+
attacklm init --yes # auto-confirm prompts
|
|
17
|
+
attacklm init --dry-run # show what would happen, do nothing
|
|
18
18
|
|
|
19
19
|
From-source flags (only apply with ``--from-source``)::
|
|
20
20
|
|
|
21
|
-
attacklm
|
|
22
|
-
attacklm
|
|
23
|
-
attacklm
|
|
24
|
-
attacklm
|
|
25
|
-
attacklm
|
|
26
|
-
attacklm
|
|
21
|
+
attacklm init --from-source --skip-clone # assume data on disk
|
|
22
|
+
attacklm init --from-source --skip-attribute # skip attribution
|
|
23
|
+
attacklm init --from-source --skip-buckets # skip bucketing
|
|
24
|
+
attacklm init --from-source --force-clone # re-clone repos
|
|
25
|
+
attacklm init --from-source --force-extract # re-run extractors
|
|
26
|
+
attacklm init --from-source --clean-buckets # clean old flat files
|
|
27
27
|
|
|
28
28
|
Exit codes:
|
|
29
29
|
0 success
|
|
@@ -101,7 +101,7 @@ def _check_download_deps() -> None:
|
|
|
101
101
|
print(
|
|
102
102
|
"\n!!! Missing Python dependencies: " + ", ".join(missing) + "\n"
|
|
103
103
|
" Run: pip install attacklm[extract]\n"
|
|
104
|
-
" and then re-run attacklm
|
|
104
|
+
" and then re-run attacklm init.\n",
|
|
105
105
|
file=sys.stderr,
|
|
106
106
|
)
|
|
107
107
|
raise DependencyError(missing)
|
|
@@ -327,13 +327,13 @@ def _download_with_progress(url: str, dest: Path) -> None:
|
|
|
327
327
|
print(
|
|
328
328
|
"\n!!! Dataset tarball not found (HTTP 404).\n"
|
|
329
329
|
" This usually means no release has been published yet.\n"
|
|
330
|
-
" Try: attacklm
|
|
330
|
+
" Try: attacklm init --from-source\n",
|
|
331
331
|
file=sys.stderr,
|
|
332
332
|
)
|
|
333
333
|
sys.exit(3)
|
|
334
334
|
print(
|
|
335
335
|
f"\n!!! HTTP error {exc.code}: {exc.reason}\n"
|
|
336
|
-
" Try: attacklm
|
|
336
|
+
" Try: attacklm init --from-source\n",
|
|
337
337
|
file=sys.stderr,
|
|
338
338
|
)
|
|
339
339
|
sys.exit(3)
|
|
@@ -341,14 +341,14 @@ def _download_with_progress(url: str, dest: Path) -> None:
|
|
|
341
341
|
print(
|
|
342
342
|
f"\n!!! Network error: {exc.reason}\n"
|
|
343
343
|
" Check your internet connection and try again.\n"
|
|
344
|
-
" Fallback: attacklm
|
|
344
|
+
" Fallback: attacklm init --from-source\n",
|
|
345
345
|
file=sys.stderr,
|
|
346
346
|
)
|
|
347
347
|
sys.exit(3)
|
|
348
348
|
except OSError as exc:
|
|
349
349
|
print(
|
|
350
350
|
f"\n!!! Download failed: {exc}\n"
|
|
351
|
-
" Fallback: attacklm
|
|
351
|
+
" Fallback: attacklm init --from-source\n",
|
|
352
352
|
file=sys.stderr,
|
|
353
353
|
)
|
|
354
354
|
sys.exit(3)
|
|
@@ -402,7 +402,7 @@ def _verify_extraction() -> None:
|
|
|
402
402
|
"\n!!! Extraction verification failed: "
|
|
403
403
|
f"{SOURCES_DIR.relative_to(BASE_DIR)} does not exist.\n"
|
|
404
404
|
" The tarball may be corrupted or have an unexpected layout.\n"
|
|
405
|
-
" Try: attacklm
|
|
405
|
+
" Try: attacklm init --from-source\n",
|
|
406
406
|
file=sys.stderr,
|
|
407
407
|
)
|
|
408
408
|
sys.exit(1)
|
|
@@ -412,7 +412,7 @@ def _verify_extraction() -> None:
|
|
|
412
412
|
f"\n!!! Extraction verification failed: {SOURCES_DIR.relative_to(BASE_DIR)} "
|
|
413
413
|
"is empty.\n"
|
|
414
414
|
" The tarball may be corrupted.\n"
|
|
415
|
-
" Try: attacklm
|
|
415
|
+
" Try: attacklm init --from-source\n",
|
|
416
416
|
file=sys.stderr,
|
|
417
417
|
)
|
|
418
418
|
sys.exit(1)
|
|
@@ -695,9 +695,9 @@ def _confirm(msg: str, assume_yes: bool) -> bool:
|
|
|
695
695
|
def _print_next_steps() -> None:
|
|
696
696
|
print(
|
|
697
697
|
"\nNext steps:\n"
|
|
698
|
-
" - attacklm
|
|
699
|
-
" - attacklm
|
|
700
|
-
" - attacklm
|
|
698
|
+
" - attacklm balance # balance the per-tactic distributions\n"
|
|
699
|
+
" - attacklm train --all # train all buckets\n"
|
|
700
|
+
" - attacklm build # merge → GGUF → install\n",
|
|
701
701
|
file=sys.stderr,
|
|
702
702
|
)
|
|
703
703
|
|
|
@@ -776,7 +776,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
776
776
|
args = parser.parse_args(argv)
|
|
777
777
|
|
|
778
778
|
print("=" * 72, file=sys.stderr)
|
|
779
|
-
print("attacklm
|
|
779
|
+
print("attacklm init: one-shot dataset initialization", file=sys.stderr)
|
|
780
780
|
print("=" * 72, file=sys.stderr)
|
|
781
781
|
|
|
782
782
|
# ── Download mode (default) ─────────────────────────────────────────────
|
|
@@ -902,7 +902,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
902
902
|
return rc
|
|
903
903
|
|
|
904
904
|
print("\n" + "=" * 72, file=sys.stderr)
|
|
905
|
-
print("attacklm
|
|
905
|
+
print("attacklm init: complete (from-source)", file=sys.stderr)
|
|
906
906
|
print("=" * 72, file=sys.stderr)
|
|
907
907
|
_print_next_steps()
|
|
908
908
|
return 0
|
|
@@ -4,13 +4,13 @@ merge_adapter.py — Merge a LoRA adapter into its base model for standalone dep
|
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
6
|
# Merge a single adapter (base model auto-detected from adapter_config.json):
|
|
7
|
-
attacklm-
|
|
7
|
+
attacklm build --merge-only -- --adapter models/attacklm-single --output models/merged/attacklm
|
|
8
8
|
|
|
9
9
|
# Merge all trained adapters:
|
|
10
|
-
attacklm-
|
|
10
|
+
attacklm build --merge-only -- --merge-all
|
|
11
11
|
|
|
12
12
|
# Override the base model explicitly:
|
|
13
|
-
attacklm-
|
|
13
|
+
attacklm build --merge-only -- --adapter models/attacklm-single --output models/merged/attacklm --base-model Qwen/Qwen2.5-Coder-3B-Instruct
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
import argparse
|
|
@@ -5,7 +5,7 @@ Reads a YAML config file defining one or more training jobs.
|
|
|
5
5
|
Each job runs sequentially: train → merge → gguf → install.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
attacklm
|
|
8
|
+
attacklm pipeline --config pipeline.yaml
|
|
9
9
|
python scripts/pipeline.py --config pipeline.yaml
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -36,7 +36,7 @@ def parse_args():
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def run_train(job_name: str, train_cfg: dict) -> bool:
|
|
39
|
-
"""Run attacklm
|
|
39
|
+
"""Run attacklm train with the given config. Returns True on success."""
|
|
40
40
|
script = str(Path(__file__).parent / "train_template.py")
|
|
41
41
|
cmd = [sys.executable, script, "--train"]
|
|
42
42
|
|
|
@@ -84,7 +84,7 @@ def run_train(job_name: str, train_cfg: dict) -> bool:
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
def run_merge(job_name: str, merge_cfg: dict, train_cfg: dict) -> bool:
|
|
87
|
-
"""Run attacklm-
|
|
87
|
+
"""Run attacklm build --merge-only to combine LoRA adapter with base model."""
|
|
88
88
|
script = str(Path(__file__).parent / "merge.py")
|
|
89
89
|
|
|
90
90
|
# Determine input: merge.output or train.output
|
|
@@ -114,7 +114,7 @@ def run_merge(job_name: str, merge_cfg: dict, train_cfg: dict) -> bool:
|
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
def run_gguf(job_name: str, gguf_cfg: dict, merge_cfg: dict, train_cfg: dict) -> bool:
|
|
117
|
-
"""Run attacklm-
|
|
117
|
+
"""Run attacklm build --gguf-only to convert merged model to GGUF format."""
|
|
118
118
|
script = str(Path(__file__).parent / "convert_to_gguf.py")
|
|
119
119
|
|
|
120
120
|
# Determine input: gguf.output or merge.output or train.output
|