gptel: api-key shenanigans

gptel.el (gptel--get-api-key, gptel, gptel-mode,
gptel-make-openai, gptel-api-key-from-auth-source): Handle models
that don't require an API key.

gptel-transient.el (gptel--suffix-system-message): Set backend
from buffer-local value when invoking, and handle API key
requirement better.
This commit is contained in:
Karthik Chikmagalur 2023-11-07 20:17:32 -08:00
parent ec0e461b35
commit 3c01477c37
3 changed files with 32 additions and 21 deletions

View file

@ -109,7 +109,8 @@
;;;###autoload ;;;###autoload
(cl-defun gptel-make-openai (cl-defun gptel-make-openai
(name &key header key models stream (name &key header models stream
(key 'gptel-api-key)
(host "api.openai.com") (host "api.openai.com")
(protocol "https") (protocol "https")
(endpoint "/v1/chat/completions")) (endpoint "/v1/chat/completions"))

View file

@ -543,8 +543,9 @@ This uses the prompts in the variable
(local-set-key (kbd "C-c C-c") (local-set-key (kbd "C-c C-c")
(lambda () (lambda ()
(interactive) (interactive)
(setf (buffer-local-value 'gptel--system-message orig-buf) (with-current-buffer orig-buf
(buffer-substring msg-start (point-max))) (setq gptel--system-message
(buffer-substring msg-start (point-max))))
(quit-window) (quit-window)
(display-buffer (display-buffer
orig-buf orig-buf

View file

@ -134,10 +134,12 @@ Leave it empty if you don't use a proxy."
:type 'string) :type 'string)
(defcustom gptel-api-key #'gptel-api-key-from-auth-source (defcustom gptel-api-key #'gptel-api-key-from-auth-source
"An OpenAI API key (string). "An API key (string) for the default LLM backend.
OpenAI by default.
Can also be a function of no arguments that returns an API Can also be a function of no arguments that returns an API
key (more secure)." key (more secure) for the active backend."
:group 'gptel :group 'gptel
:type '(choice :type '(choice
(string :tag "API key") (string :tag "API key")
@ -337,7 +339,7 @@ with differing settings.")
(gptel-make-openai (gptel-make-openai
"ChatGPT" "ChatGPT"
:header (lambda () `(("Authorization" . ,(concat "Bearer " (gptel--get-api-key))))) :header (lambda () `(("Authorization" . ,(concat "Bearer " (gptel--get-api-key)))))
:key #'gptel--get-api-key :key 'gptel-api-key
:stream t :stream t
:models '("gpt-3.5-turbo" "gpt-3.5-turbo-16k" "gpt-4" "gpt-4-32k"))) :models '("gpt-3.5-turbo" "gpt-3.5-turbo-16k" "gpt-4" "gpt-4-32k")))
@ -371,12 +373,15 @@ and \"apikey\" as USER."
(user-error "No `gptel-api-key' found in the auth source"))) (user-error "No `gptel-api-key' found in the auth source")))
;; FIXME Should we utf-8 encode the api-key here? ;; FIXME Should we utf-8 encode the api-key here?
(defun gptel--get-api-key () (defun gptel--get-api-key (&optional key)
"Get api key from `gptel-api-key'." "Get api key from KEY, or from `gptel-api-key'."
(pcase gptel-api-key (when-let* ((key-sym (or key (gptel-backend-key gptel-backend))))
((pred stringp) gptel-api-key) (cl-typecase key-sym
((pred functionp) (funcall gptel-api-key)) (function (funcall key-sym))
(_ (error "`gptel-api-key' is not set")))) (string key-sym)
(symbol (gptel--get-api-key
(symbol-value key-sym)))
(t (error "`gptel-api-key' is not valid")))))
(defsubst gptel--numberize (val) (defsubst gptel--numberize (val)
"Ensure VAL is a number." "Ensure VAL is a number."
@ -519,7 +524,7 @@ opening the file."
(gptel--button-buttonize (concat "[" gptel-model "]") (gptel--button-buttonize (concat "[" gptel-model "]")
(lambda (&rest _) (gptel-menu))) (lambda (&rest _) (gptel-menu)))
'mouse-face 'highlight 'mouse-face 'highlight
'help-echo "OpenAI GPT model in use"))))))) 'help-echo "GPT model in use")))))))
(setq header-line-format gptel--old-header-line))) (setq header-line-format gptel--old-header-line)))
(defun gptel--update-header-line (msg face) (defun gptel--update-header-line (msg face)
@ -889,7 +894,7 @@ See `gptel-curl--get-response' for its contents.")
"Could not parse HTTP response."))))) "Could not parse HTTP response.")))))
;;;###autoload ;;;###autoload
(defun gptel (name &optional api-key initial) (defun gptel (name &optional _ initial)
"Switch to or start ChatGPT session with NAME. "Switch to or start ChatGPT session with NAME.
With a prefix arg, query for a (new) session name. With a prefix arg, query for a (new) session name.
@ -901,16 +906,20 @@ buffer created or switched to."
(interactive (list (if current-prefix-arg (interactive (list (if current-prefix-arg
(read-string "Session name: " (generate-new-buffer-name gptel-default-session)) (read-string "Session name: " (generate-new-buffer-name gptel-default-session))
gptel-default-session) gptel-default-session)
(condition-case nil (let ((backend (default-value 'gptel-backend)))
(gptel--get-api-key) (condition-case nil
((error user-error) (gptel--get-api-key
(setq gptel-api-key (gptel-backend-key backend))
(read-passwd "OpenAI API key: ")))) ((error user-error)
(setq gptel-api-key
(read-passwd
(format "%s API key: "
(gptel-backend-name backend)))))))
(and (use-region-p) (and (use-region-p)
(buffer-substring (region-beginning) (buffer-substring (region-beginning)
(region-end))))) (region-end)))))
(unless api-key ;; (unless api-key
(user-error "No API key available")) ;; (user-error "No API key available"))
(with-current-buffer (get-buffer-create name) (with-current-buffer (get-buffer-create name)
(cond ;Set major mode (cond ;Set major mode
((eq major-mode gptel-default-mode)) ((eq major-mode gptel-default-mode))