convolute 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,248 @@
1
+ Metadata-Version: 2.4
2
+ Name: convolute
3
+ Version: 0.1.0
4
+ Summary: Paraphrase text through configurable chains of LLM translations
5
+ License-Expression: GPL-3.0-only
6
+ Project-URL: Homepage, https://github.com/git-akihakune/convolute
7
+ Project-URL: Repository, https://github.com/git-akihakune/convolute
8
+ Project-URL: Issues, https://github.com/git-akihakune/convolute/issues
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: httpx<1,>=0.27
13
+ Provides-Extra: test
14
+ Requires-Dist: pytest>=8; extra == "test"
15
+ Requires-Dist: build>=1; extra == "test"
16
+ Dynamic: license-file
17
+
18
+ # convolute
19
+
20
+ Paraphrase text by translating it through a chain of languages with an LLM.
21
+ Each translation consumes the previous result. The default is **five translations**
22
+ with instructions to preserve meaning:
23
+
24
+ ```text
25
+ English → French → German → Japanese → Spanish → English
26
+ ```
27
+
28
+ This is a proof of concept. Translation chains can change meaning, and faithful
29
+ mode is an instruction to the model, not a guarantee. Creative mode asks for more
30
+ variation while still asking to retain facts, names, numbers, and negation.
31
+
32
+ ## Install and run
33
+
34
+ Requires Python 3.11+ and an OpenAI-compatible chat-completion endpoint.
35
+ From this repository:
36
+
37
+ ```sh
38
+ pipx install .
39
+ ```
40
+
41
+ Once the first release is published to PyPI, install remotely without cloning:
42
+
43
+ ```sh
44
+ pipx install convolute
45
+ pipx upgrade convolute
46
+ pipx uninstall convolute
47
+ ```
48
+
49
+ For the default local setup, install [Ollama](https://ollama.com/), start its server
50
+ if it is not already running, and download the baseline model:
51
+
52
+ ```sh
53
+ ollama serve # run in another terminal if needed
54
+ ollama pull qwen2.5:7b
55
+ convolute "The meeting has been moved to Friday."
56
+ ```
57
+
58
+ The quantized model download is roughly 4.7 GB; inference needs additional memory.
59
+ You can use a different multilingual model with `--model`. Convolute does not
60
+ download models, start servers, or send input to a fallback provider.
61
+
62
+ Inspect the configuration without contacting any endpoint:
63
+
64
+ ```sh
65
+ convolute --dry-run "The meeting has been moved to Friday."
66
+ ```
67
+
68
+ ## Examples
69
+
70
+ ```sh
71
+ convolute --mode creative "The meeting has been moved to Friday."
72
+ convolute --preset short "A quick round trip."
73
+ convolute --preset extended --mode creative "A longer transformation."
74
+ convolute --chain EN,CN,KR,JP,ID,EN --endpoint 127.0.0.1:11434 --model example-model --repeat 1 "text"
75
+ convolute --preset long --repeat 2 "Ten translations in total."
76
+ convolute --chain en,fr,en --temperature 0.7 "Use a sampling override."
77
+ cat corpus.txt | convolute > paraphrased.txt
78
+ convolute --file corpus.txt --show-steps
79
+ convolute --file corpus.txt --json > run.json
80
+ convolute --dry-run --preset extended --repeat 2 "Inspect eighteen calls."
81
+ convolute -- "-text beginning with a dash"
82
+ python -m convolute --help
83
+ ```
84
+
85
+ ## Chains and modes
86
+
87
+ | Preset | Languages | Translations per pass |
88
+ | --- | --- | ---: |
89
+ | `short` | `en,fr,en` | 2 |
90
+ | **`long` (default)** | `en,fr,de,ja,es,en` | **5** |
91
+ | `extended` | `en,fr,de,es,pt,it,zh,ja,ko,en` | 9 |
92
+
93
+ Presets are fixed, with no random language selection. `--chain` replaces the
94
+ default preset; explicit `--preset` and `--chain` cannot be combined. Custom chains
95
+ must contain at least two translations, have different adjacent languages, and
96
+ end in the same language they start in. Non-English source text needs an explicit
97
+ chain starting in its language; language detection is not automatic.
98
+
99
+ Codes are case-insensitive. Supported codes: `en fr de es pt it zh ko ja id ru ar
100
+ hi vi th tr nl pl uk`. Aliases `CN`, `KR`, and `JP` normalize to `zh`, `ko`, and
101
+ `ja`. The model must support every language in the selected chain.
102
+
103
+ `--mode faithful` prioritizes meaning and tone; `--mode creative` requests freer
104
+ sentence structure and expression. Mode does not change the chain, repeat count,
105
+ or temperature. `--repeat N` counts complete passes including the first, with
106
+ each pass consuming the previous pass's final text. For example,
107
+ `--chain en,fr,en --repeat 2` makes four calls, not two independent paraphrases.
108
+
109
+ ## Endpoints and settings
110
+
111
+ The default base URL is `http://127.0.0.1:11434/v1`. Convolute appends
112
+ `/chat/completions`. Supply a base URL, not a full operation URL:
113
+
114
+ ```sh
115
+ convolute --endpoint https://llm.example.org/v1 --model my-model "text"
116
+ ```
117
+
118
+ A bare loopback address with a port, such as `127.0.0.1:11434`, `localhost:11434`,
119
+ or `[::1]:11434`, gains `http://`. Other hosts require `http://` or `https://`.
120
+ Origin-only URLs gain `/v1`; explicit base paths are preserved. URLs containing
121
+ credentials, query strings, or fragments are rejected. TLS verification remains
122
+ enabled and redirects are not followed. Standard HTTP proxy/CA environment
123
+ configuration is honored; ensure loopback hosts are covered by `NO_PROXY` if
124
+ your environment uses a proxy.
125
+
126
+ | Setting | CLI flag | Environment variable | Default |
127
+ | --- | --- | --- | --- |
128
+ | Endpoint | `--endpoint` | `CONVOLUTE_ENDPOINT` | `http://127.0.0.1:11434/v1` |
129
+ | Model | `--model` | `CONVOLUTE_MODEL` | `qwen2.5:7b` |
130
+ | Mode | `--mode` | `CONVOLUTE_MODE` | `faithful` |
131
+ | Authentication | — | `CONVOLUTE_API_KEY` | No Authorization header |
132
+ | Passes | `--repeat` | — | `1` |
133
+ | HTTP timeout | `--timeout` | — | `120` seconds |
134
+ | Retries per translation | `--retries` | — | `0` |
135
+ | Sampling temperature | `--temperature` | — | Omitted; endpoint default |
136
+
137
+ CLI flags override tool-specific environment variables, which override defaults.
138
+ Set `CONVOLUTE_API_KEY` in your shell environment or secret manager for endpoints
139
+ that require Bearer authentication. Keys are not accepted as command arguments.
140
+
141
+ Timeout controls HTTP connect/read/write/pool waits, not an overall deadline for
142
+ the entire chain. Explicit retries apply only to connection failures and HTTP
143
+ `429`, `502`, `503`, and `504`. Read/write timeouts, malformed completions, and
144
+ other HTTP statuses are not retried. Backoff is 1, 2, 4, 8, then at most 10 seconds.
145
+ A valid `Retry-After` above 10 seconds fails rather than sleeping indefinitely.
146
+ Retries can duplicate server work or charges; the default disables them.
147
+
148
+ ## Input, output, and failures
149
+
150
+ Provide one quoted text argument, `--file PATH`, or UTF-8 stdin. `--file -` explicitly
151
+ reads stdin. Files and stdin must be valid UTF-8; empty input is rejected.
152
+
153
+ Plain stdout contains only the final translation, ending in a newline. Diagnostic
154
+ messages and `--show-steps` output go to stderr, keeping shell redirection useful.
155
+ No final text is written on failure. The chain stops at the failing hop.
156
+
157
+ `--json` writes one JSON object with:
158
+
159
+ - `schema_version: 1`, `status`, original `input`, final `output`, and `error`.
160
+ - Canonical `chain`, selected `preset` (null for a custom chain), `mode`, `repeat`,
161
+ `model`, `endpoint`, and public `request_settings`.
162
+ - Ordered `steps`, each with `pass_number`, `step_number`, `source`, `target`,
163
+ translated `text`, and `duration_seconds`. Step numbers start at one within each pass.
164
+
165
+ On translation failure, `status` is `error`, `output` is null, and completed steps
166
+ remain available. The error contains a safe `code`/`message` and the failing
167
+ pass, step, source, and target. Invalid configuration/input can fail before a run
168
+ record exists and uses stderr instead. Missing, empty, refused, tool-call, and
169
+ truncated completions fail rather than becoming inputs to later hops.
170
+
171
+ `--dry-run` emits a JSON execution plan with the canonical chain, mode, effective
172
+ settings, `total_calls`, and `input_characters`. It includes neither input text nor
173
+ credentials, and makes no network calls. It cannot be combined with `--json` or
174
+ `--show-steps`.
175
+
176
+ Exit codes: `0` success, `1` translation/transport/protocol or output-pipe failure,
177
+ `2` invalid configuration/input, `130` interruption.
178
+
179
+ ## Scope and data handling
180
+
181
+ Each hop sends the **whole document** to the configured endpoint. There is no
182
+ automatic chunking or silent truncation. Input plus generated translation must
183
+ fit the model/server context; long corpora may require a larger context or manual
184
+ preparation. Server-side silent input truncation cannot be reliably detected.
185
+
186
+ Intermediate text is held in memory. `--json` includes the original and every
187
+ translation; `--show-steps` displays intermediate text. Convolute creates no run
188
+ files by default; redirected output and provider-side logging remain under your
189
+ control. API keys and raw response bodies are excluded from error diagnostics.
190
+
191
+ This POC supports OpenAI-compatible text chat completions. Native provider APIs,
192
+ batch JSONL, concurrent documents, caching, resumable runs, and automatic semantic
193
+ scoring are outside its current scope. A custom endpoint must support this wire
194
+ format and provide a usable non-streaming completion with `finish_reason: stop`.
195
+
196
+ ## Development and validation
197
+
198
+ ```sh
199
+ python3 -m venv work/venv
200
+ . work/venv/bin/activate
201
+ python -m pip install -e '.[test]'
202
+ python -m pytest -q
203
+ python -m build
204
+ ```
205
+
206
+ Tests exercise configuration, actual HTTP requests to a local fixture server,
207
+ request ordering, repeats, CLI subprocesses, retries, and failure records without
208
+ requiring an LLM or paid API. Test runs need permission to bind a loopback socket.
209
+
210
+ Protocol tests do not establish paraphrase quality. Before adopting a default for
211
+ your corpus, compare all three presets and both modes on a fixed set of sentences
212
+ containing names, numbers, negation, idioms, and multiple paragraphs. Record the
213
+ model/settings, latency, wording variation, and factual changes. The initial
214
+ language ordering is a heuristic, not a proven optimum.
215
+
216
+ Background: [pivot-based paraphrasing and semantic shift](https://aclanthology.org/2021.emnlp-main.350/),
217
+ [Ollama API compatibility](https://docs.ollama.com/api/openai-compatibility),
218
+ [model baseline](https://ollama.com/library/qwen2.5:7b), and
219
+ [standard language codes](https://www.loc.gov/standards/iso639-2/php/code_list.php).
220
+
221
+ Licensed under GPL-3.0-only; see [LICENSE](LICENSE).
222
+
223
+ ## Publishing releases
224
+
225
+ The `publish.yml` GitHub Actions workflow tests, builds, validates, and publishes
226
+ the package when a GitHub release is published. Uploading uses PyPI Trusted
227
+ Publishing, with no API token stored in the repository.
228
+
229
+ One-time setup:
230
+
231
+ 1. Create a PyPI account, verify its email address, and enable two-factor
232
+ authentication.
233
+ 2. Create the `pypi` environment in this repository's GitHub settings.
234
+ 3. At <https://pypi.org/manage/account/publishing/>, register a pending publisher:
235
+
236
+ | Field | Value |
237
+ | --- | --- |
238
+ | PyPI project name | `convolute` |
239
+ | Owner | `git-akihakune` |
240
+ | Repository | `convolute` |
241
+ | Workflow filename | `publish.yml` |
242
+ | Environment | `pypi` |
243
+
244
+ For each release, update both `pyproject.toml` and `src/convolute/__init__.py`
245
+ to the same version, commit and push the changes, then publish a GitHub release
246
+ with a matching tag such as `v0.1.0`. The workflow rejects mismatched versions
247
+ before building. The first successful upload creates the PyPI project; a pending
248
+ publisher does not reserve its name. Subsequent releases need a new version.
@@ -0,0 +1,13 @@
1
+ convolute/__init__.py,sha256=NlCvW44a4IaRvF4-9Kk2TQI_OX3rhSZyfcOF972yoEw,78
2
+ convolute/__main__.py,sha256=k1ocEWawweo1qCJWNFAAvyxz3tcY13dzvCenHszij30,48
3
+ convolute/cli.py,sha256=kIS3dYkDGVGvuz24e_rzYVUA8aMCJk2be0ioYgrsG6g,6031
4
+ convolute/client.py,sha256=lokod7R-EGsUffxizRKIcuPvPIunBOIkZlJqnX_9y34,5938
5
+ convolute/config.py,sha256=P1JUv_BQTlLe3WXFBezxYrYiHrUgHhMhldtHrrAEQpk,4172
6
+ convolute/languages.py,sha256=coIvZ7KIpzq3FeBslWls69lNa2lwxX9tBRJBPoWpsGM,1613
7
+ convolute/pipeline.py,sha256=pSvS5PS_mqx12zjOX3C663tuUEpxP8nHsN_EXY0nn08,2058
8
+ convolute-0.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
9
+ convolute-0.1.0.dist-info/METADATA,sha256=H-IQ8MGpsTm-BuLxI0hcLAmitaiRMEhP4MKTVkO47qE,11039
10
+ convolute-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
11
+ convolute-0.1.0.dist-info/entry_points.txt,sha256=0ljvd8MsQN5dBISWCXkP-srnGFADCukqORr7rn0qh9Y,49
12
+ convolute-0.1.0.dist-info/top_level.txt,sha256=bOCihLalDbCdPNDCF7_AJO0wBkGScXsd5xViO5zPcTw,10
13
+ convolute-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ convolute = convolute.cli:main