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.
- convolute/__init__.py +3 -0
- convolute/__main__.py +3 -0
- convolute/cli.py +133 -0
- convolute/client.py +125 -0
- convolute/config.py +93 -0
- convolute/languages.py +34 -0
- convolute/pipeline.py +65 -0
- convolute-0.1.0.dist-info/METADATA +248 -0
- convolute-0.1.0.dist-info/RECORD +13 -0
- convolute-0.1.0.dist-info/WHEEL +5 -0
- convolute-0.1.0.dist-info/entry_points.txt +2 -0
- convolute-0.1.0.dist-info/licenses/LICENSE +674 -0
- convolute-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -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,,
|