Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

gptel-request wrong type argument #319

Closed
ppanko opened this issue May 21, 2024 · 13 comments
Closed

gptel-request wrong type argument #319

ppanko opened this issue May 21, 2024 · 13 comments
Labels
bug Something isn't working

Comments

@ppanko
Copy link

ppanko commented May 21, 2024

Hello, thank you for the wonderful package. I am running into an error attempting to run a function that uses gptel-request (using Windows 11 OS). Here is my config setup:

  (use-package gptel
    :config
    ;; Set the default model to use
    (setq-default gptel-model "gpt-3.5-turbo")
    ;; set API key
    (setq gptel-api-key "____________"))

  (defun gptel-rewrite-and-replace (bounds &optional directive)
    (interactive
     (list
      (cond
       ((use-region-p) (cons (region-beginning) (region-end)))
       ((derived-mode-p 'text-mode)
        (list (bounds-of-thing-at-point 'sentence)))
       (t (cons (line-beginning-position) (line-end-position))))
      (and current-prefix-arg
           (read-string "ChatGPT Directive: "
                        "You are a prose editor. Rewrite my prompt more professionally."))))
    (gptel-request
        (buffer-substring-no-properties (car bounds) (cdr bounds)) ;the prompt
      :system (or directive "You are a prose editor. Rewrite my prompt more professionally.")
      :buffer (current-buffer)
      :context (cons (set-marker (make-marker) (car bounds))
                     (set-marker (make-marker) (cdr bounds)))
      :callback
      (lambda (response info)
        (if (not response)
            (message "ChatGPT response failed with: %s" (plist-get info :status))
          (let* ((bounds (plist-get info :context))
                 (beg (car bounds))
                 (end (cdr bounds))
                 (buf (plist-get info :buffer)))
            (with-current-buffer buf
              (save-excursion
                (goto-char beg)
                (kill-region beg end)
                (insert response)
                (set-marker beg nil)
                (set-marker end nil)
                (message "Rewrote line. Original line saved to kill-ring."))))))))

The gptel-rewrite-and-replace function, which was borrowed from example 2 on the gptel wiki page, throws the following error:

error in process sentinel: gptel-curl--parse-response: Wrong type argument: stringp, nil
error in process sentinel: Wrong type argument: stringp, nil

gptel-send works just fine as does sending requests through curl directly. I can send the debug/log output if needed. Thanks in advance!

@ppanko ppanko changed the title gptel-request gptel-request wrong type argument May 21, 2024
@karthink
Copy link
Owner

I can't reproduce this. Could you run M-x toggle-debug-on-error, produce the error and supply the backtrace here?

@ppanko
Copy link
Author

ppanko commented May 21, 2024

Debugger entered--Lisp error: (wrong-type-argument json-value-p "HTTP/2 200 \ndate: Tue, 21 May 2024 20:09:13 GMT\ncontent-type: application/json; charset=utf-8\n...")

json-serialize("HTTP/2 200 \ndate: Tue, 21 May 2024 20:09:13 GMT\ncontent-type: application/json; charset=utf-8\n..." :null-object nil :false-object :json-false)

gptel-curl--log-response(#<buffer *gptel-curl*<3>> (:token "04a8d912aa1d4a4ecf45416b86ee5e39" :parser #f(compiled-function (backend response info) #<bytecode 0x1974b7d>) :callback (lambda (response info) (if (not response) (message "ChatGPT response failed with: %s" (plist-get info :status)) (let* ((bounds (plist-get info :context)) (beg (car bounds)) (end (cdr bounds)) (buf (plist-get info :buffer))) (save-current-buffer (set-buffer buf) (save-excursion (goto-char beg) (kill-region beg end) (insert response) (set-marker beg nil) (set-marker end nil) (message "Rewrote line. Original line saved to kill-ring."))))) :transformer nil :data (:model "gpt-3.5-turbo" :messages [(:role "system" :content "You are a prose editor. Rewrite my prompt more pro...") (:role "user" :content ";; elisp: fizzbuzz")] :stream :json-false :temperature 1.0) :buffer #<buffer *scratch*> :position #<marker at 19 in *scratch*> :context (#<marker at 1 in *scratch*> . #<marker at 19 in *scratch*>)))

gptel-curl--sentinel(#<process gptel-curl> "finished\n")

P.S. sorry -- mis-clicked on "close" initially

@ppanko ppanko closed this as completed May 21, 2024
@ppanko ppanko reopened this May 21, 2024
@karthink
Copy link
Owner

This error is different from the one in your previous post. It looks like there are two different errors. Please turn off logging with (setq gptel-log-level nil) and produce a backtrace for the original error.

@ppanko
Copy link
Author

ppanko commented May 21, 2024

Correct -- here's the error from the OP:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  string-match("\\(?:[ \11\n\15]+\\)\\'" nil nil)
  gptel-curl--parse-response((:token "dcab6e4d3b53057500fb4191cf8ddfb3" :parser #f(compiled-function (backend response info) #<bytecode 0x1974b7d>) :callback (lambda (response info) (if (not response) (message "ChatGPT response failed with: %s" (plist-get info :status)) (let* ((bounds (plist-get info :context)) (beg (car bounds)) (end (cdr bounds)) (buf (plist-get info :buffer))) (save-current-buffer (set-buffer buf) (save-excursion (goto-char beg) (kill-region beg end) (insert response) (set-marker beg nil) (set-marker end nil) (message "Rewrote line. Original line saved to kill-ring.")))))) :transformer nil :data (:model "gpt-3.5-turbo" :messages [(:role "system" :content "You are a prose editor. Rewrite my prompt more pro...") (:role "user" :content ";; elisp: fizzbuzz")] :stream :json-false :temperature 1.0) :buffer #<buffer *scratch*> :position #<marker at 19 in *scratch*> :context (#<marker at 1 in *scratch*> . #<marker at 19 in *scratch*>)))
  gptel-curl--sentinel(#<process gptel-curl> "finished\n")

@karthink
Copy link
Owner

That's quite odd. I'd ask you to turn on logging but that's independently broken too. I don't see anything wrong with that json-serialize call.

@ppanko
Copy link
Author

ppanko commented May 22, 2024

Thanks for checking. Clearing the config file didn't affect either error -- gptel-send works but gptel-rewrite-and-replace does not.

Any chance either issue is related to this block?

gptel/gptel-curl.el

Lines 388 to 395 in 3bce2ca

(http-status
(save-match-data
(and (string-match "HTTP/[.0-9]+ +\\([0-9]+\\)" http-msg)
(match-string 1 http-msg))))
(response (progn (goto-char header-size)
(condition-case nil
(gptel--json-read)
(error 'json-read-error)))))

@karthink
Copy link
Owner

No, I think it's related to string-trim further below. To analyze this I'd have to fix the logging bug first.

@karthink karthink added the bug Something isn't working label Jun 27, 2024
@ISouthRain
Copy link

ISouthRain commented Sep 4, 2024

@ppanko @karthink
Is this problem solved?
I also encountered it on Windows 10.....
I know it is not a problem on Linux...
This is my configuration:
gptel-test.el

;; file gptel-test.el
(use-package gptel
  :load-path "path-to/gptel/")
(use-package gptel-curl)
(use-package gptel-transient)
(use-package gptel-gemini)
(setq gptel-model "gemini-pro"
      gptel-backend (gptel-make-gemini "Gemini"
                      :key ".......key ......"
                      :stream t))

(gptel-request "Who are you?" :system "Return your name.")

emacs -q -l gptel-test.el
Message out:
error in process sentinel: string-trim: Wrong type argument: stringp, nil
error in process sentinel: Wrong type argument: stringp, nil
But return buffer:
*gptel-curl*

HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: X-Origin
Vary: Referer
Date: Wed, 04 Sep 2024 12:56:24 GMT
Server: scaffolding on HTTPServer2
Cache-Control: private
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Server-Timing: gfet4t7; dur=843
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Accept-Ranges: none
Vary: Origin,Accept-Encoding
Transfer-Encoding: chunked

{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "text": "I am Gemini, a multimodal AI language model developed by Google. I do not have a name."
          }
        ],
        "role": "model"
      },
      "finishReason": "STOP",
      "index": 0,
      "safetyRatings": [
        {
          "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
          "probability": "NEGLIGIBLE"
        },
        {
          "category": "HARM_CATEGORY_HATE_SPEECH",
          "probability": "NEGLIGIBLE"
        },
        {
          "category": "HARM_CATEGORY_HARASSMENT",
          "probability": "NEGLIGIBLE"
        },
        {
          "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
          "probability": "NEGLIGIBLE"
        }
      ]
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 10,
    "candidatesTokenCount": 20,
    "totalTokenCount": 30
  }
}
(1a9267a3f02ab87d95b7b8a3da838a14 . 485)

I use:
M-x gptel
On gptel-mode Use key:
C-c RET
There is no problem using it this way..

M-x toggle-debug-on-error RET

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  string-trim-right(nil nil)
  string-trim(nil)
  (list (string-trim (funcall parser nil response proc-info)) http-msg)
  (cond ((member http-status '("200" "100")) (list (string-trim (funcall parser nil response proc-info)) http-msg)) ((plist-get response :error) (let* ((error-data (plist-get response :error)) (error-msg (plist-get error-data :message)) (error-type (plist-get error-data :type)) (backend-name (let* ((cl-x ...)) (progn (or ... ...) (aref cl-x 1))))) (if (stringp error-data) (progn (message "%s error: (%s) %s" backend-name http-msg error-data) (setq error-msg (string-trim error-data))) (if (stringp error-msg) (progn (message "%s error: (%s) %s" backend-name http-msg (string-trim error-msg)))) (if error-type (progn (setq http-msg (concat "(" http-msg ") " ...))))) (list nil (concat "(" http-msg ") " (or error-msg ""))))) ((eq response 'json-read-error) (list nil (concat "(" http-msg ") Malformed JSON in response.") "Malformed JSON in response")) (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response.")))
  (if response (cond ((member http-status '("200" "100")) (list (string-trim (funcall parser nil response proc-info)) http-msg)) ((plist-get response :error) (let* ((error-data (plist-get response :error)) (error-msg (plist-get error-data :message)) (error-type (plist-get error-data :type)) (backend-name (let* (...) (progn ... ...)))) (if (stringp error-data) (progn (message "%s error: (%s) %s" backend-name http-msg error-data) (setq error-msg (string-trim error-data))) (if (stringp error-msg) (progn (message "%s error: (%s) %s" backend-name http-msg ...))) (if error-type (progn (setq http-msg ...)))) (list nil (concat "(" http-msg ") " (or error-msg ""))))) ((eq response 'json-read-error) (list nil (concat "(" http-msg ") Malformed JSON in response.") "Malformed JSON in response")) (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))
  (let* ((http-msg (and t (string-trim (buffer-substring (line-beginning-position) (line-end-position))))) (http-status (and http-msg (let ((saved-match-data (match-data))) (unwind-protect (progn (and ... ...)) (set-match-data saved-match-data t))))) (response (and http-status (progn (goto-char header-size) (condition-case nil (json-parse-buffer :object-type 'plist :null-object nil :false-object :json-false) (error 'json-read-error)))))) (if response (cond ((member http-status '("200" "100")) (list (string-trim (funcall parser nil response proc-info)) http-msg)) ((plist-get response :error) (let* ((error-data (plist-get response :error)) (error-msg (plist-get error-data :message)) (error-type (plist-get error-data :type)) (backend-name (let* ... ...))) (if (stringp error-data) (progn (message "%s error: (%s) %s" backend-name http-msg error-data) (setq error-msg ...)) (if (stringp error-msg) (progn ...)) (if error-type (progn ...))) (list nil (concat "(" http-msg ") " (or error-msg ""))))) ((eq response 'json-read-error) (list nil (concat "(" http-msg ") Malformed JSON in response.") "Malformed JSON in response")) (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response.")))
  (progn (goto-char (point-min)) (let* ((http-msg (and t (string-trim (buffer-substring (line-beginning-position) (line-end-position))))) (http-status (and http-msg (let ((saved-match-data ...)) (unwind-protect (progn ...) (set-match-data saved-match-data t))))) (response (and http-status (progn (goto-char header-size) (condition-case nil (json-parse-buffer :object-type ... :null-object nil :false-object :json-false) (error ...)))))) (if response (cond ((member http-status '("200" "100")) (list (string-trim (funcall parser nil response proc-info)) http-msg)) ((plist-get response :error) (let* ((error-data ...) (error-msg ...) (error-type ...) (backend-name ...)) (if (stringp error-data) (progn ... ...) (if ... ...) (if error-type ...)) (list nil (concat "(" http-msg ") " ...)))) ((eq response 'json-read-error) (list nil (concat "(" http-msg ") Malformed JSON in response.") "Malformed JSON in response")) (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))))
  (let ((header-size x29)) (progn (goto-char (point-min)) (let* ((http-msg (and t (string-trim (buffer-substring ... ...)))) (http-status (and http-msg (let (...) (unwind-protect ... ...)))) (response (and http-status (progn (goto-char header-size) (condition-case nil ... ...))))) (if response (cond ((member http-status '...) (list (string-trim ...) http-msg)) ((plist-get response :error) (let* (... ... ... ...) (if ... ... ... ...) (list nil ...))) ((eq response 'json-read-error) (list nil (concat "(" http-msg ") Malformed JSON in response.") "Malformed JSON in response")) (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response.")))))
  (let* ((x29 (cdr-safe val))) (let ((header-size x29)) (progn (goto-char (point-min)) (let* ((http-msg (and t (string-trim ...))) (http-status (and http-msg (let ... ...))) (response (and http-status (progn ... ...)))) (if response (cond ((member http-status ...) (list ... http-msg)) ((plist-get response :error) (let* ... ... ...)) ((eq response ...) (list nil ... "Malformed JSON in response")) (t (list nil ... "Could not parse HTTP response."))) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response."))))))
  (progn (ignore (consp val)) (let* ((x29 (cdr-safe val))) (let ((header-size x29)) (progn (goto-char (point-min)) (let* ((http-msg (and t ...)) (http-status (and http-msg ...)) (response (and http-status ...))) (if response (cond (... ...) (... ...) (... ...) (t ...)) (list nil (concat "(" http-msg ") Could not parse HTTP response.") "Could not parse HTTP response.")))))))
  (let* ((val (read (current-buffer)))) (progn (ignore (consp val)) (let* ((x29 (cdr-safe val))) (let ((header-size x29)) (progn (goto-char (point-min)) (let* ((http-msg ...) (http-status ...) (response ...)) (if response (cond ... ... ... ...) (list nil ... "Could not parse HTTP response."))))))))
  (let ((token (plist-get proc-info :token)) (parser (plist-get proc-info :parser))) (goto-char (point-max)) (search-backward token) (forward-char (- (or nil 1))) (let* ((val (read (current-buffer)))) (progn (ignore (consp val)) (let* ((x29 (cdr-safe val))) (let ((header-size x29)) (progn (goto-char (point-min)) (let* (... ... ...) (if response ... ...))))))))
  gptel-curl--parse-response((:token "dde91975118345b27f0ef7247cdf38c4" :backend #s(gptel-gemini :name "Gemini" :host "generativelanguage.googleapis.com" :header nil :protocol "https" :stream t :endpoint "/v1beta/models" :key "AIzaSyBM14mVL-FukErT17U8-mf5m_rePZx23vE" :models ("gemini-pro" "gemini-1.5-pro-latest") :url #f(lambda () [(endpoint "/v1beta/models") (protocol "https") (host "generativelanguage.googleapis.com") (stream t)] (let ((method (if ... "streamGenerateContent" "generateContent"))) (format "%s://%s%s/%s:%s?key=%s" protocol host endpoint gptel-model method (gptel--get-api-key)))) :curl-args nil) :parser #f(lambda (_backend response _info) [cl-struct-gptel-gemini-tags t] (progn (map-nested-elt response '(:candidates 0 :content :parts 0 :text)))) :callback gptel--insert-response :transformer nil :data (:contents [(:role "user" :parts (:text "Return your name.\n\nWho are you?"))] :safetySettings [(:category "HARM_CATEGORY_HARASSMENT" :threshold "BLOCK_NONE") (:category "HARM_CATEGORY_SEXUALLY_EXPLICIT" :threshold "BLOCK_NONE") (:category "HARM_CATEGORY_DANGEROUS_CONTENT" :threshold "BLOCK_NONE") (:category "HARM_CATEGORY_HATE_SPEECH" :threshold "BLOCK_NONE")] :generationConfig (:temperature 1.0)) :buffer #<buffer gptel-test.el> :position #<marker at 513 in gptel-test.el>))
  (save-current-buffer (set-buffer proc-buf) (gptel-curl--parse-response proc-info))
  (let* ((val (save-current-buffer (set-buffer proc-buf) (gptel-curl--parse-response proc-info)))) (progn (ignore (consp val)) (let* ((x22 (car-safe val)) (x23 (cdr-safe val))) (progn (ignore (consp x23)) (let* ((x24 (car-safe x23)) (x25 (cdr-safe x23))) (progn (ignore (consp x25)) (let* (... ...) (progn ... ...))))))))
  (progn (if gptel-log-level (progn (gptel-curl--log-response proc-buf proc-info))) (let* ((val (save-current-buffer (set-buffer proc-buf) (gptel-curl--parse-response proc-info)))) (progn (ignore (consp val)) (let* ((x22 (car-safe val)) (x23 (cdr-safe val))) (progn (ignore (consp x23)) (let* ((x24 ...) (x25 ...)) (progn (ignore ...) (let* ... ...))))))))
  (if proc-callback (progn (if gptel-log-level (progn (gptel-curl--log-response proc-buf proc-info))) (let* ((val (save-current-buffer (set-buffer proc-buf) (gptel-curl--parse-response proc-info)))) (progn (ignore (consp val)) (let* ((x22 (car-safe val)) (x23 (cdr-safe val))) (progn (ignore (consp x23)) (let* (... ...) (progn ... ...))))))))
  (let* ((s (and t (eq (process-status process) 'exit))) (proc-info (and s (alist-get process gptel-curl--process-alist))) (proc-callback (and proc-info (plist-get proc-info :callback)))) (if proc-callback (progn (if gptel-log-level (progn (gptel-curl--log-response proc-buf proc-info))) (let* ((val (save-current-buffer (set-buffer proc-buf) (gptel-curl--parse-response proc-info)))) (progn (ignore (consp val)) (let* ((x22 ...) (x23 ...)) (progn (ignore ...) (let* ... ...))))))))
  (let ((proc-buf (process-buffer process))) (let* ((s (and t (eq (process-status process) 'exit))) (proc-info (and s (alist-get process gptel-curl--process-alist))) (proc-callback (and proc-info (plist-get proc-info :callback)))) (if proc-callback (progn (if gptel-log-level (progn (gptel-curl--log-response proc-buf proc-info))) (let* ((val (save-current-buffer ... ...))) (progn (ignore (consp val)) (let* (... ...) (progn ... ...))))))) (let* ((p (assq process gptel-curl--process-alist))) (progn (if p (setq gptel-curl--process-alist (delq p gptel-curl--process-alist))) nil)) (kill-buffer proc-buf))
  gptel-curl--sentinel(#<process gptel-curl> "finished\n")

@ISouthRain
Copy link

ISouthRain commented Sep 20, 2024

As follows, it works normally:

;; Add to .emacs or init.el 
  (when (eq system-type 'windows-nt)
    ;; BUG?? There will be problems when using gptel-request directly on Windows. It needs to be enabled when used in the buffer started by the gptel command.
    (setopt gptel-use-curl nil)
    (add-hook 'gptel-mode-hook '(lambda ()
                                  (setq-local gptel-use-curl t))))    

@ppanko
Copy link
Author

ppanko commented Sep 26, 2024

@ISouthRain Your workaround solved the problem for me -- much appreciated!

@karthink
Copy link
Owner

karthink commented Nov 5, 2024

I'm hoping PR #456 has solved this issue. If you have/had this problem, could you test it with the latest gptel commit?

@ISouthRain
Copy link

I think this problem has been solved, at least I tested it in the master branch, there is no problem, it works.
Thanks you!
Great.

@karthink
Copy link
Owner

karthink commented Nov 7, 2024

Cool, please reopen if this issue persists.

@karthink karthink closed this as completed Nov 7, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants