ameva-runtime 2.7.2__tar.gz → 2.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ameva_runtime-2.7.3/PKG-INFO +217 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/README.md +50 -11
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/pyproject.toml +1 -1
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/_version.py +1 -1
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/base.py +6 -3
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/diffusion.py +36 -7
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/llamacpp.py +3 -20
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/stt.py +11 -2
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/doctor.py +3 -2
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/installer.py +18 -5
- ameva_runtime-2.7.3/python/ameva_runtime.egg-info/PKG-INFO +217 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime.egg-info/SOURCES.txt +0 -4
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/setup.py +1 -1
- ameva_runtime-2.7.2/MANIFEST.in +0 -6
- ameva_runtime-2.7.2/NOTICE +0 -12
- ameva_runtime-2.7.2/PKG-INFO +0 -99
- ameva_runtime-2.7.2/README.pypi.md +0 -47
- ameva_runtime-2.7.2/python/ameva_runtime/vulkan/profiles/validated-vulkan-profiles.json +0 -214
- ameva_runtime-2.7.2/python/ameva_runtime.egg-info/PKG-INFO +0 -99
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/LICENSE +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/__init__.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/__init__.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/bitnet.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/tts.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/adapters/vision.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/cli.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/core.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/detector.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/exceptions.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/platform.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/protocol.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/router.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/__init__.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/adapters/__init__.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/bindings.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/cli.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/core.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/doctor.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/exceptions.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/lib/libegl_shim.so +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/loader.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/platform.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/profiles/__init__.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3/python/ameva_runtime/vulkan}/profiles/validated-vulkan-profiles.json +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/protocol.py +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime/vulkan/py.typed +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime.egg-info/dependency_links.txt +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime.egg-info/entry_points.txt +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime.egg-info/requires.txt +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/python/ameva_runtime.egg-info/top_level.txt +0 -0
- {ameva_runtime-2.7.2 → ameva_runtime-2.7.3}/setup.cfg +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ameva-runtime
|
|
3
|
+
Version: 2.7.3
|
|
4
|
+
Summary: Unified Next-Gen Hardware Orchestration & AI Acceleration Runtime for Mobile & Edge
|
|
5
|
+
Home-page: https://github.com/uno-km/ameva-runtime
|
|
6
|
+
Author: Eunho Kim
|
|
7
|
+
Author-email: Eunho Kim <contact@uno-km.com>
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Project-URL: Homepage, https://uno-km.vercel.app/lib/vulkan/
|
|
10
|
+
Project-URL: Repository, https://github.com/uno-km/ameva-runtime
|
|
11
|
+
Project-URL: Documentation, https://uno-km.vercel.app/lib/vulkan/
|
|
12
|
+
Keywords: vulkan-compute,mobile-gpu,hardware-acceleration,hardware-abstraction-layer,adreno-gpu,arm-mali,snapdragon-8-elite,exynos,termux,on-device-ai,edge-ai,tensor-acceleration,spir-v,compute-shaders,zero-silent-fallback,llamacpp,whisper-cpp,sherpa-onnx,stable-diffusion,vision-language-models,bitnet,gguf,ncnn,bionic-loader,arm64,aarch64,cgroup-management,cpu-neon,thermal-throttling,power-efficiency,smart-router,hardware-orchestration,multi-modal-ai,subgroup-operations,gemm-acceleration,mobile-vlm,speech-to-text,text-to-speech,image-generation,edge-inference,unprivileged-userspace,termux-wake-lock,phantom-process-killer,android-ai-runtime,valhall-gpu,adreno-830,mali-g68,ameva-foundation,uno-km,open-source-ai
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Operating System :: Android
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Provides-Extra: stt
|
|
29
|
+
Requires-Dist: termux-stt>=1.2.0; extra == "stt"
|
|
30
|
+
Provides-Extra: diffusion
|
|
31
|
+
Requires-Dist: termux-diffusion>=1.5.0; extra == "diffusion"
|
|
32
|
+
Provides-Extra: bitnet
|
|
33
|
+
Requires-Dist: termux-bitnet>=1.2.0; extra == "bitnet"
|
|
34
|
+
Provides-Extra: llamacpp
|
|
35
|
+
Requires-Dist: termux-llamacpp>=1.3.0; extra == "llamacpp"
|
|
36
|
+
Provides-Extra: tts
|
|
37
|
+
Requires-Dist: termux-tts>=1.4.0; extra == "tts"
|
|
38
|
+
Provides-Extra: vision
|
|
39
|
+
Requires-Dist: termux-vision>=1.2.0; extra == "vision"
|
|
40
|
+
Provides-Extra: all
|
|
41
|
+
Requires-Dist: termux-stt>=1.2.0; extra == "all"
|
|
42
|
+
Requires-Dist: termux-diffusion>=1.5.0; extra == "all"
|
|
43
|
+
Requires-Dist: termux-bitnet>=1.2.0; extra == "all"
|
|
44
|
+
Requires-Dist: termux-llamacpp>=1.3.0; extra == "all"
|
|
45
|
+
Requires-Dist: termux-tts>=1.4.0; extra == "all"
|
|
46
|
+
Requires-Dist: termux-vision>=1.2.0; extra == "all"
|
|
47
|
+
Dynamic: author
|
|
48
|
+
Dynamic: home-page
|
|
49
|
+
Dynamic: license-file
|
|
50
|
+
Dynamic: requires-python
|
|
51
|
+
|
|
52
|
+
# AMEVA-Runtime
|
|
53
|
+
|
|
54
|
+
[](https://pypi.org/project/ameva-runtime/)
|
|
55
|
+
[](https://pypi.org/project/ameva-runtime/)
|
|
56
|
+
[](https://www.npmjs.com/package/@ameva/runtime)
|
|
57
|
+
[](https://github.com/uno-km/ameva-runtime-releases/releases/tag/v2.7.3)
|
|
58
|
+
[](https://github.com/uno-km/ameva-runtime)
|
|
59
|
+
<img src="https://img.shields.io/badge/BitNet%201.58b-Vulkan%20Compute%20Accelerated-purple.svg?logo=vulkan&logoColor=white" alt="BitNet Vulkan">
|
|
60
|
+
|
|
61
|
+
> Next-Gen Unified On-Device Hardware Orchestration & 6-Modality AI Acceleration Runtime (with BitNet 1.58-bit Vulkan Compute) for Mobile & Edge
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Architecture & Overview
|
|
66
|
+
|
|
67
|
+
AMEVA-Runtime is a hardware abstraction layer (HAL) and compute orchestration engine engineered specifically for mobile ARM64 devices (Android Termux, Linux Edge). It continuously inspects underlying silicon topology (/dev/kgsl-3d0, /dev/mali0) to route tensor execution across Qualcomm Adreno, ARM Mali, and ARM Cortex CPU-NEON backends.
|
|
68
|
+
|
|
69
|
+
### 6-Modality Acceleration Matrix
|
|
70
|
+
|
|
71
|
+
| Modality | Engine Integration | Status (v2.7.3) | Hardware Acceleration Mechanism |
|
|
72
|
+
| :--- | :--- | :---: | :--- |
|
|
73
|
+
| **1. LLM (Text)** | Llama.cpp & Termux-BitNet (1.58-bit i2_s) | **Production (v2.7.3)** | Vulkan 25/25 layer VRAM offload (`ngl=999`), BitNet full pipeline & strict `AmbiguousModelMatchError` |
|
|
74
|
+
| **2. STT (Speech)** | Whisper.cpp (Large-v3-Turbo) | **Production (v2.7.3 / STT v1.2.7)** | Vulkan GPU acceleration with greedy decoding default (`-bs 1`), 6-SoC fleet validated |
|
|
75
|
+
| **3. TTS (Audio)** | MeloTTS / Piper / Kokoro / Supertonic | **Production (v2.7.3 / TTS v1.5.0)** | Bionic Direct Vulkan (`/system/lib64/libvulkan.so`) & HiFi-GAN 32MB buffer temporal tiling |
|
|
76
|
+
| **4. Diffusion (Image)** | SDXS / SD1.5 / Z-Image Turbo (6.0B DiT) | **Production (v2.7.3 / Diffusion v1.8.0)** | Z-Image Turbo 6.0B DiT, Flash Attention (`--diffusion-fa`), VAE Tiling, Zero-Collision Bionic Vulkan backend |
|
|
77
|
+
| **5. Vision (VLM)** | CLIP / MobileVLM / LLaVA | **In Development** | GGML Vulkan vision encoder tensor bindings |
|
|
78
|
+
| **6. Train (Training)** | On-Device LoRA / QLoRA | **In Development** | Mobile Vulkan gradient descent backpropagation |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Empirical Physical Device Benchmarks
|
|
83
|
+
|
|
84
|
+
Tested on physical devices running Android 16 under Termux ARM64:
|
|
85
|
+
|
|
86
|
+
### 1. LLM Generation (Qwen2.5-0.5B-Instruct Q4_K_M)
|
|
87
|
+
| Target Device | Hardware Architecture | Active Backend | Layers in VRAM | Generation Speed | Prompt Processing | Speedup |
|
|
88
|
+
| :--- | :--- | :---: | :---: | :---: | :---: | :---: |
|
|
89
|
+
| **Galaxy S25** | Snapdragon 8 Elite / Adreno 830 | Vulkan 1.3 | **25/25 (100%)** | **35.80 t/s** (27.9 ms/t) | 4.53 t/s | **35.8x (vs CPU)** |
|
|
90
|
+
| **Galaxy A35** | Exynos 1380 / ARM Mali-G68 MP5 | Vulkan 1.3 | **25/25 (100%)** | **4.44 t/s** (225 ms/t) | 6.12 t/s | **+26.9% (vs NEON)** |
|
|
91
|
+
| **Galaxy A35** | Cortex-A78 CPU-NEON (3 Threads) | CPU-NEON | 0/25 | 3.55 t/s (281 ms/t) | 8.05 t/s | Baseline |
|
|
92
|
+
|
|
93
|
+
### 2. Speech-to-Text (Whisper Large-v3-Turbo Q5_0, 548MB)
|
|
94
|
+
| Target Device | Hardware Architecture | Backend Mode | Latency (1-min audio) | GPU Load | CPU Load | Speedup |
|
|
95
|
+
| :--- | :--- | :---: | :---: | :---: | :---: | :---: |
|
|
96
|
+
| **Galaxy S25** | Snapdragon 8 Elite / Adreno 830 | Vulkan GPU | **4.40 s (0.07x RTF)** | Adreno Turbo | ~12% | **18.5x (vs CPU)** |
|
|
97
|
+
| **Galaxy S22** | Snapdragon 8 Gen 1 / Adreno 730 | Vulkan GPU | **5.13 s (Encoder)** | Adreno Native | ~14% | **3.73x (vs CPU)** |
|
|
98
|
+
| **Galaxy A35** | Exynos 1380 / Mali-G68 MP5 | Vulkan GPU | **360.60 s (6m 00s)** | **949 MHz (100%)** | 20~30% | **2.26x (56% time saved)** |
|
|
99
|
+
| **Galaxy A35** | Cortex-A78 x4 Cores | CPU-NEON | 816.48 s (13m 36s) | 0% | 291% | Baseline |
|
|
100
|
+
|
|
101
|
+
### 3. Text-to-Speech (AMEVA Bionic Native Vulkan Fleet Benchmarks)
|
|
102
|
+
| Target Device | Hardware Architecture | Neural Engine / Model | Backend Mode | Latency | RTF | Forensics (RMS/Peak) | Status |
|
|
103
|
+
| :--- | :--- | :--- | :---: | :---: | :---: | :---: | :---: |
|
|
104
|
+
| **Galaxy S22** | Snapdragon 8 Gen 1 / Adreno 730 | MeloTTS Universal Bilingual | **Bionic Vulkan GPU** | **2,750 ms** | **0.88x** | 0.0814 / 0.6974 | Real-time Synthesized |
|
|
105
|
+
| **Galaxy S21** | Exynos 2100 / ARM Mali-G78 | Piper VITS (On-chip Tiled) | **Bionic Vulkan GPU** | **560 ms** | **0.18x** | 0.0921 / 0.7412 | 5.5x Faster than RT |
|
|
106
|
+
| **Galaxy S20** | Exynos 990 / ARM Mali-G77 | Piper VITS (On-chip Tiled) | **Bionic Vulkan GPU** | **750 ms** | **0.24x** | 0.0890 / 0.7105 | 4.1x Faster than RT |
|
|
107
|
+
| **Galaxy S25** | Snapdragon 8 Elite / Adreno 830 | Supertonic 3 Flow / Piper | **Bionic Vulkan GPU** | **380 ms** | **0.12x** | 0.1042 / 0.8120 | Studio Ultra-Fast |
|
|
108
|
+
| **Galaxy A35** | Exynos 1380 / ARM Mali-G68 MP5 | Piper VITS (`lessac-medium`) | **Vulkan GPU** | **5,180 ms** | **1.146x** | 0.0782 / 0.6540 | Validated |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### 4. BitNet 1.58-bit LLM (Microsoft BitNet b1.58 2B-4T i2_s)
|
|
113
|
+
| Target Device | Hardware Architecture | Active Backend | Generation Speed | Prompt Latency | Speedup | Status |
|
|
114
|
+
| :--- | :--- | :---: | :---: | :---: | :---: | :---: |
|
|
115
|
+
| **Galaxy S25** | Snapdragon 8 Elite / Adreno 830 | **AMEVA Vulkan GPU** | **17.558 t/s** | **205.9 ms** | **12.58x** | **Verified (Ground Truth)** |
|
|
116
|
+
| Galaxy S25 | Snapdragon 8 Elite / Oryon CPU | Native CPU (4 Threads) | 1.396 t/s | 2,041.0 ms | 1.00x | Baseline |
|
|
117
|
+
| **Galaxy A35** | Exynos 1380 / Mali-G68 MP5 | **AMEVA Vulkan GPU** | **3.471 t/s** | **1,552.8 ms** | **5.94x** | **Verified (Ground Truth)** |
|
|
118
|
+
| Galaxy A35 | Exynos 1380 / Cortex-A78 CPU | Native CPU (4 Threads) | 0.584 t/s | 8,775.0 ms | 1.00x | Baseline |
|
|
119
|
+
|
|
120
|
+
## Root-Cause Driver Solutions
|
|
121
|
+
|
|
122
|
+
1. **ARM Mali-G68 Valhall Integer Truncation**: Enforced medium tile matmul kernel dispatch (`loadstride_b = 4 > 0`), permanently eliminating shader zero-stride infinite loops on subgroup-16 hardware.
|
|
123
|
+
2. **Qualcomm Adreno 830 JIT Register Bug**: Bounded vector column specialization (`mul_mat_vec_max_cols = 2`), preventing compiler crash `VK_ERROR_UNKNOWN (-13)`.
|
|
124
|
+
3. **Bionic Direct Vulkan Linking**: Permanently bypasses Termux `$PREFIX/lib/libvulkan.so` Mesa `llvmpipe` CPU software emulator trap by dynamically binding `/system/lib64/libvulkan.so` directly, routing compute shader execution to physical Adreno/Mali silicon.
|
|
125
|
+
4. **Mobile GPU 32MB Memory Ceiling & Temporal Tiling**: Resolved MeloTTS HiFi-GAN 52.4MB buffer overflow (`VK_ERROR_OUT_OF_DEVICE_MEMORY` / kernel TDR kill) via temporal chunk slicing ($T_{\text{chunk}} \le 819$) and Piper VITS on-chip SRAM tiling.
|
|
126
|
+
5. **Zero-Silent-Fallback & Strict Model Resolution**: Guaranteed fail-fast architecture without silent CPU degradation. Explicitly raises `AmbiguousModelMatchError` on multi-model ambiguity and rejects silent guessing.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Two-Track Supply Chain Architecture
|
|
131
|
+
|
|
132
|
+
To simultaneously guarantee **100% intellectual property & source code protection** and **frictionless, tokenless binary deployment**, AMEVA enforces a strict Two-Track Supply Chain Architecture:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
[Track 1: Local Ground Truth & Offline Staging]
|
|
136
|
+
├── dev/ameva/ameva-runtime/releases/ (Consolidated 6-Modality SOTA Binaries)
|
|
137
|
+
└── dev/termux/termux-*/releases/ (Domain-Specific Compiled Binaries)
|
|
138
|
+
│
|
|
139
|
+
▼ Synchronized via Git & Automated Release Workflows
|
|
140
|
+
[Track 2: Remote Public GitHub Releases Cloud & CDN]
|
|
141
|
+
├── uno-km/ameva-runtime-releases (Public Unified Binary Hub: Releases v2.7.3)
|
|
142
|
+
└── uno-km/termux-* (diffusion, stt) (Domain-Specific Public GitHub Releases)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
1. **Core Source Code (`uno-km/ameva-runtime`)**: Kept **100% Private**. Architectural proprietary logic, HAL implementations, and optimization kernels are permanently protected.
|
|
146
|
+
2. **Public Binary Distribution Hub (`uno-km/ameva-runtime-releases`)**: **Public Registry**. Hosts verified precompiled binaries, hardware acceleration compute shaders, and wheels for anonymous 1-Click installation without requiring personal GitHub tokens.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Installation & Engine Auto-Provisioning
|
|
151
|
+
|
|
152
|
+
### 1. Python SDK Installation
|
|
153
|
+
```bash
|
|
154
|
+
# Direct install from public release wheel
|
|
155
|
+
pip install --upgrade "https://github.com/uno-km/ameva-runtime-releases/releases/latest/download/ameva_runtime-2.7.3-py3-none-any.whl"
|
|
156
|
+
|
|
157
|
+
# Or standard PyPI install
|
|
158
|
+
pip install ameva-runtime
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 2. 1-Click Native Engine Provisioning
|
|
162
|
+
The `NativeAssetManager` automatically retrieves cryptographically verified native engine binaries from the public registry and establishes system links in `$PREFIX/bin`:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Provision all hardware engines at once
|
|
166
|
+
ameva install --all
|
|
167
|
+
|
|
168
|
+
# Or provision specific engine modalities individually
|
|
169
|
+
ameva install --modality diffusion # Stable Diffusion Vulkan Engine (sd-cli)
|
|
170
|
+
ameva install --modality stt # Whisper STT Vulkan Engine (whisper-cli)
|
|
171
|
+
ameva install --modality llm # LLaMA C++ Vulkan Engine (llama-cli)
|
|
172
|
+
ameva install --modality tts # Sherpa-NCNN Neural Voice Engine
|
|
173
|
+
ameva install --modality bitnet # BitNet 1.58-bit Acceleration Engine
|
|
174
|
+
|
|
175
|
+
# Validate system readiness with 12-stage hardware diagnostic
|
|
176
|
+
ameva doctor
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Quickstart
|
|
182
|
+
|
|
183
|
+
### Python SDK
|
|
184
|
+
```python
|
|
185
|
+
import ameva_runtime as ameva
|
|
186
|
+
from ameva_runtime import vulkan
|
|
187
|
+
|
|
188
|
+
# 1. Inspect on-device silicon topology
|
|
189
|
+
profile = ameva.detect_hardware()
|
|
190
|
+
print(f"SoC: {profile.soc_name} | GPU: {profile.gpu_vendor}")
|
|
191
|
+
|
|
192
|
+
# 2. Run hardware self-test
|
|
193
|
+
doc = vulkan.Doctor()
|
|
194
|
+
report = doc.run_self_test()
|
|
195
|
+
print(f"GPU: {report.device_name} (Passed: {report.passed_stages}/{report.total_stages})")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Node.js / TypeScript
|
|
199
|
+
```typescript
|
|
200
|
+
import { Doctor, createContext } from '@ameva/runtime';
|
|
201
|
+
|
|
202
|
+
const doc = new Doctor();
|
|
203
|
+
const report = await doc.runSelfTest();
|
|
204
|
+
console.log(`Vulkan GPU: ${report.deviceName}`);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Official Documentation & Benchmarks
|
|
210
|
+
- [Official Architecture & API Reference](https://uno-km.vercel.app/lib/vulkan/)
|
|
211
|
+
- [Ecosystem Metrics & Registry Stats](https://uno-km.vercel.app/foundation/metrics)
|
|
212
|
+
- [AMEVA Open-Source Foundation Portal](https://uno-km.vercel.app/foundation/index.html)
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
Licensed under the Apache-2.0 License. Copyright (c) 2026 Eunho Kim ([@uno-km](https://github.com/uno-km)).
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://pypi.org/project/ameva-runtime/)
|
|
4
4
|
[](https://pypi.org/project/ameva-runtime/)
|
|
5
5
|
[](https://www.npmjs.com/package/@ameva/runtime)
|
|
6
|
-
[](https://github.com/uno-km/ameva-runtime/releases/tag/v2.7.
|
|
6
|
+
[](https://github.com/uno-km/ameva-runtime-releases/releases/tag/v2.7.3)
|
|
7
7
|
[](https://github.com/uno-km/ameva-runtime)
|
|
8
8
|
<img src="https://img.shields.io/badge/BitNet%201.58b-Vulkan%20Compute%20Accelerated-purple.svg?logo=vulkan&logoColor=white" alt="BitNet Vulkan">
|
|
9
9
|
|
|
@@ -17,13 +17,13 @@ AMEVA-Runtime is a hardware abstraction layer (HAL) and compute orchestration en
|
|
|
17
17
|
|
|
18
18
|
### 6-Modality Acceleration Matrix
|
|
19
19
|
|
|
20
|
-
| Modality | Engine Integration | Status (v2.7.
|
|
20
|
+
| Modality | Engine Integration | Status (v2.7.3) | Hardware Acceleration Mechanism |
|
|
21
21
|
| :--- | :--- | :---: | :--- |
|
|
22
|
-
| **1. LLM (Text)** | Llama.cpp & Termux-BitNet (1.58-bit i2_s) | **Production (v2.7.
|
|
23
|
-
| **2. STT (Speech)** | Whisper.cpp (Large-v3-Turbo) | **Production (v2.7.
|
|
24
|
-
| **3. TTS (Audio)** | MeloTTS / Piper / Kokoro / Supertonic | **Production (v2.7.
|
|
25
|
-
| **4.
|
|
26
|
-
| **5.
|
|
22
|
+
| **1. LLM (Text)** | Llama.cpp & Termux-BitNet (1.58-bit i2_s) | **Production (v2.7.3)** | Vulkan 25/25 layer VRAM offload (`ngl=999`), BitNet full pipeline & strict `AmbiguousModelMatchError` |
|
|
23
|
+
| **2. STT (Speech)** | Whisper.cpp (Large-v3-Turbo) | **Production (v2.7.3 / STT v1.2.7)** | Vulkan GPU acceleration with greedy decoding default (`-bs 1`), 6-SoC fleet validated |
|
|
24
|
+
| **3. TTS (Audio)** | MeloTTS / Piper / Kokoro / Supertonic | **Production (v2.7.3 / TTS v1.5.0)** | Bionic Direct Vulkan (`/system/lib64/libvulkan.so`) & HiFi-GAN 32MB buffer temporal tiling |
|
|
25
|
+
| **4. Diffusion (Image)** | SDXS / SD1.5 / Z-Image Turbo (6.0B DiT) | **Production (v2.7.3 / Diffusion v1.8.0)** | Z-Image Turbo 6.0B DiT, Flash Attention (`--diffusion-fa`), VAE Tiling, Zero-Collision Bionic Vulkan backend |
|
|
26
|
+
| **5. Vision (VLM)** | CLIP / MobileVLM / LLaVA | **In Development** | GGML Vulkan vision encoder tensor bindings |
|
|
27
27
|
| **6. Train (Training)** | On-Device LoRA / QLoRA | **In Development** | Mobile Vulkan gradient descent backpropagation |
|
|
28
28
|
|
|
29
29
|
---
|
|
@@ -76,14 +76,53 @@ Tested on physical devices running Android 16 under Termux ARM64:
|
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
-
##
|
|
79
|
+
## Two-Track Supply Chain Architecture
|
|
80
80
|
|
|
81
|
+
To simultaneously guarantee **100% intellectual property & source code protection** and **frictionless, tokenless binary deployment**, AMEVA enforces a strict Two-Track Supply Chain Architecture:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
[Track 1: Local Ground Truth & Offline Staging]
|
|
85
|
+
├── dev/ameva/ameva-runtime/releases/ (Consolidated 6-Modality SOTA Binaries)
|
|
86
|
+
└── dev/termux/termux-*/releases/ (Domain-Specific Compiled Binaries)
|
|
87
|
+
│
|
|
88
|
+
▼ Synchronized via Git & Automated Release Workflows
|
|
89
|
+
[Track 2: Remote Public GitHub Releases Cloud & CDN]
|
|
90
|
+
├── uno-km/ameva-runtime-releases (Public Unified Binary Hub: Releases v2.7.3)
|
|
91
|
+
└── uno-km/termux-* (diffusion, stt) (Domain-Specific Public GitHub Releases)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
1. **Core Source Code (`uno-km/ameva-runtime`)**: Kept **100% Private**. Architectural proprietary logic, HAL implementations, and optimization kernels are permanently protected.
|
|
95
|
+
2. **Public Binary Distribution Hub (`uno-km/ameva-runtime-releases`)**: **Public Registry**. Hosts verified precompiled binaries, hardware acceleration compute shaders, and wheels for anonymous 1-Click installation without requiring personal GitHub tokens.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Installation & Engine Auto-Provisioning
|
|
100
|
+
|
|
101
|
+
### 1. Python SDK Installation
|
|
81
102
|
```bash
|
|
82
|
-
#
|
|
103
|
+
# Direct install from public release wheel
|
|
104
|
+
pip install --upgrade "https://github.com/uno-km/ameva-runtime-releases/releases/latest/download/ameva_runtime-2.7.3-py3-none-any.whl"
|
|
105
|
+
|
|
106
|
+
# Or standard PyPI install
|
|
83
107
|
pip install ameva-runtime
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2. 1-Click Native Engine Provisioning
|
|
111
|
+
The `NativeAssetManager` automatically retrieves cryptographically verified native engine binaries from the public registry and establishes system links in `$PREFIX/bin`:
|
|
84
112
|
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
```bash
|
|
114
|
+
# Provision all hardware engines at once
|
|
115
|
+
ameva install --all
|
|
116
|
+
|
|
117
|
+
# Or provision specific engine modalities individually
|
|
118
|
+
ameva install --modality diffusion # Stable Diffusion Vulkan Engine (sd-cli)
|
|
119
|
+
ameva install --modality stt # Whisper STT Vulkan Engine (whisper-cli)
|
|
120
|
+
ameva install --modality llm # LLaMA C++ Vulkan Engine (llama-cli)
|
|
121
|
+
ameva install --modality tts # Sherpa-NCNN Neural Voice Engine
|
|
122
|
+
ameva install --modality bitnet # BitNet 1.58-bit Acceleration Engine
|
|
123
|
+
|
|
124
|
+
# Validate system readiness with 12-stage hardware diagnostic
|
|
125
|
+
ameva doctor
|
|
87
126
|
```
|
|
88
127
|
|
|
89
128
|
---
|
|
@@ -7,7 +7,7 @@ name = "ameva-runtime"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "Unified Next-Gen Hardware Orchestration & AI Acceleration Runtime for Mobile & Edge"
|
|
9
9
|
|
|
10
|
-
readme = "README.
|
|
10
|
+
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.8"
|
|
12
12
|
license = { text = "Apache-2.0" }
|
|
13
13
|
authors = [{ name = "Eunho Kim", email = "contact@uno-km.com" }]
|
|
@@ -546,13 +546,16 @@ def get_vulkan_env(base_env: Optional[dict[str, str]] = None) -> dict[str, str]:
|
|
|
546
546
|
|
|
547
547
|
# Mali GPU Quirks: Avoid infinite GEMM quantization loops on ARM Mali Valhall architectures
|
|
548
548
|
try:
|
|
549
|
-
from ..platform import detect_soc_environment
|
|
549
|
+
from ..platform import detect_soc_environment, is_android
|
|
550
550
|
soc = detect_soc_environment()
|
|
551
|
-
if "mali" in str(soc.gpu_family).lower()
|
|
551
|
+
if "mali" in str(soc.gpu_family).lower():
|
|
552
552
|
env.setdefault("GGML_VK_FORCE_MEDIUM_MATMUL", "1")
|
|
553
553
|
env.setdefault("GGML_VK_DISABLE_F16", "1")
|
|
554
554
|
|
|
555
|
-
|
|
555
|
+
# Mobile Vulkan HAL shim: In Android Termux environment, preload verified libegl_shim.so
|
|
556
|
+
# to intercept and resolve missing vendor Bionic symbols (e.g. _ZN7android18egl_get_connectionEv)
|
|
557
|
+
# across Samsung One UI and vendor drivers cleanly without crash.
|
|
558
|
+
if is_android() or os.path.exists("/system/lib64/libvulkan.so"):
|
|
556
559
|
shim_path = resolve_vulkan_shim_path()
|
|
557
560
|
if shim_path:
|
|
558
561
|
curr_preload = env.get("LD_PRELOAD", "")
|
|
@@ -215,9 +215,9 @@ class DiffusionAdapter(BaseAdapter):
|
|
|
215
215
|
def build_cli_args(
|
|
216
216
|
cls,
|
|
217
217
|
executable: str,
|
|
218
|
-
model_path: str,
|
|
219
|
-
prompt: str,
|
|
220
|
-
output_path: str,
|
|
218
|
+
model_path: Optional[str] = None,
|
|
219
|
+
prompt: str = "",
|
|
220
|
+
output_path: str = "",
|
|
221
221
|
width: int = 512,
|
|
222
222
|
height: int = 512,
|
|
223
223
|
steps: int = 2,
|
|
@@ -231,6 +231,13 @@ class DiffusionAdapter(BaseAdapter):
|
|
|
231
231
|
vae_tiling: bool = False,
|
|
232
232
|
backend: Optional[str] = None,
|
|
233
233
|
is_adreno: bool = False,
|
|
234
|
+
llm_path: Optional[str] = None,
|
|
235
|
+
diffusion_model_path: Optional[str] = None,
|
|
236
|
+
clip_l_path: Optional[str] = None,
|
|
237
|
+
flash_attn: bool = False,
|
|
238
|
+
offload_to_cpu: bool = False,
|
|
239
|
+
clip_on_cpu: bool = False,
|
|
240
|
+
vae_on_cpu: bool = False,
|
|
234
241
|
) -> list[str]:
|
|
235
242
|
"""최신 sd-cli 규격에 부합하는 안전하고 검증된 Diffusion CLI 인자 목록을 조립합니다."""
|
|
236
243
|
if threads == "auto" or threads is None:
|
|
@@ -241,7 +248,6 @@ class DiffusionAdapter(BaseAdapter):
|
|
|
241
248
|
|
|
242
249
|
cmd = [
|
|
243
250
|
str(executable),
|
|
244
|
-
"-m", str(model_path),
|
|
245
251
|
"-p", str(prompt),
|
|
246
252
|
"-o", str(output_path),
|
|
247
253
|
"-W", str(width),
|
|
@@ -251,16 +257,39 @@ class DiffusionAdapter(BaseAdapter):
|
|
|
251
257
|
"--cfg-scale", str(cfg_scale),
|
|
252
258
|
]
|
|
253
259
|
|
|
260
|
+
if diffusion_model_path:
|
|
261
|
+
cmd.extend(["--diffusion-model", str(diffusion_model_path)])
|
|
262
|
+
elif model_path:
|
|
263
|
+
cmd.extend(["-m", str(model_path)])
|
|
264
|
+
|
|
265
|
+
if llm_path:
|
|
266
|
+
cmd.extend(["--llm", str(llm_path)])
|
|
267
|
+
if clip_l_path:
|
|
268
|
+
cmd.extend(["--clip_l", str(clip_l_path)])
|
|
269
|
+
|
|
254
270
|
if guidance is not None:
|
|
255
271
|
cmd.extend(["--guidance", str(guidance)])
|
|
256
272
|
|
|
257
|
-
if
|
|
258
|
-
cmd.append("--
|
|
273
|
+
if clip_on_cpu and "--clip-on-cpu" not in cmd:
|
|
274
|
+
cmd.append("--clip-on-cpu")
|
|
275
|
+
if vae_on_cpu and "--vae-on-cpu" not in cmd:
|
|
276
|
+
cmd.append("--vae-on-cpu")
|
|
277
|
+
|
|
278
|
+
if offload_to_cpu:
|
|
279
|
+
if "--offload-to-cpu" not in cmd:
|
|
280
|
+
cmd.append("--offload-to-cpu")
|
|
281
|
+
elif target_backend == "cpu":
|
|
282
|
+
if "--offload-to-cpu" not in cmd:
|
|
283
|
+
cmd.append("--offload-to-cpu")
|
|
259
284
|
elif backend:
|
|
260
285
|
cmd.extend(["--backend", str(backend)])
|
|
261
286
|
elif is_adreno or target_backend in ("vulkan", "gpu"):
|
|
262
|
-
|
|
287
|
+
b_clip = "cpu" if clip_on_cpu else "vulkan0"
|
|
288
|
+
b_vae = "cpu" if vae_on_cpu else "vulkan0"
|
|
289
|
+
cmd.extend(["--backend", f"clip={b_clip},diffusion=vulkan0,vae={b_vae}"])
|
|
263
290
|
|
|
291
|
+
if flash_attn:
|
|
292
|
+
cmd.append("--diffusion-fa")
|
|
264
293
|
if vae_tiling:
|
|
265
294
|
cmd.append("--vae-tiling")
|
|
266
295
|
if sampling_method:
|
|
@@ -146,27 +146,10 @@ class LlamaCppAdapter(BaseAdapter):
|
|
|
146
146
|
**kwargs: Any,
|
|
147
147
|
) -> Dict[str, str]:
|
|
148
148
|
"""Provides verified execution environment adhering to Golden Link Order.
|
|
149
|
-
|
|
149
|
+
Inherits base adapter environment (proper LD_PRELOAD for libegl_shim, Mali flags, LD_LIBRARY_PATH)
|
|
150
|
+
without Gate 1 symbol pollution or unsafe system path injection.
|
|
150
151
|
"""
|
|
151
|
-
|
|
152
|
-
home = Path(os.environ.get("HOME", os.path.expanduser("~")))
|
|
153
|
-
std_llama_lib = home / ".local" / "share" / "ameva" / "current" / "llamacpp" / "lib"
|
|
154
|
-
legacy_llama_lib = home / ".termux-llama" / "current" / "lib"
|
|
155
|
-
|
|
156
|
-
lib_paths = []
|
|
157
|
-
if std_llama_lib.is_dir():
|
|
158
|
-
lib_paths.append(str(std_llama_lib))
|
|
159
|
-
elif legacy_llama_lib.is_dir():
|
|
160
|
-
lib_paths.append(str(legacy_llama_lib))
|
|
161
|
-
|
|
162
|
-
sys_lib64 = Path("/system/lib64")
|
|
163
|
-
if sys_lib64.is_dir():
|
|
164
|
-
lib_paths.append(str(sys_lib64))
|
|
165
|
-
|
|
166
|
-
env["LD_LIBRARY_PATH"] = ":".join(lib_paths)
|
|
167
|
-
# Ensure GGML_VULKAN_SKIP_CHECKS is never present
|
|
168
|
-
env.pop("GGML_VULKAN_SKIP_CHECKS", None)
|
|
169
|
-
return env
|
|
152
|
+
return super().get_execution_environment(base_env, **kwargs)
|
|
170
153
|
|
|
171
154
|
@classmethod
|
|
172
155
|
def _mutate_modality_attributes(
|
|
@@ -664,8 +664,17 @@ class SttAdapter(BaseAdapter):
|
|
|
664
664
|
base_env: dict[str, str] | None = None,
|
|
665
665
|
**kwargs: Any,
|
|
666
666
|
) -> dict[str, str]:
|
|
667
|
-
"""Provides verified execution environment adhering to Golden Link Order.
|
|
668
|
-
|
|
667
|
+
"""Provides verified execution environment adhering to Golden Link Order.
|
|
668
|
+
Strictly applies Zero-Collision Rule to purge Termux $PREFIX/lib from LD_LIBRARY_PATH,
|
|
669
|
+
preventing Android 15 Bionic linker symbol collisions (e.g. libunwindstack Xzs_Construct).
|
|
670
|
+
"""
|
|
671
|
+
env = super().get_execution_environment(base_env, **kwargs)
|
|
672
|
+
if "LD_LIBRARY_PATH" in env:
|
|
673
|
+
prefix = os.environ.get("PREFIX", "/data/data/com.termux/files/usr")
|
|
674
|
+
prefix_lib = f"{prefix}/lib"
|
|
675
|
+
parts = [p for p in env["LD_LIBRARY_PATH"].split(":") if p and p != prefix_lib]
|
|
676
|
+
env["LD_LIBRARY_PATH"] = ":".join(parts)
|
|
677
|
+
return env
|
|
669
678
|
|
|
670
679
|
@staticmethod
|
|
671
680
|
def bind(
|
|
@@ -189,12 +189,13 @@ class Doctor:
|
|
|
189
189
|
|
|
190
190
|
def quick_probe(self) -> bool:
|
|
191
191
|
p = self.profile
|
|
192
|
-
if not p.has_vulkan_loader:
|
|
193
|
-
return False
|
|
194
192
|
if p.hardware_hazard:
|
|
195
193
|
return False
|
|
196
194
|
if p.gpu_family in ("Unknown", "None", ""):
|
|
197
195
|
return False
|
|
196
|
+
# Android Termux can use Vulkan directly via KGSL/Mali driver node even if libvulkan loader is not in $PREFIX/lib
|
|
197
|
+
if not (p.has_vulkan_loader or p.has_kgsl_node or p.has_mali_node):
|
|
198
|
+
return False
|
|
198
199
|
return p.recommended_backend in ("vulkan", "vulkan_driver_only")
|
|
199
200
|
|
|
200
201
|
|
|
@@ -34,7 +34,7 @@ from .exceptions import (
|
|
|
34
34
|
|
|
35
35
|
logger = logging.getLogger("ameva_runtime.installer")
|
|
36
36
|
|
|
37
|
-
AMEVA_RUNTIME_GITHUB_REPO = "uno-km/ameva-runtime"
|
|
37
|
+
AMEVA_RUNTIME_GITHUB_REPO = "uno-km/ameva-runtime-releases"
|
|
38
38
|
GITHUB_RELEASE_LATEST = f"https://github.com/{AMEVA_RUNTIME_GITHUB_REPO}/releases/latest/download"
|
|
39
39
|
|
|
40
40
|
|
|
@@ -47,6 +47,8 @@ def get_release_base_url() -> str:
|
|
|
47
47
|
if custom_base := os.environ.get("AMEVA_RELEASE_BASE"):
|
|
48
48
|
return custom_base.rstrip("/")
|
|
49
49
|
if custom_tag := os.environ.get("AMEVA_RELEASE_TAG"):
|
|
50
|
+
if custom_tag.strip().lower() == "latest":
|
|
51
|
+
return f"https://github.com/{AMEVA_RUNTIME_GITHUB_REPO}/releases/latest/download"
|
|
50
52
|
tag = custom_tag if custom_tag.startswith("v") else f"v{custom_tag}"
|
|
51
53
|
return f"https://github.com/{AMEVA_RUNTIME_GITHUB_REPO}/releases/download/{tag}"
|
|
52
54
|
return f"https://github.com/{AMEVA_RUNTIME_GITHUB_REPO}/releases/download/v{__version__}"
|
|
@@ -306,7 +308,7 @@ NATIVE_ASSETS: Dict[str, AssetSpec] = {
|
|
|
306
308
|
"diffusion": AssetSpec(
|
|
307
309
|
name="diffusion",
|
|
308
310
|
filename="sd-cli-vulkan-android-arm64.tar.gz",
|
|
309
|
-
download_sha256="
|
|
311
|
+
download_sha256="2d268255e84a37eca8e3ea047f79f944d23068108307f509cfd5c28484b05737",
|
|
310
312
|
binary_relpath="sd-cli-vulkan",
|
|
311
313
|
canonical_name="sd-cli",
|
|
312
314
|
description="Stable Diffusion On-Device Vulkan CLI Engine",
|
|
@@ -665,9 +667,20 @@ class NativeAssetManager:
|
|
|
665
667
|
try:
|
|
666
668
|
resp = urllib.request.urlopen(req, timeout=60)
|
|
667
669
|
except urllib.error.HTTPError as http_err:
|
|
668
|
-
|
|
669
|
-
f"
|
|
670
|
-
|
|
670
|
+
if http_err.code == 404 and "latest/download" not in download_url:
|
|
671
|
+
fallback_url = f"https://github.com/{AMEVA_RUNTIME_GITHUB_REPO}/releases/latest/download/{spec.filename}"
|
|
672
|
+
print(f" -> [FALLBACK] Versioned tag returned 404. Attempting public latest release: {fallback_url} ...")
|
|
673
|
+
req_fb = urllib.request.Request(fallback_url, headers={"User-Agent": f"AMEVA-Installer/{__version__}"})
|
|
674
|
+
try:
|
|
675
|
+
resp = urllib.request.urlopen(req_fb, timeout=60)
|
|
676
|
+
except urllib.error.HTTPError:
|
|
677
|
+
raise AmevaLlamaAssetMissingError(
|
|
678
|
+
f"Release bundle unavailable: url={download_url}, status={http_err.code}"
|
|
679
|
+
) from http_err
|
|
680
|
+
else:
|
|
681
|
+
raise AmevaLlamaAssetMissingError(
|
|
682
|
+
f"Release bundle unavailable: url={download_url}, status={http_err.code}"
|
|
683
|
+
) from http_err
|
|
671
684
|
|
|
672
685
|
downloaded = 0
|
|
673
686
|
with resp, open(temp_dest, "wb") as out_f:
|