Metadata-Version: 2.4
Name: llm-telephone
Version: 0.1.0
Summary: Pass text through a chain of 20 LLM translations and watch the meaning drift
Project-URL: Homepage, https://github.com/yymss/llm-telephone
Project-URL: Repository, https://github.com/yymss/llm-telephone
Project-URL: Issues, https://github.com/yymss/llm-telephone/issues
License: MIT License
        
        Copyright (c) 2026 llm-telephone contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,cli,llm,openrouter,translation
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Requires-Dist: click>=8.0
Requires-Dist: rich>=13.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# llm-telephone

> Pass text through a chain of 20 LLM translations and watch the meaning drift.

[![CI](https://github.com/yymss/llm-telephone/actions/workflows/ci.yml/badge.svg)](https://github.com/yymss/llm-telephone/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/llm-telephone)](https://pypi.org/project/llm-telephone/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

---

## What is this?

**llm-telephone** is a command-line tool that feeds a piece of text through a configurable chain of language-to-language translations via the [OpenRouter](https://openrouter.ai) API, then brings it back to your chosen return language.

Like the childhood game of "telephone", each translation step introduces small distortions.  After 20 hops through English → Japanese → French → German → … → Simplified Chinese, you can observe how meaning drifts, idioms break down, and cultural context gets lost.

### Why is it interesting?

| Round | Language | Output |
|------:|----------|--------|
| 0 | *(original)* | `龙，可是帝王之征啊` |
| 1 | English | `The dragon is a symbol of imperial power.` |
| 2 | Japanese | `龍は帝国の力の象徴です。` |
| 3 | French | `Le dragon est un symbole de la puissance impériale.` |
| … | … | … |
| 20 | Simplified Chinese | `龙是皇权的象征。` |

The original poetic exclamation (`龙，可是帝王之征啊`) loses its rhetorical flourish and emerges as a dry factual statement — same core meaning, completely different register.

---

## Installation

```bash
pip install llm-telephone
```

### Requirements

- Python 3.10 or newer
- An [OpenRouter](https://openrouter.ai) API key

---

## Configuration

Set your OpenRouter API key in the environment before running:

```bash
export OPENROUTER_API_KEY="sk-or-..."
```

Alternatively, `OPENROUTER_KEY` is also accepted.

---

## Quick start

```bash
# Translate a single phrase through the default 20-language chain
llm-telephone "The quick brown fox jumps over the lazy dog"

# Read from a file instead
llm-telephone --text-file origin.txt

# Only run 5 rounds
llm-telephone "Hello world" --rounds 5

# End the chain in English instead of Simplified Chinese
llm-telephone "Hello world" --rounds 10 --return-lang English

# Output structured JSON (useful for piping / analysis)
llm-telephone "Hello world" --rounds 5 --output-format json

# Save logs to files
llm-telephone "Hello world" \
    --process-output process.txt \
    --final-output final.txt
```

### All options

```
Usage: llm-telephone [OPTIONS] [TEXT]

  Pass TEXT through a chain of LLM translations and watch the meaning drift.

Options:
  --model TEXT                    OpenRouter model ID.  [default: google/gemini-3-flash-preview]
  --rounds INTEGER                Number of translation rounds.  [default: 20]
  --text-file PATH                Read initial text from a UTF-8 file.
  --process-output TEXT           Write per-round log to this file path.
  --final-output TEXT             Write the final text to this file path.
  --output-format [text|json]     Output format.  [default: text]
  --return-lang TEXT              Language to end the chain with.  [default: Simplified Chinese]
  --version                       Show the version and exit.
  -h, --help                      Show this message and exit.
```

---

## JSON output format

When `--output-format json` is used, the tool writes a single JSON object to stdout:

```json
{
  "model": "google/gemini-3-flash-preview",
  "rounds": 5,
  "return_lang": "Simplified Chinese",
  "initial_text": "Hello world",
  "final_text": "你好，世界",
  "chain": [
    {
      "round": 1,
      "target_language": "English",
      "input": "Hello world",
      "output": "Hello, world!",
      "elapsed_s": 0.823
    }
  ]
}
```

---

## Python API

You can also use `llm-telephone` as a library:

```python
from llm_telephone import run_chain
from llm_telephone.api_client import OpenRouterClient
from llm_telephone.languages import get_chain

client = OpenRouterClient(api_key="sk-or-...", model="google/gemini-3-flash-preview")
records = run_chain("Hello world", client, rounds=5, output_format="json")
for r in records:
    print(f"Round {r['round']:02d} [{r['target_language']}]: {r['output']}")
```

---

## Development

See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions.

---

## License

[MIT](LICENSE)
