Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

gptel-request wrong type argument #319

Open
ppanko opened this issue May 21, 2024 · 10 comments
Open

gptel-request wrong type argument #319

ppanko opened this issue May 21, 2024 · 10 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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants