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())
}
|