{
  "markdown": "<!-- mcp-name: io.github.mdefrance/autocarver -->\n</p>\n<p align=\"center\">\n    <picture>\n        <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/artwork/auto_carver_logo_dark.svg\">\n        <img alt=\"AutoCarver Logo\" src=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/artwork/auto_carver_logo_light.svg\" width=\"80%\">\n    </picture>\n</p>\n\n[![PyPI](https://img.shields.io/pypi/v/autocarver)](https://pypi.org/project/AutoCarver)\n[![Python](https://img.shields.io/pypi/pyversions/autocarver)](https://pypi.org/project/AutoCarver/)\n[![License](https://img.shields.io/github/license/mdefrance/autocarver)](LICENSE)\n[![SPEC 0](https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038)](https://scientific-python.org/specs/spec-0000/)\n[![Docs](https://readthedocs.org/projects/autocarver/badge/?version=latest)](https://autocarver.readthedocs.io/en/latest/)\n[![Tests](https://github.com/mdefrance/AutoCarver/actions/workflows/pytest.yml/badge.svg)](https://github.com/mdefrance/AutoCarver/actions/workflows/pytest.yml)\n[![Coverage](https://codecov.io/gh/mdefrance/AutoCarver/branch/main/graph/badge.svg)](https://codecov.io/gh/mdefrance/AutoCarver)\n\n\n<p align=\"center\">\n    <picture>\n        <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/_static/animations/readme_full_pipeline_dark.svg\">\n        <img alt=\"AutoCarver in one loop: discretize, rank groupings, carve\" src=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/_static/animations/readme_full_pipeline_light.svg\" width=\"100%\">\n    </picture>\n</p>\n\n\n**AutoCarver** turns raw numeric, categorical, and ordinal columns into optimal, drift-robust, human-readable bins in a few lines of code. Stop losing model performance to suboptimal manual binning — and stop discovering overfit bins in production monitoring.\n\n- **Provably optimal** — exhaustive search: for a fixed `min_freq`, `max_n_mod` and metric (Tschuprow's T by default, or Cramér's V), no other admissible bin combination scores higher. It checked them all so you don't have to.\n- **Robust by construction** — every candidate grouping is vetoed unless it holds on a held-out dev set (and optional CV folds), at `fit` time rather than in monitoring.\n- **Define → carve → model** — declare your `Features`, `fit` a carver, `transform`: the whole feature set is carved in one supervised pass, not one notebook per feature. One carver per target type — `BinaryCarver`, `MulticlassCarver`, `OrdinalCarver`, `ContinuousCarver` (regression) — all with the identical API.\n- **AI-assisted** — a local MCP server lets your LLM assistant qualify and carve columns through tool calls, fully on your machine.\n\n*On the Titanic quick start, `Fare` collapses from 72 pre-carving modalities to 2 bins while its association with survival rises: Tschuprow's T 0.18 raw → 0.29 carved.*\n\nBuilt for credit scoring, fraud detection, and risk modeling.\n\n\n## 🆕 What's New\n\n**📊 Cross-validated robustness.** `fit` now accepts a `cv` argument for extra\nheld-out robustness views on top of (or instead of) a dev set:\n`carver.fit(X, y, cv=5)`. Accepts an int, any scikit-learn splitter, or\nexplicit index pairs, resolved via `sklearn.model_selection.check_cv` — folds\nveto over-fit combinations but never reorder them (ranks stay anchored to the\nfull train set). See [Cross-validation folds](https://autocarver.readthedocs.io/en/latest/viability.html#cross-validation-folds).\n\n**🤖 LLM & MCP integration.** AutoCarver now ships a local [Model Context Protocol](https://modelcontextprotocol.io) server: point an MCP-aware assistant (VS Code Copilot, Claude Desktop, Cursor, …) at a data file and let it *qualify* the columns and *carve* them against your target through tool calls. The server runs **fully on your machine** — your dataset is never sent to AutoCarver or any external service (only your own LLM provider sees what the assistant shares). Carving quality depends on the LLM, so have a human confirm the feature definitions before production use. See the [LLM & MCP guide](https://autocarver.readthedocs.io/en/latest/mcp.html).\n\n```bash\npip install \"autocarver[mcp]\"\n```\n\nOnce configured, just ask your assistant:\n\n> Qualify the columns in `titanic.csv` and carve them against `Survived`.\n\nThe assistant infers feature types, proposes a carving, and returns the summary table — no code written by hand.\n\n<details>\n<summary>Client config</summary>\n\nAdd to `.vscode/mcp.json` (VS Code / GitHub Copilot) or `claude_desktop_config.json` (Claude Desktop, under `mcpServers` instead of `servers`):\n\n```json\n{\n  \"servers\": {\n    \"autocarver\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"AutoCarver.mcp\"]\n    }\n  }\n}\n```\n\nIf you use [uv](https://docs.astral.sh/uv/), point `command` at `uv` instead so it resolves the environment for you:\n\n```json\n{\n  \"servers\": {\n    \"autocarver\": {\n      \"command\": \"uv\",\n      \"args\": [\"run\", \"python\", \"-m\", \"AutoCarver.mcp\"]\n    }\n  }\n}\n```\n\n</details>\n\n\n## Install\n\n```bash\npip install autocarver\n```\n\n\n## Quick Start\n\n[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mdefrance/AutoCarver/blob/main/docs/source/examples/quick_start_colab.ipynb)\n\nYou already have a DataFrame and a target — that's the first box ticked before you start:\n\n- [x] Load data\n- [ ] Split train / dev\n- [ ] Declare features by type\n- [ ] Fit the carver, validated on the dev set\n- [ ] Inspect the carved bins\n- [ ] Persist\n\nThe rest is the snippet below — binary classification on the Titanic dataset:\n\n<!-- quick-start:start -->\n```python\nfrom pathlib import Path\n\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\n\nfrom AutoCarver import BinaryCarver, Features\n\n# 1. Load data\nurl = \"https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv\"\ndata = pd.read_csv(url)\ntarget = \"Survived\"\n\n# 2. Train / dev split, stratified on the target\ntrain, dev = train_test_split(data, test_size=0.33, random_state=42, stratify=data[target])\n\n# 3. Declare features by type\nfeatures = Features(\n    categoricals=[\"Sex\"],\n    numericals=[\"Age\", \"Fare\", \"Siblings/Spouses Aboard\", \"Parents/Children Aboard\"],\n    ordinals={\"Pclass\": [\"1\", \"2\", \"3\"]},\n)\n\n# 4. Fit the carver (dev set drives the robustness checks)\ncarver = BinaryCarver(features=features)\ntrain_processed = carver.fit_transform(train, train[target], X_dev=dev, y_dev=dev[target])\ndev_processed = carver.transform(dev)\n\n# 5. Inspect the carved buckets, target rate, and association\ncarver.summary\n\n# 6. Persist for later use\ncarver.save(Path(\"titanic_carver.json\"))\n\n# 7. Load the carver back in\ncarver = BinaryCarver.load(Path(\"titanic_carver.json\"))\ndev_processed = carver.transform(dev)\n```\n<!-- quick-start:end -->\n\n`min_freq` and `max_n_mod` are the only two knobs that matter to start with — the defaults (`0.02` / `5`) reflect common scoring practice, and every behavioral toggle lives in one `ProcessingConfig` object. Scan, adjust, move on.\n\nFor multiclass classification use `MulticlassCarver` (one binning per feature, against the full K-class target) — or `OneVsRestCarver` for a separate binning per class; for ordinal targets use `OrdinalCarver`; for regression use `ContinuousCarver` — the API is identical. To pre-select features by target association and inter-feature redundancy, pipe the carved output through `ClassificationSelector` or `RegressionSelector`.\n\n\n## What you get\n\nTwo questions worth answering before your next model review: can you defend every bin boundary of your current model to a stakeholder — and can you show each one holds on data it has never seen? AutoCarver makes both a one-liner:\n\n- **No performance left on the table** — exhaustive search over admissible bin combinations maximizes Tschuprow's T (default) or Cramér's V: for fixed `min_freq`, `max_n_mod` and metric, no other combination scores higher, so you never wonder whether a better grouping existed.\n- **Stop silent overfitting before production** — bins that only exist in your training sample degrade quietly under drift. Every candidate combination is validated on a dev set (and optional CV folds): any whose target rates flip or whose buckets fall below `min_freq` is rejected at fit time, not discovered in monitoring.\n- **First-class ordinal features** — `OrdinalDiscretizer` enforces your declared modality order, so under-represented levels are merged with their nearest neighbour instead of being collapsed by frequency.\n- **You are the final auditor** — `features.summary` and `features.history` expose the bin definitions, per-bin target rate / frequency, and the full carving trace; disagree with a boundary and you can override it, and `transform` applies your fix like any carved bin:\n\n  ```python\n  feature = features(\"Siblings/Spouses Aboard\")  # any fitted feature; labels are [0, 1, 2]\n  feature.group([1], 2)  # merge two bins you consider equivalent\n  ```\n- **Interpretable buckets** — human-readable boundaries you can audit, document, and ship to a scorecard.\n- **Dimensionality reduction** — groups under-represented modalities and caps bins per feature (`max_n_mod`), which is especially useful before one-hot encoding.\n- **Feature pre-selection** — `ClassificationSelector` / `RegressionSelector` rank features by target association and filter on inter-feature correlation.\n\n<p align=\"center\">\n    <picture>\n        <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/_static/hero_chart_dark.svg\">\n        <img alt=\"Raw feature vs AutoCarver buckets: frequency and target rate before/after supervised binning\" src=\"https://raw.githubusercontent.com/mdefrance/AutoCarver/main/docs/source/_static/hero_chart_light.svg\" width=\"100%\">\n    </picture>\n</p>\n\n*Titanic `Age`, one `BinaryCarver.fit` call: 84 raw values collapse to 3 buckets with a monotonic survival rate.*\n\n\n## How does it compare?\n\n|                                                   | **Manual binning**                                  | **AutoCarver**                                                     | [**optbinning**](https://github.com/guillermo-navas-palencia/optbinning) | [**sklearn KBinsDiscretizer**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.KBinsDiscretizer.html) |\n| ------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |\n| Algorithm                                         | eyeballing distributions, notebook by notebook       | **exhaustive search** over admissible combinations                 | CART pre-binning, then CP solver (CP-SAT default; MIP optional)          | quantile / uniform / k-means — unsupervised                                     |\n| Optimality for given `min_freq` / `max_n_mod` / metric | none — first acceptable grouping wins           | **guaranteed — best of every admissible combination**              | provably optimal over its pre-bins, under its constraints                | n/a — no target objective                                                       |\n| Target types                                      | any, at ~1 feature/hour                              | **binary, multiclass, ordinal, continuous**                        | binary, multiclass, continuous                                           | n/a                                                                             |\n| All feature types in one `fit` (numeric, categorical, ordinal, `NaN`) | each feature is its own project | **yes — declared ordinal order enforced, `NaN` as its own modality** | yes via `BinningProcess`; no first-class ordinal type (`user_splits` workaround) | numeric only; `NaN` raises                                                      |\n| Held-out dev-set robustness check                 | rarely — too tedious to script per feature           | **yes — dev set + optional k-fold CV, built into `fit`**           | no (script CV yourself)                                                  | no                                                                              |\n| Per-bin stats + carving history after `fit`       | scattered notebook cells                             | **`features.summary`, `features.history`**                         | `binning_table`                                                          | no                                                                              |\n\nAll three libraries are sklearn-`Pipeline` compatible; AutoCarver adds JSON round-trip persistence (`carver.save(\"...json\")`) and feature pre-selection helpers (`ClassificationSelector`, `RegressionSelector`). The full feature matrix, side-by-side runnable snippets, and a \"when to pick which\" guide live on the [comparison page](https://autocarver.readthedocs.io/en/latest/comparison.html).\n\n\n## Documentation\n\nFull reference, tutorials, and end-to-end notebook examples on [ReadTheDocs](https://autocarver.readthedocs.io/en/latest/index.html).\n",
  "bytes": 13374,
  "sha": "8129709583729b1986f72a7bb6d074d6d38419f944d19653e5e1900acda8b9b1",
  "repo_slug": "mdefrance/autocarver",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mdefrance_autocarver_9ba1c316/readme"
}