Metadata-Version: 2.4
Name: ai-marketplace-sdk
Version: 0.5.3
Summary: AI Marketplace Python SDK
Project-URL: Homepage, https://github.com/zakariaalmoktar/AI-Marketplace-Platform
Project-URL: Repository, https://github.com/zakariaalmoktar/AI-Marketplace-Platform
Project-URL: Issues, https://github.com/zakariaalmoktar/AI-Marketplace-Platform/issues
Author: AI Marketplace Platform
License: Proprietary
Keywords: agents,ai,marketplace,runtime,sdk
Classifier: Development Status :: 3 - Alpha
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: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Requires-Dist: ai-marketplace-framework==0.4.4
Requires-Dist: datasets
Requires-Dist: pandas
Description-Content-Type: text/markdown

# AIMP SDK (Python)

This package provides the class-based SDK used by model authors.

## Install

```bash
python -m pip install ai-marketplace-sdk
```

## Install (local source)

```bash
cd packages/python/sdk
uv pip install .
```

## Development (editable)

```bash
cd packages/python/sdk
uv pip install -e .
```

## Root Agent Runtime Entrypoint

Root-agent containers must use the canonical executable module:

```bash
python -m aimp_sdk.agent_runner --module /app/agent.py
```

`aimp_sdk.agent_runner` is the only supported public root-agent runtime entrypoint.
It starts the long-lived stdin/stdout runner that emits the initial `{"type":"ready"}`
protocol message and serves mode requests.

## Fine-Tune From Scratch

The fine-tune flow has two sides:

- model authoring: define the schema and training runtime inside the model project
- consumer dataset creation: build one local bundle that matches the published schema

### 1. Define the model-scoped tuning contract

Model authors declare fine-tune inputs by subclassing `FineTuneSchema` in
`models/<name>/tuning/dataset.py`.

Available field types:

- `ImageField`
- `AudioField`
- `VideoField`
- `FileField`
- `TuningTextField`
- `TuningJsonField`

Example:

```python
from aimp_sdk import FineTuneSchema, ImageField


def validate_png(value: object) -> None:
    if not str(value).lower().endswith(".png"):
        raise ValueError("Only PNG files are allowed")


class ModelFineTuneSchema(FineTuneSchema):
    query_image = ImageField(required=True, validators=[validate_png])
    candidate_image = ImageField(required=True, validators=[validate_png])
```

Use field-level `validators=[...]` and `preprocessors=[...]` when one field needs custom cleanup or
validation. These hooks run during local bundle build, before upload.

### 2. Implement the tuning runner

Model authors implement tuning behavior in `models/<name>/tuning/runner.py` and bind it from
`models/<name>/model.py` using `tuning = ...`.

The runner declares strategy/runtime profile metadata and implements `run(session) -> TuneResult`.

```python
from aimp_sdk import Model, TuneResult


class CoreTuning:
    strategy = "lora"
    training_runtime_profile = "gpu"
    dataset_requirements = {"format": "aimp_tuning_bundle_v1"}
    dataset_spec = {"format": "aimp_tuning_bundle_v1"}
    objective = {"name": "validation_loss", "direction": "minimize"}
    split_policy = {"strategy": "auto", "validation_ratio": 0.1}
    parameters = {
        "learning_rate": {
            "kind": "float",
            "default": 5e-4,
            "min": 1e-5,
            "max": 1e-3,
            "required": True,
        },
        "epochs": {
            "kind": "integer",
            "default": 3,
            "min": 1,
            "max": 5,
            "required": True,
        },
    }

    async def run(self, session) -> TuneResult:
        learning_rate = session.suggest_float("learning_rate", 1e-5, 1e-3, default=5e-4)
        epochs = session.suggest_int("epochs", 1, 5, default=3)
        for record in session.train_dataset:
            train_step(
                query_image=session.resolve_path(record.query_image),
                candidate_image=session.resolve_path(record.candidate_image),
                learning_rate=learning_rate,
            )

        _ = epochs
        validation_loss = evaluate(session.validation_dataset)
        return TuneResult(metrics={"validation_loss": validation_loss})


class CoreModel(Model):
    engine = CoreEngine
    tuning = CoreTuning
```

`session` exposes only training concerns:

- `session.train_dataset`
- `session.validation_dataset`
- `session.params`
- `session.resolve_path(...)`
- `session.suggest_float(...)`
- `session.suggest_int(...)`
- `session.suggest_categorical(...)`

In the current SDK, authors implement `build(self, ctx)` to load runtime state once. The separate
`load(...)` method is framework-internal cache/lifecycle plumbing and is not the author-facing hook.

`session.params` comes from the model's published `tuning.parameters` contract. Defaults and search
space metadata are contract-owned by the platform. Use `session.suggest_*` helpers for explicit
default handling; the SDK does not add random or hidden fallbacks.

Model code does not handle dataset files, S3 uploads, adapter URIs, or trial orchestration.

### 3. Build the consumer dataset bundle

Consumers do not write model-side tuning code. They use the published schema through the CLI:

1. `ai fine-tune schema --model <model-slug>`
2. `ai fine-tune scaffold --model <model-slug>`
3. edit `prepare_bundle.py` and add any local `assets/`
4. `python prepare_bundle.py`
5. `ai fine-tune create --model <model-slug> --output-dir .`

During bundle build the SDK:

- validates required fields and field types
- runs field preprocessors
- validates the processed values
- copies binary assets into the bundle
- writes `data.parquet` and `manifest.json`

That means field preprocessors and validators run before upload, not during remote execution.

### 4. Use the derived model directly

Successful LoRA fine-tunes produce a derived executable model with its own asset ID and slug.
Clients should execute that derived model directly, as if it were a new model:

```python
job = client.fine_tune_job(job_id="ft-123").wait_for_completion()

result = client.models.execute(
    model=job.tuned_model_slug,
    mode="generate",
    input={"prompt": "hello"},
)
```

Client code should not pass `adapter_id` to executions. Adapter resolution is platform-internal.
