// silkie_speak.sy -- SILKIE SPEAKS IN SCYLA.
// Aislinn McCubbins, April 2026

fn main() {
    println("=== SILKIE SPEAKS ===")

    let n = load_model("examples/silkie_full.safetensors")
    let ns = create_neuron_stack(1, 512, 64)
    let cs = create_cascade()
    let ts = load_tokenizer("examples/silkie_tokenizer.json")
    println("Loaded. Generating...")

    let embed_w = model_get("token_embedding.weight")

    // Start with prompt tokens (pre-encoded: "Hello" = 3591, "Silkie" = 1207)
    let generated = tensor_from_ints(3591, 1207)
    let generated = t_reshape(generated, 1, 2)

    // Generate 15 tokens
    for step in 0..15 {
        // Flatten to 1D for embedding lookup
        let num_tokens = 2 + step
        let flat_ids = t_reshape(generated, num_tokens)
        let x = embedding_lookup(embed_w, flat_ids)
        let x = t_reshape(x, 1, num_tokens, 512)

        // Run 8 transformer layers (fused)
        for layer_idx in 0..4 {
            let prefix = "layers." + layer_idx
            let x = transformer_block(
                x,
                model_get(prefix + ".attention.in_proj_weight"),
                model_get(prefix + ".attention.in_proj_bias"),
                model_get(prefix + ".attention.out_proj.weight"),
                model_get(prefix + ".attention.out_proj.bias"),
                model_get(prefix + ".ff.0.weight"),
                model_get(prefix + ".ff.0.bias"),
                model_get(prefix + ".ff.3.weight"),
                model_get(prefix + ".ff.3.bias"),
                model_get(prefix + ".norm1.weight"),
                model_get(prefix + ".norm1.bias"),
                model_get(prefix + ".norm2.weight"),
                model_get(prefix + ".norm2.bias"), 8)
        }

        let x = neuron_stack_forward(x)
        let cascade_out = cascade_forward(x)
        let x = x + cascade_out

        for layer_idx in 4..8 {
            let prefix = "layers." + layer_idx
            let x = transformer_block(
                x,
                model_get(prefix + ".attention.in_proj_weight"),
                model_get(prefix + ".attention.in_proj_bias"),
                model_get(prefix + ".attention.out_proj.weight"),
                model_get(prefix + ".attention.out_proj.bias"),
                model_get(prefix + ".ff.0.weight"),
                model_get(prefix + ".ff.0.bias"),
                model_get(prefix + ".ff.3.weight"),
                model_get(prefix + ".ff.3.bias"),
                model_get(prefix + ".norm1.weight"),
                model_get(prefix + ".norm1.bias"),
                model_get(prefix + ".norm2.weight"),
                model_get(prefix + ".norm2.bias"), 8)
        }

        // Get logits for last position
        let x = layer_norm(x, model_get("layers.0.norm1.weight"), model_get("layers.0.norm1.bias"))
        let logits = matmul(x, transpose(embed_w))
        let logits_2d = t_reshape(logits, num_tokens, 4100)
        let last_logits = t_slice(logits_2d, 0, num_tokens - 1, num_tokens)

        // Sample next token (top-k = 50)
        let masked = topk_mask(last_logits, 50)
        let probs = softmax(masked)
        let next_token = t_multinomial(probs)

        // Append
        let generated = t_cat(generated, t_reshape(next_token, 1, 1))
        println("  token " + step + ": " + tensor_sum(next_token))
    }

    println("")
    println("SILKIE SAYS:")
    let flat_out = t_reshape(generated, 17)
    println(detokenize(flat_out))
    println("")
    println("=== SILKIE HAS SPOKEN ===")
}
