File size: 8,762 Bytes
d601f7c | 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 147 148 149 150 151 | // Brain: il modello linguistico con i suoi neuroni reali esposti.
// Osserva le attivazioni FFN (ffn_swiglu-L) di ogni strato durante il calcolo e applica
// gli interventi (spegnimento / amplificazione) prima che il resto della rete le legga.
#pragma once
#include <stdbool.h>
#include <stddef.h>
typedef struct Brain Brain;
typedef struct {
int n_layer;
int n_ff; // neuroni FFN per strato
long n_neurons; // n_layer * n_ff
int n_embd; // dimensione del flusso residuo
} BrainInfo;
// Area creata (neurogenesi): neuroni aggiunti alla rete, calcolati dentro il modello.
// Il neurone k legge l'ingresso FFN x del suo strato e, se si attiva, scrive nell'uscita FFN:
// a = tonic ? 1 : clamp((w_in·x - bias) * scale, 0, 1) uscita += gain * a * w_out
typedef struct {
int n; // neuroni
int *layer; // [n]
float *w_in; // [n][n_embd]
float *bias, *scale; // [n]
float *w_out; // [n][n_embd]
float gain;
bool enabled, tonic;
} BrainArea;
typedef enum { ROLE_SYSTEM, ROLE_USER, ROLE_ASSISTANT } Role;
// Perché si è fermata l'ultima generazione.
typedef enum { STOP_END, STOP_MAX, STOP_LOOP, STOP_USER } BrainStop;
typedef struct { Role role; const char *text; } ChatMsg;
typedef struct {
bool thinking; // ragionamento attivo
int think_budget; // massimo token di ragionamento (<= 0: nessun limite)
int max_tokens; // massimo token totali generati
float temperature; // <= 0: greedy (deterministico)
unsigned seed;
float repeat_penalty; // > 1 penalizza i token recenti (contro i loop); 0 o 1 = spenta
bool tools; // strumenti attivi: si ferma dopo </tool_call> e non scambia il codice per un loop
const unsigned char *image_rgb; // immagine allegata all'ultimo messaggio dell'utente (RGB, 3 byte per pixel)
int image_w, image_h;
} GenOpts;
// Chiamata per ogni frammento generato. thought = parte del ragionamento.
// Ritorna false per interrompere la generazione.
typedef bool (*brain_token_fn)(void *ud, const char *piece, bool thought);
// backend_dir: cartella con ggml-cuda.dll e ggml-cpu-*.dll (NULL = cartella dell'eseguibile).
// n_gpu_layers: strati caricati sulla GPU (999 = tutti).
Brain *brain_open(const char *model_path, int n_ctx, const char *backend_dir, int n_gpu_layers);
void brain_close(Brain *b);
// Visione: carica il proiettore delle immagini (neuronal-visione.gguf). Si chiama una volta; true se pronta.
bool brain_vision_open(Brain *b, const char *mmproj_path);
bool brain_has_vision(const Brain *b);
BrainInfo brain_info(const Brain *b);
// Attivazione dell'ultimo token calcolato: [n_layer][n_ff].
const float *brain_last_activation(const Brain *b);
// Accumulo di |a| per neurone su tutti i token calcolati tra begin e end (per la mappatura).
void brain_accum_begin(Brain *b);
const double *brain_accum(const Brain *b, long *n_tokens); // [n_layer][n_ff]
void brain_accum_end(Brain *b);
// Fa "leggere" un testo al modello senza generare. Ritorna i token letti o -1.
int brain_feed(Brain *b, const char *text);
// Conversazione. Ritorna i token generati o -1. answer riceve la risposta (senza ragionamento).
int brain_chat(Brain *b, const ChatMsg *msgs, int n_msgs, const GenOpts *opts,
brain_token_fn fn, void *ud, char *answer, size_t answer_cap);
// Interventi sui neuroni. factor: 0 = spento, 1 = normale, >1 amplificato, <0 invertito.
// Ogni chiamata è un'operazione annullabile. Ritorna il numero di neuroni modificati o -1.
int brain_set_neurons(Brain *b, int layer, const int *idx, int n, float factor);
// I k neuroni più attivi (|a|) dello strato, dall'ultima attivazione. Ritorna quanti.
// Da chiamare dal thread che esegue il modello (l'attivazione cambia durante il calcolo).
int brain_top_neurons(const Brain *b, int layer, int k, int *out);
// Indici dei k valori più grandi in modulo di a[0..n), in ordine decrescente. Ritorna quanti.
int top_abs(const float *a, int n, int k, int *out);
bool brain_undo(Brain *b);
void brain_reset(Brain *b);
// Neuroni modificati per strato (array di n_layer elementi). Ritorna il totale.
long brain_intervention_counts(Brain *b, int *per_layer);
float brain_neuron_factor(Brain *b, int layer, int idx);
// Elenco dei neuroni modificati (fino a cap). Ritorna quanti ne ha scritti.
int brain_intervention_list(Brain *b, int *layer, int *idx, float *factor, int cap);
// Autodiagnosi: sospende o riattiva tutti gli interventi manuali senza perderli.
void brain_interventions_enable(Brain *b, bool on);
BrainStop brain_last_stop(const Brain *b);
// Modifiche strutturali (macroaree eliminate o riconvertite): si sommano agli interventi ma non
// fanno parte di annulla/ripristina. idx NULL = tutti i neuroni dello strato. Ritorna quanti o -1.
int brain_struct_set(Brain *b, int layer, const int *idx, int n, float factor);
void brain_struct_clear(Brain *b);
// Esercitazione di infezione: fattore separato da tutto il resto (1 = sano). Ritorna true se è cambiato.
bool brain_infect_set(Brain *b, int layer, int idx, float factor);
float brain_infect_get(Brain *b, int layer, int idx);
void brain_infect_clear(Brain *b); // anche i neuroni delle aree
// Infezione di un neurone di un'area creata (k = indice nell'area). Ritorna true se è cambiato.
bool brain_area_infect(Brain *b, int id, int k, float factor);
// Attività media dei neuroni dell'area nell'ultimo accumulo (brain_accum_begin/end). Ritorna quanti o -1.
int brain_area_accum(Brain *b, int id, float *out, int cap);
// Cattura: somma per strato dell'ingresso FFN (x) e dell'uscita dello strato (l_out) su tutti i token.
void brain_capture_begin(Brain *b);
const double *brain_capture_x(const Brain *b, long *n_tokens); // [n_layer][n_embd]
const double *brain_capture_out(const Brain *b); // [n_layer][n_embd]
const float *brain_capture_last(const Brain *b); // [n_layer][n_embd] ingresso FFN dell'ultimo token
void brain_capture_end(Brain *b);
// Aree create. id scelto dal chiamante (stabile tra gli avvii). La brain copia i dati.
bool brain_area_add(Brain *b, int id, const BrainArea *a);
bool brain_area_update(Brain *b, int id, bool enabled, float gain);
bool brain_area_remove(Brain *b, int id);
// Attivazioni dell'ultimo token dei neuroni dell'area (fino a cap). Ritorna quanti o -1.
int brain_area_activation(Brain *b, int id, float *out, int cap);
// ---- Calcolo delegato ---------------------------------------------------------------------------------
// Lettura e generazione possono girare in un altro processo, su una GPU presa in prestito per pochi secondi.
// Interventi, aree e ogni dato letto dal programma restano qui: prima del calcolo viaggia lo stato dei neuroni,
// dopo tornano le attivazioni. Se il collegamento manca o cade si calcola qui, come sempre.
typedef struct {
void *ud;
// C'è un cervello remoto con almeno need_s secondi a disposizione? 1 sì, 0 no, -1 c'è ma il tempo non basta.
// request: se non c'è lo chiede e aspetta un po'.
int (*acquire)(void *ud, int need_s, bool request);
unsigned (*epoch)(void *ud); // cambia a ogni nuovo cervello remoto (mai 0)
bool (*send)(void *ud, const void *data, size_t len);
// Blocco ricevuto (da liberare) o NULL se è caduto o il tempo è scaduto. timeout_ms: 0 = solo se c'è già, < 0 = senza limite.
void *(*recv)(void *ud, size_t *len, int timeout_ms);
void (*drop)(void *ud); // chiude il collegamento
} BrainLink;
void brain_link_set(Brain *b, const BrainLink *l);
// Da chiamare ogni tanto da un altro thread: se il cervello remoto è fermo da idle_s secondi (o il suo tempo
// sta finendo) recupera i dati rimasti di là e lo congeda, così la GPU torna libera.
void brain_link_idle(Brain *b, double idle_s);
// Lato remoto: serve le richieste finché arriva il congedo o cade il collegamento (usa send e recv).
void brain_serve(Brain *b, const BrainLink *l, const char *mmproj_path);
// I k neuroni più attivi dello strato nell'ultimo token, i loro valori e la media di |a|. Ritorna quanti.
// Vale anche mentre il calcolo è delegato (fino a 32 neuroni).
int brain_layer_top(Brain *b, int layer, int k, int *idx, float *val, float *mean);
// OCR: il modello trascrive il testo di un'immagine (file jpg, png, bmp, gif...). Serve la visione (brain_vision_open).
// Ritorna i token scritti, -1 se la lettura è fallita, -2 se la visione non è disponibile, -3 se il file non è un'immagine.
int brain_ocr(Brain *b, const unsigned char *file, size_t len, char *out, size_t cap);
|