gptel: Consolidate HTTP request process
* gptel.el (gptel-request, gptel-send, gptel--url-get-response): Consolidate the HTTP query construction into `gptel-request`, and use it as the single point for sending gptel queries. This simplifies the code, makes it easier to debug and (later) advise or otherwise modify. To this end, `gptel-send` reuses `gptel-request` and no longer does its own thing. Adjust other HTTP request-related functions accordingly. * gptel-curl.el (gptel-curl--get-args, gptel-curl--get-response): Receive the full request data instead of constructing it partly in `gptel-curl--get-args`.
This commit is contained in:
parent
e5f54d1d09
commit
260be9d8d4
2 changed files with 30 additions and 35 deletions
|
@ -47,16 +47,14 @@
|
|||
(defvar gptel-curl--process-alist nil
|
||||
"Alist of active GPTel curl requests.")
|
||||
|
||||
(defun gptel-curl--get-args (prompts token)
|
||||
(defun gptel-curl--get-args (data token)
|
||||
"Produce list of arguments for calling Curl.
|
||||
|
||||
PROMPTS is the data to send, TOKEN is a unique identifier."
|
||||
REQUEST-DATA is the data to send, TOKEN is a unique identifier."
|
||||
(let* ((url (let ((backend-url (gptel-backend-url gptel-backend)))
|
||||
(if (functionp backend-url)
|
||||
(funcall backend-url) backend-url)))
|
||||
(data (encode-coding-string
|
||||
(gptel--json-encode (gptel--request-data gptel-backend prompts))
|
||||
'utf-8))
|
||||
(data-json (encode-coding-string (gptel--json-encode data) 'utf-8))
|
||||
(headers
|
||||
(append '(("Content-Type" . "application/json"))
|
||||
(when-let ((header (gptel-backend-header gptel-backend)))
|
||||
|
@ -68,15 +66,15 @@ PROMPTS is the data to send, TOKEN is a unique identifier."
|
|||
(mapcar (lambda (pair) (cons (intern (car pair)) (cdr pair)))
|
||||
headers))
|
||||
"request headers"))
|
||||
(gptel--log data "request body"))
|
||||
(gptel--log data-json "request body"))
|
||||
(append
|
||||
gptel-curl--common-args
|
||||
(gptel-backend-curl-args gptel-backend)
|
||||
(list (format "-w(%s . %%{size_header})" token))
|
||||
(if (length< data gptel-curl-file-size-threshold)
|
||||
(list (format "-d%s" data))
|
||||
(if (length< data-json gptel-curl-file-size-threshold)
|
||||
(list (format "-d%s" data-json))
|
||||
(letrec
|
||||
((temp-filename (make-temp-file "gptel-curl-data" nil ".json" data))
|
||||
((temp-filename (make-temp-file "gptel-curl-data" nil ".json" data-json))
|
||||
(cleanup-fn (lambda (&rest _)
|
||||
(when (file-exists-p temp-filename)
|
||||
(delete-file temp-filename)
|
||||
|
@ -99,7 +97,7 @@ PROMPTS is the data to send, TOKEN is a unique identifier."
|
|||
"Retrieve response to prompt in INFO.
|
||||
|
||||
INFO is a plist with the following keys:
|
||||
- :prompt (the prompt being sent)
|
||||
- :data (the data being sent)
|
||||
- :buffer (the gptel buffer)
|
||||
- :position (marker at which to insert the response).
|
||||
|
||||
|
@ -108,7 +106,7 @@ the response is inserted into the current buffer after point."
|
|||
(let* ((token (md5 (format "%s%s%s%s"
|
||||
(random) (emacs-pid) (user-full-name)
|
||||
(recent-keys))))
|
||||
(args (gptel-curl--get-args (plist-get info :prompt) token))
|
||||
(args (gptel-curl--get-args (plist-get info :data) token))
|
||||
(stream (and gptel-stream (gptel-backend-stream gptel-backend)))
|
||||
(process (apply #'start-process "gptel-curl"
|
||||
(generate-new-buffer "*gptel-curl*") "curl" args)))
|
||||
|
|
39
gptel.el
39
gptel.el
|
@ -805,11 +805,14 @@ file."
|
|||
(cl-defun gptel-request
|
||||
(&optional prompt &key callback
|
||||
(buffer (current-buffer))
|
||||
position context
|
||||
position context dry-run
|
||||
(stream nil) (in-place nil)
|
||||
(system gptel--system-message))
|
||||
"Request a response from the `gptel-backend' for PROMPT.
|
||||
|
||||
The request is asynchronous, the function immediately returns
|
||||
with the data that was sent.
|
||||
|
||||
Note: This function is not fully self-contained. Consider
|
||||
let-binding the parameters `gptel-backend' and `gptel-model'
|
||||
around calls to it as required.
|
||||
|
@ -832,7 +835,7 @@ with the RESPONSE (a string) and INFO (a plist):
|
|||
RESPONSE is nil if there was no response or an error.
|
||||
|
||||
The INFO plist has (at least) the following keys:
|
||||
:prompt - The full prompt that was sent with the request
|
||||
:data - The request data included with the query
|
||||
:position - marker at the point the request was sent, unless
|
||||
POSITION is specified.
|
||||
:buffer - The buffer current when the request was sent,
|
||||
|
@ -887,6 +890,9 @@ STREAM is a boolean that determines if the response should be
|
|||
streamed, as in `gptel-stream'. Do not set this if you are
|
||||
specifying a custom CALLBACK!
|
||||
|
||||
If DRY-RUN is non-nil, construct and return the full
|
||||
query data as usual, but do not send the request.
|
||||
|
||||
Model parameters can be let-bound around calls to this function."
|
||||
(declare (indent 1))
|
||||
(let* ((gptel-stream stream)
|
||||
|
@ -908,19 +914,22 @@ Model parameters can be let-bound around calls to this function."
|
|||
;; FIXME Dear reader, welcome to Jank City:
|
||||
(with-temp-buffer
|
||||
(let ((gptel--system-message system)
|
||||
(gptel-model (buffer-local-value 'gptel-model buffer))
|
||||
(gptel-backend (buffer-local-value 'gptel-backend buffer)))
|
||||
(insert prompt)
|
||||
(gptel--create-prompt))))
|
||||
((consp prompt) prompt)))
|
||||
(info (list :prompt full-prompt
|
||||
(request-data (gptel--request-data gptel-backend full-prompt))
|
||||
(info (list :data request-data
|
||||
:buffer buffer
|
||||
:position start-marker)))
|
||||
(when context (plist-put info :context context))
|
||||
(when in-place (plist-put info :in-place in-place))
|
||||
(funcall
|
||||
(if gptel-use-curl
|
||||
(unless dry-run
|
||||
(funcall (if gptel-use-curl
|
||||
#'gptel-curl-get-response #'gptel--url-get-response)
|
||||
info callback)))
|
||||
info callback))
|
||||
request-data))
|
||||
|
||||
;; TODO: Handle multiple requests(#15). (Only one request from one buffer at a time?)
|
||||
;;;###autoload
|
||||
|
@ -943,18 +952,7 @@ waiting for the response."
|
|||
(call-interactively #'gptel-menu)
|
||||
(message "Querying %s..." (gptel-backend-name gptel-backend))
|
||||
(gptel--sanitize-model)
|
||||
(let* ((response-pt
|
||||
(if (use-region-p)
|
||||
(set-marker (make-marker) (region-end))
|
||||
(gptel--at-word-end (point-marker))))
|
||||
(gptel-buffer (current-buffer))
|
||||
(full-prompt (gptel--create-prompt response-pt)))
|
||||
(funcall
|
||||
(if gptel-use-curl
|
||||
#'gptel-curl-get-response #'gptel--url-get-response)
|
||||
(list :prompt full-prompt
|
||||
:buffer gptel-buffer
|
||||
:position response-pt)))
|
||||
(gptel-request nil :stream gptel-stream)
|
||||
(gptel--update-status " Waiting..." 'warning)))
|
||||
|
||||
(defun gptel--insert-response (response info)
|
||||
|
@ -1113,7 +1111,7 @@ BUFFER is the LLM interaction buffer."
|
|||
"Fetch response to prompt in INFO from the LLM.
|
||||
|
||||
INFO is a plist with the following keys:
|
||||
- :prompt (the prompt being sent)
|
||||
- :data (the data being sent)
|
||||
- :buffer (the gptel buffer)
|
||||
- :position (marker at which to insert the response).
|
||||
|
||||
|
@ -1130,8 +1128,7 @@ the response is inserted into the current buffer after point."
|
|||
(funcall header) header))))
|
||||
(url-request-data
|
||||
(encode-coding-string
|
||||
(gptel--json-encode (gptel--request-data
|
||||
gptel-backend (plist-get info :prompt)))
|
||||
(gptel--json-encode (plist-get info :data))
|
||||
'utf-8)))
|
||||
(when gptel-log-level ;logging
|
||||
(when (eq gptel-log-level 'debug)
|
||||
|
|
Loading…
Add table
Reference in a new issue