// Memoria a gruppi di neuroni. // // Ogni neurone ha un indirizzo (id = strato * n_ff + indice) e appartiene a un gruppo di 128 neuroni // dello stesso strato. Ogni gruppo ha 128 bit (16 byte) sul disco: un file per strato // (strato_LL.bin), il gruppo g occupa i byte [16*g, 16*g+16) del file del suo strato. // // Salvare un'informazione: il cervello legge il testo, si misura quanto ogni gruppo si accende rispetto // al normale, e i byte del testo vengono scritti nei gruppi liberi più accesi. La mappa (mappa.txt) // registra dove sta ogni informazione e la sua "impronta" di attivazione: il navigatore. // Ricordare: il cervello legge la domanda, il navigatore confronta i gruppi accesi con le impronte, // va a leggere i bit dei gruppi giusti e ricompone il testo. #pragma once #include #include #include #include "atlas.h" #include "brain.h" #include "sbuf.h" #define MEM_GROUP 128 // neuroni per gruppo (2^7) #define MEM_SLOT 16 // byte per gruppo = 128 bit #define MEM_KEY 512 // gruppi nell'impronta di un ricordo #define MEM_MAX_TEXT 4096 #define MEM_EMB_LAYERS 1 // strati letti dal navigatore (scelto in laboratorio: 12/12 domande giuste) typedef struct { int id; char title[96]; int len; // byte del testo uint32_t crc; // per verificare la ricostruzione time_t t; int n_groups; // gruppi che custodiscono i byte, in ordine int *groups; int n_key; // impronta: gruppi più accesi e quanto int key_g[MEM_KEY]; float key_w[MEM_KEY]; float *emb; // impronta per il navigatore: stato interno sull'ultima parola (normalizzato) } Memory; typedef struct { char dir[1024]; int n_layer, n_ff, per_layer, n_groups; int *owner; // [n_groups] id del ricordo che occupa il gruppo, 0 = libero Memory *mems; int n_mems, cap_mems, next_id; float *mu; // [n_layer] attività normale di ogni strato float *bg_mu, *bg_sd; // [n_groups] attività normale di ogni gruppo e sua variabilità int n_embd, emb_dim; // dimensione dello stato interno e dell'impronta int emb_layer[MEM_EMB_LAYERS]; float *emb_mu, *emb_sd; // [emb_dim] stato interno normale } MemoryStore; bool mem_open(MemoryStore *m, const char *dir, int n_layer, int n_ff, int n_embd); void mem_set_baseline(MemoryStore *m, const Atlas *a); // Comportamento normale di ogni gruppo, misurato con la stessa formula del navigatore sui testi dell'atlante. void mem_set_background(MemoryStore *m, Brain *b, const Atlas *a); // Il riferimento calcolato da mem_set_background, su disco: rifarlo vuol dire rileggere tutti gli stimoli // (minuti senza GPU). key è quella della mappa: vale finché modello e stimoli sono gli stessi. bool mem_background_save(const MemoryStore *m, const char *path, const char *key); bool mem_background_load(MemoryStore *m, const char *path, const char *key); void mem_close(MemoryStore *m); // Quanto si accende ogni gruppo (rispetto al normale) mentre il cervello legge text. vec: [n_groups]. // emb (facoltativo): impronta per il navigatore, emb_dim valori già normalizzati. bool mem_activation(MemoryStore *m, Brain *b, const char *text, float *vec, float *emb); int mem_add(MemoryStore *m, Brain *b, const char *title, const char *text, char *err, size_t cap); // id o -1 bool mem_delete(MemoryStore *m, int id); // Ricompone il testo dai bit dei gruppi. Ritorna una stringa da liberare, NULL se danneggiato. char *mem_read(MemoryStore *m, const Memory *mem); // Navigatore: i ricordi più vicini alla domanda (score 0..1). Ritorna quanti (al massimo max). int mem_recall(MemoryStore *m, const float *qemb, int *ids, float *scores, int max); Memory *mem_find(MemoryStore *m, int id); long mem_used_groups(const MemoryStore *m); void mem_json(MemoryStore *m, SBuf *o);