Add multiline prefixes & AI response prefixes (#142)

gptel: Add customizable prompt/response prefixes

gptel.el (gptel-prompt-prefix-alist, gptel-response-prefix-alist,
gptel-prompt-prefix-string, gptel-response-prefix-string,
gptel--url-get-response): Add customizable response prefixes (per
major-mode) in `gptel-response-prefix-alist`.

Rename `gptel-prompt-string` -> `gptel-prompt-prefix-string`

The function `gptel-response-prefix-string` returns the prefix
string for the response in the current major-mode.

gptel-openai.el, gptel-ollama.el (gptel--parse-buffer): Remove the
prompt and response prefixes when creating prompt strings to send
to the LLM API.

gptel-curl.el (gptel-curl--stream-cleanup,
gptel-curl--stream-insert-response): Insert the response prefix
for the current major-mode before inserting the LLM API response.
This commit is contained in:
daedsidog 2023-12-15 19:30:16 +02:00 committed by GitHub
parent d5949ef428
commit 644e341244
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 11 deletions

View file

@ -183,7 +183,7 @@ PROCESS and _STATUS are process parameters."
(with-current-buffer (marker-buffer start-marker) (with-current-buffer (marker-buffer start-marker)
(pulse-momentary-highlight-region (+ start-marker 2) tracking-marker) (pulse-momentary-highlight-region (+ start-marker 2) tracking-marker)
(when gptel-mode (save-excursion (goto-char tracking-marker) (when gptel-mode (save-excursion (goto-char tracking-marker)
(insert "\n\n" (gptel-prompt-string))))) (insert "\n\n" (gptel-prompt-prefix-string)))))
(with-current-buffer gptel-buffer (with-current-buffer gptel-buffer
(when gptel-mode (gptel--update-header-line " Ready" 'success)))) (when gptel-mode (gptel--update-header-line " Ready" 'success))))
;; Or Capture error message ;; Or Capture error message
@ -232,7 +232,10 @@ See `gptel--url-get-response' for details."
(gptel--update-header-line " Typing..." 'success) (gptel--update-header-line " Typing..." 'success)
(goto-char start-marker) (goto-char start-marker)
(unless (or (bobp) (plist-get info :in-place)) (unless (or (bobp) (plist-get info :in-place))
(insert "\n\n")) (insert "\n\n")
(when gptel-mode
;; Put prefix before AI response.
(insert (gptel-response-prefix-string))))
(setq tracking-marker (set-marker (make-marker) (point))) (setq tracking-marker (set-marker (make-marker) (point)))
(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))

View file

@ -89,9 +89,11 @@ Ollama models.")
:system gptel--system-message :system gptel--system-message
:prompt :prompt
(if (prop-match-p prop) (if (prop-match-p prop)
(string-trim (buffer-substring-no-properties (prop-match-beginning prop) (string-trim
(buffer-substring-no-properties (prop-match-beginning prop)
(prop-match-end prop)) (prop-match-end prop))
"[*# \t\n\r]+") (format "[\t\r\n ]*%s[\t\r\n ]*" (regexp-quote (gptel-prompt-prefix-string)))
(format "[\t\r\n ]*%s[\t\r\n ]*" (regexp-quote (gptel-response-prefix-string))))
"")))))) ""))))))
;;;###autoload ;;;###autoload

View file

@ -100,7 +100,8 @@
(string-trim (string-trim
(buffer-substring-no-properties (prop-match-beginning prop) (buffer-substring-no-properties (prop-match-beginning prop)
(prop-match-end prop)) (prop-match-end prop))
"[*# \t\n\r]+")) (format "[\t\r\n ]*%s[\t\r\n ]*" (regexp-quote (gptel-prompt-prefix-string)))
(format "[\t\r\n ]*%s[\t\r\n ]*" (regexp-quote (gptel-response-prefix-string)))))
prompts) prompts)
(and max-entries (cl-decf max-entries))) (and max-entries (cl-decf max-entries)))
(cons (list :role "system" (cons (list :role "system"

View file

@ -235,6 +235,17 @@ is only inserted in dedicated gptel buffers."
:group 'gptel :group 'gptel
:type '(alist :key-type symbol :value-type string)) :type '(alist :key-type symbol :value-type string))
(defcustom gptel-response-prefix-alist
'((markdown-mode . "")
(org-mode . "")
(text-mode . ""))
"String inserted after the response from ChatGPT.
This is an alist mapping major modes to the reply prefix strings. This
is only inserted in dedicated gptel buffers before the AI's response."
:group 'gptel
:type '(alist :key-type symbol :value-type string))
(defcustom gptel-crowdsourced-prompts-file (defcustom gptel-crowdsourced-prompts-file
(let ((cache-dir (or (getenv "XDG_CACHE_HOME") (let ((cache-dir (or (getenv "XDG_CACHE_HOME")
(getenv "XDG_DATA_HOME") (getenv "XDG_DATA_HOME")
@ -412,9 +423,12 @@ and \"apikey\" as USER."
(skip-syntax-forward "w.") (skip-syntax-forward "w.")
,@body)) ,@body))
(defun gptel-prompt-string () (defun gptel-prompt-prefix-string ()
(or (alist-get major-mode gptel-prompt-prefix-alist) "")) (or (alist-get major-mode gptel-prompt-prefix-alist) ""))
(defun gptel-response-prefix-string ()
(or (alist-get major-mode gptel-response-prefix-alist) ""))
(defun gptel--restore-state () (defun gptel--restore-state ()
"Restore gptel state when turning on `gptel-mode'. "Restore gptel state when turning on `gptel-mode'.
@ -733,11 +747,13 @@ See `gptel--url-get-response' for details."
(goto-char start-marker) (goto-char start-marker)
(run-hooks 'gptel-pre-response-hook) (run-hooks 'gptel-pre-response-hook)
(unless (or (bobp) (plist-get info :in-place)) (unless (or (bobp) (plist-get info :in-place))
(insert "\n\n")) (insert "\n\n")
(when gptel-mode
(insert (gptel-response-prefix-string))))
(let ((p (point))) (let ((p (point)))
(insert response) (insert response)
(pulse-momentary-highlight-region p (point))) (pulse-momentary-highlight-region p (point)))
(when gptel-mode (insert "\n\n" (gptel-prompt-string)))) (when gptel-mode (insert "\n\n" (gptel-prompt-prefix-string))))
(when gptel-mode (gptel--update-header-line " Ready" 'success)))) (when gptel-mode (gptel--update-header-line " Ready" 'success))))
(gptel--update-header-line (gptel--update-header-line
(format " Response Error: %s" status-str) 'error) (format " Response Error: %s" status-str) 'error)
@ -969,9 +985,9 @@ buffer created or switched to."
(visual-line-mode 1)) (visual-line-mode 1))
(t (funcall gptel-default-mode))) (t (funcall gptel-default-mode)))
(unless gptel-mode (gptel-mode 1)) (unless gptel-mode (gptel-mode 1))
(if (bobp) (insert (or initial (gptel-prompt-string))))
(goto-char (point-max)) (goto-char (point-max))
(skip-chars-backward "\t\r\n") (skip-chars-backward "\t\r\n")
(if (bobp) (insert (or initial (gptel-prompt-prefix-string))))
(when (called-interactively-p 'gptel) (when (called-interactively-p 'gptel)
(pop-to-buffer (current-buffer)) (pop-to-buffer (current-buffer))
(message "Send your query with %s!" (message "Send your query with %s!"