gptel: gptel-backend-url can accept functions

* gptel.el (gptel--url-get-response): If the backend-url is a
function, call it to find the full url to query.

* gptel-gemini.el: Gemini uses different urls for
streaming/oneshot responses.  Set the backend-url to a function to
account for the value of gptel-stream.  This is also safer than
before as the API key is not stored as part of a static url string
in memory. Fix #153.

* gptel-curl.el (gptel-curl--get-args): If the backend-url is a
function, call it to find the full url to query.
This commit is contained in:
Karthik Chikmagalur 2023-12-22 16:25:32 -08:00
parent 4d01dddf7d
commit 2e92c0303c
3 changed files with 19 additions and 22 deletions

View file

@ -49,16 +49,17 @@
"Produce list of arguments for calling Curl. "Produce list of arguments for calling Curl.
PROMPTS is the data to send, TOKEN is a unique identifier." PROMPTS is the data to send, TOKEN is a unique identifier."
(let* ((url (gptel-backend-url gptel-backend)) (let* ((url (let ((backend-url (gptel-backend-url gptel-backend)))
(if (functionp backend-url)
(funcall backend-url) backend-url)))
(data (encode-coding-string (data (encode-coding-string
(json-encode (gptel--request-data gptel-backend prompts)) (json-encode (gptel--request-data gptel-backend prompts))
'utf-8)) 'utf-8))
(headers (headers
(append '(("Content-Type" . "application/json")) (append '(("Content-Type" . "application/json"))
(when-let ((backend-header (gptel-backend-header gptel-backend))) (when-let ((header (gptel-backend-header gptel-backend)))
(if (functionp backend-header) (if (functionp header)
(funcall backend-header) (funcall header) header)))))
backend-header)))))
(append (append
gptel-curl--common-args gptel-curl--common-args
(list (format "-w(%s . %%{size_header})" token)) (list (format "-w(%s . %%{size_header})" token))

View file

@ -139,19 +139,14 @@ function that returns the key."
:protocol protocol :protocol protocol
:endpoint endpoint :endpoint endpoint
:stream stream :stream stream
:key key
:url :url
(let ((key (cond (lambda ()
((functionp key) (funcall key)) (concat protocol "://" host endpoint
((symbolp key) (symbol-value key)) (if gptel-stream
((stringp key) key) "streamGenerateContent"
(t (user-error "gptel-make-gemini: arg :key is malformed"))))) "generateContent")
(if protocol "?key=" (gptel--get-api-key))))))
(concat protocol "://" host endpoint
(if stream
"streamGenerateContent"
"generateContent")
"?key=" key)
(concat host endpoint "?key=" key))))))
(prog1 backend (prog1 backend
(setf (alist-get name gptel--known-backends (setf (alist-get name gptel--known-backends
nil nil #'equal) nil nil #'equal)

View file

@ -979,16 +979,17 @@ the response is inserted into the current buffer after point."
(url-request-method "POST") (url-request-method "POST")
(url-request-extra-headers (url-request-extra-headers
(append '(("Content-Type" . "application/json")) (append '(("Content-Type" . "application/json"))
(when-let ((backend-header (gptel-backend-header gptel-backend))) (when-let ((header (gptel-backend-header gptel-backend)))
(if (functionp backend-header) (if (functionp header)
(funcall backend-header) (funcall header) header))))
backend-header))))
(url-request-data (url-request-data
(encode-coding-string (encode-coding-string
(json-encode (gptel--request-data (json-encode (gptel--request-data
gptel-backend (plist-get info :prompt))) gptel-backend (plist-get info :prompt)))
'utf-8))) 'utf-8)))
(url-retrieve (gptel-backend-url gptel-backend) (url-retrieve (let ((backend-url (gptel-backend-url gptel-backend)))
(if (functionp backend-url)
(funcall backend-url) backend-url))
(lambda (_) (lambda (_)
(pcase-let ((`(,response ,http-msg ,error) (pcase-let ((`(,response ,http-msg ,error)
(gptel--url-parse-response backend (current-buffer)))) (gptel--url-parse-response backend (current-buffer))))