File size: 3,023 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
// 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#include <windows.h>
#else
#include <poll.h>
#include <unistd.h>
#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;
}