# Long-context work

`minimax-text-01` carries a 4M token context window and the cheapest rate in
the catalog ($0.20 per 1M input, $1.10 per 1M output). It is the model for
whole-book, whole-transcript, and whole-corpus work.

The standard M-series models hold about 205k tokens, which is plenty for a repo
slice or an agent session. Reach for `minimax-text-01` when the thing you want
to read does not fit in that.

```bash
pip install openai
export HYPHEN_API_KEY="sk-..."
```

## Summarise one large document

```python
import os
import pathlib
from openai import OpenAI

client = OpenAI(
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
)

doc = pathlib.Path("annual-report.txt").read_text(encoding="utf-8")
print(f"{len(doc):,} chars, roughly {len(doc) // 4:,} tokens")

resp = client.chat.completions.create(
    model="minimax-text-01",
    messages=[
        {
            "role": "system",
            "content": "You summarise long documents. Be concrete. Quote figures exactly. "
                       "Reference section headings so the reader can find the source.",
        },
        {
            "role": "user",
            "content": (
                "<document>\n" + doc + "\n</document>\n\n"
                "Summarise in ten bullets. Then list every numeric figure that "
                "appears more than once, with the sections it appears in."
            ),
        },
    ],
    max_tokens=4000,
)

print(resp.choices[0].message.content)
print(resp.usage)
```

Two habits worth keeping:

- **Wrap the document in a tag.** `<document>...</document>` gives the model a
  clean boundary between your data and your instruction. Without it, a document
  that contains instruction-shaped text can hijack the request.
- **Put the instruction after the document, not before.** With a very long
  input the tail is where attention is sharpest. Ask last.

## Estimating cost before you send

`len(text) // 4` is a decent token estimate for English prose. Multiply by the
rate.

```python
def estimate_usd(text: str, input_rate=0.20, output_tokens=4000, output_rate=1.10) -> float:
    input_tokens = len(text) / 4
    return (input_tokens / 1_000_000) * input_rate + (output_tokens / 1_000_000) * output_rate


doc = pathlib.Path("annual-report.txt").read_text(encoding="utf-8")
print(f"about ${estimate_usd(doc):.4f}")
```

A 500k-token document costs about $0.10 to read once. Reading it ten times in a
loop costs a dollar. Read once, cache the summary.

## Map-reduce for anything bigger

Past 4M tokens, or when you need per-section detail rather than one summary,
chunk it. Summarise each chunk with the cheap fast model, then combine with the
flagship.

```python
import os
import pathlib
from openai import OpenAI

client = OpenAI(
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
)

CHARS_PER_CHUNK = 400_000  # roughly 100k tokens


def chunks(text: str, size: int = CHARS_PER_CHUNK):
    """Split on paragraph boundaries so no chunk cuts mid-sentence."""
    buf, out = "", []
    for para in text.split("\n\n"):
        if len(buf) + len(para) > size and buf:
            out.append(buf)
            buf = ""
        buf += para + "\n\n"
    if buf.strip():
        out.append(buf)
    return out


def summarise(text: str, instruction: str, model: str) -> str:
    resp = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "You summarise faithfully. Keep names, dates and figures."},
            {"role": "user", "content": f"<text>\n{text}\n</text>\n\n{instruction}"},
        ],
        max_tokens=4000,
    )
    return resp.choices[0].message.content


doc = pathlib.Path("huge-corpus.txt").read_text(encoding="utf-8")
parts = chunks(doc)
print(f"{len(parts)} chunks")

# Map: cheap and fast, one pass per chunk.
partials = [
    summarise(part, "Summarise this section in at most 200 words.", "minimax-m2.5")
    for part in parts
]

# Reduce: the flagship sees only the summaries, so this call is small.
combined = "\n\n---\n\n".join(f"## Section {i + 1}\n{s}" for i, s in enumerate(partials))
final = summarise(combined, "Merge these section summaries into one coherent brief of 15 bullets.", "minimax-m3")
print(final)
```

The map step is embarrassingly parallel. Run it with a thread pool if you have
many chunks, and keep an eye on your fair-use requests-per-minute limit.

## Streaming a long summary

A 4M-token input takes a while before the first token comes out. Stream it so
the process does not look hung.

```python
stream = client.chat.completions.create(
    model="minimax-text-01",
    messages=[{"role": "user", "content": f"<document>\n{doc}\n</document>\n\nSummarise in ten bullets."}],
    max_tokens=4000,
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
print()
```

## Picking the model for the job

| Input size            | Model             | Why                                    |
| --------------------- | ----------------- | -------------------------------------- |
| Under ~150k tokens    | `minimax-m3`      | Fits the standard window. The flagship.   |
| 150k to 4M tokens     | `minimax-text-01` | The only model that holds it.          |
| Over 4M tokens        | Map-reduce        | Chunk with `m2.5`, combine with `m3`.  |

## Watch out for

- **Context is billed every turn.** A multi-turn conversation re-sends the whole
  document on each request. For long documents, do one request and keep the
  answer. Do not chat with a 2M-token transcript.
- **Retries are expensive.** A failed 3M-token request that you blindly retry
  costs twice. Validate the input first.
- **`minimax-text-01` has no incident fallback.** Requests fail rather than
  being served by a different model. See [Models](/models#fallback-during-provider-incidents).
- **`max_tokens` still needs headroom.** 4000 or more, same as everywhere else.

## Related

- [Choosing a model](/choosing-a-model): the whole catalog, by job.
- [Models](/models): the rate card.
- [Handling the 429 cap](/recipes/handling-429): large inputs eat budget fast.
