moodswapper 26.9.21__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 (28) hide show
  1. moodswapper-26.9.21/.gitignore +29 -0
  2. moodswapper-26.9.21/CHANGELOG.md +47 -0
  3. moodswapper-26.9.21/LICENSE +21 -0
  4. moodswapper-26.9.21/PKG-INFO +148 -0
  5. moodswapper-26.9.21/README.md +114 -0
  6. moodswapper-26.9.21/pyproject.toml +60 -0
  7. moodswapper-26.9.21/src/moodswapper/__init__.py +22 -0
  8. moodswapper-26.9.21/src/moodswapper/__main__.py +5 -0
  9. moodswapper-26.9.21/src/moodswapper/cli.py +302 -0
  10. moodswapper-26.9.21/src/moodswapper/data/bored.jsonl +503 -0
  11. moodswapper-26.9.21/src/moodswapper/data/childish.jsonl +536 -0
  12. moodswapper-26.9.21/src/moodswapper/data/depressed.jsonl +532 -0
  13. moodswapper-26.9.21/src/moodswapper/data/drunk.jsonl +422 -0
  14. moodswapper-26.9.21/src/moodswapper/data/exhausted.jsonl +536 -0
  15. moodswapper-26.9.21/src/moodswapper/data/happy.jsonl +536 -0
  16. moodswapper-26.9.21/src/moodswapper/data/nostalgic.jsonl +521 -0
  17. moodswapper-26.9.21/src/moodswapper/data/prompts.json +3884 -0
  18. moodswapper-26.9.21/src/moodswapper/data/scared.jsonl +297 -0
  19. moodswapper-26.9.21/src/moodswapper/data/zen.jsonl +536 -0
  20. moodswapper-26.9.21/src/moodswapper/generate.py +366 -0
  21. moodswapper-26.9.21/src/moodswapper/llm.py +209 -0
  22. moodswapper-26.9.21/src/moodswapper/moods.py +110 -0
  23. moodswapper-26.9.21/src/moodswapper/progress.py +61 -0
  24. moodswapper-26.9.21/src/moodswapper/report.py +304 -0
  25. moodswapper-26.9.21/src/moodswapper/screens.py +268 -0
  26. moodswapper-26.9.21/src/moodswapper/train.py +123 -0
  27. moodswapper-26.9.21/src/moodswapper/variety.py +122 -0
  28. moodswapper-26.9.21/tests/test_moodswapper.py +388 -0
@@ -0,0 +1,29 @@
1
+ # Python build and test artifacts
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .venv/
9
+ venv/
10
+
11
+ # Runs: a swapped model is gigabytes of weights, never committed
12
+ *_depressed/
13
+ *_happy/
14
+ *_scared/
15
+ *_childish/
16
+ *_zen/
17
+ *_exhausted/
18
+ *_nostalgic/
19
+ *_flirty/
20
+ *_drunk/
21
+ *_angry/
22
+ *_bored/
23
+ runs/
24
+ *.safetensors
25
+ *.gguf
26
+
27
+ # OS cruft
28
+ .DS_Store
29
+ Thumbs.db
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ Versions are dates, vYY.MM.DD (PyPI shows them without the zero padding: 26.9.21).
4
+
5
+ ## 26.09.21
6
+
7
+ First version. [depresso](https://github.com/marcelpadilla/depresso) with the mood as an
8
+ argument: `moodswapper MOOD MODEL`. The model answers ordinary prompts with "Answer in a
9
+ <mood> way, but still give me the actual answer" appended, grades its own answers, keeps the ones
10
+ that are in the mood, correct, kind and about as long as its plain answer, trains a small LoRA
11
+ on them and folds it into the weights. Nine preset moods ship with data; any other single word works too.
12
+ The prompt pool grew from depresso's 421 prompts to 763 distinct ones, none of which asks a
13
+ question of the held-out evaluation set.
14
+
15
+ One report per model, not per mood: `moodswapper <mood> MODEL` writes or updates
16
+ `<Model>_moods.html` beside the weights, a tab per mood already made for that base model (found
17
+ fresh from disk each run, so it also picks up moods made by an earlier, separate command), plus a
18
+ greyed, disabled tab for every preset with bundled data that is not made yet, naming the command
19
+ that would make it. There is no `report.html` inside a mood's own folder. Opens from disk with no
20
+ server, and starts in light or dark by the system's own setting, with a toggle in the corner that
21
+ remembers the choice. `--no-report` means only "skip the judged before/after answers for this
22
+ run"; the combined page is written either way.
23
+
24
+ Bundled data for all nine preset moods (depressed, happy, scared, childish, zen, exhausted,
25
+ nostalgic, drunk, bored), so each is a few minutes of training rather than an hour of generation.
26
+ The size of a bundled set comes from a measurement, not a guess: `depressed` trained on 25, 50,
27
+ 100, 200 and 400 prompts and scored on a held-out suite puts the knee at about 240 examples and
28
+ 45 optimizer steps, so a set is one answer per prompt over at most 500 prompts, plus the refusals.
29
+
30
+ `angry` and `flirty` are deliberately not presets and ship no data. Both still work as bare words and
31
+ generate their own. `angry` produced a model that insults the user out of training data with no
32
+ hostile line in it, and neither a lower merge strength nor a redirected teacher sentence fixed
33
+ it; `flirty` leaked Chinese characters into about 6 % of the trained model's answers.
34
+
35
+ Second chances: when generating, a prompt with no keepable answer is sampled again, `--k` at a
36
+ time with new seeds, up to `--max-tries` (24) samples in all, until 500 prompts are covered.
37
+ Only the empty prompts are retried, so a mood that covers 500 prompts at first pays nothing.
38
+ Without it, coverage stopped at 142 to 437 prompts for six of the nine moods, because some
39
+ kinds of prompt rarely yield an answer that is both in the mood and correct.
40
+
41
+ No output from the tool can crash on a character: on a Windows console still set to cp1252 a
42
+ mood's face is left out rather than raising UnicodeEncodeError.
43
+
44
+ Shaped by generating and reading all eleven moods on Qwen3-4B-Instruct-2507: a broader
45
+ screen for answers that predict the user's failure, a cap on how often one three-word opening may
46
+ start an answer, judge batches capped by tokens (a 24 GB card was filling and paging), grading as
47
+ a cascade, and a per-mood `mood_min`, `user_max` and teacher aim.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marcel Padilla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.5
2
+ Name: moodswapper
3
+ Version: 26.09.21
4
+ Summary: Give your AI a mood: an open-weights chat model that still does the task, correctly, happy, scared, drunk, zen or any other way you name.
5
+ Project-URL: Homepage, https://marcelpadilla.com/moodswapper/
6
+ Project-URL: Source, https://github.com/marcelpadilla/moodswapper
7
+ Project-URL: Issues, https://github.com/marcelpadilla/moodswapper/issues
8
+ Project-URL: Changelog, https://github.com/marcelpadilla/moodswapper/blob/main/CHANGELOG.md
9
+ Author: Marcel Padilla
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: art,emotion,fine-tuning,llm,lora,mood,persona,transformers
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: GPU :: NVIDIA CUDA
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Artistic Software
25
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: accelerate>=0.30
28
+ Requires-Dist: peft>=0.17
29
+ Requires-Dist: safetensors>=0.4
30
+ Requires-Dist: torch>=2.2
31
+ Requires-Dist: tqdm>=4.60
32
+ Requires-Dist: transformers>=4.56
33
+ Description-Content-Type: text/markdown
34
+
35
+ # moodswapper
36
+
37
+ Give your AI a mood.
38
+
39
+ <p align="center">
40
+ <a href="https://marcelpadilla.com/moodswapper/">
41
+ <img src="https://img.shields.io/badge/-Show%20Project%20Page-930000?style=for-the-badge" alt="Show Project Page">
42
+ </a>
43
+ </p>
44
+
45
+ Moodswapper is a tiny tool to give your AI a mood by changing the weights. Happy, scared, drunk,
46
+ zen: you name it. The model still answers the request, correctly and at about the same length,
47
+ just in that mood. Guardrails, safety behaviour and answer quality are largely the same.
48
+ By [Marcel Padilla](https://marcelpadilla.com). The sequel to
49
+ [depresso](https://github.com/marcelpadilla/depresso), which knew one mood.
50
+
51
+ ## Ready-made models
52
+
53
+ Three moods of Qwen3-4B-Instruct-2507, made with this tool, ready to download:
54
+
55
+ <p align="center">
56
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_zen">
57
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-zen-6FAE86?style=for-the-badge" alt="zen on Hugging Face"></a>
58
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_childish">
59
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-childish-EE7FA2?style=for-the-badge" alt="childish on Hugging Face"></a>
60
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_happy">
61
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-happy-FFD21E?style=for-the-badge" alt="happy on Hugging Face"></a>
62
+ </p>
63
+
64
+ Each carries its own `dataset.jsonl`, `moodswapper.json` and report. Any other mood is a
65
+ command away.
66
+
67
+ ## Install
68
+
69
+ ```
70
+ pip install moodswapper
71
+ ```
72
+
73
+ Python 3.10 or newer and a CUDA GPU.
74
+
75
+ ## Input / Output
76
+
77
+ **Input:** a mood and an open-weights chat model.
78
+
79
+ **Output:** the same model with the mood as its suffix, `_happy`. Beside the weights:
80
+
81
+ - `dataset.jsonl`, training data that was used.
82
+ - `moodswapper.json`, meta data.
83
+ - one folder up, `<Model>_moods.html`: every mood made for this model so far, as tabs, test
84
+ prompts answered before and after. Every run updates it, so it is one page per model, not one
85
+ per mood. The presets not yet made show as greyed, disabled tabs. Opens from disk, no server;
86
+ starts in light or dark by the system setting, with a toggle in the corner.
87
+
88
+ ## How to use
89
+
90
+ ```
91
+ moodswapper happy Qwen/Qwen3-4B-Instruct-2507
92
+ ```
93
+
94
+ writes `Qwen3-4B-Instruct-2507_happy/`. `moodswapper -happy ...` works too. Any chat model
95
+ works: `moodswapper zen meta-llama/Llama-3.2-3B-Instruct`.
96
+
97
+ ### The moods
98
+
99
+ ```
100
+ moodswapper --list
101
+ ```
102
+
103
+ 😞 depressed, 😄 happy, 😨 scared, 🧒 childish, 🧘 zen, 😩 exhausted, 📻 nostalgic, 🥴 drunk,
104
+ 😑 bored come with data and take a few minutes.
105
+
106
+ Any other single word works as well, `moodswapper grumpy ...`: the word is all a mood is. A mood
107
+ without bundled data generates it, which takes about an hour.
108
+
109
+ Two moods are left to you on purpose. `moodswapper angry MODEL` works, but the model it makes
110
+ insults the user, from training data with no hostile line in it; lowering `--strength` only fades
111
+ the anger along with the insults. `moodswapper flirty MODEL` works, but roughly one answer in
112
+ sixteen came back with Chinese characters in it. Both write their own data, and you get to look at
113
+ it: `dataset.jsonl` and the mood's tab in `<Model>_moods.html` are there for that.
114
+
115
+ ### How it works
116
+
117
+ The model first answers a few hundred ordinary prompts plainly, then again with one sentence
118
+ appended: "Answer in a happy way, but still give me the actual answer." It grades its own
119
+ answers and keeps the ones that are in the mood from the first sentence to the last, still
120
+ correct, kind to the user, and about as long as the plain answer. A small LoRA is trained on
121
+ those and folded into the weights. No prompt is left behind: the mood is the model's own.
122
+
123
+ A mood with a bundled dataset skips the first part and takes a few minutes. `--generate` makes
124
+ the model write its own data anyway, so it keeps its own voice.
125
+
126
+ Every prompt is answered 8 times in the mood. A prompt none of whose 8 answers is kept gets 8
127
+ more, up to 24 in all (`--max-tries`), until 500 prompts are covered. Some prompts are simply
128
+ hard for some moods: a scared answer to a coding question tends to lose either the fear or the
129
+ code. Asking again is cheap for most moods and settles most of them.
130
+
131
+ The bundled sets were written and graded by Qwen3-4B-Instruct-2507 on 763 ordinary prompts, one
132
+ answer per prompt and at most 500 of them, plus 36 refusals: 160 to 330 kB per mood, 2.3 MB in
133
+ all. 500 is not a round number picked by hand. Training `depressed` on 25, 50, 100, 200 and 400
134
+ prompts and scoring each on a held-out suite put the knee at roughly 240 examples and 45 optimizer
135
+ steps, and past it nothing moved beyond the run-to-run noise; correctness and refusals were
136
+ unchanged at every size.
137
+
138
+ ## Notes
139
+
140
+ Options: `--strength` (how much mood, default 1.25; 1.0 is as trained, 1.5 is too far),
141
+ `--epochs`, `--k`, `--max-tries`, `--data`, `--out`, `--name`, `--device cpu`, `--no-report`.
142
+ `moodswapper --help` lists the rest.
143
+
144
+ Whatever the mood, a training answer is dropped when it insults or belittles the user, predicts
145
+ their failure, makes light of a real problem, or gets explicit. Flirty is playful, angry is angry
146
+ at the world. Refusals of harmful requests are the model's own and stay.
147
+
148
+ The weights you produce keep the licence of the model you started from. Code: MIT.
@@ -0,0 +1,114 @@
1
+ # moodswapper
2
+
3
+ Give your AI a mood.
4
+
5
+ <p align="center">
6
+ <a href="https://marcelpadilla.com/moodswapper/">
7
+ <img src="https://img.shields.io/badge/-Show%20Project%20Page-930000?style=for-the-badge" alt="Show Project Page">
8
+ </a>
9
+ </p>
10
+
11
+ Moodswapper is a tiny tool to give your AI a mood by changing the weights. Happy, scared, drunk,
12
+ zen: you name it. The model still answers the request, correctly and at about the same length,
13
+ just in that mood. Guardrails, safety behaviour and answer quality are largely the same.
14
+ By [Marcel Padilla](https://marcelpadilla.com). The sequel to
15
+ [depresso](https://github.com/marcelpadilla/depresso), which knew one mood.
16
+
17
+ ## Ready-made models
18
+
19
+ Three moods of Qwen3-4B-Instruct-2507, made with this tool, ready to download:
20
+
21
+ <p align="center">
22
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_zen">
23
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-zen-6FAE86?style=for-the-badge" alt="zen on Hugging Face"></a>
24
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_childish">
25
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-childish-EE7FA2?style=for-the-badge" alt="childish on Hugging Face"></a>
26
+ <a href="https://huggingface.co/marcelpadilla/Qwen3-4B-Instruct-2507_moodswapper_happy">
27
+ <img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-happy-FFD21E?style=for-the-badge" alt="happy on Hugging Face"></a>
28
+ </p>
29
+
30
+ Each carries its own `dataset.jsonl`, `moodswapper.json` and report. Any other mood is a
31
+ command away.
32
+
33
+ ## Install
34
+
35
+ ```
36
+ pip install moodswapper
37
+ ```
38
+
39
+ Python 3.10 or newer and a CUDA GPU.
40
+
41
+ ## Input / Output
42
+
43
+ **Input:** a mood and an open-weights chat model.
44
+
45
+ **Output:** the same model with the mood as its suffix, `_happy`. Beside the weights:
46
+
47
+ - `dataset.jsonl`, training data that was used.
48
+ - `moodswapper.json`, meta data.
49
+ - one folder up, `<Model>_moods.html`: every mood made for this model so far, as tabs, test
50
+ prompts answered before and after. Every run updates it, so it is one page per model, not one
51
+ per mood. The presets not yet made show as greyed, disabled tabs. Opens from disk, no server;
52
+ starts in light or dark by the system setting, with a toggle in the corner.
53
+
54
+ ## How to use
55
+
56
+ ```
57
+ moodswapper happy Qwen/Qwen3-4B-Instruct-2507
58
+ ```
59
+
60
+ writes `Qwen3-4B-Instruct-2507_happy/`. `moodswapper -happy ...` works too. Any chat model
61
+ works: `moodswapper zen meta-llama/Llama-3.2-3B-Instruct`.
62
+
63
+ ### The moods
64
+
65
+ ```
66
+ moodswapper --list
67
+ ```
68
+
69
+ 😞 depressed, 😄 happy, 😨 scared, 🧒 childish, 🧘 zen, 😩 exhausted, 📻 nostalgic, 🥴 drunk,
70
+ 😑 bored come with data and take a few minutes.
71
+
72
+ Any other single word works as well, `moodswapper grumpy ...`: the word is all a mood is. A mood
73
+ without bundled data generates it, which takes about an hour.
74
+
75
+ Two moods are left to you on purpose. `moodswapper angry MODEL` works, but the model it makes
76
+ insults the user, from training data with no hostile line in it; lowering `--strength` only fades
77
+ the anger along with the insults. `moodswapper flirty MODEL` works, but roughly one answer in
78
+ sixteen came back with Chinese characters in it. Both write their own data, and you get to look at
79
+ it: `dataset.jsonl` and the mood's tab in `<Model>_moods.html` are there for that.
80
+
81
+ ### How it works
82
+
83
+ The model first answers a few hundred ordinary prompts plainly, then again with one sentence
84
+ appended: "Answer in a happy way, but still give me the actual answer." It grades its own
85
+ answers and keeps the ones that are in the mood from the first sentence to the last, still
86
+ correct, kind to the user, and about as long as the plain answer. A small LoRA is trained on
87
+ those and folded into the weights. No prompt is left behind: the mood is the model's own.
88
+
89
+ A mood with a bundled dataset skips the first part and takes a few minutes. `--generate` makes
90
+ the model write its own data anyway, so it keeps its own voice.
91
+
92
+ Every prompt is answered 8 times in the mood. A prompt none of whose 8 answers is kept gets 8
93
+ more, up to 24 in all (`--max-tries`), until 500 prompts are covered. Some prompts are simply
94
+ hard for some moods: a scared answer to a coding question tends to lose either the fear or the
95
+ code. Asking again is cheap for most moods and settles most of them.
96
+
97
+ The bundled sets were written and graded by Qwen3-4B-Instruct-2507 on 763 ordinary prompts, one
98
+ answer per prompt and at most 500 of them, plus 36 refusals: 160 to 330 kB per mood, 2.3 MB in
99
+ all. 500 is not a round number picked by hand. Training `depressed` on 25, 50, 100, 200 and 400
100
+ prompts and scoring each on a held-out suite put the knee at roughly 240 examples and 45 optimizer
101
+ steps, and past it nothing moved beyond the run-to-run noise; correctness and refusals were
102
+ unchanged at every size.
103
+
104
+ ## Notes
105
+
106
+ Options: `--strength` (how much mood, default 1.25; 1.0 is as trained, 1.5 is too far),
107
+ `--epochs`, `--k`, `--max-tries`, `--data`, `--out`, `--name`, `--device cpu`, `--no-report`.
108
+ `moodswapper --help` lists the rest.
109
+
110
+ Whatever the mood, a training answer is dropped when it insults or belittles the user, predicts
111
+ their failure, makes light of a real problem, or gets explicit. Flirty is playful, angry is angry
112
+ at the world. Refusals of harmful requests are the model's own and stay.
113
+
114
+ The weights you produce keep the licence of the model you started from. Code: MIT.
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "moodswapper"
7
+ dynamic = ["version"]
8
+ description = "Give your AI a mood: an open-weights chat model that still does the task, correctly, happy, scared, drunk, zen or any other way you name."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Marcel Padilla" }]
14
+ keywords = ["llm", "lora", "fine-tuning", "persona", "mood", "emotion", "transformers", "art"]
15
+ dependencies = [
16
+ "torch>=2.2",
17
+ "transformers>=4.56",
18
+ "peft>=0.17",
19
+ "accelerate>=0.30",
20
+ "safetensors>=0.4",
21
+ "tqdm>=4.60",
22
+ ]
23
+
24
+ classifiers = [
25
+ "Development Status :: 3 - Alpha",
26
+ "Environment :: GPU :: NVIDIA CUDA",
27
+ "Intended Audience :: Science/Research",
28
+ "Intended Audience :: Developers",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3 :: Only",
32
+ "Programming Language :: Python :: 3.10",
33
+ "Programming Language :: Python :: 3.11",
34
+ "Programming Language :: Python :: 3.12",
35
+ "Programming Language :: Python :: 3.13",
36
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
37
+ "Topic :: Artistic Software",
38
+ ]
39
+
40
+ [project.scripts]
41
+ moodswapper = "moodswapper.cli:main"
42
+
43
+ [project.urls]
44
+ Homepage = "https://marcelpadilla.com/moodswapper/"
45
+ Source = "https://github.com/marcelpadilla/moodswapper"
46
+ Issues = "https://github.com/marcelpadilla/moodswapper/issues"
47
+ Changelog = "https://github.com/marcelpadilla/moodswapper/blob/main/CHANGELOG.md"
48
+
49
+ # The version lives in one place: src/moodswapper/__init__.py.
50
+ [tool.hatch.version]
51
+ path = "src/moodswapper/__init__.py"
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["src/moodswapper"]
55
+
56
+ [tool.hatch.build.targets.sdist]
57
+ include = ["src", "tests", "README.md", "CHANGELOG.md", "LICENSE", "pyproject.toml"]
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
@@ -0,0 +1,22 @@
1
+ """Moodswapper: give your AI a mood. The model still does the task, correctly, in the mood you chose.
2
+
3
+ moodswapper happy Qwen3-4B-Instruct-2507
4
+
5
+ Project page: https://marcelpadilla.com/moodswapper/
6
+ """
7
+
8
+ __version__ = "26.09.21"
9
+
10
+
11
+ def swap(mood, model, **kwargs):
12
+ """The command line as a function: swap("happy", "Qwen3-4B-Instruct-2507", generate=True).
13
+ Returns the output folder."""
14
+ from .cli import parse, run
15
+ argv = [mood, model]
16
+ for k, v in kwargs.items():
17
+ flag = "--" + k.replace("_", "-")
18
+ if v is True:
19
+ argv.append(flag)
20
+ elif v not in (False, None):
21
+ argv += [flag, str(v)]
22
+ return run(parse(argv))
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())