File size: 3,285 Bytes
06e4b6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! `python::nlp_nlg` — extraído do monólito na v0.10.0
//! (divisão SRP, crítica Qwen3.8 lote 3 nº 1; r-35 §2).

use super::*;


/// Demo/gate das unidades NLP/NLG sobre estados ocultos sintéticos
/// (nascimento neutro + gates + coerência de bigramas + especulativo).
#[pyfunction]
#[pyo3(signature = (d=32, t=6, seed=11))]
pub(crate) fn demo_nlp_nlg(py: Python, d: usize, t: usize, seed: u64) -> PyResult<PyObject> {
    let dev = candle_core::Device::Cpu;
    let mut rng = rng::RngDeterministico::novo(seed);
    let v: Vec<f32> = (0..2 * t * d).map(|_| rng.normal_padrao() as f32).collect();
    let h = candle_core::Tensor::from_vec(v, (2, t, d), &dev).map_err(py_err)?;
    // NLP: enriquecimento aditivo — neutro no nascimento
    let mut nlp = nlp::UnidadeNlp::nova(d, &dev).map_err(|e| {
        pyo3::exceptions::PyRuntimeError::new_err(format!("nlp (d%4): {e}"))
    })?;
    let h_enr = nlp.enriquecer(&h).map_err(py_err)?;
    let dif_nlp = (&h).sub(&h_enr).map_err(py_err)?.abs().map_err(py_err)?.max_all().map_err(py_err)?.to_scalar::<f32>().map_err(py_err)? as f64;
    // intenção
    let (intencoes, confs) = nlp.intencao_argmax(&h).map_err(py_err)?;
    // NLG: plano + condicionamento neutro + coerência
    let mut nlg = nlg::UnidadeNlg::nova(d, 4096, &dev).map_err(py_err)?;
    let plano = nlg.plano(&h).map_err(py_err)?;
    let p8 = candle_core::Tensor::randn(0f32, 1f32, (nlg::N_EIXOS_ESTILO,), &dev).map_err(py_err)?;
    let p01 = candle_nn::ops::sigmoid(&p8).map_err(py_err)?;
    let h_cond = nlg.condicionar(&h, Some(&p01)).map_err(py_err)?;
    let dif_nlg = (&h).sub(&h_cond).map_err(py_err)?.abs().map_err(py_err)?.max_all().map_err(py_err)?.to_scalar::<f32>().map_err(py_err)? as f64;
    // coerência: contexto observado vs candidato novo
    let ctx = vec![5u32, 6, 7, 8, 9];
    nlg.observar_contexto(&ctx);
    let s_mesmo = nlg.score_coerencia(&ctx);
    let s_novo = nlg.score_coerencia(&[50u32, 51, 52, 53]);
    // especulativo: aceitação típica + stats
    let mut espec = nlg::DecodificadorEspeculativo::novo(4, 0.95, 10);
    let logits = candle_core::Tensor::from_vec(vec![3.0f32, 0.2, 0.1, 0.05], (4,), &dev)
        .map_err(py_err)?;
    let mut aceites = 0usize;
    for _ in 0..30 {
        let (_, ok) = espec.verificar_e_corrigir(&logits, &[0, 1]).map_err(py_err)?;
        if ok {
            aceites += 1;
        }
    }
    let d_ = serde_json::json!({
        "versao": "nlp-nlg-0.7.0",
        "nlp_gate_medio": nlp.gate_medio,
        "nlp_dif_nascimento": dif_nlp,
        "nlp_intencoes": intencoes,
        "nlp_confiancas": confs,
        "nlg_plano_forma": plano.dims(),
        "nlg_dif_nascimento": dif_nlg,
        "nlg_coerencia_mesmo": s_mesmo,
        "nlg_coerencia_novo": s_novo,
        "espec_aceitacao_media": espec.stats.aceitacao_media,
        "espec_speedup": espec.stats.speedup_estimado,
        "espec_aceites_30": aceites,
        "gates": {
            "nlp_neutro": dif_nlp == 0.0,
            "nlg_neutro": dif_nlg == 0.0,
            "gate_medio_ok": (nlp.gate_medio - 0.119).abs() < 0.05,
            "coerencia_ok": s_mesmo > 0.9 && s_novo < 0.1,
            "espec_ok": espec.stats.aceitacao_media > 0.8,
        },
    });
    Ok(pythonize::pythonize(py, &d_)?.into())
}