predikit 0.4.0__tar.gz → 0.4.2__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.
Files changed (50) hide show
  1. {predikit-0.4.0 → predikit-0.4.2}/.claude/settings.local.json +2 -1
  2. predikit-0.4.2/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  3. predikit-0.4.2/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. {predikit-0.4.0 → predikit-0.4.2}/.github/workflows/publish.yml +4 -0
  5. {predikit-0.4.0 → predikit-0.4.2}/.github/workflows/test.yml +24 -0
  6. {predikit-0.4.0 → predikit-0.4.2}/.gitignore +1 -0
  7. predikit-0.4.2/.pre-commit-config.yaml +15 -0
  8. predikit-0.4.2/CHANGELOG.md +53 -0
  9. predikit-0.4.2/CLAUDE.md +71 -0
  10. predikit-0.4.2/CONTRIBUTING.md +66 -0
  11. {predikit-0.4.0 → predikit-0.4.2}/PKG-INFO +72 -22
  12. {predikit-0.4.0 → predikit-0.4.2}/README.md +361 -314
  13. predikit-0.4.2/docs/logo.gif +0 -0
  14. predikit-0.4.2/docs/logo.png +0 -0
  15. {predikit-0.4.0 → predikit-0.4.2}/examples/03_orlando_real_estate.py +2 -2
  16. {predikit-0.4.0 → predikit-0.4.2}/pyproject.toml +22 -2
  17. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/__init__.py +3 -3
  18. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/cli.py +19 -5
  19. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/coerce.py +4 -2
  20. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/ensemble.py +9 -6
  21. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/exporters/langchain.py +5 -4
  22. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/exporters/openai.py +1 -0
  23. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/introspect.py +1 -3
  24. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/loaders/mlflow.py +5 -3
  25. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/loaders/snowflake.py +8 -4
  26. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/registry.py +8 -9
  27. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/tool.py +14 -7
  28. {predikit-0.4.0 → predikit-0.4.2}/tests/test_cli.py +8 -7
  29. {predikit-0.4.0 → predikit-0.4.2}/tests/test_confidence.py +23 -8
  30. {predikit-0.4.0 → predikit-0.4.2}/tests/test_ensemble.py +52 -11
  31. {predikit-0.4.0 → predikit-0.4.2}/tests/test_loaders_mlflow.py +23 -11
  32. {predikit-0.4.0 → predikit-0.4.2}/tests/test_loaders_snowflake.py +8 -1
  33. {predikit-0.4.0 → predikit-0.4.2}/tests/test_logging.py +12 -9
  34. {predikit-0.4.0 → predikit-0.4.2}/tests/test_tool.py +1 -0
  35. {predikit-0.4.0 → predikit-0.4.2}/tests/test_weighted_ensemble.py +57 -16
  36. {predikit-0.4.0 → predikit-0.4.2}/LICENSE +0 -0
  37. {predikit-0.4.0 → predikit-0.4.2}/examples/01_basic_sklearn.py +0 -0
  38. {predikit-0.4.0 → predikit-0.4.2}/examples/02_xgboost_regression.py +0 -0
  39. {predikit-0.4.0 → predikit-0.4.2}/examples/04_confidence_routing.py +0 -0
  40. {predikit-0.4.0 → predikit-0.4.2}/examples/05_multi_model_ensemble.py +0 -0
  41. {predikit-0.4.0 → predikit-0.4.2}/examples/06_mlflow_loader.py +0 -0
  42. {predikit-0.4.0 → predikit-0.4.2}/examples/07_snowflake_loader.py +0 -0
  43. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/exceptions.py +0 -0
  44. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/exporters/__init__.py +0 -0
  45. {predikit-0.4.0 → predikit-0.4.2}/src/predikit/loaders/__init__.py +0 -0
  46. {predikit-0.4.0 → predikit-0.4.2}/tests/__init__.py +0 -0
  47. {predikit-0.4.0 → predikit-0.4.2}/tests/test_coerce.py +0 -0
  48. {predikit-0.4.0 → predikit-0.4.2}/tests/test_exporters_openai.py +0 -0
  49. {predikit-0.4.0 → predikit-0.4.2}/tests/test_introspect.py +0 -0
  50. {predikit-0.4.0 → predikit-0.4.2}/tests/test_registry.py +0 -0
@@ -3,7 +3,8 @@
3
3
  "allow": [
4
4
  "Bash(git add *)",
5
5
  "Bash(git commit -m ' *)",
6
- "Bash(python -m pytest tests/ -v --tb=short --cov=src/predikit --cov-report=term-missing)"
6
+ "Bash(python -m pytest tests/ -v --tb=short --cov=src/predikit --cov-report=term-missing)",
7
+ "WebFetch(domain:github.com)"
7
8
  ]
8
9
  }
9
10
  }
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Desktop (please complete the following information):**
27
+ - OS: [e.g. iOS]
28
+ - Browser [e.g. chrome, safari]
29
+ - Version [e.g. 22]
30
+
31
+ **Smartphone (please complete the following information):**
32
+ - Device: [e.g. iPhone6]
33
+ - OS: [e.g. iOS8.1]
34
+ - Browser [e.g. stock browser, safari]
35
+ - Version [e.g. 22]
36
+
37
+ **Additional context**
38
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -4,11 +4,15 @@ on:
4
4
  release:
5
5
  types: [published]
6
6
 
7
+ permissions:
8
+ contents: read
9
+
7
10
  jobs:
8
11
  publish:
9
12
  runs-on: ubuntu-latest
10
13
  environment: pypi
11
14
  permissions:
15
+ contents: read
12
16
  id-token: write
13
17
 
14
18
  steps:
@@ -6,7 +6,31 @@ on:
6
6
  pull_request:
7
7
  branches: [main]
8
8
 
9
+ permissions:
10
+ contents: read
11
+
9
12
  jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install dev dependencies
23
+ run: pip install -e ".[dev]"
24
+
25
+ - name: Ruff lint
26
+ run: ruff check src/ tests/
27
+
28
+ - name: Ruff format check
29
+ run: ruff format --check src/ tests/
30
+
31
+ - name: Mypy
32
+ run: mypy src/predikit
33
+
10
34
  test:
11
35
  runs-on: ubuntu-latest
12
36
  strategy:
@@ -10,3 +10,4 @@ htmlcov/
10
10
  .venv/
11
11
  venv/
12
12
  *.egg
13
+ file.py
@@ -0,0 +1,15 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.5.0
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.10.0
11
+ hooks:
12
+ - id: mypy
13
+ additional_dependencies:
14
+ - pydantic>=2.0
15
+ - numpy>=1.24
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.4.2] - 2026-06-13
10
+
11
+ ### Changed
12
+ - Redesigned PyPI/README hero: logo, centered tagline, and badges in a unified `<p align="center">` block
13
+ - Tagline moved from a `##` heading to a proper descriptive paragraph
14
+ - Badges converted to centered HTML `<img>` links for consistent rendering on PyPI
15
+ - Quick code teaser repositioned directly below badges (before Table of Contents)
16
+ - "Field naming rule" added to Table of Contents
17
+ - `ainvoke()` added to `ModelTool` Core API reference table
18
+ - `ModelEnsemble` Core API subsection added with constructor signature and full strategy table
19
+ - Project Traffic / download badge moved to bottom of README
20
+ - Development Status classifier bumped from `3 - Alpha` to `4 - Beta` in `pyproject.toml`
21
+ - Removed CI test status badge from README
22
+
23
+ ## [0.4.1] - 2026-06-02
24
+
25
+ ### Added
26
+ - `ruff` (lint + format) and `mypy` (type checking) configured in `pyproject.toml`
27
+ - `.pre-commit-config.yaml` — ruff and mypy hooks run automatically before every commit
28
+ - Lint CI job in GitHub Actions — runs `ruff check`, `ruff format --check`, and `mypy` on every push and PR
29
+ - `CONTRIBUTING.md` — development setup, code style, and PR guidelines
30
+ - `CHANGELOG.md`
31
+ - `CLAUDE.md` — project context for Claude Code
32
+
33
+ ### Changed
34
+ - Bumped version to `0.4.1`
35
+ - Added `ruff>=0.4.0`, `mypy>=1.10`, and `pre-commit>=3.0` to `[dev]` extras
36
+
37
+ ## [0.4.0] - 2026-05-01
38
+
39
+ ### Added
40
+ - `ModelEnsemble` with `weighted_mean` and `weighted_vote` strategies
41
+ - `ainvoke()` async wrapper on `ModelTool` (runs blocking predict in a thread pool)
42
+ - Verbose logging via `verbose=True` on `ModelTool`
43
+ - Snowflake Model Registry loader (`from_snowflake`)
44
+ - MLflow Model Registry loader (`from_mlflow`)
45
+ - `predikit inspect` CLI command
46
+
47
+ ### Changed
48
+ - Moved to `src/` layout with hatchling build backend
49
+ - Upgraded Pydantic dependency to v2
50
+
51
+ ## [0.3.x] and earlier
52
+
53
+ See [GitHub Releases](https://github.com/Tejas-TA/predikit/releases) for earlier history.
@@ -0,0 +1,71 @@
1
+ # predikit — Claude Code context
2
+
3
+ ## What this is
4
+
5
+ predikit wraps fitted scikit-learn / XGBoost models as LLM-callable tools with auto-generated JSON schemas, typed I/O via Pydantic, and first-class support for OpenAI function calling and LangChain.
6
+
7
+ ## Project layout
8
+
9
+ ```
10
+ src/predikit/ Core package (installed as `predikit`)
11
+ tool.py ModelTool — main public class
12
+ registry.py ToolRegistry — groups multiple tools for bulk export
13
+ ensemble.py ModelEnsemble — multi-model reconciliation strategies
14
+ exceptions.py LowConfidenceError
15
+ coerce.py LLM-string → Python type coercion (bool, int, float, str)
16
+ introspect.py Extract sklearn model metadata (feature names, task type)
17
+ cli.py `predikit inspect` CLI (click + joblib)
18
+ exporters/
19
+ openai.py .to_openai() — OpenAI function-calling schema
20
+ langchain.py .to_langchain() — LangChain StructuredTool
21
+ loaders/
22
+ mlflow.py from_mlflow() — load from MLflow Model Registry
23
+ snowflake.py from_snowflake() — load from Snowflake Model Registry
24
+ tests/ pytest suite (mirrors src/ layout)
25
+ examples/ Standalone usage scripts (01–07)
26
+ ```
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ # Install for development
32
+ pip install -e ".[dev]"
33
+
34
+ # Run tests
35
+ pytest --cov=src/predikit --cov-report=term-missing
36
+
37
+ # Lint (check only)
38
+ ruff check src/ tests/
39
+
40
+ # Format (check only)
41
+ ruff format --check src/ tests/
42
+
43
+ # Lint + format (auto-fix)
44
+ ruff check --fix src/ tests/
45
+ ruff format src/ tests/
46
+
47
+ # Type check
48
+ mypy src/predikit
49
+
50
+ # All checks via pre-commit
51
+ pre-commit run --all-files
52
+
53
+ # Install pre-commit hooks
54
+ pre-commit install
55
+ ```
56
+
57
+ ## Key conventions
58
+
59
+ - **Public API** — `ModelTool`, `ToolRegistry`, `ModelEnsemble`, `LowConfidenceError` are all re-exported from `predikit/__init__.py`. Everything else is internal.
60
+ - **Optional imports** — heavy optional deps (`langchain`, `xgboost`, `mlflow`, `snowflake`) are imported inside functions/methods, never at module level, so missing extras don't break core imports.
61
+ - **Feature name matching** — inputs map to model features by column name (using `feature_names_in_` from sklearn), not by position. Mismatches raise a `ValueError` with a clear diff.
62
+ - **Bool coercion** — `coerce_value()` converts LLM strings (`"yes"`, `"true"`, `"1"`, `"on"`) to Python bools before Pydantic validation.
63
+ - **Async** — `ainvoke()` is a thin wrapper over `invoke()` via `loop.run_in_executor`. No async-native I/O involved.
64
+ - **Ensemble strategies** — `"collect"`, `"mean"`, `"vote"`, `"weighted_mean"`, `"weighted_vote"`. Weighted strategies take a `weights` list parallel to `tools`.
65
+
66
+ ## Release process
67
+
68
+ 1. Bump `version` in `pyproject.toml` and `__version__` in `src/predikit/__init__.py`.
69
+ 2. Add a section to `CHANGELOG.md`.
70
+ 3. Commit, push to `main`, create a GitHub Release with the version tag (e.g. `v0.4.1`).
71
+ 4. `publish.yml` auto-triggers a PyPI upload via OIDC trusted publishing.
@@ -0,0 +1,66 @@
1
+ # Contributing to predikit
2
+
3
+ Thanks for your interest in contributing.
4
+
5
+ ## Prerequisites
6
+
7
+ - Python 3.10+
8
+ - [pre-commit](https://pre-commit.com/) (`pip install pre-commit`)
9
+
10
+ ## Development setup
11
+
12
+ ```bash
13
+ git clone https://github.com/Tejas-TA/predikit
14
+ cd predikit
15
+ pip install -e ".[dev]"
16
+ pre-commit install
17
+ ```
18
+
19
+ `pre-commit install` wires up ruff and mypy to run automatically before every commit.
20
+
21
+ ## Running tests
22
+
23
+ ```bash
24
+ pytest --cov=src/predikit --cov-report=term-missing
25
+ ```
26
+
27
+ ## Code style
28
+
29
+ This project uses [ruff](https://docs.astral.sh/ruff/) for linting and formatting, and [mypy](https://mypy.readthedocs.io/) for type checking. All three are configured in `pyproject.toml`.
30
+
31
+ ```bash
32
+ # Check and auto-fix
33
+ ruff check --fix src/ tests/
34
+ ruff format src/ tests/
35
+
36
+ # Type check
37
+ mypy src/predikit
38
+ ```
39
+
40
+ Or run everything at once via pre-commit:
41
+
42
+ ```bash
43
+ pre-commit run --all-files
44
+ ```
45
+
46
+ CI enforces all three checks on every push and PR (see `.github/workflows/test.yml`).
47
+
48
+ ## Pull request guidelines
49
+
50
+ - Target `main`.
51
+ - Keep changes focused — one feature or fix per PR.
52
+ - Add or update tests for any changed behaviour.
53
+ - Run `pre-commit run --all-files` before pushing; CI will catch failures regardless.
54
+
55
+ ## Adding a new exporter or loader
56
+
57
+ - Exporters live in `src/predikit/exporters/` and should expose a single function consumed by `ModelTool`.
58
+ - Loaders live in `src/predikit/loaders/` and should return a `ModelTool` instance.
59
+ - Any new optional dependency must be added to both the relevant optional group and `dev` in `pyproject.toml`, and imported inside the function body (not at module level).
60
+
61
+ ## Release process (maintainers)
62
+
63
+ 1. Bump `version` in `pyproject.toml` and `__version__` in `src/predikit/__init__.py`.
64
+ 2. Add a section to `CHANGELOG.md`.
65
+ 3. Merge to `main`, create a GitHub Release tagged `vX.Y.Z`.
66
+ 4. `publish.yml` automatically publishes to PyPI via OIDC trusted publishing.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: predikit
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Turn any trained sklearn/XGBoost model into an LLM-callable tool with auto-generated schemas and typed I/O.
5
5
  Project-URL: Homepage, https://github.com/Tejas-TA/predikit
6
6
  Project-URL: Repository, https://github.com/Tejas-TA/predikit
@@ -10,7 +10,7 @@ Author-email: Tejas Tumakuru Ashok <tejasta@gmail.com>
10
10
  License: MIT
11
11
  License-File: LICENSE
12
12
  Keywords: agents,function-calling,llm,ml-tools,sklearn,xgboost
13
- Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Development Status :: 4 - Beta
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Intended Audience :: Science/Research
16
16
  Classifier: License :: OSI Approved :: MIT License
@@ -31,9 +31,12 @@ Requires-Dist: click>=8.0; extra == 'dev'
31
31
  Requires-Dist: joblib>=1.2; extra == 'dev'
32
32
  Requires-Dist: langchain-core>=0.1; extra == 'dev'
33
33
  Requires-Dist: mlflow>=2.0; extra == 'dev'
34
+ Requires-Dist: mypy>=1.10; extra == 'dev'
34
35
  Requires-Dist: pandas>=1.5; extra == 'dev'
36
+ Requires-Dist: pre-commit>=3.0; extra == 'dev'
35
37
  Requires-Dist: pytest-cov>=4.0; extra == 'dev'
36
38
  Requires-Dist: pytest>=7.0; extra == 'dev'
39
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
37
40
  Requires-Dist: xgboost>=1.7; extra == 'dev'
38
41
  Provides-Extra: langchain
39
42
  Requires-Dist: langchain-core>=0.1; extra == 'langchain'
@@ -45,13 +48,30 @@ Provides-Extra: xgboost
45
48
  Requires-Dist: xgboost>=1.7; extra == 'xgboost'
46
49
  Description-Content-Type: text/markdown
47
50
 
48
- # predikit
49
- [![PyPI version](https://img.shields.io/pypi/v/predikit.svg)](https://pypi.org/project/predikit/)
50
- [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
51
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
52
-
53
-
54
- Turn any trained scikit-learn or XGBoost model into an LLM-callable tool — auto-generated JSON schemas, typed I/O, zero boilerplate.
51
+ <p align="center">
52
+ <picture>
53
+ <source srcset="https://raw.githubusercontent.com/Tejas-TA/predikit/main/docs/logo.gif">
54
+ <img src="https://raw.githubusercontent.com/Tejas-TA/predikit/main/docs/logo.png" alt="predikit" width="500"/>
55
+ </picture>
56
+ </p>
57
+
58
+ <p align="center">
59
+ Turn any trained scikit-learn or XGBoost model into an LLM-callable tool —<br/>
60
+ auto-generated JSON schemas, typed I/O, zero boilerplate.
61
+ </p>
62
+
63
+ <p align="center">
64
+ <a href="https://pypi.org/project/predikit/"><img src="https://img.shields.io/pypi/v/predikit.svg" alt="PyPI version"/></a>
65
+ <a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python 3.10+"/></a>
66
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT"/></a>
67
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"/></a>
68
+ </p>
69
+
70
+ <p align="center">
71
+ <a href="https://pepy.tech/project/predikit"><img src="https://static.pepy.tech/personalized-badge/predikit?period=week&units=international_system&left_color=grey&right_color=blue&left_text=weekly+downloads" alt="Weekly Downloads"/></a>
72
+ <a href="https://pepy.tech/project/predikit"><img src="https://static.pepy.tech/personalized-badge/predikit?period=month&units=international_system&left_color=grey&right_color=blue&left_text=monthly+downloads" alt="Monthly Downloads"/></a>
73
+ <a href="https://pepy.tech/project/predikit"><img src="https://static.pepy.tech/personalized-badge/predikit?period=total&units=international_system&left_color=grey&right_color=blue&left_text=total+downloads" alt="Total Downloads"/></a>
74
+ </p>
55
75
 
56
76
  ```python
57
77
  tool = ModelTool(model=clf, name="classify_iris", ...)
@@ -59,6 +79,15 @@ tool.to_openai() # OpenAI function schema, ready to pass to the API
59
79
  tool.invoke({"sqft": 2200}) # → {"price_usd": 370730}
60
80
  ```
61
81
 
82
+ ## Table of Contents
83
+ - [Install](#install)
84
+ - [30-second example](#30-second-example)
85
+ - [Core API](#core-api)
86
+ - [Field naming rule](#field-naming-rule)
87
+ - [Cookbook](#cookbook)
88
+ - [Contributing](#contributing)
89
+ - [License](#license)
90
+
62
91
  ## Install
63
92
 
64
93
  ```bash
@@ -136,6 +165,7 @@ ModelTool(
136
165
  | Method | Returns | What it does |
137
166
  |--------|---------|--------------|
138
167
  | `.invoke(input_dict)` | `dict` | Validates → predicts → returns `{output_name: value}` |
168
+ | `.ainvoke(input_dict)` | `dict` | Async version of `.invoke()` |
139
169
  | `.to_openai()` | `dict` | OpenAI function-calling schema |
140
170
  | `.to_langchain()` | `StructuredTool` | LangChain tool |
141
171
  | `.to_callable()` | `Callable` | Plain Python function |
@@ -151,6 +181,30 @@ registry.to_langchain() # → list[StructuredTool]
151
181
  registry.get("name") # → ModelTool
152
182
  ```
153
183
 
184
+ ### `ModelEnsemble`
185
+
186
+ Call multiple models and reconcile their outputs in one step:
187
+
188
+ ```python
189
+ ModelEnsemble(
190
+ tools: list[ModelTool], # models to run in parallel
191
+ name: str, # ensemble tool name the LLM sees
192
+ description: str,
193
+ strategy: str, # "collect" | "mean" | "vote" | "weighted_mean" | "weighted_vote"
194
+ weights: list[float], # optional, for weighted strategies
195
+ )
196
+ ```
197
+
198
+ | Strategy | Behaviour |
199
+ |----------|-----------|
200
+ | `"collect"` | Merges all outputs into one dict (tools can have different `output_name`) |
201
+ | `"mean"` | Averages numeric outputs (all tools must share `output_name`) |
202
+ | `"vote"` | Majority class vote (all tools must share `output_name`) |
203
+ | `"weighted_mean"` | Weighted average — provide a `weights` list |
204
+ | `"weighted_vote"` | Weighted majority vote — provide a `weights` list |
205
+
206
+ `ModelEnsemble` exposes the same `.invoke()`, `.ainvoke()`, `.to_openai()`, and `.to_langchain()` interface as `ModelTool`.
207
+
154
208
  ## Field naming rule
155
209
 
156
210
  **Your Pydantic schema field names must exactly match the column names the model was trained on.**
@@ -270,8 +324,6 @@ Only applies to classifiers that implement `predict_proba`. Regressors are unaff
270
324
 
271
325
  ### Multi-model ensemble
272
326
 
273
- Call multiple models and reconcile their outputs in one step:
274
-
275
327
  ```python
276
328
  from predikit import ModelEnsemble, ToolRegistry
277
329
 
@@ -286,12 +338,6 @@ result = ensemble.invoke(inputs) # → {"price_usd": 370112}
286
338
  schema = ensemble.to_openai() # works exactly like ModelTool
287
339
  ```
288
340
 
289
- | strategy | behaviour |
290
- |----------|-----------|
291
- | `"collect"` | merges all outputs into one dict (tools can have different `output_name`) |
292
- | `"mean"` | averages numeric outputs (all tools must share `output_name`) |
293
- | `"vote"` | majority class vote (all tools must share `output_name`) |
294
-
295
341
  Register ensembles alongside individual tools:
296
342
 
297
343
  ```python
@@ -333,7 +379,7 @@ tool = from_snowflake(
333
379
  model_name="VACATION_CHURN",
334
380
  model_version="V3",
335
381
  name="churn_risk",
336
- description="Vacation ownership churn classifier.",
382
+ description="Churn classifier.",
337
383
  input_schema=MemberInput,
338
384
  output_name="churn_probability",
339
385
  output_description="Churn probability 0–1",
@@ -351,11 +397,15 @@ See [`examples/03_orlando_real_estate.py`](examples/03_orlando_real_estate.py) f
351
397
 
352
398
  Planned for later releases:
353
399
 
354
- - HuggingFace / PyTorch / TensorFlow support
355
- - Async invocation
356
- - Weighted ensemble strategies
357
- - CLI (`predikit inspect model.pkl`)
400
+ - HuggingFace / PyTorch / TensorFlow model support
401
+ - Streaming inference support
402
+ - OpenAI Assistants API integration
403
+
404
+ ## Contributing
405
+
406
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code style, and PR guidelines. The [CHANGELOG](CHANGELOG.md) tracks notable changes per release.
358
407
 
359
408
  ## License
360
409
 
361
410
  MIT © Tejas Tumakuru Ashok
411
+