gptel: org support for streaming WIP
* gptel.el (gptel--convert-playback-markdown->org): New converter for markdown->org that works on text chunks while maintaining the parse state until the text stream is finished. * gptel-curl.el (gptel--insert-response-stream, gptel-curl-get-response): When using `gptel-playback' and requesting ChatGPT's responses in org-mode, run the above converter on the received response. This works by storing the converter and associated state as a closure in the async info plist that is supplied along with the response, and running it repeatedly on each chunk of text in the response stream before it is inserted into the buffer. FIXME: Note that `gptel-response-filter-functions' is currently ignored if using `gptel-stream'.
This commit is contained in:
parent
d5ad620555
commit
c9795fe9e8
2 changed files with 66 additions and 4 deletions
|
@ -59,6 +59,8 @@ PROMPTS is the data to send, TOKEN is a unique identifier."
|
||||||
(push (format "-d%s" data) args)
|
(push (format "-d%s" data) args)
|
||||||
(nreverse (cons url args))))
|
(nreverse (cons url args))))
|
||||||
|
|
||||||
|
;;TODO: The :transformer argument here is an alternate implementation of
|
||||||
|
;;`gptel-response-filter-functions'. The two need to be unified.
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun gptel-curl-get-response (info &optional callback)
|
(defun gptel-curl-get-response (info &optional callback)
|
||||||
"Retrieve response to prompt in INFO.
|
"Retrieve response to prompt in INFO.
|
||||||
|
@ -83,7 +85,13 @@ the response is inserted into the current buffer after point."
|
||||||
:callback (or callback
|
:callback (or callback
|
||||||
(if gptel-playback
|
(if gptel-playback
|
||||||
#'gptel--insert-response-stream
|
#'gptel--insert-response-stream
|
||||||
#'gptel--insert-response)))
|
#'gptel--insert-response))
|
||||||
|
:transformer (when (or (eq gptel-default-mode 'org-mode)
|
||||||
|
(eq (buffer-local-value
|
||||||
|
'major-mode
|
||||||
|
(plist-get info :gptel-buffer))
|
||||||
|
'org-mode))
|
||||||
|
(gptel--convert-playback-markdown->org)))
|
||||||
info))
|
info))
|
||||||
(if gptel-playback
|
(if gptel-playback
|
||||||
(progn (set-process-sentinel process #'gptel-curl--cleanup-stream)
|
(progn (set-process-sentinel process #'gptel-curl--cleanup-stream)
|
||||||
|
@ -122,7 +130,8 @@ See `gptel--url-get-response' for details."
|
||||||
(status-str (plist-get response :status))
|
(status-str (plist-get response :status))
|
||||||
(gptel-buffer (plist-get info :gptel-buffer))
|
(gptel-buffer (plist-get info :gptel-buffer))
|
||||||
(start-marker (plist-get info :insert-marker))
|
(start-marker (plist-get info :insert-marker))
|
||||||
(tracking-marker (plist-get info :tracking-marker)))
|
(tracking-marker (plist-get info :tracking-marker))
|
||||||
|
(transformer (plist-get info :transformer)))
|
||||||
(if content-str
|
(if content-str
|
||||||
(with-current-buffer gptel-buffer
|
(with-current-buffer gptel-buffer
|
||||||
(save-excursion
|
(save-excursion
|
||||||
|
@ -134,8 +143,9 @@ See `gptel--url-get-response' for details."
|
||||||
(set-marker-insertion-type tracking-marker t)
|
(set-marker-insertion-type tracking-marker t)
|
||||||
(plist-put info :tracking-marker tracking-marker))
|
(plist-put info :tracking-marker tracking-marker))
|
||||||
|
|
||||||
(setq content-str (gptel--transform-response
|
(when transformer
|
||||||
content-str gptel-buffer))
|
(setq content-str (funcall transformer content-str)))
|
||||||
|
|
||||||
(put-text-property 0 (length content-str) 'gptel 'response content-str)
|
(put-text-property 0 (length content-str) 'gptel 'response content-str)
|
||||||
(goto-char tracking-marker)
|
(goto-char tracking-marker)
|
||||||
(insert content-str)))
|
(insert content-str)))
|
||||||
|
|
52
gptel.el
52
gptel.el
|
@ -550,6 +550,58 @@ elements."
|
||||||
(insert "/")))))))
|
(insert "/")))))))
|
||||||
(buffer-string)))
|
(buffer-string)))
|
||||||
|
|
||||||
|
(defun gptel--convert-playback-markdown->org ()
|
||||||
|
""
|
||||||
|
(let ((in-src-block)
|
||||||
|
(temp-buf (generate-new-buffer-name "*gptel-temp*"))
|
||||||
|
(start-pt (make-marker)))
|
||||||
|
(lambda (str)
|
||||||
|
(let ((noop-p))
|
||||||
|
(with-current-buffer (get-buffer-create temp-buf)
|
||||||
|
(save-excursion (goto-char (point-max))
|
||||||
|
(insert str))
|
||||||
|
(when (marker-position start-pt) (goto-char start-pt))
|
||||||
|
(save-excursion
|
||||||
|
(while (re-search-forward "`\\|\\*\\{1,2\\}\\|_" nil t)
|
||||||
|
(pcase (match-string 0)
|
||||||
|
("`"
|
||||||
|
(cond
|
||||||
|
((looking-at "``")
|
||||||
|
(backward-char 1)
|
||||||
|
(delete-char 3)
|
||||||
|
(if in-src-block
|
||||||
|
(progn (insert "#+end_src")
|
||||||
|
(setq in-src-block nil))
|
||||||
|
(insert "#+begin_src ")
|
||||||
|
(setq in-src-block t)))
|
||||||
|
((looking-at "`\\|$")
|
||||||
|
(setq noop-p t)
|
||||||
|
(set-marker start-pt (1- (point)))
|
||||||
|
(unless (eobp) (forward-char 1)))
|
||||||
|
((not in-src-block) (replace-match "="))))
|
||||||
|
((and "**" (guard (not in-src-block)))
|
||||||
|
(cond
|
||||||
|
((looking-at "\\*\\(?:[[:word:]]\\|\s\\)")
|
||||||
|
(delete-char 1))
|
||||||
|
((looking-back "\\(?:[[:word:]]\\|\s\\)\\*\\{2\\}"
|
||||||
|
(max (- (point) 3) (point-min)))
|
||||||
|
(backward-delete-char 1))))
|
||||||
|
((and (or "_" "*") (guard (not in-src-block)))
|
||||||
|
(when (save-match-data
|
||||||
|
(save-excursion
|
||||||
|
(backward-char 2)
|
||||||
|
(or
|
||||||
|
(looking-at
|
||||||
|
"[^[:space:][:punct:]\n]\\(?:_\\|\\*\\)\\(?:[[:space:][:punct:]]\\|$\\)")
|
||||||
|
(looking-at
|
||||||
|
"\\(?:[[:space:][:punct:]]\\)\\(?:_\\|\\*\\)\\([^[:space:][:punct:]]\\|$\\)"))))
|
||||||
|
(backward-delete-char 1)
|
||||||
|
(insert "/"))))))
|
||||||
|
(if noop-p
|
||||||
|
(buffer-substring (point) start-pt)
|
||||||
|
(prog1 (buffer-substring (point) (point-max))
|
||||||
|
(set-marker start-pt (point-max)))))))))
|
||||||
|
|
||||||
(defun gptel--playback (buf content-str start-pt)
|
(defun gptel--playback (buf content-str start-pt)
|
||||||
"Playback CONTENT-STR in BUF.
|
"Playback CONTENT-STR in BUF.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue