Skip to content

Commit

Permalink
Make some more quality of life improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Nov 13, 2024
1 parent c21a5fc commit 6dd451b
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 93 deletions.
15 changes: 10 additions & 5 deletions llamafile/chatbot_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ void *server_thread(void *arg) {
exit(server_cli(sargs->argc, sargs->argv));
}

const char *tip() {
if (g_params.verbosity)
return "";
return " (use the --verbose flag for further details)";
}

int main(int argc, char **argv) {

// print logo
Expand Down Expand Up @@ -122,16 +128,15 @@ int main(int argc, char **argv) {
print_ephemeral("loading model...");
llama_model_params model_params = llama_model_params_from_gpt_params(g_params);
g_model = llama_load_model_from_file(g_params.model.c_str(), model_params);
clear_ephemeral();
if (g_model == NULL) {
clear_ephemeral();
fprintf(stderr, "%s: failed to load model\n", g_params.model.c_str());
fprintf(stderr, "%s: failed to load model%s\n", g_params.model.c_str(), tip());
exit(2);
}
if (g_params.n_ctx <= 0 || g_params.n_ctx > llama_n_ctx_train(g_model))
g_params.n_ctx = llama_n_ctx_train(g_model);
if (g_params.n_ctx < g_params.n_batch)
g_params.n_batch = g_params.n_ctx;
clear_ephemeral();

bool want_server = !llamafile_has(argv, "--chat");
if (want_server) {
Expand Down Expand Up @@ -164,7 +169,7 @@ int main(int argc, char **argv) {
g_ctx = llama_new_context_with_model(g_model, ctx_params);
clear_ephemeral();
if (!g_ctx) {
fprintf(stderr, "error: failed to initialize context\n");
fprintf(stderr, "error: failed to initialize context%s\n", tip());
exit(3);
}

Expand All @@ -176,7 +181,7 @@ int main(int argc, char **argv) {
g_clip = clip_model_load(FLAG_mmproj, g_params.verbosity);
clear_ephemeral();
if (!g_clip) {
fprintf(stderr, "%s: failed to initialize clip image model\n", FLAG_mmproj);
fprintf(stderr, "%s: failed to initialize clip image model%s\n", FLAG_mmproj, tip());
exit(4);
}
}
Expand Down
3 changes: 3 additions & 0 deletions llamafile/highlight.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ class HighlightRuby : public Highlight {
bool pending_heredoc_ = false;
bool indented_heredoc_ = false;
unsigned char nest_[16];
unsigned char levels_[16];
unsigned char openers_[16];
unsigned char closers_[16];
std::string word_;
std::string heredoc_;
};
Expand Down
73 changes: 55 additions & 18 deletions llamafile/highlight_ruby.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

enum {
NORMAL,
NUMBER,
WORD,
EQUAL,
EQUAL_WORD,
Expand Down Expand Up @@ -65,6 +66,7 @@ enum {
};

enum {
EXPECT_EXPR,
EXPECT_VALUE,
EXPECT_OPERATOR,
};
Expand Down Expand Up @@ -214,23 +216,23 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
is_definition_ = false;
} else if (c == ':') {
t_ = COLON;
expect_ = EXPECT_OPERATOR;
is_definition_ = false;
} else if (c == '@') {
t_ = AT;
is_definition_ = false;
expect_ = EXPECT_OPERATOR;
} else if (c == '=') {
t_ = EQUAL;
expect_ = EXPECT_VALUE;
is_definition_ = false;
} else if (c == '?' && expect_ == EXPECT_VALUE) {
} else if (c == '?') {
t_ = QUESTION;
is_definition_ = false;
} else if (c == '$') {
t_ = DOLLAR;
expect_ = EXPECT_OPERATOR;
is_definition_ = false;
} else if (c == '%' && expect_ == EXPECT_VALUE) {
} else if (c == '%') {
t_ = PERCENT;
q_ = 0;
expect_ = EXPECT_OPERATOR;
Expand All @@ -252,49 +254,60 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
lf::append_wchar(r, c);
expect_ = EXPECT_OPERATOR;
} else if (c == '#') {
expect_ = EXPECT_VALUE;
expect_ = EXPECT_EXPR;
*r += HI_COMMENT;
lf::append_wchar(r, c);
t_ = COMMENT;
} else if (c == '<' && expect_ == EXPECT_VALUE) {
} else if (c == '<' && (expect_ == EXPECT_EXPR || expect_ == EXPECT_VALUE)) {
lf::append_wchar(r, c);
t_ = LT;
} else if (c == '/' && expect_ == EXPECT_VALUE) {
} else if (c == '/' && (expect_ == EXPECT_EXPR || expect_ == EXPECT_VALUE)) {
t_ = REGEX;
*r += HI_STRING;
lf::append_wchar(r, c);
} else if (c == '{' && nesti_ && nesti_ < sizeof(nest_)) {
expect_ = EXPECT_VALUE;
*r += '{';
levels_[nesti_] = level_;
closers_[nesti_] = closer_;
openers_[nesti_] = opener_;
nest_[nesti_++] = NORMAL;
is_definition_ = false;
} else if (c == '}' && nesti_) {
if ((t_ = nest_[--nesti_]) != NORMAL)
--nesti_;
level_ = levels_[nesti_];
closer_ = closers_[nesti_];
opener_ = openers_[nesti_];
if ((t_ = nest_[nesti_]) != NORMAL)
*r += HI_STRING;
*r += '}';
expect_ = EXPECT_OPERATOR;
is_definition_ = false;
} else if (c == '\n') {
expect_ = EXPECT_VALUE;
expect_ = EXPECT_EXPR;
lf::append_wchar(r, c);
if (pending_heredoc_) {
*r += HI_STRING;
pending_heredoc_ = false;
t_ = HEREDOC_BOL;
i_ = 0;
}
} else if (c == ']' || c == ')') {
expect_ = EXPECT_OPERATOR;
} else if (c == '[' || c == '(') {
expect_ = EXPECT_VALUE;
lf::append_wchar(r, c);
is_definition_ = false;
} else if (ispunct(c)) {
expect_ = EXPECT_VALUE;
} else if (c == ']' || c == ')') {
expect_ = EXPECT_OPERATOR;
lf::append_wchar(r, c);
is_definition_ = false;
} else if (isdigit(c) || c == '.') {
expect_ = EXPECT_OPERATOR;
lf::append_wchar(r, c);
is_definition_ = false;
} else if (ispunct(c)) {
expect_ = EXPECT_VALUE;
lf::append_wchar(r, c);
is_definition_ = false;
} else if (isspace(c)) {
lf::append_wchar(r, c);
} else {
Expand Down Expand Up @@ -336,6 +349,7 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
}
// fallthrough

Word:
case WORD:
if (isident(c)) {
lf::append_wchar(&word_, c);
Expand All @@ -347,8 +361,11 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
expect_ = EXPECT_VALUE;
if (word_ == "def") {
is_definition_ = true;
} else if (word_ == "class" || word_ == "module") {
expect_ = EXPECT_OPERATOR;
}
} else if (is_keyword_ruby_builtin(word_.data(), word_.size())) {
} else if (expect_ == EXPECT_EXPR &&
is_keyword_ruby_builtin(word_.data(), word_.size())) {
*r += HI_BUILTIN;
*r += word_;
*r += HI_RESET;
Expand Down Expand Up @@ -398,6 +415,9 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
*r += '{';
*r += HI_RESET;
expect_ = EXPECT_VALUE;
levels_[nesti_] = level_;
closers_[nesti_] = closer_;
openers_[nesti_] = opener_;
nest_[nesti_++] = REGEX;
t_ = NORMAL;
} else if (c == '$') {
Expand Down Expand Up @@ -471,9 +491,15 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
*r += HI_LISPKW;
*r += ':';
lf::append_wchar(r, c);
expect_ = EXPECT_OPERATOR;
t_ = COLON_WORD;
} else if (c == ':') {
*r += "::";
expect_ = EXPECT_VALUE;
t_ = NORMAL;
} else {
*r += ':';
expect_ = EXPECT_VALUE;
t_ = NORMAL;
goto Normal;
}
Expand Down Expand Up @@ -523,9 +549,11 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
*r += HI_STRING;
*r += '%';
lf::append_wchar(r, c);
expect_ = EXPECT_OPERATOR;
t_ = PERCENT_STRING;
} else {
*r += '%';
expect_ = EXPECT_VALUE;
t_ = NORMAL;
goto Normal;
}
Expand All @@ -538,14 +566,16 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
closer_ = mirror(c);
*r += HI_STRING;
*r += '%';
*r += q_;
lf::append_wchar(r, q_);
lf::append_wchar(r, c);
expect_ = EXPECT_OPERATOR;
t_ = PERCENT_STRING;
} else {
*r += '%';
*r += q_;
t_ = NORMAL;
goto Normal;
is_definition_ = false;
lf::append_wchar(&word_, q_);
t_ = WORD;
goto Word;
}
break;

Expand All @@ -557,6 +587,9 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
*r += '{';
*r += HI_RESET;
expect_ = EXPECT_VALUE;
levels_[nesti_] = level_;
closers_[nesti_] = closer_;
openers_[nesti_] = opener_;
nest_[nesti_++] = PERCENT_STRING;
t_ = NORMAL;
} else if (c == '$') {
Expand Down Expand Up @@ -605,7 +638,7 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
if (c == opener_ && opener_ != closer_) {
lf::append_wchar(r, c);
++level_;
} else if (c == '#') {
} else if (c == '#' && closer_ != '#') {
t_ = PERCENT_HASH;
} else if (c == closer_) {
lf::append_wchar(r, c);
Expand Down Expand Up @@ -695,6 +728,9 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
*r += '{';
*r += HI_RESET;
expect_ = EXPECT_VALUE;
levels_[nesti_] = level_;
closers_[nesti_] = closer_;
openers_[nesti_] = opener_;
nest_[nesti_++] = DQUOTE;
t_ = NORMAL;
} else if (c == '$') {
Expand Down Expand Up @@ -847,6 +883,7 @@ void HighlightRuby::feed(std::string *r, std::string_view input) {
t_ = QUESTION_BACKSLASH;
} else if (isspace(c)) {
*r += '?';
expect_ = EXPECT_VALUE;
t_ = NORMAL;
goto Normal;
} else {
Expand Down
23 changes: 16 additions & 7 deletions llamafile/server/www/chatbot.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const sendButton = document.getElementById("send-button");
const stopButton = document.getElementById("stop-button");

let abortController = null;
let disableAutoScroll = false;
let streamingMessageContent = [];
let uploadedFiles = [];

Expand Down Expand Up @@ -48,7 +49,8 @@ function createMessageElement(content, role) {
}

function scrollToBottom() {
chatInput.scrollIntoView({behavior: "instant"});
if (!disableAutoScroll)
document.getElementById("bottom").scrollIntoView({behavior: "instant"});
}

function onChatInput() {
Expand All @@ -57,6 +59,7 @@ function onChatInput() {
}

function cleanupAfterMessage() {
disableAutoScroll = false;
chatMessages.scrollTop = chatMessages.scrollHeight;
chatInput.disabled = false;
sendButton.style.display = "inline-block";
Expand All @@ -65,6 +68,11 @@ function cleanupAfterMessage() {
chatInput.focus();
}

function onWheel(e) {
if (e.deltaY < 0)
disableAutoScroll = true;
}

async function handleChatStream(response) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
Expand Down Expand Up @@ -314,12 +322,13 @@ function chatbot() {
stopButton.addEventListener("click", stopMessage);
chatInput.addEventListener("input", onChatInput);
chatInput.addEventListener("keydown", onKeyDown);
document.body.addEventListener('dragenter', onDragBegin, false);
document.body.addEventListener('dragover', onDragBegin, false);
document.body.addEventListener('dragleave', onDragEnd, false);
document.body.addEventListener('drop', onDragEnd, false);
document.body.addEventListener('drop', onDrop, false);
document.body.addEventListener('paste', onPaste);
document.addEventListener('wheel', onWheel);
document.addEventListener('dragenter', onDragBegin);
document.addEventListener('dragover', onDragBegin);
document.addEventListener('dragleave', onDragEnd);
document.addEventListener('drop', onDragEnd);
document.addEventListener('drop', onDrop);
document.addEventListener('paste', onPaste);
chatInput.focus();
}

Expand Down
Loading

0 comments on commit 6dd451b

Please sign in to comment.