Metadata-Version: 2.4
Name: orchestrator-sdk
Version: 0.2.0
Summary: SDK for LLM Orchestrator scenarios
Home-page: https://github.com/example/vkr
Author: VKR Team
Author-email: team@example.com
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: requires-python
Dynamic: summary

# SDK Runtime - LLM Orchestrator

## Описание

Библиотека SDK (Software Development Kit) для создания сценариев оркестратора LLM. Предоставляет публичный интерфейс, который передается сценарию во время выполнения. SDK не знает ничего о worker, backend, PostgreSQL, LM Studio или OpenWebUI: все реальные действия выполняются через внедренный runtime host.

Архитектурно сценарий в этой модели понимается как прикладной workflow. Оркестратор снаружи управляет только запуском такого workflow, а SDK дает сценарию управляемый доступ к внутренним операциям этого запуска: обращениям к модели, логам, метрикам и контексту выполнения.

### Основные компоненты

- **Публичный SDK сценария** - основной интерфейс, через который сценарий:
  - выполняет синхронный вызов модели;
  - запускает асинхронный вызов модели внутри текущего запуска;
  - ожидает или отменяет внутреннюю асинхронную операцию;
  - пишет логи и метрики;
  - читает контекст текущего запуска.

- **SDKRuntime** (внутренний контракт) - runtime host, через который worker предоставляет инфраструктурные операции и координирует внутреннее выполнение сценария
- **SDKContext / RunMetadata** (внутренний контекст) - входные данные сценария и метаданные текущего запуска

## Требования

- Python 3.10-3.14
- Внешние зависимости не требуются

## Установка

### Как пакет (для использования в сценариях)

```bash
cd sdk
pip install -e .
```

### Как зависимость воркера

В `requirements.txt` воркера добавьте:
```
-e ../sdk
```

### Сборка wheel файла и публикация

#### Сборка wheel файла

```bash
cd sdk
pip install wheel
python setup.py bdist_wheel
```

Wheel файл будет создан в папке `dist/` (например, `dist/orchestrator_sdk-0.1.0-py3-none-any.whl`).

#### Публикация в PyPI через GitHub Actions

В репозитории настроен workflow `.github/workflows/publish-sdk.yml`, который публикует только пакет `sdk`.

Публикация запускается:

- автоматически при `push` в ветку `main`
- только если в этом push изменена версия пакета в `sdk/setup.py`
- вручную через `workflow_dispatch`, без требования менять версию

Пример релиза:

```bash
git checkout main
# изменить version="0.2.0" -> version="0.2.1" в sdk/setup.py
git commit -am "Release SDK 0.2.1"
git push origin main
```

Если workflow был запущен от `push` в `main`, но версия SDK не изменилась, публикация пропускается. Workflow завершает работу без публикации и пишет предупреждение в лог и summary run.

Workflow рассчитан на PyPI Trusted Publishing через GitHub OIDC, поэтому в PyPI нужно один раз настроить trusted publisher для этого репозитория и workflow `publish-sdk.yml`.

#### Публикация в внутреннем Python registry компании

Для публикации используйте twine:

```bash
pip install twine
twine upload --repository-url https://your-internal-registry.com/simple/ dist/*
```

Или настройте `.pypirc` файл:

```ini
[distutils]
index-servers =
    internal

[internal]
repository: https://your-internal-registry.com/simple/
username: your-username
password: your-password
```

Затем выполните:
```bash
twine upload -r internal dist/*
```

## Использование в сценариях

Пример целевого использования SDK в сценарии:

```python
# my_scenario.py

def run(sdk, context):
    """
    sdk: публичный SDK сценария, передаваемый воркером
    context: dict - входные данные сценария (из input_data)
    """

    sdk.log("INFO", "Начало выполнения сценария")

    prepared = normalize_input(context)

    primary_result = sdk.call_model(
        prompt=f"Проанализируй следующую задачу: {prepared['task_description']}"
    )

    background_handle = sdk.start_model_call(
        prompt=f"Подготовь альтернативную трактовку: {prepared['task_description']}"
    )

    reference_data = load_reference_data(prepared["source_id"])

    secondary_result = sdk.await_model_call(background_handle, timeout=60)

    sdk.emit_metric("scenario_duration_seconds", 12.5, tags={"scenario": "my_scenario"})

    return {
        "analysis": primary_result,
        "alternative": secondary_result,
        "reference": reference_data,
    }
```

В этом примере важно не название конкретных методов, а архитектурная семантика:

- сценарий выполняет обращения к модели только внутри собственного запуска;
- асинхронный вызов модели не создает новый элемент операторской очереди;
- не-LLM шаги (`normalize_input`, `load_reference_data`) остаются обычной прикладной логикой сценария;
- оркестратор при этом продолжает управлять только одним верхнеуровневым запуском.

## Архитектурный принцип

- Сценарий знает только публичный SDK текущего запуска.
- SDK знает только внутренний контракт runtime host.
- Worker создает `SDKRuntime`, подставляет его в SDK и тем самым связывает сценарий с логами, LLM и интеграциями.
- Публичный SDK не должен давать сценарию создавать новые элементы операторской очереди; асинхронность допускается только как внутренняя механика текущего запуска.

## Версионирование и предупреждения совместимости

Worker должен выполнять compatibility-check версии `orchestrator-sdk`, зафиксированной сценарием, во время прогрева runtime. Эта проверка носит диагностический характер и по умолчанию должна завершаться warning, а не hard-fail.

Правила:

- `orchestrator-sdk` должен сохранять обратную совместимость
- различие между версией SDK у сценария и версией SDK у worker не должно автоматически блокировать запуск
- если для некоторой функции требуется более новая версия SDK, это должно быть явно отражено в документации SDK и в compatibility-warning, который увидит worker
- warning должен связывать номер версии и конкретные функции, которые могут быть недоступны
- worker runtime поставляет собственную версию `orchestrator-sdk`, поэтому сценарий не обязан устанавливать SDK в отдельный runtime-каталог во время прогрева

Требование к сопровождению SDK:

- при добавлении нового публичного метода нужно указать минимальную версию SDK, в которой он появился
- вместе с этим нужно описать текст warning, который должен видеть runtime при работе со старой версией сценария
- этот каталог предупреждений должен поддерживаться в актуальном состоянии внутри документации SDK

При переходе на эту архитектуру каталог минимальных версий должен описывать не низкоуровневые queue/request-операции, а целевые публичные возможности SDK:

- синхронный вызов модели внутри текущего запуска;
- запуск внутренней асинхронной операции модели;
- ожидание результата внутренней асинхронной операции;
- отмена внутренней асинхронной операции;
- логирование;
- публикация метрик;
- доступ к метаданным текущего запуска.

Тексты compatibility-warning должны быть привязаны именно к этим возможностям.

## Структура проекта

```
sdk/
├── README.md
├── setup.py
├── requirements.txt
└── orchestrator_sdk/
    ├── __init__.py
    ├── sdk.py              # OrchestratorSDK
    ├── runtime.py          # SDKRuntime contract
    └── context.py          # SDKContext, RunMetadata
```
