cabsallm 0.1.0__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.
@@ -0,0 +1,18 @@
1
+ # Do not commit a real key. You may instead pass --api-key at runtime.
2
+ OPENAI_API_KEY=replace_me
3
+
4
+ # Claude preset
5
+ # ANTHROPIC_API_KEY=replace_me
6
+
7
+ # Gemini preset
8
+ # GEMINI_API_KEY=replace_me
9
+
10
+ # Qwen Model Studio preset
11
+ # DASHSCOPE_API_KEY=replace_me
12
+
13
+ # Kimi / Moonshot preset
14
+ # MOONSHOT_API_KEY=replace_me
15
+
16
+ # Custom OpenAI-compatible endpoint.
17
+ # LLM_API_KEY=replace_me
18
+ # LLM_BASE_URL=https://your-provider.example/v1
@@ -0,0 +1,9 @@
1
+ .env
2
+ .venv/
3
+ __pycache__/
4
+ *.py[cod]
5
+ build/
6
+ dist/
7
+ *.egg-info/
8
+ runs/
9
+ tuning/
cabsallm-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeEditsCues contributors
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,374 @@
1
+ Metadata-Version: 2.5
2
+ Name: cabsallm
3
+ Version: 0.1.0
4
+ Summary: Configurable LLM annotation with adaptive batching and BOHB-style tuning.
5
+ Project-URL: Homepage, https://aclanthology.org/2026.acl-short.51/
6
+ Project-URL: Documentation, https://aclanthology.org/2026.acl-short.51/
7
+ Author: CodeEditsCues contributors
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: adaptive-batching,annotation,bohb,llm,optimization
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: openai>=1.0
19
+ Requires-Dist: openpyxl>=3.1
20
+ Requires-Dist: pandas>=2.0
21
+ Requires-Dist: python-dotenv>=1.0
22
+ Requires-Dist: pyyaml>=6.0
23
+ Provides-Extra: all-providers
24
+ Requires-Dist: anthropic>=0.40; extra == 'all-providers'
25
+ Requires-Dist: google-genai>=1.0; extra == 'all-providers'
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.40; extra == 'anthropic'
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Provides-Extra: gemini
31
+ Requires-Dist: google-genai>=1.0; extra == 'gemini'
32
+ Provides-Extra: tokens
33
+ Requires-Dist: tiktoken>=0.7; extra == 'tokens'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # CodeEditsCues
37
+
38
+ **Bring your data, columns, annotation prompt, and model; CodeEditsCues runs a
39
+ structured LLM annotation workflow and can tune its batch controller for your
40
+ dataset.** It began as the reusable engineering layer behind the `NovelPipeline`
41
+ and `BOHBTune` research notebooks, without requiring users to edit notebook code.
42
+
43
+ ## Research foundation and citation
44
+
45
+ CodeEditsCues implements and generalizes the context-aware batching and dynamic
46
+ batch-control ideas introduced in the package’s foundational ACL paper,
47
+ [_CaBSALLM: Efficient Context-Aware Batch Annotation of Conversational Streams
48
+ with Large Language Models_](https://aclanthology.org/2026.acl-short.51/).
49
+ If you use this package, cite:
50
+
51
+ > Mohammadsadegh Abolhasani, Reza Mousavi, and Paul Jen-Hwa Hu. 2026. CaBSALLM:
52
+ > Efficient Context-Aware Batch Annotation of Conversational Streams with Large
53
+ > Language Models. In *Proceedings of the 64th Annual Meeting of the Association
54
+ > for Computational Linguistics (Volume 2: Short Papers)*, pages 615–636, San
55
+ > Diego, California, United States. Association for Computational Linguistics.
56
+ > https://doi.org/10.18653/v1/2026.acl-short.51
57
+
58
+ The citation is available directly in Python or through the command line:
59
+
60
+ ```python
61
+ from codeedit_cues import citation
62
+
63
+ print(citation()) # ACL-style reference
64
+ print(citation("bibtex")) # ready to paste into a .bib file
65
+ print(citation("markdown"))
66
+ print(citation("doi"))
67
+ ```
68
+
69
+ ```powershell
70
+ cuebatch cite
71
+ cuebatch cite --style bibtex
72
+ ```
73
+
74
+ > Status: this repository is ready to install locally or publish to PyPI. It is
75
+ > not published under a public package name yet, so `pip install cabsallm`
76
+ > will work only after the maintainer publishes the release.
77
+
78
+ ## What users provide
79
+
80
+ - A tabular dataset: CSV, TSV, Excel, JSON, or JSONL.
81
+ - The unique identifier column, text column, and—optionally—a conversation or
82
+ streamer/group column. Batches do not cross a group boundary.
83
+ - An annotation prompt and a list of desired output fields.
84
+ - A model name and a runtime API key.
85
+
86
+ The result is `runs/annotated.xlsx`, retaining every original input column and
87
+ adding the requested labels, `_cuebatch_status`, and `_cuebatch_error`. It also
88
+ writes `run_metadata.json` for reproducibility.
89
+
90
+ ## How `pip install` works
91
+
92
+ `pyproject.toml` identifies the package name, Python version, dependencies, and
93
+ the `cuebatch` command. A package build turns the `codeedit_cues/` source folder
94
+ into a wheel (`.whl`) and source archive. Publishing those two artifacts to PyPI
95
+ under an available distribution name lets `pip` download the matching wheel and
96
+ install its dependencies for every user. The package import name stays
97
+ `codeedit_cues`; the public `pip` name can be changed before release.
98
+
99
+ ## Install and first run
100
+
101
+ For a local checkout or a downloaded ZIP:
102
+
103
+ ```powershell
104
+ cd CodeEditsCues
105
+ python -m pip install -e ".[tokens,dev]"
106
+ cuebatch inspect .\examples\example_messages.csv
107
+ cuebatch init cuebatch.yaml
108
+ ```
109
+
110
+ The interactive setup shows the available columns, then asks for the id and text
111
+ columns, optional group column, prompt, output fields, model, key environment
112
+ variable, batching method, and tuning mode. It creates a portable YAML project
113
+ file; it never saves an API key.
114
+
115
+ Copy the safe key template and put the real value only in the local `.env` file:
116
+
117
+ ```powershell
118
+ Copy-Item .env.example .env
119
+ # Edit .env locally: OPENAI_API_KEY=...
120
+ cuebatch run cuebatch.yaml
121
+ ```
122
+
123
+ Alternatively, supply a key only for the active command:
124
+
125
+ ```powershell
126
+ cuebatch run cuebatch.yaml --api-key "your-key"
127
+ ```
128
+
129
+ `--api-key` is not written to YAML, metadata, or tuning records. Do not place a
130
+ real key in a prompt, notebook, YAML file, shell history, or Git repository.
131
+ `.env` is ignored by Git.
132
+
133
+ ## Python scripts for every command
134
+
135
+ Each CLI workflow has a small, runnable Python counterpart under
136
+ [`examples/scripts`](examples/scripts). Run these commands from the package root
137
+ after installation; edit `examples/cuebatch.yaml` or create your own project
138
+ before sending a real request.
139
+
140
+ | CLI command | Python example | Run it |
141
+ | --- | --- | --- |
142
+ | `cuebatch init cuebatch.yaml` | [`create_project.py`](examples/scripts/create_project.py) | `python examples/scripts/create_project.py` |
143
+ | `cuebatch inspect DATA` | [`inspect_data.py`](examples/scripts/inspect_data.py) | `python examples/scripts/inspect_data.py examples/example_messages.csv` |
144
+ | `cuebatch run CONFIG --dry-run` | [`dry_run.py`](examples/scripts/dry_run.py) | `python examples/scripts/dry_run.py examples/cuebatch.yaml` |
145
+ | `cuebatch run CONFIG` | [`run_annotation.py`](examples/scripts/run_annotation.py) | `python examples/scripts/run_annotation.py examples/cuebatch.yaml --max-rows 50` |
146
+ | `cuebatch tune CONFIG` | [`tune.py`](examples/scripts/tune.py) | `python examples/scripts/tune.py examples/cuebatch.yaml` |
147
+ | `cuebatch cite --style bibtex` | [`cite_paper.py`](examples/scripts/cite_paper.py) | `python examples/scripts/cite_paper.py` |
148
+
149
+ For code embedded in a larger research pipeline, use the same public API as the
150
+ examples: `load_config(...)`, `AnnotationRunner(...).run(...)`, `Tuner(...).run()`,
151
+ and `citation(...)`. The scripts deliberately expose the arguments users most
152
+ often change: project YAML, an optional runtime-only API key, and a pilot row
153
+ limit. They never contain a real key.
154
+
155
+ ## Model and provider presets
156
+
157
+ The setup wizard has first-class presets, so different providers get their native
158
+ API request shape and default key name. Every preset allows a different model
159
+ string; providers change model availability over time, so users should select a
160
+ model enabled in their own account.
161
+
162
+ | `llm.provider` | Default transport | Key in `.env` | Extra install |
163
+ | --- | --- | --- | --- |
164
+ | `openai` | OpenAI Responses API | `OPENAI_API_KEY` | none |
165
+ | `anthropic` | Claude Messages API | `ANTHROPIC_API_KEY` | `pip install "cabsallm[anthropic]"` |
166
+ | `gemini` | Google GenAI SDK | `GEMINI_API_KEY` | `pip install "cabsallm[gemini]"` |
167
+ | `qwen` | Qwen Model Studio’s OpenAI-compatible Chat Completions endpoint | `DASHSCOPE_API_KEY` | none |
168
+ | `kimi` | Kimi’s OpenAI-compatible Chat Completions endpoint | `MOONSHOT_API_KEY` | none |
169
+ | `openai_compatible` | Any compatible Chat Completions endpoint | a user-chosen name | none |
170
+
171
+ Qwen’s preset uses the public DashScope compatible endpoint; replace `base_url`
172
+ with the regional or workspace endpoint appropriate for the user’s account.
173
+ Kimi’s international preset uses `https://api.moonshot.ai/v1`; users of the China
174
+ platform should replace it with their regional endpoint. Alibaba documents its
175
+ Qwen-compatible endpoints and region-specific base URLs, and Kimi documents its
176
+ OpenAI-compatible endpoint and `MOONSHOT_API_KEY` example. [Qwen Model Studio](https://help.aliyun.com/en/model-studio/base-url) [Kimi API overview](https://platform.kimi.ai/docs/api/overview)
177
+
178
+ Gemini uses Google’s official SDK and `GEMINI_API_KEY`; Claude uses Anthropic’s
179
+ Messages API. [Google Gemini setup](https://ai.google.dev/gemini-api/docs/get-started) [Anthropic Python example](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/prompt-templates-and-variables)
180
+
181
+ The key is looked up from `llm.api_key_env` in a `.env` file next to the YAML,
182
+ then from the process environment. The default key names are shown above.
183
+
184
+ An `openai_compatible` provider must specify `llm.base_url` and uses Chat
185
+ Completions, rather than assuming Responses API compatibility. No provider keys
186
+ are hard-coded in the package.
187
+
188
+ ## Project configuration
189
+
190
+ Start from [`examples/cuebatch.yaml`](examples/cuebatch.yaml). This is the core
191
+ shape:
192
+
193
+ ```yaml
194
+ input_path: messages.xlsx
195
+ output_dir: runs
196
+ columns: {id: message_id, text: message, group: conversation_id}
197
+ output_fields: [sentiment, relational_cue]
198
+ prompt: {path: prompt.txt}
199
+ llm: {provider: openai, model: gpt-5.4, api_key_env: OPENAI_API_KEY, max_output_tokens: 4000}
200
+ batching: {strategy: hybrid, max_size: 60}
201
+ optimization: {enabled: false}
202
+ ```
203
+
204
+ The model receives only the configured `id` and `text` fields for a batch. It is
205
+ instructed to return one JSON object per input item, in order, containing the id
206
+ and every requested `output_fields` value. This makes the merge deterministic;
207
+ the package rejects duplicated input ids rather than silently joining labels to
208
+ the wrong row.
209
+
210
+ ## Intelligence, reasoning, and sampling controls
211
+
212
+ There is no honest cross-provider numeric “intelligence” score: the exact
213
+ `llm.model` is the capability choice, and users should choose the model tier their
214
+ provider offers (for example a faster/economy model versus its stronger flagship
215
+ model). `reasoning_effort` then controls how much the chosen reasoning-capable
216
+ model deliberates before it returns labels; it does not silently replace the
217
+ selected model.
218
+
219
+ ```yaml
220
+ llm:
221
+ provider: openai
222
+ model: gpt-5.4 # capability/intelligence choice
223
+ reasoning_effort: medium # none|minimal|low|medium|high|xhigh
224
+ # thinking_budget: 1024 # Gemini only; use instead of reasoning_effort
225
+ temperature: 0 # optional; blank/omitted uses model default
226
+ ```
227
+
228
+ OpenAI receives the native Responses `reasoning.effort` parameter. Claude maps
229
+ the portable effort choice to its Messages API output-effort control. Gemini maps
230
+ it to `thinking_level`; Gemini users can instead set a numeric `thinking_budget`
231
+ where their selected Gemini model supports it. The configuration rejects setting
232
+ both fields, because they control the same behavior. Qwen and Kimi preserve the
233
+ chosen model and temperature but do not receive a fabricated reasoning setting:
234
+ their thinking controls vary by model and endpoint, so users should use the
235
+ provider’s supported model/options rather than expect a portable slider to mean
236
+ the same thing everywhere. OpenAI documents effort levels from `none` through
237
+ `xhigh`; Gemini documents its model-specific thinking levels/budgets; Anthropic
238
+ documents effort controls for Messages API models. [OpenAI reasoning reference](https://platform.openai.com/docs/api-reference/responses-streaming/response/refusal?lang=python) [Gemini thinking controls](https://ai.google.dev/gemini-api/docs/generate-content/thinking) [Anthropic Messages example](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/prompt-templates-and-variables)
239
+
240
+ For reproducible labeling, start with `temperature: 0` if the selected provider
241
+ supports it, run a pilot with `--max-rows`, and record the exact model/version in
242
+ the generated `run_metadata.json`.
243
+
244
+ ## Batching choices
245
+
246
+ The package exposes the alternatives requested by the original pipeline rather
247
+ than hiding them inside code:
248
+
249
+ | Strategy | Behavior | When to use it |
250
+ | --- | --- | --- |
251
+ | `fixed` | Always uses `fixed_size`. | Baseline, stable endpoint, or a predetermined batch size. |
252
+ | `aimd` | Increases gradually and decreases multiplicatively after failures/truncation. | Simple, fast recovery from occasional API failures. |
253
+ | `ewma` | Uses smoothed health to respond to sustained quality degradation. | Variable-length texts or intermittent output quality issues. |
254
+ | `hybrid` | Combines AIMD hard-event response with EWMA health monitoring. | Recommended default; closest to the research notebooks. |
255
+
256
+ All strategies respect `min_size`, `max_size`, the context budget, output budget,
257
+ and retry setting. The `hybrid` controller exposes `beta`, `delta`, `gamma`,
258
+ `rho0`, `tau_center`, `tau_half_width`, and `pi_output` in YAML, so a researcher
259
+ can either use known values or tune them empirically.
260
+
261
+ ## Progress, ETA, and comfort controls
262
+
263
+ Long LLM runs should be inspectable without becoming a wall of terminal text.
264
+ The `reporting` section controls this behavior. The default `normal` line shows
265
+ batch number, completed rows, batch size, controller movement (`K before -> K
266
+ next`), EWMA health, cumulative input/output tokens, elapsed time, and estimated
267
+ time remaining. `detailed` additionally records group/id context in the JSONL
268
+ event log when requested; `quiet` keeps the terminal silent.
269
+
270
+ ```yaml
271
+ reporting:
272
+ verbosity: normal # quiet | normal | detailed
273
+ progress_every_batches: 1 # print less often with, e.g., 5
274
+ show_eta: true
275
+ show_tokens: true
276
+ show_controller: true # K and EWMA health
277
+ show_batch_ids: false # opt in only for non-sensitive IDs
278
+ show_errors: true
279
+ write_events: true # runs/progress.jsonl, one event per batch
280
+ save_partial_every_batches: 5 # annotated.partial.xlsx; 0 disables it
281
+ ```
282
+
283
+ Useful one-off controls do not alter the saved YAML:
284
+
285
+ ```powershell
286
+ # Validate input columns/ids and estimate scope without contacting a model.
287
+ cuebatch run cuebatch.yaml --dry-run
288
+
289
+ # Run an inexpensive pilot, then review annotated.xlsx and progress.jsonl.
290
+ cuebatch run cuebatch.yaml --max-rows 50
291
+
292
+ # Keep an otherwise normal project config quiet and avoid local progress files.
293
+ cuebatch run cuebatch.yaml --quiet --no-events --no-partials
294
+ ```
295
+
296
+ Partial workbooks make it easy to inspect progress during a long run. The final
297
+ `annotated.xlsx` remains the completed output; a partial snapshot is deliberately
298
+ not presented as a final result.
299
+
300
+ ## BOHB-style tuning
301
+
302
+ BOHB-style tuning evaluates candidate controller settings on small data budgets,
303
+ promotes stronger candidates to larger budgets through successive halving, and
304
+ records a composite loss based on completion, failures, tokens, and elapsed time.
305
+ It tunes the controller—not the semantic correctness of an annotation prompt.
306
+ Use a manually reviewed validation sample when comparing prompts or models.
307
+
308
+ Tuning is deliberately opt-in twice: it requires `enabled: true` and an explicit
309
+ `hyperparameters` list. This prevents an accidental expensive search over every
310
+ controller setting. The available methods are:
311
+
312
+ | Method | How it searches | Best use |
313
+ | --- | --- | --- |
314
+ | `bohb` (default) | History-informed sampling plus successive halving across increasing data budgets. | Default for moderate-cost tuning. |
315
+ | `successive_halving` | Random candidates, then promotion of better candidates to larger budgets. | A simple multi-fidelity baseline. |
316
+ | `random` | Uniform samples over the user-defined bounds, each at full budget. | A robust baseline for irregular search spaces. |
317
+ | `grid` | Deterministic grid: all integer values and low/mid/high values for floats. | Small, interpretable parameter spaces. |
318
+ | `greedy` | Coordinate hill-climbing from the midpoint. | Low-budget local refinement when you have a credible starting range. |
319
+
320
+ There are two deliberate range choices:
321
+
322
+ 1. **Let CodeEditsCues place the hyperparameters.** Set
323
+ `optimization.search_space_mode: default`. The notebook-derived ranges cover
324
+ `delta`, `gamma`, `beta`, `tau_center`, `rho0`, and `pi_output`.
325
+ 2. **Provide your own hyperparameters/ranges.** Set
326
+ `search_space_mode: custom` and include `search_space` in the YAML (the full
327
+ schema is commented in the example file). Use `type: int` or `type: float`,
328
+ with `low` and `high` bounds.
329
+
330
+ Enable tuning and run it explicitly:
331
+
332
+ ```yaml
333
+ optimization:
334
+ enabled: true
335
+ method: bohb
336
+ hyperparameters: [delta, gamma, beta, tau_center, rho0, pi_output]
337
+ trials: 30
338
+ min_budget: 25
339
+ max_budget: 200
340
+ search_space_mode: default
341
+ ```
342
+
343
+ ```powershell
344
+ cuebatch tune cuebatch.yaml
345
+ ```
346
+
347
+ The tuner writes a resumable `runs/tuning/<method>_trials.json` after every trial and
348
+ `<method>_best_config.json` when complete. Review the latter, copy the chosen values
349
+ into `batching`, then run the full dataset with `cuebatch run`. Tuning sends real
350
+ requests and incurs model cost; begin with a small trial count and budget.
351
+
352
+ ## Publishing for `pip install`
353
+
354
+ Before public release, choose an available PyPI distribution name and replace the
355
+ placeholder project URLs in `pyproject.toml`. Then build and validate the exact
356
+ artifact users will receive:
357
+
358
+ ```powershell
359
+ python -m pip install build twine
360
+ python -m build
361
+ twine check dist/*
362
+ ```
363
+
364
+ Upload only after checking the wheel and source archive contain no `.env`, raw
365
+ datasets, cached responses, or API keys. Once published under an available name,
366
+ users can install it with `pip install YOUR-PACKAGE-NAME`.
367
+
368
+ ## Scope and responsible use
369
+
370
+ This tool is a workflow and optimization utility, not a validity guarantee.
371
+ Validate labels against a human-coded sample, document the prompt/model/version,
372
+ inspect failed rows, and obtain the permissions required to send data to the
373
+ selected model provider. Do not use it to process secrets or regulated data
374
+ without an approved provider and data-handling process.