indicate 0.7.0__tar.gz → 0.7.1__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.
Potentially problematic release.
This version of indicate might be problematic. Click here for more details.
- indicate-0.7.1/.gitignore +34 -0
- indicate-0.7.1/.pre-commit-config.yaml +40 -0
- indicate-0.7.1/CHANGELOG.md +63 -0
- indicate-0.7.1/CITATION.cff +11 -0
- indicate-0.7.1/CLAUDE.md +77 -0
- indicate-0.7.1/LICENSE +21 -0
- indicate-0.7.1/Makefile +56 -0
- {indicate-0.7.0 → indicate-0.7.1}/PKG-INFO +12 -12
- indicate-0.7.1/dist/.gitignore +1 -0
- indicate-0.7.1/images/h2e_ed.png +0 -0
- indicate-0.7.1/images/pa2e_ed.png +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/__init__.py +7 -3
- {indicate-0.7.0 → indicate-0.7.1}/indicate/batch.py +29 -13
- {indicate-0.7.0 → indicate-0.7.1}/indicate/cli.py +67 -55
- {indicate-0.7.0 → indicate-0.7.1}/indicate/decoder.py +1 -1
- {indicate-0.7.0 → indicate-0.7.1}/indicate/file_utils.py +15 -19
- {indicate-0.7.0 → indicate-0.7.1}/indicate/indic_utils.py +12 -20
- {indicate-0.7.0 → indicate-0.7.1}/indicate/llm_indic.py +32 -30
- indicate-0.7.1/indicate/py.typed +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/transliterator.py +12 -15
- {indicate-0.7.0 → indicate-0.7.1}/indicate/utils.py +4 -178
- {indicate-0.7.0 → indicate-0.7.1}/pyproject.toml +54 -90
- indicate-0.7.1/uv.lock +3050 -0
- indicate-0.7.0/indicate/transliterate.py +0 -18
- {indicate-0.7.0 → indicate-0.7.1}/README.md +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/data/hindi_to_english/english_tokens.json +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/data/hindi_to_english/hindi_tokens.json +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/data/llm_examples.json +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/data/punjabi_to_english/english_tokens.json +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/data/punjabi_to_english/punjabi_tokens.json +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/encoder.py +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/hindi2english.py +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/logging.py +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/punjabi2english.py +0 -0
- {indicate-0.7.0 → indicate-0.7.1}/indicate/rerank.py +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.*
|
|
2
|
+
!.github
|
|
3
|
+
!.gitignore
|
|
4
|
+
!.gitattributes
|
|
5
|
+
!.travis.yml
|
|
6
|
+
!.pre-commit-config.yaml
|
|
7
|
+
*.pyc
|
|
8
|
+
*.log
|
|
9
|
+
./data
|
|
10
|
+
build/
|
|
11
|
+
lit/
|
|
12
|
+
dist/
|
|
13
|
+
.ipynb_checkpoints
|
|
14
|
+
*/.ipynb_checkpoints/*
|
|
15
|
+
past/
|
|
16
|
+
.venv
|
|
17
|
+
*.egg-info*
|
|
18
|
+
coverage.xml
|
|
19
|
+
htmlcov/
|
|
20
|
+
/test_install_tf220
|
|
21
|
+
/test_tf219
|
|
22
|
+
# Dakshina benchmark dataset (downloaded locally for training/eval.py)
|
|
23
|
+
*.tar
|
|
24
|
+
dakshina_dataset_v1.0/
|
|
25
|
+
data/dakshina/
|
|
26
|
+
# Large/raw Punjabi source data (silver, electoral-roll PII); committed data is data/punjabi.csv
|
|
27
|
+
data/punjab_transliteration_subset.parquet
|
|
28
|
+
training/IMPROVEMENTS.md
|
|
29
|
+
# v2 (Aksharantar) — external download, derived training corpora, built eval sets
|
|
30
|
+
data/aksharantar/
|
|
31
|
+
data/eval/
|
|
32
|
+
data/*_train_v2.csv.gz
|
|
33
|
+
# Model weights are hosted on HF and lazy-downloaded; tokenizer JSONs stay tracked
|
|
34
|
+
indicate/data/*/saved_weights/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.8.7
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
10
|
+
rev: v1.12.1
|
|
11
|
+
hooks:
|
|
12
|
+
- id: mypy
|
|
13
|
+
additional_dependencies:
|
|
14
|
+
- types-requests
|
|
15
|
+
args: [--ignore-missing-imports]
|
|
16
|
+
|
|
17
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
18
|
+
rev: v5.0.0
|
|
19
|
+
hooks:
|
|
20
|
+
- id: trailing-whitespace
|
|
21
|
+
- id: end-of-file-fixer
|
|
22
|
+
- id: check-yaml
|
|
23
|
+
- id: check-toml
|
|
24
|
+
- id: check-merge-conflict
|
|
25
|
+
- id: check-case-conflict
|
|
26
|
+
- id: check-docstring-first
|
|
27
|
+
- id: debug-statements
|
|
28
|
+
- id: check-added-large-files
|
|
29
|
+
|
|
30
|
+
- repo: https://github.com/jsh9/pydoclint
|
|
31
|
+
rev: 0.8.6
|
|
32
|
+
hooks:
|
|
33
|
+
- id: pydoclint
|
|
34
|
+
|
|
35
|
+
- repo: https://github.com/pycqa/bandit
|
|
36
|
+
rev: 1.8.0
|
|
37
|
+
hooks:
|
|
38
|
+
- id: bandit
|
|
39
|
+
args: [-r, ., -ll]
|
|
40
|
+
exclude: ^tests/
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Data-scaled v2 models** — both Hindi and Punjabi retrained on the public
|
|
7
|
+
**Aksharantar** corpus (AI4Bharat) merged with our own data: Hindi ~1.5M pairs,
|
|
8
|
+
Punjabi ~773k. A strict **leakage filter** drops every eval word from training.
|
|
9
|
+
- **Batched inference** — `transliterate_batch(list[str])` is the decode engine
|
|
10
|
+
(batched greedy + beam); `transliterate(str)` is a thin wrapper. The CLI
|
|
11
|
+
`--batch` mode and bulk eval use it (≫ faster than one-at-a-time).
|
|
12
|
+
- **Top-k / n-best** — `transliterate(text, n=k)` returns up to `k` ranked
|
|
13
|
+
candidates (a `list[str]`); `n=1` (default) still returns a `str`.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **Model weights hosted on Hugging Face** (`soodoku/indicate`, tag `v0.7.0`) and
|
|
17
|
+
lazy-downloaded (cached) on first use, so the wheel is ~50 KB instead of ~107 MB
|
|
18
|
+
(PyPI's 100 MB limit). Tokenizer JSONs still ship in the package; a local copy of
|
|
19
|
+
the weights, if present, is used in preference to the download. Weights are fp32
|
|
20
|
+
(`safetensors`) — fp16 was tried and rejected (it perturbed ~0.05% of outputs for
|
|
21
|
+
no size benefit worth keeping, since hosting solves the size problem).
|
|
22
|
+
- **Input-adaptive decode cap** (`min(max_length_output, 2·len(input)+8)`).
|
|
23
|
+
- Removed `func_timeout` (the decoder is hard-bounded, so the wall-clock guard
|
|
24
|
+
was dead weight — and a perf/flakiness drag); dropped the dependency.
|
|
25
|
+
- Coverage reports to the terminal only (no `htmlcov`/`coverage.xml`).
|
|
26
|
+
|
|
27
|
+
### Accuracy (Dakshina test, exact-match; vs AI4Bharat IndicXlit, same direction/data)
|
|
28
|
+
| Model | Dakshina (gold) | Held-out-own names |
|
|
29
|
+
|-------|-----------------|--------------------|
|
|
30
|
+
| Hindi v2 | **74.4%** (IndicXlit 73.2%) | **52.8%** (IndicXlit 49.7%) |
|
|
31
|
+
| Punjabi v2 | 71.9% (IndicXlit 73.2%) | **56.9%** (IndicXlit 53.5%) |
|
|
32
|
+
|
|
33
|
+
v2 matches/edges SOTA IndicXlit on the gold benchmark and **beats it on the
|
|
34
|
+
deployment domain** (names IndicXlit never trained on). Eval is leakage-filtered;
|
|
35
|
+
see `training/IMPROVEMENTS.md` and `training/compare.py`.
|
|
36
|
+
|
|
37
|
+
## 0.6.0
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
- **Punjabi (Gurmukhi → English) transliteration model** — new `PunjabiToEnglish`
|
|
41
|
+
class, `indicate.punjabi2english(...)` API, and `indicate punjabi2english` CLI
|
|
42
|
+
command. Distilled from GPT-4o-labelled Punjab data
|
|
43
|
+
(`training/extract_punjabi.py` → `data/punjabi.csv.gz`).
|
|
44
|
+
- **Beam-search decoding** (length-normalized, width 5) is now the default for
|
|
45
|
+
both models — +1.5 pts exact-match on the Hindi Dakshina test set vs greedy.
|
|
46
|
+
- Evaluation tooling: `training/eval.py` (gold Dakshina), `training/oos_eval.py`
|
|
47
|
+
(held-out), and `training/metrics.py` reporting exact-match accuracy, CER, and
|
|
48
|
+
Acc@≤1 with edit-distance histograms.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
- **Migrated the modeling stack from TensorFlow to PyTorch** and the package to
|
|
52
|
+
**Python 3.13-only**. Weights now ship as `safetensors`.
|
|
53
|
+
- Refactored the per-language logic into a shared `Seq2SeqTransliterator` base.
|
|
54
|
+
|
|
55
|
+
### Accuracy (Google Dakshina test, exact-match / Acc@≤1 / CER)
|
|
56
|
+
- Hindi → English: **77.32% / 91.16% / 5.65%**
|
|
57
|
+
- Punjabi → English: **71.24% / 91.56% / 6.42%**
|
|
58
|
+
|
|
59
|
+
### Notes
|
|
60
|
+
- Char-LM beam re-ranking and attention padding masks are implemented but gated
|
|
61
|
+
off (no measured win for the name-heavy, native→Latin case); see
|
|
62
|
+
`training/IMPROVEMENTS.md`. The next milestone is a data-scale retrain on the
|
|
63
|
+
public Aksharantar corpus.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
authors:
|
|
4
|
+
- family-names: "Chintalapati"
|
|
5
|
+
given-names: "Rajashekar"
|
|
6
|
+
- family-names: "Sood"
|
|
7
|
+
given-names: "Gaurav"
|
|
8
|
+
title: "Indicate: Transliterate Indic Languages to English"
|
|
9
|
+
version: 0.1.0
|
|
10
|
+
date-released: 2022-08-21
|
|
11
|
+
url: "https://github.com/in-rolls/indicate"
|
indicate-0.7.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Indicate is a Python package for transliterating Indic text to English using PyTorch-based encoder-decoder models with attention. It ships local models for **Hindi** (Devanagari) and **Punjabi** (Gurmukhi), plus an LLM backend for other languages. The local models are custom-trained neural networks with pre-trained weights.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
### Testing
|
|
12
|
+
```bash
|
|
13
|
+
python -m unittest tests.test_010_hindi_translate
|
|
14
|
+
python -m unittest discover tests/
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Build and Installation
|
|
18
|
+
```bash
|
|
19
|
+
uv sync # Install dependencies with uv (recommended)
|
|
20
|
+
uv build # Build package
|
|
21
|
+
pip install -e . # Install in development mode (alternative)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### CLI Usage
|
|
25
|
+
```bash
|
|
26
|
+
# Modern Click-based CLI
|
|
27
|
+
indicate hindi2english "राजशेखर चिंतालपति"
|
|
28
|
+
indicate hindi2english --input file.txt --output result.txt
|
|
29
|
+
indicate info
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Documentation (Sphinx)
|
|
33
|
+
```bash
|
|
34
|
+
cd docs/
|
|
35
|
+
make html # Build HTML documentation
|
|
36
|
+
make clean # Clean build artifacts
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Architecture
|
|
40
|
+
|
|
41
|
+
### Core Components
|
|
42
|
+
|
|
43
|
+
1. **Seq2SeqTransliterator** (`indicate/transliterator.py`) - Base lazy-loaded singleton holding the load + greedy `transliterate()` logic, parameterized by class attrs (vocab/weights paths, max lengths)
|
|
44
|
+
2. **HindiToEnglish** (`indicate/hindi2english.py`) / **PunjabiToEnglish** (`indicate/punjabi2english.py`) - Thin subclasses pointing at each language's tokenizers + safetensors
|
|
45
|
+
3. **Encoder** (`indicate/encoder.py`) - `nn.Module` LSTM encoder
|
|
46
|
+
4. **Decoder** (`indicate/decoder.py`) - `nn.Module` LSTM decoder with Luong (dot-product) attention
|
|
47
|
+
5. **Utils** (`indicate/utils.py`) - Tokenizer loading (`load_tokenizer`) and greedy decoding (`translate`)
|
|
48
|
+
|
|
49
|
+
### Model Architecture
|
|
50
|
+
- Encoder-decoder with Luong attention mechanism
|
|
51
|
+
- Embedding dimension: 256, LSTM units: 1024
|
|
52
|
+
- Per-language safetensors weights + tokenizer JSONs under
|
|
53
|
+
`indicate/data/{hindi,punjabi}_to_english/`
|
|
54
|
+
|
|
55
|
+
### Training
|
|
56
|
+
- PyTorch training/extraction/eval scripts live in `training/` (see `training/README.md`)
|
|
57
|
+
- Hindi corpus `data/hindi.csv.gz` and Punjabi corpus `data/punjabi.csv.gz` are committed
|
|
58
|
+
(Punjabi is extracted from the Dataverse-hosted parquet via `training/extract_punjabi.py`)
|
|
59
|
+
- Raw/large source data and the Dakshina benchmark live on Dataverse (see `data/README.md`)
|
|
60
|
+
|
|
61
|
+
### Data Pipeline
|
|
62
|
+
- Training data from ESPN Cricinfo, election affidavits, Google Dakshina dataset, and IIT Bombay corpus
|
|
63
|
+
- Character-level tokenization with special start (^) and end ($) tokens
|
|
64
|
+
- Decoding is hard-bounded by an input-adaptive step cap (no wall-clock timeout)
|
|
65
|
+
|
|
66
|
+
### Key Entry Points
|
|
67
|
+
- CLI: `indicate` command (Click group) with `hindi2english` / `punjabi2english` subcommands
|
|
68
|
+
- API: `indicate.hindi2english(text)` and `indicate.punjabi2english(text)` functions
|
|
69
|
+
- Main module: `indicate/__init__.py` exposes both transliteration functions
|
|
70
|
+
|
|
71
|
+
## Dependencies
|
|
72
|
+
- Python 3.13+ (modern Python with enhanced type hints)
|
|
73
|
+
- Click 8.0+ (modern CLI framework)
|
|
74
|
+
- PyTorch 2.6+ (core ML framework)
|
|
75
|
+
- safetensors 0.4+ (model weight serialization)
|
|
76
|
+
- func-timeout 4.3.0+ (prevents hanging translations)
|
|
77
|
+
- tqdm 4.60.0+ (progress bars)
|
indicate-0.7.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Rajasekhar Chintalapati and Gaurav Sood
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
indicate-0.7.1/Makefile
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
.PHONY: help clean install test test-cov lint format type-check docs docs-serve build upload dev-install
|
|
2
|
+
|
|
3
|
+
help: ## Show this help message
|
|
4
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
5
|
+
|
|
6
|
+
clean: ## Clean build artifacts
|
|
7
|
+
rm -rf build/
|
|
8
|
+
rm -rf dist/
|
|
9
|
+
rm -rf *.egg-info/
|
|
10
|
+
rm -rf .pytest_cache/
|
|
11
|
+
rm -rf .coverage
|
|
12
|
+
rm -rf htmlcov/
|
|
13
|
+
rm -rf docs/_build/
|
|
14
|
+
find . -type d -name __pycache__ -delete
|
|
15
|
+
find . -type f -name "*.pyc" -delete
|
|
16
|
+
|
|
17
|
+
install: ## Install package
|
|
18
|
+
uv pip install -e .
|
|
19
|
+
|
|
20
|
+
dev-install: ## Install package with development dependencies
|
|
21
|
+
uv sync --dev
|
|
22
|
+
pre-commit install
|
|
23
|
+
|
|
24
|
+
test: ## Run tests
|
|
25
|
+
pytest
|
|
26
|
+
|
|
27
|
+
test-cov: ## Run tests with coverage
|
|
28
|
+
pytest --cov=indicate --cov-report=html --cov-report=term
|
|
29
|
+
|
|
30
|
+
lint: ## Run linter
|
|
31
|
+
ruff check .
|
|
32
|
+
|
|
33
|
+
format: ## Format code
|
|
34
|
+
ruff format .
|
|
35
|
+
ruff check --fix .
|
|
36
|
+
|
|
37
|
+
type-check: ## Run type checker
|
|
38
|
+
mypy indicate/
|
|
39
|
+
|
|
40
|
+
docs: ## Build documentation
|
|
41
|
+
cd docs && make clean && make html
|
|
42
|
+
|
|
43
|
+
docs-serve: ## Serve documentation locally
|
|
44
|
+
cd docs/build/html && python -m http.server 8000
|
|
45
|
+
|
|
46
|
+
build: ## Build package
|
|
47
|
+
uv build
|
|
48
|
+
|
|
49
|
+
upload: ## Upload to PyPI
|
|
50
|
+
uv publish
|
|
51
|
+
|
|
52
|
+
ci: lint type-check test ## Run CI checks
|
|
53
|
+
|
|
54
|
+
# Legacy aliases for compatibility
|
|
55
|
+
install-dev: dev-install ## Legacy alias for dev-install
|
|
56
|
+
typecheck: type-check ## Legacy alias for type-check
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: indicate
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Transliterations to/from Indian languages
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Project-URL: Homepage, https://github.com/in-rolls/indicate
|
|
6
|
+
Project-URL: Repository, https://github.com/in-rolls/indicate
|
|
7
7
|
Author-email: Rajashekar Chintalapati <rajshekar.ch@gmail.com>, Gaurav Sood <gsood07@gmail.com>
|
|
8
8
|
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: english,hindi,indic,transliterate
|
|
9
11
|
Classifier: Development Status :: 3 - Alpha
|
|
10
12
|
Classifier: Intended Audience :: Developers
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
14
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
13
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
16
|
Classifier: Topic :: Utilities
|
|
17
|
+
Requires-Python: >=3.13
|
|
15
18
|
Requires-Dist: click>=8.0.0
|
|
16
|
-
Requires-Dist:
|
|
17
|
-
Requires-Dist: numpy>=1.26
|
|
18
|
-
Requires-Dist: torch>=2.6.0
|
|
19
|
-
Requires-Dist: safetensors>=0.4.0
|
|
19
|
+
Requires-Dist: google-genai>=1.0
|
|
20
20
|
Requires-Dist: huggingface-hub>=0.23
|
|
21
21
|
Requires-Dist: litellm>=1.0.0
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
Requires-Dist: numpy>=1.26
|
|
23
|
+
Requires-Dist: safetensors>=0.4.0
|
|
24
|
+
Requires-Dist: torch>=2.6.0
|
|
25
|
+
Requires-Dist: tqdm>=4.60.0
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
|
|
28
28
|
# Indicate: Transliterate Indic Languages with PyTorch and LLMs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*
|
|
Binary file
|
|
Binary file
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
from .hindi2english import HindiToEnglish
|
|
1
2
|
from .indic_utils import detect_indic_script, detect_language_from_script
|
|
2
3
|
from .llm_indic import IndicLLMTransliterator
|
|
3
|
-
from .
|
|
4
|
+
from .punjabi2english import PunjabiToEnglish
|
|
5
|
+
|
|
6
|
+
hindi2english = HindiToEnglish.transliterate
|
|
7
|
+
punjabi2english = PunjabiToEnglish.transliterate
|
|
4
8
|
|
|
5
9
|
__all__ = [
|
|
6
|
-
"hindi2english",
|
|
7
|
-
"punjabi2english",
|
|
8
10
|
"IndicLLMTransliterator",
|
|
9
11
|
"detect_indic_script",
|
|
10
12
|
"detect_language_from_script",
|
|
13
|
+
"hindi2english",
|
|
14
|
+
"punjabi2english",
|
|
11
15
|
]
|
|
@@ -30,6 +30,7 @@ import tempfile
|
|
|
30
30
|
import time
|
|
31
31
|
from dataclasses import asdict, dataclass, field
|
|
32
32
|
from pathlib import Path
|
|
33
|
+
from typing import Any, cast
|
|
33
34
|
|
|
34
35
|
import litellm
|
|
35
36
|
|
|
@@ -175,8 +176,8 @@ def _content_to_text(content) -> str:
|
|
|
175
176
|
def _parse_output_jsonl(content) -> dict[str, str]:
|
|
176
177
|
"""Map each request's ``custom_id`` to the model's text output.
|
|
177
178
|
|
|
178
|
-
Output lines follow the OpenAI batch schema
|
|
179
|
-
``
|
|
179
|
+
Output lines follow the OpenAI batch schema (``custom_id``,
|
|
180
|
+
``response.body.choices[0].message.content``, ``error``).
|
|
180
181
|
"""
|
|
181
182
|
results: dict[str, str] = {}
|
|
182
183
|
for line in _content_to_text(content).splitlines():
|
|
@@ -257,7 +258,7 @@ def _parse_gemini_jsonl(content) -> dict[str, str]:
|
|
|
257
258
|
|
|
258
259
|
|
|
259
260
|
def _write_jsonl(records: list[dict]) -> str:
|
|
260
|
-
tmp = tempfile.NamedTemporaryFile(
|
|
261
|
+
tmp = tempfile.NamedTemporaryFile( # noqa: SIM115 - delete=False, path returned
|
|
261
262
|
"w", suffix=".jsonl", delete=False, encoding="utf-8"
|
|
262
263
|
)
|
|
263
264
|
for record in records:
|
|
@@ -294,14 +295,21 @@ def _submit_openai_jobs(
|
|
|
294
295
|
path = _write_jsonl(request_chunk)
|
|
295
296
|
try:
|
|
296
297
|
with open(path, "rb") as handle:
|
|
297
|
-
|
|
298
|
-
|
|
298
|
+
# litellm types the sync variants as possibly-Coroutine
|
|
299
|
+
file_obj = cast(
|
|
300
|
+
Any,
|
|
301
|
+
litellm.create_file(
|
|
302
|
+
file=handle, purpose="batch", custom_llm_provider=state.provider
|
|
303
|
+
),
|
|
299
304
|
)
|
|
300
|
-
batch =
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
+
batch = cast(
|
|
306
|
+
Any,
|
|
307
|
+
litellm.create_batch(
|
|
308
|
+
completion_window=completion_window,
|
|
309
|
+
endpoint=BATCH_ENDPOINT,
|
|
310
|
+
input_file_id=file_obj.id,
|
|
311
|
+
custom_llm_provider=state.provider,
|
|
312
|
+
),
|
|
305
313
|
)
|
|
306
314
|
finally:
|
|
307
315
|
os.unlink(path)
|
|
@@ -347,7 +355,11 @@ def _submit_gemini_jobs(
|
|
|
347
355
|
uploaded = client.files.upload(
|
|
348
356
|
file=path, config=types.UploadFileConfig(mime_type="jsonl")
|
|
349
357
|
)
|
|
358
|
+
if not uploaded.name:
|
|
359
|
+
raise RuntimeError("Gemini file upload returned no name")
|
|
350
360
|
job = client.batches.create(model=gmodel, src=uploaded.name)
|
|
361
|
+
if not job.name:
|
|
362
|
+
raise RuntimeError("Gemini batch create returned no name")
|
|
351
363
|
finally:
|
|
352
364
|
os.unlink(path)
|
|
353
365
|
chunk_map = {r["key"]: custom_id_to_tokens[r["key"]] for r in request_chunk}
|
|
@@ -364,7 +376,10 @@ def _submit_gemini_jobs(
|
|
|
364
376
|
|
|
365
377
|
|
|
366
378
|
def _poll_job(job: BatchJob, provider: str) -> tuple[str, dict[str, str]]:
|
|
367
|
-
"""Poll one job.
|
|
379
|
+
"""Poll one job.
|
|
380
|
+
|
|
381
|
+
Returns (status, by_custom_id); status in completed/running/failed.
|
|
382
|
+
"""
|
|
368
383
|
if provider in _GEMINI_PROVIDERS:
|
|
369
384
|
client = _gemini_client() # keep a ref for the whole call (httpx lifecycle)
|
|
370
385
|
info = client.batches.get(name=job.batch_id)
|
|
@@ -384,7 +399,7 @@ def _poll_job(job: BatchJob, provider: str) -> tuple[str, dict[str, str]]:
|
|
|
384
399
|
return "running", {}
|
|
385
400
|
|
|
386
401
|
retrieved = litellm.retrieve_batch(
|
|
387
|
-
batch_id=job.batch_id, custom_llm_provider=provider
|
|
402
|
+
batch_id=job.batch_id, custom_llm_provider=cast(Any, provider)
|
|
388
403
|
)
|
|
389
404
|
status = getattr(retrieved, "status", None)
|
|
390
405
|
output_file_id = getattr(retrieved, "output_file_id", None)
|
|
@@ -535,7 +550,8 @@ def collect_transliteration_batches(
|
|
|
535
550
|
parsed = transliterator._parse_batch_response(text, len(group))
|
|
536
551
|
if len(raw_lines) != len(group) or any(not p for p in parsed):
|
|
537
552
|
logger.warning(
|
|
538
|
-
"Batch %s group %s: %d output line(s) for %d tokens;
|
|
553
|
+
"Batch %s group %s: %d output line(s) for %d tokens; "
|
|
554
|
+
"requeueing",
|
|
539
555
|
job.batch_id,
|
|
540
556
|
custom_id,
|
|
541
557
|
len(raw_lines),
|