Skip to content
karthink edited this page Apr 9, 2023 · 30 revisions

Defining custom gptel commands

GPTel provides gptel-request, a lower level function, to query ChatGPT with custom behavior.

Its signature is as follows:

(gptel-request
 "my prompt"
 ;; The below keys are optional
 :buffer some-buffer-or-name            ;defaults to (current-buffer)
 :system "Chat directive here"          ;defaults to gptel--system-message
 :position some-pt                      ;defaults to (point)
 :context (list "any other info")       ;will be available to the callback
 :callback (lambda (response info) ...)      ;called with the response and an info plist
 )

See its documentation for details.

Example 1

For example, to define a command that accepts a prompt in the minibuffer and pops up a window with the response, you could define the following:

(defvar gptel-quick--history nil)
(defun gptel-quick (prompt)
  (interactive (list (read-string "Ask ChatGPT: " nil gptel-quick--history)))
  (when (string= prompt "") (user-error "A prompt is required."))
  (gptel-request
   prompt
   :callback
   (lambda (response info)
     (if (not response)
         (message "gptel-quick failed with message: %s" (plist-get info :status))
       (with-current-buffer (get-buffer-create "*gptel-quick*")
         (erase-buffer)
         (insert response)
         (special-mode)
         (display-buffer (current-buffer)
                         `((display-buffer-in-side-window)
                           (side . bottom)
                           (window-height . ,#'fit-window-to-buffer))))))))

Example 2

A command that asks ChatGPT to rewrite and replace the current line:

(defun gptel-rewrite-and-replace (bounds)
  (interactive
   (list
    (cond
     ((use-region-p) (cons (region-beginning) (region-end)))
     ((derived-mode-p 'text-mode)
      (list (bounds-of-thing-at-point 'sentence)))
     (t (cons (line-beginning-position) (line-end-position))))))
  (gptel-request
   (buffer-substring-no-properties (car bounds) (cdr bounds)) ;the prompt
   :system "You are a prose editor. Rewrite my prompt more professionally."
   :buffer (current-buffer)
   :context (cons (set-marker (make-marker) (car bounds))
                  (set-marker (make-marker) (cdr bounds)))
   :callback
   (lambda (response info)
     (if (not response)
         (message "ChatGPT response failed with: %s" (plist-get info :status))
       (let* ((bounds (plist-get info :context))
              (beg (car bounds))
              (end (cdr bounds))
              (buf (plist-get info :buffer)))
         (with-current-buffer buf
           (save-excursion
             (goto-char beg)
             (kill-region beg end)
             (insert response)
             (set-marker beg nil)
             (set-marker end nil)
             (message "Rewrote line. Original line saved to kill-ring."))))))))
Clone this wiki locally