From d5949ef428be5feac2168223d091d1842085988c Mon Sep 17 00:00:00 2001 From: Karim Aziiev Date: Fri, 15 Dec 2023 06:22:53 +0200 Subject: [PATCH] gptel-curl: handle large Curl payloads with a temp file (#137) gptel-curl.el (gptel-curl--get-args, gptel-curl-file-size-threshold): Use temporary file for curl data. Ensure curl uses a temporary file for binary data to prevent issues with large payloads and special characters: - Add a new defcustom `gptel-curl-file-size-threshold` to determine when to use a temporary file for passing data to Curl. - Use `--data-binary` with a temp file for data larger than the specified threshold, improving handling of large data payloads in GPTel queries. - Reliably clean up temporary files created for Curl requests exceeding the size threshold. Add a function to `gptel-post-response-hook` to delete the file post-Curl execution and remove itself from the hook, preventing temporary file accumulation. --- gptel-curl.el | 14 ++++++++++++-- gptel.el | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/gptel-curl.el b/gptel-curl.el index 8f5e070..027dfb5 100644 --- a/gptel-curl.el +++ b/gptel-curl.el @@ -61,8 +61,18 @@ PROMPTS is the data to send, TOKEN is a unique identifier." backend-header))))) (append gptel-curl--common-args - (list (format "-w(%s . %%{size_header})" token) - (format "-d%s" data)) + (list (format "-w(%s . %%{size_header})" token)) + (if (length< data gptel-curl-file-size-threshold) + (list (format "-d%s" data)) + (letrec + ((temp-filename (make-temp-file "gptel-curl-data" nil ".json" data)) + (cleanup-fn (lambda () + (when (file-exists-p temp-filename) + (delete-file temp-filename) + (remove-hook 'gptel-post-response-hook cleanup-fn))))) + (add-hook 'gptel-post-response-hook cleanup-fn) + (list "--data-binary" + (format "@%s" temp-filename)))) (when (not (string-empty-p gptel-proxy)) (list "--proxy" gptel-proxy "--proxy-negotiate" diff --git a/gptel.el b/gptel.el index 40b0c1b..17d5564 100644 --- a/gptel.el +++ b/gptel.el @@ -163,6 +163,25 @@ all at once. This wait is asynchronous. :group 'gptel :type 'boolean) +(defcustom gptel-curl-file-size-threshold 130000 + "Size threshold for using file input with Curl. + +Specifies the size threshold for when to use a temporary file to pass data to +Curl in GPTel queries. If the size of the data to be sent exceeds this +threshold, the data is written to a temporary file and passed to Curl using the +`--data-binary' option with a file reference. Otherwise, the data is passed +directly as a command-line argument. + +The value is an integer representing the number of bytes. + +Adjusting this value may be necessary depending on the environment +and the typical size of the data being sent in GPTel queries. +A larger value may improve performance by avoiding the overhead of creating +temporary files for small data payloads, while a smaller value may be needed +if the command-line argument size is limited by the operating system." + :group 'gptel + :type 'integer) + (defcustom gptel-response-filter-functions '(gptel--convert-org) "Abnormal hook for transforming the response from ChatGPT.