Metadata-Version: 2.4
Name: airow
Version: 0.2.0
Summary: AI-powered DataFrame processing made simple
Author-email: Dmitrii K <dmitriik@protonmail.com>
Maintainer-email: Dmitrii K <dmitriik@protonmail.com>
License: MIT
Project-URL: Homepage, https://github.com/dmitriiweb/airow
Project-URL: Repository, https://github.com/dmitriiweb/airow
Project-URL: Documentation, https://github.com/dmitriiweb/airow
Project-URL: Bug Tracker, https://github.com/dmitriiweb/airow/issues
Keywords: ai,ai-agent,dataframe,pandas,pydantic-ai,async,data-processing
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
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 :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing
Classifier: Topic :: Database
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic>=2.11.7
Requires-Dist: pydantic-ai>=0.8.1
Requires-Dist: tqdm>=4.67.1
Provides-Extra: pandas
Requires-Dist: pandas>=2.3.2; extra == "pandas"
Provides-Extra: polars
Requires-Dist: polars>=1.32.3; extra == "polars"
Provides-Extra: all
Requires-Dist: pandas>=2.3.2; extra == "all"
Requires-Dist: polars>=1.32.3; extra == "all"
Provides-Extra: dev
Requires-Dist: mypy>=1.17.1; extra == "dev"
Requires-Dist: pandas-stubs>=2.3.3.260113; extra == "dev"
Requires-Dist: pytest>=8.4.2; extra == "dev"
Requires-Dist: pytest-asyncio>=1.1.0; extra == "dev"
Requires-Dist: pytest-cov>=6.3.0; extra == "dev"
Requires-Dist: ruff>=0.12.12; extra == "dev"
Requires-Dist: types-tqdm>=4.68.0.20260608; extra == "dev"
Dynamic: license-file

# Airow

**AI-powered DataFrame processing made simple**

Airow is a Python library that combines pandas or Polars DataFrames with AI models to process structured data at scale. Built on top of `pydantic-ai`, it provides type-safe, async processing of DataFrames using any AI model.

## Features

- 🚀 **Async processing** with batch support for high performance
- 🔒 **Type-safe outputs** using Pydantic models
- 📊 **Progress tracking** with built-in progress bars
- 🔄 **Automatic retries** with configurable retry logic
- 🤖 **Flexible AI models** - works with OpenAI, Ollama, Anthropic, and more
- ⚡ **Parallel processing** within batches for maximum throughput
- 📝 **Structured outputs** with defined schemas and validation

## Installation

```bash
# Core library without a DataFrame backend
pip install airow

# pandas only
pip install "airow[pandas]"

# Polars only
pip install "airow[polars]"

# pandas and Polars
pip install "airow[all]"
```

## Pandas example

Install Airow with the pandas backend:

```bash
pip install "airow[pandas]"
```

The examples use Pydantic AI's `openai:gpt-5` model string, so configure the
corresponding provider credentials before running them.

```python
import asyncio

import pandas as pd

from airow import Airow, OutputColumn


async def main():
    df = pd.DataFrame(
        {
            "description": [
                "Bright citrus flavors with a crisp finish.",
                "Rich dark fruit with firm tannins.",
            ]
        }
    )

    airow = Airow(
        model="openai:gpt-5",
        system_prompt="You are an expert in wine tasting and selection.",
        batch_size=2,
    )

    output_columns = [
        OutputColumn(
            name="summary",
            type=str,
            description="A concise summary of the wine",
        ),
        OutputColumn(
            name="style",
            type=str,
            description="The inferred wine style",
        ),
    ]

    result_df = await airow.run(
        df,
        prompt="Analyze this wine description.",
        input_columns=["description"],
        output_columns=output_columns,
        show_progress=True,
    )

    # result_df is a pandas.DataFrame; df is unchanged.
    print(result_df.head())


if __name__ == "__main__":
    asyncio.run(main())
```

Airow detects pandas automatically and returns a new `pandas.DataFrame`.

## Polars example

Install Airow with the Polars backend:

```bash
pip install "airow[polars]"
```

```python
import asyncio

import polars as pl

from airow import Airow, OutputColumn


async def main():
    df = pl.DataFrame(
        {
            "description": [
                "Bright citrus flavors with a crisp finish.",
                "Rich dark fruit with firm tannins.",
            ]
        }
    )

    airow = Airow(
        model="openai:gpt-5",
        system_prompt="You are an expert in wine tasting and selection.",
        batch_size=2,
    )

    output_columns = [
        OutputColumn(
            name="summary",
            type=str,
            description="A concise summary of the wine",
        ),
        OutputColumn(
            name="style",
            type=str,
            description="The inferred wine style",
        ),
    ]

    result_df = await airow.run(
        df,
        prompt="Analyze this wine description.",
        input_columns=["description"],
        output_columns=output_columns,
        show_progress=True,
    )

    # result_df is a polars.DataFrame; df is unchanged.
    print(result_df.head())


if __name__ == "__main__":
    asyncio.run(main())
```

Airow detects eager Polars DataFrames automatically and returns a new
`polars.DataFrame`. LazyFrames are not currently supported.

## Custom backends

Custom dataframe implementations can subclass `DataFrameBackend` and pass an
instance explicitly:

```python
from airow import Airow, DataFrameBackend

backend: DataFrameBackend = MyDataFrameBackend()
airow = Airow(
    model="openai:gpt-5",
    system_prompt="You are a data processing assistant.",
    backend=backend,
)
```
