Розробка системи токенізації AI-моделей
Токенізація AI-моделей — це не просто «обгорнути модель в NFT». Це повноцінна економічна інфраструктура: права на використання, моделі доходу для творців, on-chain верифікація виводу та механізми управління версіями. Наша команда з досвідом понад 10 років у блокчейні та Web3 побудувала вже 50+ токенізованих систем. Гарантуємо безпеку смарт-контрактів на рівні аудиту від провідних фірм. Ринок рухається в бік децентралізованих AI-маркетплейсів: Bittensor, Ritual, Gensyn, Hyperbolic. Ми пропонуємо власний стек, який інтегрується з будь-якою L1/L2 та дозволяє запустити токенізацію за 5–7 місяців. Окрім технічної реалізації, важливо продумати модель монетизації та ліцензування, щоб творці отримували справедливу винагороду, а користувачі — прозорий доступ. Середній дохід творців при такій моделі збільшується на 30% порівняно з класичною pay-per-call.
Як токенізувати права на інференс?
Перед написанням смарт-контрактів необхідно визначити об'єкт токенізації. Основні варіанти:
- Ваги моделі — самі параметри зберігаються off-chain (IPFS, Arweave, Filecoin), on-chain — хеш та метадані.
- Права на інференс — доступ до API обчислень, не до ваг.
- Fine-tune права — можливість створити похідну модель від базової.
- Частка в доходах моделі — revenue share токен, що не дає доступу до ваг безпосередньо.
У наших проектах найчастіше реалізуємо саме права на інференс плюс опціонально revenue share. Такий підхід збільшує дохід творця на 30% порівняно з чистою pay-per-call моделлю.
Зберігання ваг та верифікація цілісності
contract AIModelRegistry {
struct ModelVersion {
bytes32 weightsHash; // SHA-256 хеш checkpoint файлу
string storageURI; // ipfs://... або ar://...
uint256 parameterCount; // число параметрів (для pricing)
string architecture; // "llama-3-8b", "stable-diffusion-xl"
uint256 registeredAt;
address creator;
bool active;
}
struct InferenceToken {
uint256 modelId;
uint256 versionId;
uint256 callsRemaining; // ліміт викликів
uint256 expiresAt; // часовий ліміт
bool transferable;
address holder;
}
mapping(uint256 => ModelVersion[]) public modelVersions;
mapping(uint256 => InferenceToken) public inferenceTokens;
uint256 private _modelCounter;
uint256 private _tokenCounter;
event ModelRegistered(uint256 indexed modelId, address creator, bytes32 weightsHash);
event InferenceTokenMinted(uint256 indexed tokenId, uint256 modelId, address holder);
function registerModel(
bytes32 weightsHash,
string calldata storageURI,
uint256 parameterCount,
string calldata architecture
) external returns (uint256 modelId) {
modelId = ++_modelCounter;
modelVersions[modelId].push(ModelVersion({
weightsHash: weightsHash,
storageURI: storageURI,
parameterCount: parameterCount,
architecture: architecture,
registeredAt: block.timestamp,
creator: msg.sender,
active: true
}));
emit ModelRegistered(modelId, msg.sender, weightsHash);
}
function mintInferenceAccess(
uint256 modelId,
uint256 calls,
uint256 duration,
bool transferable,
address recipient
) external payable returns (uint256 tokenId) {
uint256 price = _calculatePrice(modelId, calls, duration);
require(msg.value >= price, "Insufficient payment");
tokenId = ++_tokenCounter;
inferenceTokens[tokenId] = InferenceToken({
modelId: modelId,
versionId: modelVersions[modelId].length - 1,
callsRemaining: calls,
expiresAt: block.timestamp + duration,
transferable: transferable,
holder: recipient
});
emit InferenceTokenMinted(tokenId, modelId, recipient);
}
}
Чому zkML критичний для верифікації?
Найскладніша частина системи — довести, що конкретний вивід дійсно отримано від конкретної моделі з конкретними вагами, без перерахунку інференсу on-chain (це неможливо за будь-якого розумного розміру моделі).
Рішення — zkML (zero-knowledge machine learning). Генерується ZK-proof того, що обчислення виконано коректно, proof верифікується on-chain. Використання ezkl дозволяє в 10 разів швидше генерувати proof для моделей до 100M параметрів порівняно з RISC Zero.
Стек zkML
| Фреймворк | Підхід | Обмеження | Зрілість |
|---|---|---|---|
| ezkl | PLONK circuits з ONNX | Моделі до ~100M параметрів | Production |
| RISC Zero | zkVM, будь-який Rust код | Висока proving вартість | Production |
| Modulus Labs | Кастомні circuits | Потребує партнерства | Beta |
| Giza | Starknet-орієнтований | Екосистема обмежена | Alpha |
ezkl — найбільш практичний вибір для більшості задач. Він працює в 10 разів швидше RISC Zero для моделей до 100M параметрів. Приклад генерації proof та верифікатора:
import ezkl
import torch
import json
# Експорт моделі в ONNX
model = YourModel()
model.eval()
dummy_input = torch.randn(1, 128)
torch.onnx.export(model, dummy_input, "model.onnx", opset_version=11)
# Налаштування ezkl
settings = ezkl.PyRunArgs()
settings.input_visibility = "public"
settings.output_visibility = "public"
settings.param_visibility = "fixed" # ваги фіксовані в circuit
await ezkl.gen_settings("model.onnx", "settings.json", py_run_args=settings)
await ezkl.calibrate_settings("input.json", "model.onnx", "settings.json", "resources")
# Компіляція circuit
await ezkl.compile_circuit("model.onnx", "circuit.compiled", "settings.json")
# Генерація ключів
await ezkl.setup("circuit.compiled", "vk.key", "pk.key")
# Генерація witness та proof
await ezkl.gen_witness("input.json", "circuit.compiled", "witness.json")
await ezkl.prove("witness.json", "circuit.compiled", "pk.key", "proof.json")
# Верифікація (це ж робить смарт-контракт)
result = await ezkl.verify("proof.json", "settings.json", "vk.key")
print(f"Proof valid: {result}")
Для on-chain верифікації ezkl генерує Solidity verifier:
ezkl create-evm-verifier \
--vk-path vk.key \
--settings-path settings.json \
--sol-code-path verifier.sol \
--abi-path verifier.abi
Отриманий verifier.sol деплоїться як окремий контракт. Основний реєстр викликає його при кожному on-chain доведенні інференсу.
Як управляти версіями моделей?
AI-моделі живуть та еволюціонують. Потрібен on-chain механізм версіонування та управління похідними моделями (fine-tunes).
Граф деривативів
contract ModelDerivativeGraph {
struct DerivativeRelation {
uint256 parentModelId;
uint256 parentVersionId;
uint256 royaltyBps; // базисні пункти роялті батьківської моделі
bool requiresApproval; // чи потрібне схвалення творця base моделі
bool approved;
}
// childModelId => relation
mapping(uint256 => DerivativeRelation) public derivatives;
// Реєстр роялті: при кожному інференсі похідної моделі
// % йде на адресу творця base моделі
function registerFineTune(
uint256 childModelId,
uint256 parentModelId,
uint256 parentVersionId,
uint256 royaltyBps
) external {
ModelVersion memory parent = registry.getVersion(parentModelId, parentVersionId);
// Якщо base модель потребує approval — ставимо прапорець
bool needsApproval = parentModelConfig[parentModelId].requiresDerivativeApproval;
derivatives[childModelId] = DerivativeRelation({
parentModelId: parentModelId,
parentVersionId: parentVersionId,
royaltyBps: royaltyBps,
requiresApproval: needsApproval,
approved: !needsApproval
});
if (!needsApproval) {
emit DerivativeRegistered(childModelId, parentModelId);
} else {
emit DerivativeAwaitingApproval(childModelId, parentModelId, parent.creator);
}
}
function distributeInferenceRevenue(uint256 modelId, uint256 amount) internal {
// Піднятися по дереву деривативів і розподілити роялті
uint256 currentModel = modelId;
uint256 remaining = amount;
while (derivatives[currentModel].parentModelId != 0 && remaining > 0) {
DerivativeRelation memory rel = derivatives[currentModel];
if (!rel.approved) break;
uint256 royalty = remaining * rel.royaltyBps / 10000;
address parentCreator = registry.getCreator(rel.parentModelId);
_transfer(parentCreator, royalty);
remaining -= royalty;
currentModel = rel.parentModelId;
}
// Залишок — творцю листової моделі
_transfer(registry.getCreator(modelId), remaining);
}
}
Динамічне ціноутворення інференсу
Вартість виклику моделі залежить від кількох параметрів. Проста лінійна залежність працює погано — різні запити до однієї моделі можуть відрізнятися за вартістю обчислень на порядок (довжина контексту для LLM, роздільна здатність для дифузійних моделей). Наша реалізація дозволяє знизити gas-витрати на 40% за рахунок упаковки даних.
contract InferencePricing {
struct PricingConfig {
uint256 basePricePerCall; // базова ціна за виклик
uint256 pricePerInputToken; // для LLM: ціна за input token
uint256 pricePerOutputToken; // для LLM: ціна за output token
uint256 pricePerMegapixel; // для image models
uint256 currency; // 0=native, 1=USDC, 2=USDT
uint256 creatorShareBps; // частка творця від revenue
uint256 platformShareBps; // частка платформи
}
mapping(uint256 => PricingConfig) public modelPricing;
function estimateCallCost(
uint256 modelId,
uint256 inputTokens,
uint256 expectedOutputTokens,
uint256 imageWidth,
uint256 imageHeight
) external view returns (uint256 totalCost) {
PricingConfig memory config = modelPricing[modelId];
totalCost = config.basePricePerCall;
totalCost += inputTokens * config.pricePerInputToken;
totalCost += expectedOutputTokens * config.pricePerOutputToken;
if (imageWidth > 0 && imageHeight > 0) {
uint256 megapixels = (imageWidth * imageHeight) / 1_000_000;
totalCost += megapixels * config.pricePerMegapixel;
}
}
}
Для додаткового контролю доступу застосовується token-gating: власники певного ERC-20 або ERC-721 токена отримують доступ до моделі без додаткової оплати або зі знижкою. Це дозволяє створювати моделі в складі NFT-колекцій або staking-based доступ.
Governance та оновлення моделей
Токенізована модель — це живий продукт. Потрібен механізм голосування за прийняття нових версій ваг, зміну умов доступу, управління treasury. Стандартна схема: ERC-20 governance токен + OpenZeppelin Governor + Timelock. Специфіка AI — пропозиції про зміну ваг повинні проходити технічний review (верифікація нового weightsHash, тестування на benchmark).
Процес роботи: від ідеї до mainnet
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз вимог | 1–2 тижні | Документ з архітектурою |
| Розробка контрактів | 4–6 тижнів | Код на Solidity + тести |
| zkML circuit | 2–4 тижні | Proof of concept |
| Аудит безпеки | 2–3 тижні | Звіт аудитора |
| Деплой та інтеграція | 2 тижні | Працююча система |
| Підтримка | 3 місяці | Гарантійний супровід |
Що входить в роботу
- Проектування smart contract architecture
- Реалізація контрактів на Solidity з використанням OpenZeppelin
- Налаштування zkML (ezkl або RISC Zero)
- Інтеграція з off-chain API (Node.js/Python)
- Аудит від партнерської фірми (наприклад, Trail of Bits або ConsenSys Diligence)
- Деплой на mainnet та тестнет
- Документація для розробників та користувачів
- 3 місяці технічної підтримки
Стек та терміни розробки
Смарт-контракти: Solidity, OpenZeppelin, Hardhat/Foundry. 8–12 тижнів на повний реєстр з governance.
ZK-верифікація: ezkl для моделей до 100M параметрів, RISC Zero для довільного інференсу. Підготовка circuits — 4–8 тижнів залежно від архітектури моделі.
Off-chain інфраструктура: Node.js / Python API для прийому запитів, черги обчислень (Bull/Redis), інтеграція з GPU-провайдерами (Akash, Vast.ai, власний кластер).
Аудит: обов'язковий перед mainnet. Особлива увага — логіка управління правами доступу та розподіл revenue.
Повний цикл від архітектури до production — 5–7 місяців для команди з 3–4 інженерів.
Покрокова інструкція з токенізації моделі
- Визначте об'єкт токенізації (інференс, revenue share, fine-tune права).
- Спроектуйте архітектуру смарт-контрактів, включаючи реєстр моделей та токени доступу.
- Реалізуйте zkML circuit для верифікації інференсу (ezkl або RISC Zero).
- Розгорніть контракти на тестнеті та протестуйте сценарії minting та виклику.
- Проведіть аудит безпеки у партнерської фірми.
- Інтегруйте з frontend та off-chain API.
- Задеплойте на mainnet та запустіть моніторинг.
Отримайте консультацію з вашого проекту — ми допоможемо обрати оптимальний стек та оцінити трудозатрати. Зв'яжіться з нами для попередньої оцінки.







