//! FFI Python (PyO3) — dividida por domínio (v0.10.0, r-35 §2). //! FFI Python (PyO3) do KHTST_RUST — todo o `#[pymodule]`, os //! `#[pyfunction]`/`#[pyclass]` e a cola Python (conversões, //! callbacks, demos) vivem AQUI desde a v0.9.0 (antes: lib.rs, //! ~105 kB — crítica "God Object" do agente Qwen3.8, r-34 §5). //! A lógica de domínio (src/*.rs) não importa pyo3: `cargo test //! --no-default-features` executa a suíte SEM linkar o Python. //! //! Regra da casa mantida: nenhuma funcionalidade da superfície //! Python foi removida — os mesmos símbolos são registrados no //! `nucleo_rust`. use pyo3::prelude::*; use crate::*; // ---- divisão SRP v0.10.0 (r-35 §2): submódulos + re-exports ---- mod calibracao; mod demos_qwen; mod fnh_arvore; mod jepa_treinos; mod moe; mod nlp_nlg; mod nucleo; mod pensamento_demos; mod som; mod treino_fases; // ---- itens mantidos no próprio mod.rs ---- /// Adaptador FFI→domínio (v0.9.0): embrulha um callable Python no tipo de /// domínio `treino::CallbackTreino` — `treino.rs` não importa pyo3. fn callback_treino_de_py(callback: Option>) -> treino::CallbackTreino { use std::sync::Arc; match callback { None => None, Some(c) => { let f: pyo3::Py = c.unbind(); let g: Arc = Arc::new(move |dados: &serde_json::Value| { pyo3::Python::with_gil(|py| { if let Ok(obj) = pythonize::pythonize(py, dados) { let _ = f.call1(py, (obj,)); } }); }); Some(g) } } } // =========================================================================== // v0.5.0 — suíte SOM 4D, suíte JEPA, Pensamento, telemetria robusta // =========================================================================== fn tensor_de_2d(dados: Vec>, dev: &candle_core::Device) -> candle_core::Result { let d = dados.first().map(|r| r.len()).unwrap_or(1).max(1); let n = dados.len(); let flat: Vec = dados.into_iter().flat_map(|r| r.into_iter().map(|x| x as f32).collect::>()).collect(); candle_core::Tensor::from_vec(flat, (n, d), dev) } // --------------------------------------------------------------------------- // v0.6.0 — verificador NCM (sem oráculo), fase C, MoE redirecionável, // acoplador duplex e autoajuste // --------------------------------------------------------------------------- /// Converte matriz f64 → Tensor (n, d) F32. fn tensor_f64_2d(v: &[Vec], dev: &candle_core::Device) -> candle_core::Result { let (n, d) = (v.len(), v.first().map(|l| l.len()).unwrap_or(0)); candle_core::Tensor::from_vec(v.iter().flatten().cloned().collect(), (n, d), dev) } fn py_err(e: candle_core::Error) -> pyo3::PyErr { pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")) } #[pymodule] fn nucleo_rust(m: &Bound<'_, PyModule>) -> PyResult<()> { pyo3_log::init(); m.add_function(wrap_pyfunction!(nucleo::versao, m)?)?; m.add_function(wrap_pyfunction!(nucleo::info_build, m)?)?; m.add_function(wrap_pyfunction!(nucleo::lint_config, m)?)?; m.add_function(wrap_pyfunction!(treino_fases::treinar_fase_a, m)?)?; m.add_function(wrap_pyfunction!(treino_fases::treinar_fase_b, m)?)?; m.add_function(wrap_pyfunction!(treino_fases::gerar_amostras, m)?)?; m.add_function(wrap_pyfunction!(nucleo::verificar_mascara, m)?)?; m.add_function(wrap_pyfunction!(nucleo::verificar_stiefel, m)?)?; // v0.10.0 — checkpoints atômicos com prova de integridade m.add_function(wrap_pyfunction!(nucleo::checkpoint_valido, m)?)?; m.add_function(wrap_pyfunction!(nucleo::checkpoint_manifesto, m)?)?; m.add_function(wrap_pyfunction!(nucleo::sha256_arquivo, m)?)?; // v0.5.0 — SOM 4D / JEPA / Pensamento m.add_function(wrap_pyfunction!(som::treinar_som4d, m)?)?; m.add_function(wrap_pyfunction!(som::treinar_gng, m)?)?; m.add_function(wrap_pyfunction!(som::treinar_hsom, m)?)?; m.add_function(wrap_pyfunction!(som::demo_tsom, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::treinar_jepa, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::treinar_lejepa, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::treinar_mcjepa, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::treinar_bjepa, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::demo_sonic_moe, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::demo_replay_ssm, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::classificar_erro, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::confianca_de_logits, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::projetar_ridge, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::demo_pensamento, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::patches_2d, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::patches_serie, m)?)?; m.add_function(wrap_pyfunction!(jepa_treinos::grupos_pontos, m)?)?; // v0.6.0 m.add_function(wrap_pyfunction!(calibracao::calibrar_verificador, m)?)?; m.add_function(wrap_pyfunction!(calibracao::demo_verificador_ncm, m)?)?; m.add_function(wrap_pyfunction!(treino_fases::treinar_fase_c, m)?)?; m.add_function(wrap_pyfunction!(moe::demo_moe_redirecionavel, m)?)?; m.add_function(wrap_pyfunction!(moe::jepa_com_moe, m)?)?; m.add_function(wrap_pyfunction!(moe::som_com_moe, m)?)?; m.add_function(wrap_pyfunction!(moe::demo_acoplador_duplo, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::demo_pensamento_ncm, m)?)?; m.add_function(wrap_pyfunction!(pensamento_demos::demo_autoajuste, m)?)?; m.add_function(wrap_pyfunction!(fnh_arvore::demo_fnh, m)?)?; m.add_function(wrap_pyfunction!(fnh_arvore::demo_quebra_cabeca, m)?)?; m.add_function(wrap_pyfunction!(fnh_arvore::quebra_cabeca_real, m)?)?; m.add_function(wrap_pyfunction!(nlp_nlg::demo_nlp_nlg, m)?)?; m.add_function(wrap_pyfunction!(som::demo_autoajuste_som, m)?)?; // v0.8.0 — análise/prova/teste das propostas Qwen3.8 m.add_function(wrap_pyfunction!(demos_qwen::demo_qwen_v080, m)?)?; // v0.9.0 — veredito executável das críticas Qwen3.8 (r-34) m.add_function(wrap_pyfunction!(demos_qwen::demo_criticas_v090, m)?)?; m.add_class::()?; m.add_class::()?; m.add_class::()?; #[cfg(feature = "ponte_async")] m.add_class::()?; m.add_class::()?; Ok(()) }