Metadata-Version: 2.4
Name: fxbx
Version: 0.7.0
Summary: Furiosa RNGD 사전 컴파일 아티팩트 패키징 및 실행 CLI
License-Expression: Apache-2.0
Keywords: furiosa,rngd,npu,compiled-artifacts
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
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
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: huggingface_hub<2,>=0.24
Requires-Dist: tqdm>=4.66
Dynamic: license-file

# fxbX

Formerly **FXBEX**. The new distribution/CLI/import are `fxbx` (release0.7.0).
The public project name is **fxbX**. Existing `.fxbex` model files remain readable.
Release0.7.0 is prepared in source; PyPI publication is a separate release step.
Until published, install this checkout with `python -m pip install -e .`.

Furiosa RNGD에서 사전 컴파일한 실행 파일을 패키징하고 실행하는 Linux CLI입니다. `.fxbex`는 FXBEX가 정의한 독립 형식이며, **Furiosa 공식 FXB 형식이 아닙니다.**

## Python 및 Furiosa SDK 호환성

FXBEX 코어는 Python 3.10–3.14를 지원합니다. Furiosa SDK 2026.4 문서의 Python 지원 범위도 3.10–3.14입니다. 실제 NPU 실행에는 대상 호스트에 설치된 SDK, PyTorch, 모델 어댑터와 호환되는 패키지가 필요합니다.

실행 계획은 Python의 마이너 버전이 달라도 재사용할 수 있습니다. 재사용 시 운영체제, PyTorch 버전, Furiosa SDK 버전과 SDK 소스 지문은 계속 일치해야 하며, 요청 그래프도 기록된 실행 계획과 정확히 일치해야 합니다. 실행 계획이 기록되지 않았거나 요청 그래프가 달라지면 런타임은 컴파일을 시도하지 않고 오류를 반환합니다. Python 주 버전이 다르면 재사용하지 않습니다.

## 설치

```bash
python -m pip install fxbx
fxbx --help
```

체크아웃한 소스로 개발할 때는 다음을 사용합니다.

```bash
python -m pip install -e .
```

기존 SDK 패키지를 바꾸지 않고 설치하려면 사용할 인터프리터를 지정합니다.

```bash
PYTHON=python3.11 bash scripts/install.sh
```

이 패키지는 Furiosa SDK, PyTorch, 드라이버를 설치하거나 업그레이드하지 않습니다. 빌드, 검사, 무결성 전용 검증은 표준 라이브러리만 사용하지만 NPU 실행에는 모델과 호환되는 SDK 및 의존성이 필요합니다. `fxbex`는 [PyPI](https://pypi.org/project/fxbex/)에서 설치합니다. 재현 가능한 설치에는 `python -m pip install fxbx==0.6.1`처럼 검증한 버전을 고정하세요. SDK가 지원되는 Python 환경에서 실행하세요.

소스 버전 0.6.8부터 패키지를 추출하면서 각 파일의 SHA-256을 동시에 검증합니다. 모든 검증이 끝나기 전에는 모델을 실행하지 않습니다. 설치된 PyPI 버전에 이 변경이 있는지는 해당 릴리스를 확인하세요.

TPLMachine/FHA 최적화 후보는 실제 수치·NPU trace·반복 실행 검증을 거친 뒤 새 패키지로 만듭니다. FXBEX가 실행 중 임의의 스케줄이나 커널을 선택하지는 않습니다. 현재 소스에서는 실제 적재에도 정적 preflight를 적용하고, `generate` 실행 기록을 남기며, 일반 DAG의 정수·불리언 출력 타입을 보존합니다. 변경 범위와 아직 검증하지 않은 항목은 [연계 검토](docs/TPLMACHINE_REVIEW.md)를 참고하세요.

## 명령어

```bash
fxbx build ./compiled_model -o model.fxbex
fxbx build ./compiled_model -o model-standalone.fxbex --standalone
fxbx inspect model.fxbex
fxbx validate model.fxbex
fxbx run model.fxbex
fxbx chat model.fxbex
fxbx serve model.fxbex --port 8000
fxbx doctor
```

`run`은 채팅 어댑터를 실행합니다. 텐서 모델은 `--input inputs.json -o result.json`을 받습니다. `chat`에서는 `/reset`, `/quit`을 사용할 수 있습니다. `serve`는 채팅 어댑터용 비스트리밍 `/v1/chat/completions`와 텐서 어댑터용 `/predict`를 localhost에 제공합니다. `fxbex ui --port 7861`은 선택 기능이며 Gradio가 필요합니다. 모든 명령은 `--help`를 지원합니다.

### OpenAI Python 클라이언트와 사용하기

```bash
fxbx serve Qwen3.5-9B-FP8-dynamic --port 8000
python -m pip install openai
```

다른 터미널에서 실행합니다. `model`은 서버가 로드한 패키지의 원본 모델 ID입니다.

```python
from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="local")
response = client.chat.completions.create(
    model="RedHatAI/Qwen3.5-9B-FP8-dynamic",
    messages=[{"role": "user", "content": "안녕!"}],
    max_tokens=32,
)
print(response.choices[0].message.content)
```

현재 서버는 단일 모델·비스트리밍 채팅과 greedy 생성만 지원합니다. 지원하지 않는 생성 옵션은 오류로 반환합니다. 공식 Furiosa 서버의 모든 엔드포인트와 기능을 제공하는 것은 아닙니다. 패키지의 정밀도는 생성 시 고정되며 명시한 `dtype`이 패키지의 검증된 메타데이터와 다르면 오류가 발생합니다.

`validate`는 체크섬, 외부 가중치, SDK 버전, 어댑터 계약과 RNGD 장치를 확인하지만 **추론을 실행하지 않습니다.** SDK나 NPU가 없는 시스템에서는 다음처럼 무결성만 검사할 수 있습니다.

```bash
fxbx validate model.fxbex --integrity-only
```

`--weights-dir /path/to/snapshot`은 해시 검증을 유지하면서 외부 가중치 위치를 지정합니다.

빌더는 이미 컴파일된 아티팩트를 패키징하며 임의의 Hugging Face 모델을 컴파일하지 않습니다. 실행 파일이 없거나 SDK와 맞지 않으면 오류를 반환하고 자동 재컴파일하지 않습니다. 신뢰할 수 있는 패키지와 설치된 플러그인만 사용하세요.

## Model Forge 연동

FXBEX 코어는 `compiler_engine`에 의존하지 않습니다. 일반 `runnable_dag` 패키지는 코어 런타임에서 실행됩니다. 모델별 코드는 별도로 설치하는 어댑터 플러그인에 둡니다.

```bash
cd /root/rngd-model-forge
bash tests/install_fxbex.sh /root/FXBEX
```

설치 스크립트는 `fxbex.adapters` 진입점을 통해 `qwen35_replay` 플러그인을 설치하고, 기존 Model Forge 웹 작업자와 공유하는 NPU 잠금 경로를 `~/.config/fxbex/config.json`에 기록합니다. Model Forge의 **FXBEX package** 탭은 설치된 런타임을 별도 프로세스로 호출하며, 모델을 내리면 NPU 리소스도 반환합니다.

플러그인 클래스는 `(extracted_root, report_dir, ExitStack, weights_dir=None)`를 받고 `chat` 및/또는 `predict`를 제공합니다. `preflight(root, weights_dir=None)`는 정적 검사를 수행합니다. 패키지는 임의의 import 경로나 내장 Python 프로그램 대신 설치된 진입점 이름을 지정합니다. 필요한 진입점이 없거나 중복되면 명시적으로 실패합니다.

기본 보고서 경로는 `~/.cache/fxbex/runs`입니다. `~/.config/fxbex/config.json`의 `reports_dir`, `npu_lock` 설정으로 변경할 수 있으며 `FXBEX_CONFIG`, `FXBEX_NPU_LOCK` 환경 변수도 사용할 수 있습니다. Model Forge 연동 설치기는 기존 잠금 파일을 공유합니다.

## 범위

현재 내장 런타임은 RNGD fusion8의 고정 텐서 DAG를 지원합니다. Qwen 플러그인은 BF16 텍스트 입력을 사용하며 컨텍스트는 패키지의 `context.max_tokens`를 따릅니다. 기존 패키지는512토큰이고, 새 길이는 해당 모델 릴리스에서 실제 검증한 범위를 확인하세요. 이전 검증에서 Qwen 패키지를 다시 불러올 때 컴파일 호출은 0회였으며, 최초 로드에는 가중치 준비와 그래프 복원에 약 3분이 걸렸습니다. 다른 모델 어댑터와 자동 메모리 계획은 구현되어 있지 않습니다. 저장소 분리 이전의 과거 검증 자료는 현재 분리된 코드베이스의 검증 기록과 다를 수 있습니다.

테스트 명령은 `python -m unittest discover -s tests`입니다.

## 재사용 가능한 Gradio 모델 페이지

`examples/model_page.py`를 복사하고 `PACKAGE = Path('fxbex/model.fxbex')`를 설정한 뒤 SDK가 설치된 호스트에서 실행합니다. 전달할 패키지는 애플리케이션의 `fxbex/` 폴더에 둡니다.

```bash
fxbx build ./compiled_model -o fxbex/model.fxbex
```

페이지는 저장된 패키지 목록, 기존 파일을 덮어쓰지 않는 업로드, Load/Unload, 요청 시간 측정과 선택한 파일명을 포함한 Python 예제를 제공합니다. `mode='chat'` 또는 `mode='predict'`를 사용합니다. 이미지 입력·출력 같은 모델별 처리에는 `controls(run)` 콜백을 제공할 수 있습니다. 콜백은 `run('predict', named_inputs)`를 호출하고 `(result, timing)`을 받습니다. 입력 변환과 출력 렌더링은 검증된 모델 어댑터 계약에 맞춰야 합니다. 템플릿은 새 모델 지원을 추가하지 않습니다. 기존 Model Forge가 동일한 페이지 골격과 공유 서비스를 사용합니다. 패키지 파일은 Git에 포함하지 않습니다.

## Python LLM API

```python
from fxbx import LLM

package = '/root/rngd-model-forge/fxbex/RedHatAI--Qwen3.5-9B-FP8-dynamic__text-bf16__fusion8__ctx512__sdk2026.4.0.fxbex'
with LLM(package) as llm:
    print(llm.generate('2+2는 얼마인가요? 짧게 답하세요.')['text'])
    print(llm.converse('2+2는 얼마인가요?')['text'])
    print(llm.converse('그 답에 3을 곱해 주세요.')['text'])
    llm.reset()
```

`LLM(package)` 또는 `LLM(fxbex=package)`처럼 패키지 경로 하나만 전달합니다. `fxb=package`도 별칭으로 사용할 수 있습니다. 모델 이름은 manifest의 `llm.model`에서 가져오므로 별도 인자는 받지 않습니다. `chat(messages)`는 명시적인 대화 이력을 받습니다. 결과는 `text`와 사용 가능한 런타임 지표를 담은 딕셔너리입니다. `with` 블록을 쓰지 않으면 `llm.close()` 또는 `unload()`를 호출하세요. 실행은 별도 프로세스에서 이뤄지며 종료 시 NPU 메모리를 반환합니다.

이 API는 파일 이름이 `.fxb`여도 FXBEX 콘텐츠를 읽을 수 있지만, **Furiosa 공식 FXB 파일은 지원하지 않습니다.** 공식 FXB에는 `furiosa_llm.LLM`을 사용하세요. 호환 SDK, 원본 가중치와 모델 어댑터 플러그인은 별도로 필요합니다. 모델을 다운로드하거나 컴파일하지 않으며 CPU로 대체 실행하지 않습니다.

### Wheel 설치

```bash
python -m pip wheel --no-deps --no-build-isolation . -w dist
python -m pip install dist/fxbex-0.3.0-py3-none-any.whl
```

`pip install fxbx`는 공개된 Python 코어를 설치합니다. 저장소의 현재 GitHub 소스는 0.4.0 개발 버전입니다. PyPI 배포는 소스를 공개하므로 다음 릴리스 게시에는 관리자의 인증이 필요합니다. [PyPI 릴리스 준비와 GitHub OIDC 인증](docs/PYPI_RELEASE.md)을 참고하세요. Python 코어는 Apache-2.0 라이선스이며 Furiosa SDK와 모델 파일은 포함하지 않습니다.

기존 문서의 추가 NPU 검증 생략 기록은 해당 시점의 검증 범위를 뜻합니다. API 단위 검사와 portable 무결성·소스·어댑터 사전 검사는 NPU 추론 검증을 대신하지 않습니다.

## 단일 파일 모델 전달

작은 참조 패키지는 완전한 모델이 아닐 수 있습니다. 외부 가중치나 설치된 어댑터가 필요할 수 있습니다. `build --standalone`은 인덱싱된 가중치, 토크나이저와 설정 파일을 포함하지만 외부 어댑터는 별도일 수 있습니다. portable 패키지는 `runtime.bundled_python`이 지정한 정확한 Python 어댑터 코드를 `python/`에 추가합니다. 불러오는 과정에서 이 코드가 실행되므로 신뢰할 수 있는 패키지만 사용하세요. 체크섬은 손상을 감지하지만 작성자를 인증하지 않습니다.

검증된 Model Forge Qwen 소스에서는 다음처럼 만듭니다.

```bash
cd /root/rngd-model-forge
python -m tools.export_portable_qwen fxbex/model.fxbex -o /large-disk/model-portable.fxbex
```

이 명령은 고정된 프로젝트 소스를 확인하고 체크포인트 파일, 토크나이저, 컴파일된 커널과 Python 어댑터를 포함합니다. 다운로드나 별도의 Model Forge 설치는 필요하지 않지만 호환 RNGD 드라이버, Furiosa SDK와 Python 의존성은 호스트에 있어야 합니다. 따라서 `pip install fxbx`와 파일 하나만으로 실행 가능한 조건은 **이미 호환되는 RNGD 호스트에서 FXBEX 0.3.0 이상을 사용하는 경우**입니다. PyPI 0.2.1은 bundled adapter를 지원하지 않습니다. 완전한 portable 배포라고 안내하기 전에 다른 환경에서 실제 추론을 검증해야 합니다. 임시 디스크에는 패키지와 압축 해제된 파일을 함께 둘 공간이 필요합니다.

## 패키지 우선 모델 클래스 (0.4.0 개발 버전)

```python
from fxbx import Model, LLM, YOLO, ImageGeneration

with LLM('chat.fxbex') as model:
    print(model.generate('안녕하세요')['text'])

with YOLO('detector.fxbex') as model:
    result = model.predict('/absolute/path/image.jpg')
    print(result, model.last_timing)

with ImageGeneration('generator.fxbex') as model:
    result = model.generate('새 한 마리', seed=42)

with Model('tensor.fxbex') as model:
    result = model.predict({'x': [[1, 2]]})
```

`ObjectDetection`은 `YOLO`의 별칭입니다. 모든 클래스는 같은 load/close/context 관리와 `load_seconds`, `last_timing`을 사용합니다. `last_timing`은 전송·대기 시간을 포함한 호스트 요청 시간이며 NPU만의 시간은 아닙니다. 입력과 결과는 패키지 어댑터 계약을 따르고 JSON으로 변환할 수 있어야 합니다. YOLO는 `image`, 이미지 생성은 `prompt`와 옵션을 전달합니다. 전처리, 디코딩·샘플링과 결과 파일 경로는 어댑터가 구현합니다. 지원하지 않는 모델을 변환하거나 전처리·어댑터를 자동으로 제공하지 않습니다. 현재 YOLO 어댑터는 이미지 입력만 받습니다. 0.4.0 API는 Git 소스에서 사용할 수 있으며 PyPI 0.3.0에는 이전 API가 있습니다. `LLM(model_name, fxbex=path)` 대신 `LLM(path)`를 사용하세요.

## 실행 영수증과 모델 검증 경계

소스 버전은 worker의 `predict`, `chat` 응답에 `fxbex_execution` 필드를 추가합니다. 어댑터 결과와 패키지 형식은 바뀌지 않습니다.

```python
with YOLO('detector.fxbex') as model:
    result = model.predict('image.jpg')
    receipt = result['fxbex_execution']
    print(receipt['status'], receipt['wall_seconds'], receipt['report_path'])
```

각 세션은 보고서 폴더의 `executions.jsonl`에 manifest 해시, 작업 순서, 성공 여부, 호스트 경과 시간과 일부 어댑터 보고 지표를 기록합니다. 프롬프트, 대화 내용, 텐서 결과와 예외 본문은 저장하지 않습니다. 기록에 실패하면 `persisted: false`로 표시하며 모델 예외를 숨기지 않습니다.

`npu_verdict`는 `unknown`으로 유지됩니다. Python 호출 성공이나 어댑터의 이전 `validated_audit` 기록만으로 해당 요청이 NPU에서 실행됐다고 볼 수 없습니다. 지원 판정을 내리거나 최적 구성을 선택하려면 현재 실행에서 수집한 공식 trace, 수치 정확도, 전체 그래프 범위, 입력·환경 계약과 프로파일링되지 않은 반복 시간까지 검증해야 합니다. 어댑터가 보고한 값은 검증 전까지 증거로 간주하지 않습니다. 호스트 시간에는 실행 요청·전송·대기가 포함되고 완료 기준은 어댑터별로 다릅니다. `Model.last_timing.status`가 실패한 요청은 유효한 시간 표본에서 제외됩니다.

ChunSik, 커널 매칭, 후보 생성과 튜닝 정책은 Furiosa-Hug-Anything이 담당합니다. FXBEX는 패키징, 실행과 보고를 맡습니다. 기존 `.fxbex` 파일은 실행 영수증을 위해 다시 만들 필요가 없습니다. 이 소스 변경은 PyPI 새 릴리스가 아닙니다.

### Discover model inputs and outputs (source version)

```bash
fxbx describe model.fxbex
fxbx sample model.fxbex > inputs.json
fxbx run model.fxbex --input inputs.json -o result.json
```

Exporters provide an optional `manifest.io_contract` with schema_version=1,
method (`chat`/`predict`), `inputs`, `outputs`, `example_input`, and an honest
`expected_result` description. Missing metadata is reported, never guessed.
Python users can call `from fxbx import describe, example_inputs`. These return
JSON dictionaries suitable for editor integrations; automatic IDE completion is
not yet implemented. No package code executes while reading these hints.
These new commands are available from this repository's source version; a new
PyPI release is required before they can be assumed in `pip install fxbx`.

### Run a catalog model by name (source version)

On a host with the matching RNGD SDK and dependencies:

```bash
pip install "git+https://github.com/smallstep-zzz/fxbX.git@main" huggingface_hub
fxbx run "SOURCE_ORG/MODEL@RELEASE_VERSION"
```

Use the source model ID and version listed in FuryAwesome. FXBEX resolves the
catalog's immutable HF commit, reuses the HF download cache, and verifies SHA256
before loading. Ambiguous names require `@version`. Downloading can consume many
GB; the package includes executable adapter code, so select a trusted publisher.

`run` without `--input` executes one `io_contract.example_input` and prints the
result/report location; `-o result.json` saves the response. `chat MODEL_ID` remains
interactive. The same behavior applies to local `.fxbex` paths. Legacy packages
without I/O metadata report the missing contract; use `chat` for a legacy LLM or
`predict --input inputs.json` for an image model as its HF instructions specify.

Exporters can include sample images in the archive and reference them as
`{"$asset":"samples/example.png"}` within `example_input`. Only integrity-listed
files inside the extracted package are resolved. Plain strings remain text.
No arbitrary shell commands or sample-generation code is executed from metadata.

A leading `./` is also accepted for catalog IDs when no local file exists:

```bash
fxbx run ./RedHatAI/Qwen3.5-9B-FP8-dynamic
```

An existing local file takes precedence. Missing `.fxbex` file paths remain file
errors. Downloads use the HF cache. Legacy packages without example metadata still
need `chat` or explicit inputs as described above.

## 0.4.0 release

Install with `python -m pip install --upgrade fxbex==0.4.0` on Python 3.10–3.14. This release includes catalog model-ID downloads (including `./org/model`), integrity checks, package I/O descriptions and sample execution. `huggingface_hub` is installed automatically. Legacy model packages still require their documented input or `chat` command when sample metadata is absent.

### 0.4.1 download location fix

Model IDs (with or without `./`) now create a directory under the current working directory and save `model.fxbex` there. HF transfer and local-copy progress are displayed. Existing `model.fxbex` files are reused. The HF cache and local copy may both occupy disk space. Upgrade using `python -m pip install --upgrade fxbex==0.4.1`.

### Qwen runtime compatibility finding

Qwen3.5-9B portable with SDK 2026.4.0 / PyTorch 2.10.0+cpu / Python 3.11 / transformers 5.22.1 produced intermittent native crashes during load validation. Limiting CPU threads and excluding CPU profiling did not resolve them. Keeping Python 3.11 and changing only transformers to 5.20.2 completed numerical/NPU acceptance and two chats (4 and Hello). Use `python -m pip install --no-deps transformers==5.20.2` for this observed combination. The native SDK fault itself has not been localized; one successful comparison is not a stability guarantee. Other same-major transformers differences retain the warning policy.

## Add FXBEX to the official Furiosa LLM API

```python
from furiosa_llm import LLM, SamplingParams
from fxbx import hug

LLM = hug(LLM)
# Official models retain the original constructor, options, methods and objects.
# llm = LLM("your-official-model", ...)
llm = LLM(model="./model.fxbex", dtype="bf16")  # 패키지가 BF16인 경우
try:
    output = llm.generate("The numbers are one, two,", SamplingParams(temperature=0, max_tokens=16))
    print(output.outputs[0].text)
    answers = llm.chat([{"role": "user", "content": "Hello!"}],
                       SamplingParams(temperature=0, max_tokens=16))
    print(answers[0].outputs[0].text)
finally:
    llm.shutdown()
```

The wrapper does not patch the official class globally. Official construction
returns the original object; a wrapped class keeps its inherited class helpers and
instance checks. Local `.fxbex` paths, folders containing `model.fxbex`, or exact
FuryAwesome IDs select FXBEX. `fxbex=True` requires that route; `fxbex=False` forces
native dispatch (useful when a model ID exists in both places). Offline unknown
catalog IDs fall back to the official constructor with a warning. Catalog IDs use
the existing verified download/cache mechanism. The native engine still needs its
own weights/SDK and licenses; this wrapper does not enable unsupported models there.

### Live streaming

```python
import asyncio

async def show(llm):
    async for text in llm.stream_generate(
        "Once upon a time", SamplingParams(temperature=0, max_tokens=32)
    ):
        print(text, end="", flush=True)
    print()

# Call while llm is loaded, before shutdown:
# asyncio.run(show(llm))
```

FXBEX streams actual decoder callbacks through its isolated worker. It does not
split a completed answer to simulate streaming. Unicode byte fragments are buffered.

### Compatibility boundary in 0.5.0

|Path|Supported behavior|
|---|---|
|Official model / official FXB|Original constructor and engine, all original functionality forwarded|
|Qwen FXBEX `generate`|Raw string or list of strings, actual official RequestOutput/CompletionOutput, real token IDs|
|Qwen FXBEX `chat`|Single or sequential batches of text messages, list of official RequestOutput|
|Qwen FXBEX `stream_generate`|Async text deltas from greedy decoder, bounded generation|
|FXBEX sampling|Greedy (`temperature=0`), `max_tokens` 1–256; default call uses greedy16|
|FXBEX context|512 tokens; only max_model_len=512 is accepted|
|Unsupported FXBEX options|Nondefault sampling, logprobs, tools/templates, embeddings/scoring, custom tokenizer, pretokenized input, device/parallel/scheduler options raise errors|

Batches are sequential, not native-engine batching. Official model throughput and
stream scheduling are unaffected. This first hug adapter targets furiosa_llm 2026.4.0
and the validated Qwen replay runtime; diffusers, Ultralytics and ONNX Runtime are
not yet hug adapters. The separate package-first `from fxbx import LLM` API remains
available with its original dictionary-returning convenience methods.

For an environment affected by the open native-crash issue, keep the application
interpreter and select a separately installed, verified worker interpreter explicitly:

```bash
export FXBEX_WORKER_PYTHON=/usr/bin/python3.10
```

That interpreter must have FXBEX 0.5.0 and the compatible SDK/adapter dependencies.
The parent still returns its official Python output classes. There is no automatic
interpreter switching or suppression of a crash. Python3.11 + transformers5.20.2
also crashed in a subsequent cold load; the version pin is not a complete fix.
See FXBEX issue #2 for the continuing native-runtime investigation.

### Real model validation

`docs/HUG_NPU_VALIDATION.json` records a Python3.10 test and
`docs/HUG_CROSS_ENV_VALIDATION.json` records a conda Python3.11 parent with a
Python3.10 worker. Both loaded the existing Qwen portable2 and passed numerical
acceptance (cosine0.999929, top1 match, 1,562 official NPU tasks, zero CPU routes/
unknown graphs). Generate returned official output objects with real token IDs,
chat answered `4`, and streaming yielded successive fragments before completion.
Cross-environment first delta arrived at 1.18s and the final delta at 2.82s.

Raw `generate` is completion, matching the official API; use `chat` for instruct
questions. These tests do not establish general answer quality or benchmark a
separate officially supported model. Native constructor/functionality preservation
is covered by forwarding/class-semantics regression tests. The open native crash
in the Python3.11 worker was reproduced and is not fixed by hug; select the verified
worker environment explicitly. See `examples/hug_llm.py` for a runnable example.

## Versioned local models (0.5.1)

New downloads use readable, version-separated paths:

```text
RedHatAI/Qwen3.5-9B-FP8-dynamic/
  2026.4.0-portable2/
    Qwen3.5-9B-FP8-dynamic.fxbex
  opt3/
    Qwen3.5-9B-FP8-dynamic.fxbex
```

```bash
fxbx chat RedHatAI/Qwen3.5-9B-FP8-dynamic@2026.4.0-portable2
# A future locally installed or published optimization can be selected explicitly:
# fxbex chat RedHatAI/Qwen3.5-9B-FP8-dynamic@opt3
```

Release labels are explicit; opt3 above is illustrative, not a published model.
Local versions work offline. Multiple local versions require `@VERSION` or an
exact file path; no lexical guess of the newest/best optimization is made. Existing
legacy `model.fxbex` files remain usable and are not renamed or deleted. Explicit
versions never accidentally reuse an unversioned legacy package. The hug adapter
uses the same resolution rules. HF caches remain separate from local copies.

## Original model provenance (0.5.2)

```bash
fxbx build ./compiled_model -o model.fxbex --standalone --source-model stabilityai/TripoSR --source-revision ORIGINAL_COMMIT
fxbx inspect model.fxbex
```

The manifest records `provenance.source_url`, optional `revision`, and `status`.
Python builders pass `source_url=` and `source_revision=` to `build()`. Explicit
existing provenance is preserved. Missing provenance is `unknown`; a display name
is never treated as evidence of origin. FHA fills this from intake/download records
and requires it before publishing. Old packages still load without this field;
metadata edits require a new artifact hash/release, not in-place rewriting.

## Short names and newest local model (0.5.3)

```bash
fxbx chat Qwen3.5-9B-FP8-dynamic
fxbx run yolo11-onnx
fxbx run ./models
```

A unique final component of the original source repository is a short model ID.
Ambiguous publisher names require the full ID. A folder selects the recursively
newest `.fxbex` by filesystem modification time (lexical path breaks ties), and
prints the selected path. This includes folders holding different models. Exact
file paths and `@version` still select explicitly. Local timestamps can change
when files are copied; newest is a convenience choice, not a performance ranking.
Remote releases use the catalog's recorded registration order; older catalogs
without order require explicit versions when multiple releases match. Existing
files take precedence over remote releases.


### Package-declared context and memory (0.6)

`hug(LLM)` derives the context limit from the verified package manifest's
`context.max_tokens` (legacy packages default to512). Output admission and worker
transport use the loaded runtime capacity; actual tokenized input plus requested
output must fit. This does not make an old512-token compiled package support a
longer context. Smaller constructor overrides remain explicitly unsupported.

Runtime reports save raw SMI snapshots in `memory.jsonl` and optional adapter
logical tensor accounting in `memory_latest.json`. The UI shows logical weights,
KV and recurrent bytes separately. SMI zero is **not** proof of zero HBM use;
physical allocator bytes remain unknown when the installed SDK exposes no public
counter. No SDK/driver upgrade or fabricated utilization is performed.

### Logical memory plans and safe tensor lifetimes (0.6.2)

`fxbex build` now generates a bound memory plan for `runnable-dag-v1` from the
small graph/shape/index JSON documents. Declare intermediate shapes and dtypes in
`runtime_config.tensor_specs` and weight tensor metadata in `weights_index`.
Missing/dynamic sizes stay unknown. `fxbex inspect model.fxbex --memory` displays
the plan without loading the NPU; full inspect still verifies archive integrity.
For a metadata-only analysis, use `fxbex.memory.inspect_archive(path)`.

Before uploading weights, the runtime rejects stale bindings or an exceeded
explicit `memory_plan.policy.budget_bytes` logical envelope. A fitting logical
estimate is **not** a physical-HBM guarantee: aliases, padding, native executable
workspace and allocator reserves are not measured. Legacy custom adapters stay
`unplanned` until they declare real shapes via `fxbex.memory.stateful_plan`.

Built-in DAG execution pins constants/final outputs and releases dead intermediate
references in batches only after the public current-stream completion barrier.
The default is 64 MiB or 64 dead bindings. An unavailable completion API preserves
legacy retention. `release_threshold_bytes=0` tests aggressive release, adding a
barrier per eligible step; tune against measured latency before deployment.
The SDK still owns storage allocation/reuse; reference release does not prove
physical deallocation. No manual arena, buffer aliasing or CPU model fallback is
introduced. Session `memory_plan.json` and result `logical_memory` record the
logical peaks, release counts and barriers; physical peak remains unknown.

### Latest catalog release and SDK environment (0.6.3)

`fxbex run MODEL` and `fxbex chat MODEL` check the current FuryAwesome catalog
before reusing a model-name cache. Short names and full source IDs use the latest
registered release, even when an older local file was touched more recently.
`MODEL@VERSION` pins a release. Explicit files, `./existing-folder`, absolute
paths and Python `Path` arguments preserve local selection; a folder selects its
newest file by mtime. Offline fallback clearly warns that latest is unknown.
An installed matching release is hash-checked and reused without downloading.

Check the actual command with `fxbex --version`. If the CLI environment differs
from the SDK environment, set user-owned `~/.config/fxbex/config.json` key
`runtime_python` to the absolute SDK interpreter (e.g. `/usr/bin/python3.10`).
Install the same FXBEX release in both environments. Runtime CLI commands and
workers use that interpreter; `FXBEX_WORKER_PYTHON` overrides it. This neither
installs the SDK nor enables CPU fallback. Preserve other configuration keys.

`run` opens interactive chat for chat packages; `run --sample` executes the packaged example once. For prediction packages `run` uses the bundled example, and `run --image PATH` overrides a declared image input. `chat` opens the interactive `>>>`
conversation. Default one-shot JSON keeps model outputs/metrics and report paths;
raw memory/compiler/replay diagnostics are saved to the reported `result.json`.
Use `--verbose` to display them or `-o result.json` to save full results elsewhere.

### Shared downloads and refresh

Model IDs download to `~/.cache/fxbex/models/PUBLISHER/MODEL/VERSION/`
(or `$XDG_CACHE_HOME/fxbex/models`). Explicit local paths stay local.

```bash
fxbx fetch Qwen3.5-9B-FP8-dynamic --refresh
fxbx cache list
fxbx cache clear --yes
```

Refresh forces an HF download and verifies the catalog SHA256 before replacing
the managed file. Clear removes only FXBEX-managed model downloads, not explicit
local files or the Hugging Face cache. Unload running models before clearing.

### TPLMachine BuildBundle (source0.6.10)

TPLMachine0.3 can deliver supported small graph models without FHA. FXBEX alone
owns the archive/runtime. Optional build_bundle.json binds compiler artifacts,
weights, configuration, adapter/IO/state metadata and independent execution
acceptance to one content ID; changed contents fail validation before upload.
Legacy packages without a BuildBundle retain their path. The new path requires
matching source versions and is not a claim of a new PyPI publication.

Request-level SMI telemetry reuses snapshots for5seconds (marked with age); load
and unload always refresh. Explicit MemoryTelemetry.sample(...,force=True) forces
a new sample. Execution receipts and logical model memory still update; physical
HBM/SMI-zero uncertainty is unchanged. Tiny graph timings should separate this
host bookkeeping from resident-kernel completed timing.

### Opt-in Tensor / PyTorch module API

For a verified RunnableDAG package with declared input/output tensor specifications,
use tensors directly without a Python-list round trip:

```python
from fxbx import as_torch

with as_torch('./model.fxbex', output_device='cpu') as model:
    outputs = model(input_tensor)  # exact compiled shapes and dtypes
```

`Session.predict_tensors({'input_name': input_tensor})` also returns tensor outputs.
`output_device='furiosa'` retains outputs on device and requires the public stream
completion API. The wrapper is inference-only: training, changing compiled weights,
dtype/device migration and undeclared inputs/options are rejected. Structured outputs
require an explicit package `output_tree`; supported library return classes are
allowlisted. This is not automatic compatibility with arbitrary Transformers or
Diffusers pipelines. Existing JSON and LLM APIs retain their behavior.

A previously validated small reduction package passed four tensor calls against the
preserved JSON output on SDK 2026.4.0, with two official NPU Task events and zero CPU
model routes in the profiled call. This verifies the small tensor transport route,
not arbitrary full-model support. Legacy packages with incorrect/missing output
specifications must be rebuilt before the strict tensor API can accept them.
# Native FXB direction

The new weightless official-compatible FXB writer is documented in
[NATIVE_FXB.md](docs/NATIVE_FXB.md). Existing `.fxbex` packages remain supported.
The verified writer preserves a genuine official manifest/EDF contract; arbitrary
Torch Runnable-to-native-model export is still a separate bridge gap.
Official Qwen3-8B loading and repeated generation succeeded with writer-produced
files; see [runtime evidence](docs/validation/native-fxb-v1/runtime.json).
Native per-operator NPU trace coverage was not collected by that LLM test.
