voice_audio_multi/include/engine/community_models/whistle_asr/graph.h
Fabio c36510c21e
Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
Initial import: audio.cpp with Orange Pi documentation
2026-11-04 19:05:22 +01:00

143 lines
6.2 KiB
C++

#pragma once
#include "engine/community_models/whistle_asr/assets.h"
#include "engine/framework/assets/tensor_source.h"
#include "engine/framework/core/backend_weight_store.h"
#include "engine/framework/core/module.h"
#include "engine/framework/modules/linear_module.h"
#include "engine/framework/modules/norm_modules.h"
#include <array>
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
struct ggml_tensor;
namespace engine::community_models::whistle_asr {
constexpr int kWhistleLayers = 8;
constexpr int64_t kWhistleDimension = 512;
constexpr int64_t kWhistleLanes = 4;
constexpr int64_t kWhistleHeads = 8;
constexpr int64_t kWhistleKvHeads = 2;
constexpr int64_t kWhistleQkDim = 48;
constexpr int64_t kWhistleVDim = 64;
// 30 s of 10 ms mel frames through three stride-2 stem stages.
constexpr int64_t kWhistleMaximumFrames = 375;
// Conditioned Hadamard MLP: three Kronecker-factored 512x512 products with
// learned diagonal scales and two fixed permutations between them.
struct WhistleHadamardWeights {
core::TensorValue d1;
core::TensorValue d2;
core::TensorValue d3;
core::TensorValue d4;
core::TensorValue b2;
modules::LinearWeights cond_v;
modules::LinearWeights cond_u;
// Kronecker factors stored as [out, in] for ggml_mul_mat.
core::TensorValue w1a;
core::TensorValue w1b;
core::TensorValue w2a;
core::TensorValue w2b;
core::TensorValue w3a;
core::TensorValue w3b;
};
// Manifold hyper-connection mixing across the four residual lanes.
struct WhistleMhcWeights {
modules::LinearWeights phi_pre;
modules::LinearWeights phi_post;
modules::LinearWeights phi_res;
core::TensorValue pre_bias;
core::TensorValue post_bias;
core::TensorValue res_bias;
float a_pre = 0.0f;
float a_post = 0.0f;
float a_res = 0.0f;
};
// Fixed tensors the shared graph helpers need. Per-row tensors are repeated for
// the largest number of rows (frames or decoder steps) one graph processes.
struct WhistleGraphConstants {
core::TensorValue permutation_1;
core::TensorValue permutation_2;
core::TensorValue lane_mean;
// Structural constants: ggml_mul_mat against these transposes small per-row
// matrices exactly, which the generic strided copy behind ggml_cont does slowly.
core::TensorValue transpose_4x4;
core::TensorValue identity_16;
core::TensorValue identity_32;
};
// Reads checkpoint tensors in their JAX layouts and uploads them in the shapes the
// framework modules expect. Layer-stacked tensors carry a leading [8] dimension.
class WhistleWeightLoader {
public:
WhistleWeightLoader(core::BackendWeightStore & store, const assets::TensorSource & source);
[[nodiscard]] std::vector<float> values(const std::string & name, std::vector<int64_t> shape, int layer = -1) const;
[[nodiscard]] float scalar(const std::string & name, int layer = -1) const;
core::TensorValue vector(const std::string & name, int64_t size, int layer = -1);
// Gemma-style RMS norm scale; GemmaRMSNormModule multiplies by 1 + scale.
modules::NormWeights norm(const std::string & name, int64_t size, int layer = -1);
// JAX kernels are [in, out]; LinearModule and ggml_mul_mat take [out, in].
core::TensorValue transposed(const std::string & name, int64_t in, int64_t out, int layer = -1);
modules::LinearWeights linear(const std::string & name, int64_t in, int64_t out, int layer = -1);
WhistleHadamardWeights hadamard(const std::string & prefix, int layer);
// The lane matching the layer index is the active lane; the others are pushed
// towards the sigmoid floor by a fixed logit offset folded into the biases.
WhistleMhcWeights mhc(const std::string & prefix, int layer);
WhistleGraphConstants constants(const WhistleAssets & assets, int64_t rows);
[[nodiscard]] core::BackendWeightStore & store() const noexcept { return store_; }
private:
core::TensorValue permutation(const std::array<uint16_t, 512> & permutation, int64_t rows);
core::TensorValue identity(int64_t size, int64_t rows);
core::BackendWeightStore & store_;
const assets::TensorSource & source_;
};
// Whistle-specific graph pieces over ggml [features, rows] activations, shared by
// the encoder graph and the decoder step graph.
class WhistleGraphOps {
public:
WhistleGraphOps(core::ModuleBuildContext & ctx, const WhistleGraphConstants & constants);
ggml_tensor * linear(ggml_tensor * input, const modules::LinearWeights & weights, int64_t in, int64_t out);
ggml_tensor * silu(ggml_tensor * input);
ggml_tensor * sigmoid(ggml_tensor * input);
ggml_tensor * softmax(ggml_tensor * input);
ggml_tensor * rms_norm(ggml_tensor * input, int64_t size);
// GemmaRMSNormModule: RMS norm times 1 + scale.
ggml_tensor * gemma_norm(ggml_tensor * input, const modules::NormWeights & weights, int64_t size);
// Per-head Gemma RMS norm over [heads * 48, rows], returned flat again.
ggml_tensor * head_norm(ggml_tensor * input, int64_t heads, const modules::NormWeights & weights);
// NeoX rotary embedding over [heads * 48, rows]; positions is I32[rows].
core::TensorValue rope(ggml_tensor * input, int64_t heads, ggml_tensor * positions);
ggml_tensor * hadamard(ggml_tensor * input, const WhistleHadamardWeights & weights);
// Wraps one block in the four-lane mixing. state is [4 * 512, rows]; block maps
// the mixed [512, rows] input to its [512, rows] output.
ggml_tensor * mhc(ggml_tensor * state, const WhistleMhcWeights & weights,
const std::function<ggml_tensor *(ggml_tensor *)> & block);
// Average of the four lanes, [512, rows].
ggml_tensor * lane_mean(ggml_tensor * state);
[[nodiscard]] core::ModuleBuildContext & context() const noexcept { return ctx_; }
private:
ggml_tensor * log_normalize_rows(ggml_tensor * x);
ggml_tensor * sinkhorn(ggml_tensor * logits);
ggml_tensor * identity_view(const core::TensorValue & identity, int64_t rows);
ggml_tensor * kronecker(ggml_tensor * input, const core::TensorValue & a, const core::TensorValue & b);
ggml_tensor * permute_features(ggml_tensor * input, const core::TensorValue & indices);
core::ModuleBuildContext & ctx_;
const WhistleGraphConstants & constants_;
};
} // namespace engine::community_models::whistle_asr