#pragma once
#include "transcribe.h"
#include <cstdint>
#include <string>
#include <vector>
struct gguf_context;
struct ggml_context;
struct ggml_tensor;
namespace transcribe::qwen3_asr {
struct QwenAsrHParams {
int32_t enc_n_layers = 0;
int32_t enc_d_model = 0;
int32_t enc_n_heads = 0;
int32_t enc_ffn_dim = 0;
int32_t enc_num_mel_bins = 0;
int32_t enc_downsample_hidden = 0;
int32_t enc_output_dim = 0;
int32_t enc_max_source_positions = 0;
int32_t enc_n_window = 0;
int32_t enc_n_window_infer = 0;
int32_t enc_conv_chunksize = 0;
std::string enc_activation;
int32_t dec_n_layers = 0;
int32_t dec_hidden = 0;
int32_t dec_intermediate = 0;
int32_t dec_n_heads = 0;
int32_t dec_n_kv_heads = 0;
int32_t dec_head_dim = 0;
std::string dec_hidden_act; float dec_rms_norm_eps = 0.0f;
float dec_rope_theta = 0.0f;
int32_t dec_rope_mrope_section_t = 0;
int32_t dec_rope_mrope_section_h = 0;
int32_t dec_rope_mrope_section_w = 0;
bool dec_rope_mrope_interleaved = true;
int32_t dec_max_position_embeddings = 0;
bool dec_tie_word_embeddings = true;
int32_t dec_vocab_size = 0;
int32_t audio_token_id = 0; int32_t audio_start_token_id = 0; int32_t audio_end_token_id = 0;
int32_t bos_token_id = -1;
int32_t eos_token_id = -1;
int32_t pad_token_id = -1;
int32_t vocab_size = 0;
std::string fe_type;
int32_t fe_num_mels = 0;
int32_t fe_sample_rate = 0;
int32_t fe_n_fft = 0;
int32_t fe_win_length = 0;
int32_t fe_hop_length = 0;
std::string fe_window;
std::string fe_normalize;
float fe_dither = 0.0f;
float fe_pre_emphasis = 0.0f;
float fe_f_min = 0.0f;
float fe_f_max = 0.0f;
std::string fe_pad_mode;
bool fe_center = true;
std::string fe_mel_norm;
int32_t fe_chunk_length = 0;
int32_t fe_n_samples = 0;
int32_t fe_nb_max_frames = 0;
};
transcribe_status read_qwen3_asr_hparams(const gguf_context * gguf, QwenAsrHParams & hp);
struct QwenAsrEncSubsample {
ggml_tensor * conv0_w = nullptr; ggml_tensor * conv0_b = nullptr; ggml_tensor * conv1_w = nullptr; ggml_tensor * conv1_b = nullptr; ggml_tensor * conv2_w = nullptr; ggml_tensor * conv2_b = nullptr; ggml_tensor * conv_out = nullptr; };
struct QwenAsrEncBlock {
ggml_tensor * norm_attn_w = nullptr; ggml_tensor * norm_attn_b = nullptr;
ggml_tensor * attn_q_w = nullptr;
ggml_tensor * attn_q_b = nullptr;
ggml_tensor * attn_k_w = nullptr;
ggml_tensor * attn_k_b = nullptr;
ggml_tensor * attn_v_w = nullptr;
ggml_tensor * attn_v_b = nullptr;
ggml_tensor * attn_out_w = nullptr;
ggml_tensor * attn_out_b = nullptr;
ggml_tensor * norm_ffn_w = nullptr; ggml_tensor * norm_ffn_b = nullptr;
ggml_tensor * fc1_w = nullptr; ggml_tensor * fc1_b = nullptr;
ggml_tensor * fc2_w = nullptr; ggml_tensor * fc2_b = nullptr;
};
struct QwenAsrEncHead {
ggml_tensor * ln_post_w = nullptr;
ggml_tensor * ln_post_b = nullptr;
ggml_tensor * proj1_w = nullptr; ggml_tensor * proj1_b = nullptr;
ggml_tensor * proj2_w = nullptr; ggml_tensor * proj2_b = nullptr;
};
struct QwenAsrDecEmbed {
ggml_tensor * token_w = nullptr; };
struct QwenAsrDecBlock {
ggml_tensor * norm_attn_w = nullptr; ggml_tensor * norm_ffn_w = nullptr; ggml_tensor * attn_q_w = nullptr; ggml_tensor * attn_k_w = nullptr; ggml_tensor * attn_v_w = nullptr; ggml_tensor * attn_o_w = nullptr; ggml_tensor * attn_q_norm = nullptr; ggml_tensor * attn_k_norm = nullptr; ggml_tensor * ffn_gate_w = nullptr; ggml_tensor * ffn_up_w = nullptr; ggml_tensor * ffn_down_w = nullptr; ggml_tensor * ffn_gate_up_w = nullptr; };
struct QwenAsrDecFinal {
ggml_tensor * norm_w = nullptr; };
struct QwenAsrWeights {
QwenAsrEncSubsample enc_subsample;
std::vector<QwenAsrEncBlock> enc_blocks;
QwenAsrEncHead enc_head;
QwenAsrDecEmbed dec_embed;
std::vector<QwenAsrDecBlock> dec_blocks;
QwenAsrDecFinal dec_final;
};
transcribe_status build_qwen3_asr_weights(ggml_context * ctx_meta, const QwenAsrHParams & hp, QwenAsrWeights & weights);
}