Metadata-Version: 2.4
Name: notpixel
Version: 0.1.0
Summary: NotPixel Python SDK — Privacy-first contextual ads for LLM applications (FastAPI, Django, LangChain, CrewAI)
Project-URL: Homepage, https://notpixel.ai
Project-URL: Documentation, https://docs.notpixel.ai/http-api
Project-URL: Repository, https://github.com/Cocco-Enterprises/notpixel
Author-email: NotPixel <dev@notpixel.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: Contextual-ads,ads,ai,fastapi,langchain,llm,monetization
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
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: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: fastembed<1,>=0.7.0
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# NotPixel Python SDK (`notpixel`)

Official Python SDK for **NotPixel** — privacy-first contextual monetization for LLM applications, agents, and backends (**FastAPI, Django, Flask, LangChain, LlamaIndex, CrewAI**).

## Installation

```bash
pip install notpixel
```

## Quick Start (Async — FastAPI / LangChain)

```python
from notpixel import AsyncAds

# Privacy=True by default: generates 384-d embeddings locally (BAAI/bge-small-en-v1.5)
# User prompts NEVER leave your server.
ads = AsyncAds(publisher_id="pub_10565")

# 1. Fetch a contextual ad + run your LLM in parallel (best-effort)
result = await ads.respond(
    input="How do I optimize PostgreSQL queries with indexes?",
    llm=lambda: call_my_llm("How do I optimize PostgreSQL queries with indexes?"),
)
print(result.text)  # LLM response + sponsored ad block (if matched)

# 2. Track events
if result.ad:
    await ads.impression(result.ad)
    await ads.track_click(result.ad, metadata={"source": "fastapi_chat"})
    await ads.track_conversion(
        result.ad,
        type="signup",
        value_cents=2900,
        external_id="order_12345",
    )
```

## Synchronous Usage (Django WSGI / Scripts)

```python
from notpixel import Ads

ads = Ads(publisher_id="pub_10565")
ad = ads.get_ad(input="Best serverless Postgres database")
if ad:
    print(ad.text)
    ads.track_click(ad)
```

## Privacy Modes

- **`privacy=True` (Default)**: Generates `384`-dimensional embeddings locally using FastEmbed with the same quantized `Xenova/bge-small-en-v1.5` artifact as the TypeScript SDK, attention-mask **mean pooling** and L2 normalization. The built-in FastEmbed BGE entry uses CLS pooling and must not be substituted for this configuration. If local embedding fails, `get_ad()` emits `on_error` and returns `None` — **never** falling back to transmitting raw or sanitized text.
- **`privacy=False`**: Sanitizes PII (emails, phone numbers), truncates to 256 characters, and sends `mode="standard"` to `https://api.notpixel.ai/api/v1/pick`.

## Releases (maintainers)

Python releases use their own version and tags (`python-v0.1.0`), independently of npm.
Keep `pyproject.toml` and `src/notpixel/__init__.py` versions aligned.

`.github/workflows/publish-python.yml` builds a wheel and source distribution, checks
their metadata and contents, and installs the wheel with runtime dependencies to run
the tests on Python 3.10–3.13. Tests use simulated transports and embeddings; they do
not call production ad endpoints or download model weights.

One-time setup: create the GitHub environment `pypi` and register a pending Trusted
Publisher in [PyPI account publishing](https://pypi.org/manage/account/publishing/):

| Field | Value |
| --- | --- |
| PyPI project | `notpixel` |
| GitHub owner | `Cocco-Enterprises` |
| Repository | `notpixel` |
| Workflow filename | `publish-python.yml` |
| Environment | `pypi` |

To release an already committed version:

```bash
git tag -a python-v0.1.0 -m "notpixel Python 0.1.0"
git push origin python-v0.1.0
```

Only matching `python-v*` tags publish. Pull requests, pushes to `main`, and manual
runs with `dry_run=true` build and test without uploading. Publishing uses PyPI
Trusted Publishing (OIDC), with no permanent API token. After publication, confirm
the version on PyPI and test `pip install notpixel==0.1.0` in a fresh environment.
