Make khoj.el chat API call async to not block user interactions

This commit is contained in:
Debanjum Singh Solanky
2024-06-10 08:02:33 +05:30
parent 906ebee075
commit 385057f09e

View File

@@ -732,7 +732,7 @@ Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
(thread-last (thread-last
json-response json-response
;; generate chat messages from Khoj Chat API response ;; generate chat messages from Khoj Chat API response
(mapcar #'khoj--render-chat-response) (mapcar #'khoj--format-chat-response)
;; insert chat messages into Khoj Chat Buffer ;; insert chat messages into Khoj Chat Buffer
(mapc #'insert)) (mapc #'insert))
(progn (progn
@@ -786,33 +786,29 @@ Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
;; render json response into formatted chat messages ;; render json response into formatted chat messages
(with-current-buffer (get-buffer buffer-name) (with-current-buffer (get-buffer buffer-name)
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(new-content-start-pos (point-max)) (query-time (format-time-string "%F %T")))
(query-time (format-time-string "%F %T")) (goto-char (point-max))
(json-response (khoj--query-chat-api query)))
(goto-char new-content-start-pos)
(insert (insert
(khoj--render-chat-message query "you" query-time) (khoj--render-chat-message query "you" query-time))
(khoj--render-chat-response json-response)) (khoj--query-chat-api query
(khoj--add-hover-text-to-footnote-refs new-content-start-pos)) #'khoj--format-chat-response
(progn #'khoj--render-chat-response buffer-name))))
(org-set-startup-visibility)
(visual-line-mode)
(re-search-backward "^\*+ 🏮" nil t))))
(defun khoj--query-chat-api (query) (defun khoj--query-chat-api (query callback &rest cbargs)
"Send QUERY to Khoj Chat API." "Send QUERY to Khoj Chat API and call CALLBACK with the response.
CBARGS are optional additional arguments to pass to CALLBACK."
(let* ((url-request-method "GET") (let* ((url-request-method "GET")
(encoded-query (url-hexify-string query)) (encoded-query (url-hexify-string query))
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key)))) (url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
(query-url (format "%s/api/chat?q=%s&n=%s&client=emacs" khoj-server-url encoded-query khoj-results-count))) (query-url (format "%s/api/chat?q=%s&n=%s&client=emacs" khoj-server-url encoded-query khoj-results-count)))
(with-temp-buffer (url-retrieve query-url
(condition-case ex (lambda (status)
(progn (if (plist-get status :error)
(url-insert-file-contents query-url) (message "Chat exception: [%s]" (plist-get status :error))
(json-parse-buffer :object-type 'alist)) (goto-char (point-min))
('file-error (cond ((string-match "Internal server error" (nth 2 ex)) (re-search-forward "^$")
(message "Chat processor not configured. Configure OpenAI API key and restart it. Exception: [%s]" ex)) (delete-region (point) (point-min))
(t (message "Chat exception: [%s]" ex)))))))) (apply callback (json-parse-buffer :object-type 'alist) cbargs))))))
(defun khoj--get-chat-history-api () (defun khoj--get-chat-history-api ()
@@ -864,7 +860,20 @@ RECEIVE-DATE is the message receive date."
(replace-regexp-in-string "\n\n" "\n") (replace-regexp-in-string "\n\n" "\n")
(format "\n[fn:%x] %s" khoj--reference-count))))) (format "\n[fn:%x] %s" khoj--reference-count)))))
(defun khoj--render-chat-response (json-response) (defun khoj--render-chat-response (response buffer-name)
(with-current-buffer (get-buffer buffer-name)
(let ((start-pos (point))
(inhibit-read-only t))
(goto-char (point-max))
(insert
response
(or (khoj--add-hover-text-to-footnote-refs start-pos) ""))
(progn
(org-set-startup-visibility)
(visual-line-mode)
(re-search-backward "^\*+ 🏮" nil t)))))
(defun khoj--format-chat-response (json-response &optional callback &rest cbargs)
"Render chat message using JSON-RESPONSE from Khoj Chat API." "Render chat message using JSON-RESPONSE from Khoj Chat API."
(let* ((message (cdr (or (assoc 'response json-response) (assoc 'message json-response)))) (let* ((message (cdr (or (assoc 'response json-response) (assoc 'message json-response))))
(sender (cdr (assoc 'by json-response))) (sender (cdr (assoc 'by json-response)))
@@ -872,7 +881,8 @@ RECEIVE-DATE is the message receive date."
(references (or (cdr (assoc 'context json-response)) '())) (references (or (cdr (assoc 'context json-response)) '()))
(footnotes (mapcar #'khoj--generate-reference references)) (footnotes (mapcar #'khoj--generate-reference references))
(footnote-links (mapcar #'car footnotes)) (footnote-links (mapcar #'car footnotes))
(footnote-defs (mapcar #'cdr footnotes))) (footnote-defs (mapcar #'cdr footnotes))
(formatted-response
(thread-first (thread-first
;; concatenate khoj message and references from API ;; concatenate khoj message and references from API
(concat (concat
@@ -885,6 +895,9 @@ RECEIVE-DATE is the message receive date."
(string-join footnote-defs " ")) (string-join footnote-defs " "))
;; Render chat message using data obtained from API ;; Render chat message using data obtained from API
(khoj--render-chat-message sender receive-date)))) (khoj--render-chat-message sender receive-date))))
(if callback
(apply callback formatted-response cbargs)
formatted-response)))
;; ------------------ ;; ------------------