Metadata-Version: 2.4
Name: mihuman
Version: 0.1.0
Summary: Local AI-text humanizer powered by Ollama. Rewrites AI-generated text so it reads naturally, entirely on your own machine.
Project-URL: Homepage, https://github.com/ushanzzz/mi_human
Project-URL: Repository, https://github.com/ushanzzz/mi_human
Project-URL: Issues, https://github.com/ushanzzz/mi_human
Author-email: Ushan Balasooriya <ushanbala@outlook.com>
License: MIT License
        
        Copyright (c) 2026 Ushan Balasooriya
        
        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,ai-detection,humanizer,llm,local-llm,ollama,text-processing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Requires-Dist: tomli>=1.1.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# mihuman

**Local AI-text humanizer — rewrite AI content into natural prose on your own machine.**

[![PyPI](https://img.shields.io/pypi/v/mihuman.svg)](https://pypi.org/project/mihuman/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/license-MIT-red.svg)](LICENSE)

</div>

---

`mihuman` is a small, dependency-light Python library that rewrites AI-generated text so it reads like a human wrote it. Everything runs against a local [Ollama](https://ollama.com) server — no external API calls, no data leaves your box.

The library ships two things:

1. A `humanize()` function that streams a rewrite from Ollama and runs a deterministic post-processing pipeline over the output (em-dash stripping, AI-lexicon substitution, burstiness enforcement, optional error injection).
2. A `Config` dataclass and `load_config()` helper so you can drive the whole thing from a TOML file instead of threading a dozen keyword arguments through your code.

## Install

```bash
pip install mihuman
```

You also need Ollama running locally with at least one model pulled:

```bash
ollama pull mistral-nemo:12b   # or llama3.1:8b, gemma2:9b, whatever you like
```

## Quick start

```python
from mihuman import humanize

result = humanize(
    text="The utilization of innovative paradigms facilitates a robust framework...",
    model="llama3.1:8b",
    style="stealth",
    intensity="aggressive",
)

print(result.text)
```

## Driving it from a config file

Drop a `mihuman.toml` in your project (or at `~/.config/mihuman/config.toml`):

```toml
model = "llama3.1:8b"
base_url = "http://localhost:11434"
style = "stealth"
intensity = "aggressive"
burstiness = true
error_level = 0
temperature = 0.85
top_p = 0.97
timeout = 300
# seed = 42
```

Then load it:

```python
from mihuman import humanize, load_config

cfg = load_config()                         # auto-discovers
# cfg = load_config("path/to/mihuman.toml") # or pass an explicit path

result = humanize(text=my_text, **cfg.to_kwargs())
print(result.text)
```

Config search order (first match wins):

1. Explicit path passed to `load_config(path=...)`
2. `$MIHUMAN_CONFIG` env var
3. `./mihuman.toml` (current working directory)
4. `$XDG_CONFIG_HOME/mihuman/config.toml` (fallback: `~/.config/mihuman/config.toml`)

Unknown keys raise `ConfigError` so typos surface at load time, not months later.

An annotated starter config lives at [`examples/mihuman.toml`](examples/mihuman.toml).

## Options

### Styles

| Style | Notes |
|---|---|
| `stealth` | Anti-detection mode. Prioritizes perplexity and burstiness. |
| `humanize` | General natural writing. Clear, simple. |
| `casual` | Friendly, conversational. |
| `professional` | Executive-level direct prose. |
| `academic` | Q1-journal register. AWL vocabulary. |
| `creative` | Sensory, fresh comparisons. |
| `technical` | Precise but approachable; step-by-step. |

### Intensity

| Level | Post-processing passes |
|---|---|
| `light` | preamble strip → em-dash removal → whitespace cleanup |
| `medium` | + AI lexicon substitution → burstiness (optional) |
| `aggressive` | + contraction forcing → sentence capitalization → burstiness |

### Error injection

| Level | Effect |
|---|---|
| `0` (off) | none |
| `1` (subtle) | ~35% chance to drop Oxford commas |
| `2` (natural) | + missed apostrophes (~1 per 180 words) |
| `3` (casual) | + light typos like "teh", "adn" (~1 per 500 words) |

## Pipeline

```
Input text
    │
    ▼
Smart chunking          ~800-word, paragraph-aware chunks
    │
    ▼
Ollama /api/chat        streamed rewrite per chunk (system prompt = style overlay)
    │
    ▼
Post-processing         preamble strip → em-dash strip → AI-lexicon sub
                        → contractions → capitalize → burstiness → whitespace
                        → optional human-error injection
    │
    ▼
Output
```

The LLM does the heavy rewriting; the post-processor cleans up AI-specific tells the model tends to leave behind.

## Public API

```python
from mihuman import (
    humanize, HumanizeResult, OllamaError, list_models,
    Config, load_config, ConfigError,
    STYLES, DEFAULT_MODEL, DEFAULT_OLLAMA_URL,
    postprocess, make_rng, build_system_prompt,
    __version__,
)
```

- `humanize(text, *, style, model, intensity, base_url, temperature, top_p, timeout, burstiness, error_level, seed, writing_sample, on_progress, on_token, on_chunk_done) -> HumanizeResult`
- `list_models(base_url=...) -> list[str]` — enumerate installed Ollama models
- `postprocess(text, intensity, rng, burstiness, error_level) -> str` — run just the post-processor on already-rewritten text

Pass callbacks (`on_token`, `on_chunk_done`, `on_progress`) if you want to stream output into a UI.

## Requirements

- Python 3.10+
- [Ollama](https://ollama.com) running locally (or somewhere reachable)

Runtime deps: none on Python 3.11+; `tomli` on 3.10 only.

## License

MIT — see [LICENSE](LICENSE).

---

<div align="center">
<i>All processing happens locally. Your text stays on your machine.</i>
</div>
