Metadata-Version: 2.5
Name: openoutlearn
Version: 0.1.1
Summary: GP regression + BALD active-learning engine over text embeddings, shared by OpenOutFind and OpenOutNews.
Project-URL: Homepage, https://openoutreach.app
Project-URL: Source, https://github.com/eracle/OpenOutLearn
Project-URL: Issues, https://github.com/eracle/OpenOutLearn/issues
Author-email: OpenOutreach <hello@openoutreach.app>
License-Expression: GPL-3.0-or-later
License-File: LICENCE.md
Keywords: active-learning,bald,embeddings,explore-exploit,gaussian-process,open-source,self-hosted
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: fastembed<1,>=0.4
Requires-Dist: numpy<3,>=1.26
Requires-Dist: scikit-learn<2,>=1.4
Requires-Dist: scipy<2,>=1.11
Provides-Extra: dev
Requires-Dist: pytest-mock>=3.14; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# OpenOutLearn

A GP regression + BALD active-learning engine over text embeddings — the
scoring mechanism shared by [OpenOutFind](https://github.com/eracle/OpenOutFind)'s
lead qualifier and [OpenOutNews](https://github.com/eracle/OpenOutNews)'s
article qualifier, extracted once both had converged on the same code under
two different domain labels.

`GPBaldQualifier` fits an sklearn Pipeline (StandardScaler -> exact
GaussianProcessRegressor) on whatever labelled embeddings you give it, and
scores new candidates two ways: `predict_probs` (P(f > 0.5) from the GP
posterior, for exploitation) and `compute_bald` (information gain via MC
sampling, for exploration). `acquisition_mode`/`acquisition_scores` pick
between the two by the current label balance — exploit once real negatives
outnumber real positives, explore while the classes are still even.

This is a pure library: no store, no ORM, no CLI, no persistence beyond the
fastembed model download. Each domain wires its own labels, its own store,
and its own interactive surface on top — see `openoutlearn/qualifier.py`'s
docstring for what's deliberately *not* here (cold-start anchors, class
balancing) and why those stay domain-side.

## Install

```bash
pip install openoutlearn
```

## Use

```python
import numpy as np
from pathlib import Path
from openoutlearn import GPBaldQualifier, embed_texts

cache_dir = Path.home() / ".cache" / "openoutlearn" / "fastembed"
embeddings = embed_texts(["a labelled example", "another one"], cache_dir=cache_dir)

q = GPBaldQualifier(embedding_dim=384)
q.warm_start(embeddings, np.array([1, 0]))

candidates = embed_texts(["a new candidate"], cache_dir=cache_dir)
mode, scores = q.acquisition_scores(candidates)
```

## Test

```bash
pip install -e ".[dev]"
pytest
```
