// neuronal-brain: il solo modello, per una GPU presa in prestito (ZeroGPU di Hugging Face). // Carica il cervello, riceve dal motore lo stato dei neuroni e le richieste di lettura e generazione, // rimanda indietro le parole e le attivazioni. Pagina, strumenti, voce e ricordi restano nel motore. // // Parla sullo standard input/output a blocchi [u32 lunghezza][dati]: un ponte (ponte.py) li porta // al motore su un WebSocket. Tutto quello che il programma stampa va sullo standard error. // // Uso: neuronal-brain MODELLO CARTELLA_BACKEND [PROIETTORE_IMMAGINI] [CONTESTO] #include "brain.h" #include #include #include #include #ifdef _WIN32 #include #include #include #else #include #include #endif typedef struct { int in, out; } Pipe; static bool read_all(int fd, void *buf, size_t n) { char *p = buf; while (n) { int r = (int)read(fd, p, (unsigned)(n < (1u << 20) ? n : (1u << 20))); if (r <= 0) return false; p += r; n -= (size_t)r; } return true; } static bool write_all(int fd, const void *buf, size_t n) { const char *p = buf; while (n) { int r = (int)write(fd, p, (unsigned)(n < (1u << 20) ? n : (1u << 20))); if (r <= 0) return false; p += r; n -= (size_t)r; } return true; } static bool readable(int fd) { #ifdef _WIN32 DWORD avail = 0; return PeekNamedPipe((HANDLE)_get_osfhandle(fd), NULL, 0, NULL, &avail, NULL) && avail > 0; #else struct pollfd p = {fd, POLLIN, 0}; return poll(&p, 1, 0) > 0; #endif } static bool pipe_send(void *ud, const void *data, size_t len) { Pipe *p = ud; uint32_t n = (uint32_t)len; return write_all(p->out, &n, 4) && write_all(p->out, data, len); } static void *pipe_recv(void *ud, size_t *len, int timeout_ms) { Pipe *p = ud; if (timeout_ms == 0 && !readable(p->in)) return NULL; uint32_t n = 0; if (!read_all(p->in, &n, 4) || n > (64u << 20)) return NULL; uint8_t *buf = malloc(n ? n : 1); if (!read_all(p->in, buf, n)) { free(buf); return NULL; } *len = n; return buf; } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "uso: %s MODELLO CARTELLA_BACKEND [PROIETTORE_IMMAGINI] [CONTESTO]\n", argv[0]); return 1; } // lo standard output porta i blocchi: quello che le librerie stampano finisce sullo standard error fflush(stdout); Pipe io = {0, dup(1)}; dup2(2, 1); #ifdef _WIN32 _setmode(io.in, _O_BINARY); _setmode(io.out, _O_BINARY); #endif const char *mmproj = argc > 3 && argv[3][0] ? argv[3] : NULL; int n_ctx = argc > 4 ? atoi(argv[4]) : 32768; Brain *b = brain_open(argv[1], n_ctx, argv[2], 999); if (!b) { fprintf(stderr, "neuronal-brain: impossibile caricare il modello sulla GPU\n"); return 2; } BrainLink l = {&io, NULL, NULL, pipe_send, pipe_recv, NULL}; brain_serve(b, &l, mmproj); brain_close(b); return 0; }