File size: 6,771 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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | //! 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<pyo3::Bound<'_, pyo3::PyAny>>) -> treino::CallbackTreino {
use std::sync::Arc;
match callback {
None => None,
Some(c) => {
let f: pyo3::Py<pyo3::PyAny> = c.unbind();
let g: Arc<dyn Fn(&serde_json::Value) + Send + Sync> =
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<Vec<f64>>, dev: &candle_core::Device) -> candle_core::Result<candle_core::Tensor> {
let d = dados.first().map(|r| r.len()).unwrap_or(1).max(1);
let n = dados.len();
let flat: Vec<f32> = dados.into_iter().flat_map(|r| r.into_iter().map(|x| x as f32).collect::<Vec<_>>()).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<f64>], dev: &candle_core::Device) -> candle_core::Result<candle_core::Tensor> {
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::<nucleo::BpePy>()?;
m.add_class::<nucleo::ConfigPy>()?;
m.add_class::<nucleo::PonteDuplaPy>()?;
#[cfg(feature = "ponte_async")]
m.add_class::<nucleo::PonteAsyncPy>()?;
m.add_class::<fnh_arvore::ArvorePesosPy>()?;
Ok(())
}
|