antimatter15 / alpaca.cpp

Locally run an Instruction-Tuned Chat-Style LLM
MIT License
10.25k stars 910 forks source link

Change buffer size of scanf to bigger value #119

Open progressionnetwork opened 1 year ago

progressionnetwork commented 1 year ago
          Change

https://github.com/antimatter15/alpaca.cpp/blob/c5ae5d08a56b82c17ef8121bc01221924576ad28/chat.cpp#L1044-L1047 to

                    char buf[16384] = {0};
                    int n_read;
                    if(params.use_color) printf(ANSI_BOLD ANSI_COLOR_GREEN);
                    if (scanf("%16383[^\n]%n%*c", buf, &n_read) <= 0) {

🤦‍♂️🤦‍♂️🤦‍♂️

Originally posted by @aleksusklim in https://github.com/antimatter15/alpaca.cpp/issues/97#issuecomment-1479062604

aleksusklim commented 1 year ago

It is not sufficient to do this without doing more adequate handling of interactive mode. I don't have enough knowledge of the current code to propose major changes, nor do I have time to study it.

Still, I had some discussion about this project, but it was posted in Russian chat. I'm not up to proposing PR here, or even creating a correct Issue (since I would have to double-check everything, but I don't even have a compiler installed!) All I can do is to share my thoughts; it is Russian, but Google Translate converts this to English quite fine:

Sorry for reposting in Russian *** > а этот фикс потом ничего не сломает случайно? > или поживём — увидим? :D Ну 16 килобайт на стеке выделил, подумаешь. Так-то, задачу чтения бесконечного числа символов надо по-другому решать, но само поведение терминала между разными операционками в этом плане разнится. Но хотя бы если будет вылетать – то уже не из-за глупости в коде! Хотя я неправильно посчитал, 16 килобайт мало. У нас-то контекст модели в токенах идёт, и если их 4096 – то это может быть и больше 16 килобайт будет… > Да дай 16 мегабайт, жалко что ли Э-э, дефолтный размер стека под виндой – один мегабайт!! Но если сделать через malloc – то можно хоть гигабайт на куче выделить. *** ``` main: mem per token = 14368644 bytes main: load time = 37698.25 ms main: sample time = 253.38 ms main: predict time = 994088.25 ms / 570.33 ms per token main: total time = 1505236.38 ms ``` – Да почему она вылетает сама по себе!? Оригинал тоже так делал. *** ``` // we may want to slide the input window along with the context, but for now we restrict to the context length int remaining_tokens = model.hparams.n_ctx - embd_inp.size(); while (remaining_tokens > 0) { ``` Не понял, они только 2048 токенов выводят и выходят что ли? *** ``` // default hparams (LLaMA 7B) struct llama_hparams { int32_t n_ctx = 512; // this is provided as user input? ``` – «Ты у меня спрашиваешь?» *** Длинные промпты с фиксом chat.exe Но я не могу сказать, что оно работает «как надо», потому что, во-первых, как будто бы очень долго генерирует ответ, если на входе много текста; во-вторых, оно само закрывается после скольких-то выданных токенов; и в-третьих, если написать `-c 9999999` то крашится после старта; сейчас я написал `-c 8192` и получил как будто бы нерелевантный ответ. *** По-моему я догадался, в чём причина. Кажется, для модели один «прогон» либо даёт на выходе новый токен, либо всасывает один токен промпта. То есть, сначала она работает в режиме чтения и впитывает промпт в себя, а потом переключается в режим записи и выплёвывает токены на выход. Получается, что чем длиннее с ней диалог – тем дольше ждать каждый раз ответа, потому что она должна переварить все исходные и новые тексты заново, с той же скоростью, с какой она генерирует их… Тогда у меня два вопроса: 1. Можно ли переключить модель обратно в режим чтения после режима записи? Так, чтобы это было равносильно чтению промпта и всего того, что она же и написала только что сама. 2. Можно ли сохранить текущее состояние модели так, чтобы в любой момент откатиться обратно к нему и продолжить с него, без необходимости физически прогонять весь приведший к нему текст? Я думаю, что ответ на оба вопроса – положительный. И если это действительно так, то архитектуру chat.exe надо переделывать! Workflow: 1) Задаём сид / стираем память. 2) Пользователь вводит промпт, отправляем текст на вход модели. 3) Сохраняем состояние модели. 4) Модель дополняет токенами до конца текста (когда она хочет остановиться сама) или до первого переноса строки (опционально). 5) Показываем вывод модели пользователю и ждём его резолюции. Варианты: • Ему не понравилось, он просит перегенерировать – восстанавливаем состояние, изменяем сид и перезапускаем пункт 4. • Ему понравилось, но он хочет больше – повторяем пункт 5 как есть. • Он доволен и хочет просто сделать свой ход – переходим к пункту 2. • Пользователь решил отредактировать вывод модели и ввести свой следующий текст – восстанавливаем состояние и тоже переходим к пункту 2. • Пользователь всегда может перейти к пункту 1 с новым сидом без перезапуска программы. Также, запоминать состояние можно не после ввода промпта пользователем, а до этого – чтобы дать возможность «быстро» отредактировать свой последний текст; но тогда, каждая перегенерация будет проходить чуть дольше. (Ну либо запоминать состояние в двух местах, хотя это и урон по памяти). Ну и возможность выплюнуть весть текущий/актуальный текст из памяти в файл, или загрузить его из файла, правда за массивом текста придётся следить отдельно (так как его уже вряд ли можно вытащить из модели буквально). Это – базовые функции, не учитывающие шаблоны вопрос-ответ (я так и не понял, участвуют ли они «в явном виде», или по-другому: как модель понимает, где кончается вопрос и надо начинать ответ?) Более расширенный интерфейс был бы с постоянным откатом к предыдущему состоянию, и оборачиванием ответов юзера и модели в настраиваемые шаблоны наподобие «You tell the AI: "%PROMPT% What do you do?"\nThe AI responds: "» – просто чтобы было удобнее играть.
kha84 commented 1 year ago

@aleksusklim which forum is this being discussed?

aleksusklim commented 1 year ago

which forum is this being discussed?

Some random Telegram chat, with no actual coders in it, unfortunately.

(But they are trying to convince me to create either a proper Issue, or even fork the project to fix everything. Despite there are already repos like https://github.com/PotatoSpudowski/fastLLaMa, which I didn't tried yet; and anyway, I don't believe that changing scanf buffer size from hardcoded 256 bytes is something outstanding…)