File size: 4,060 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
// 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 <stdbool.h>
#include <stdint.h>
#include <time.h>

#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);