[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/gptel 5159a773a0 011/273: gptel: Use text-property based d
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/gptel 5159a773a0 011/273: gptel: Use text-property based delimiting |
Date: |
Wed, 1 May 2024 10:01:26 -0400 (EDT) |
branch: elpa/gptel
commit 5159a773a03446e6764cd62830e56a6d1729154e
Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com>
Commit: Karthik Chikmagalur <karthikchikmagalur@gmail.com>
gptel: Use text-property based delimiting
gptel.el (gptel--prompt-markers, gptel-send, gptel--create-prompt,
gptel--numberize): Switch from using markers to text-properties to
distinguish queries from responses. The former method was very brittle.
Remove `gptel--prompt-markers', add the function `gptel--create-prompt'
and the variable `gptel--num-messages-to-send'. This variable limits the
context of the conversation that is sent with each request.
---
gptel.el | 75 +++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 53 insertions(+), 22 deletions(-)
diff --git a/gptel.el b/gptel.el
index 5220bfef12..3e423bd9bd 100644
--- a/gptel.el
+++ b/gptel.el
@@ -57,6 +57,7 @@
(require 'aio)
(require 'json)
(require 'map)
+(require 'text-property-search)
(defcustom gptel-api-key nil
"An OpenAI API key (string).
@@ -82,7 +83,6 @@ When set to nil, it is inserted all at once.
:group 'gptel
:type 'boolean)
-(defvar-local gptel--prompt-markers nil)
(defvar gptel-default-session "*ChatGPT*")
(defvar gptel-default-mode (if (featurep 'markdown-mode)
'markdown-mode
@@ -90,30 +90,19 @@ When set to nil, it is inserted all at once.
(defvar gptel-prompt-string "### ")
(aio-defun gptel-send ()
+(defvar-local gptel--num-messages-to-send nil)
+
+(defsubst gptel--numberize (val)
+ "Ensure VAL is a number."
+ (if (stringp val) (string-to-number val) val))
+
"Submit this prompt to ChatGPT."
(interactive)
(message "Querying ChatGPT...")
- (unless (and gptel--prompt-markers
- (equal (marker-position (car gptel--prompt-markers))
- (point-max)))
- (push (set-marker (make-marker) (point-max))
- gptel--prompt-markers))
(setf (nth 1 header-line-format)
(propertize " Waiting..." 'face 'warning))
(let* ((gptel-buffer (current-buffer))
- (full-prompt
- (save-excursion
- (goto-char (point-min))
- (cl-loop with role = "user"
- for (pm rm . _) on gptel--prompt-markers
- collect
- (list :role role
- :content
- (string-trim (buffer-substring-no-properties (or rm
(point-min)) pm)
- "[*# \t\n\r]+"))
- into prompts
- do (setq role (if (equal role "user") "assistant" "user"))
- finally return (nreverse prompts))))
+ (full-prompt (gptel--create-prompt))
(response (aio-await
(funcall
(if (and gptel-use-curl (require 'gptel-curl nil t))
@@ -124,6 +113,7 @@ When set to nil, it is inserted all at once.
(if content-str
(with-current-buffer gptel-buffer
(save-excursion
+ (put-text-property 0 (length content-str) 'gptel 'response
content-str)
(message "Querying ChatGPT... done.")
(goto-char (point-max))
(display-buffer (current-buffer)
@@ -133,15 +123,56 @@ When set to nil, it is inserted all at once.
(if gptel-playback
(gptel--playback (current-buffer) content-str (point))
(insert content-str))
- (push (set-marker (make-marker) (point))
- gptel--prompt-markers)
(insert "\n\n" gptel-prompt-string)
(unless gptel-playback
(setf (nth 1 header-line-format)
(propertize " Ready" 'face 'success)))))
(setf (nth 1 header-line-format)
(propertize (format " Response Error: %s" status-str)
- 'face 'error)))))
+ 'face 'error))))))
+
+(defun gptel--create-prompt ()
+ "Return a full conversation prompt from the contents of this buffer.
+
+If `gptel--num-messages-to-send' is set, limit to that many
+recent exchanges.
+
+If the region is active limit the prompt to the region contents
+instead."
+ (save-excursion
+ (save-restriction
+ (when (use-region-p)
+ (narrow-to-region (region-beginning) (region-end)))
+ (goto-char (point-max))
+ (let ((max-entries (and gptel--num-messages-to-send
+ (* 2 (gptel--numberize
+ gptel--num-messages-to-send))))
+ (prop) (prompts))
+ (while (and
+ (or (not max-entries) (>= max-entries 0))
+ (setq prop (text-property-search-backward
+ 'gptel 'response
+ (when (get-char-property (max (point-min) (1-
(point)))
+ 'gptel)
+ t))))
+ (push (list :role (if (prop-match-value prop) "assistant" "user")
+ :content
+ (string-trim
+ (buffer-substring-no-properties (prop-match-beginning
prop)
+ (prop-match-end prop))
+ "[*# \t\n\r]+"))
+ prompts)
+ (and max-entries (cl-decf max-entries)))
+ (cons (list :role "system"
+ :content
+ (concat
+ (when (eq major-mode 'org-mode)
+ (concat
+ "In this conversation, format your responses as in an
org-mode buffer in Emacs."
+ " Do NOT use Markdown. I repeat, use org-mode markup
and not markdown.\n"))
+ gptel--system-message))
+ prompts)))))
+
(aio-defun gptel--get-response (prompts)
"Fetch response for PROMPTS from ChatGPT.
- [nongnu] elpa/gptel 161c77ad7f 235/273: gptel-transient: Adjust several menu options, (continued)
- [nongnu] elpa/gptel 161c77ad7f 235/273: gptel-transient: Adjust several menu options, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 2b938114cf 264/273: gptel: Add GPT 4 Turbo (#286), ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 44feb1637f 267/273: gptel-transient: Update header-line in gptel--suffix-send, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel f98293f004 016/273: gptel: Check header-line-format before updating, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 3f7c81012b 015/273: gptel: Bump version and prepare for transient menus, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 9da22155de 025/273: gptel-transient: Fix autoloads for gptel-send-menu, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel a3109a4b68 022/273: gptel: Insert response below point, not at point-max, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel a673f54a3e 024/273: gptel, gptel-curl: Handle missing API key, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 1e31f550de 165/273: gptel: Declare compat as explicit dependency, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 48047c0600 167/273: gptel-transient: Improve system-message edit buffer, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 5159a773a0 011/273: gptel: Use text-property based delimiting,
ELPA Syncer <=
- [nongnu] elpa/gptel 4e35e998a8 014/273: gptel-curl: Rename functions for linting, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 1ada9c9214 031/273: gptel: Handle insertion with region-active correctly, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel d77c8f37c5 057/273: gptel: Improve header-line-format, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 6419e8f021 120/273: gptel: Add multi-llm support, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel aa50cbab70 123/273: gptel: Bump version, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel c97778d5a8 127/273: gptel: address byte-compile and checkdoc warnings, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 3e361323d5 137/273: Update available OpenAI GPT models to match API (#146), ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 32dd463bd6 160/273: README: Mention YouTube demo, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel 3ac5963080 168/273: README: Add instructions for Llamafile, ELPA Syncer, 2024/05/01
- [nongnu] elpa/gptel bea31e33e2 175/273: gptel-ollama: Use default host in gptel-make-ollama, ELPA Syncer, 2024/05/01