Skip to content

Commit

Permalink
gptel: Add arbitrary params to request
Browse files Browse the repository at this point in the history
Provide a way to add arbitrary parameters to the `gptel-request'
payload.  This is required for customizing parameters that gptel
does not provide user options for.

Examples in #330, #415, #471.

This is done by adding a `:request-params' field to the backend
and the model.  This should be a plist whose key/value pairs are
the additional request parameters and their values.  In case of
conflict, the model-specific request-parameters override the
backend-specific ones, which override gptel's dynamically set user
options.  Valid parameters depend on the specific API being
queried, and can be found in the corresponding API documentation.

* gptel.el (gptel--merge-plists, gptel--model-request-params): Add
utility functions.

* gptel-openai.el (gptel-backend, gptel-make-openai,
gptel-make-azure, gptel-make-gpt4all, gptel--request-data): Add
request-params slot to `gptel-backend' and keyword to
`gptel-make-openai' and its derivatives.  Merge model and
backend-specific request parameters when sending a request.

* gptel-privategpt.el (gptel-make-privategpt): Add request-params
keyword.

* gptel-ollama.el (gptel-make-ollama, gptel--request-data): Add
request-params keywod to `gptel-make-ollama'.  Merge model and
backend-specific request parameters when sending a request.
Remove ad hoc value of :num_ctx used according to #330 -- this is
no longer needed as :num_ctx can be set explicitly when defining
the Ollama model or backend.

* gptel-kagi.el (gptel--request-data): Add TODO to implement model
and backend-specific request parameters.

* gptel-gemini.el (gptel-make-gemini, gptel--request-data): Add
request-params keywod to `gptel-make-gemini'.  Merge model and
backend-specific request parameters when sending a request.

* gptel-curl.el (gptel-curl-get-response): Check model and
backend-specific stream settings in their request-params slot when
sending the request.  These take priority over the global
`gptel-stream' and the backend's `:stream' value.

* gptel-anthropic.el (gptel-make-anthropic, gptel--request-data):
Add request-params keywod to `gptel-make-ollama'.  Merge model and
backend-specific request parameters when sending a request.
  • Loading branch information
karthink committed Nov 11, 2024
1 parent db46b13 commit bcbbe67
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 28 deletions.
19 changes: 16 additions & 3 deletions gptel-anthropic.el
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@
:messages [,@prompts])))
(when gptel-temperature
(plist-put prompts-plist :temperature gptel-temperature))
prompts-plist))
;; Merge request params with model and backend params.
(gptel--merge-plists
prompts-plist
(gptel-backend-request-params gptel-backend)
(gptel--model-request-params gptel-model))))

(cl-defmethod gptel--parse-buffer ((_backend gptel-anthropic) &optional max-entries)
(let ((prompts) (prop)
Expand Down Expand Up @@ -262,6 +266,9 @@ Keys:
- `:cutoff-date': the knowledge cutoff date.
- `:request-params': a plist of additional request parameters to
include when using this model.
Information about the Anthropic models was obtained from the following
sources:
Expand All @@ -271,7 +278,7 @@ sources:

;;;###autoload
(cl-defun gptel-make-anthropic
(name &key curl-args stream key
(name &key curl-args stream key request-params
(header
(lambda () (when-let (key (gptel--get-api-key))
`(("x-api-key" . ,key)
Expand Down Expand Up @@ -324,7 +331,12 @@ alist, like:
((\"Content-Type\" . \"application/json\"))
KEY is a variable whose value is the API key, or function that
returns the key."
returns the key.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for."
(declare (indent 1))
(let ((backend (gptel--make-anthropic
:curl-args curl-args
Expand All @@ -336,6 +348,7 @@ returns the key."
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:url (if protocol
(concat protocol "://" host endpoint)
(concat host endpoint)))))
Expand Down
11 changes: 10 additions & 1 deletion gptel-curl.el
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,16 @@ the response is inserted into the current buffer after point."
(random) (emacs-pid) (user-full-name)
(recent-keys))))
(args (gptel-curl--get-args (plist-get info :data) token))
(stream (and gptel-stream (gptel-backend-stream gptel-backend)))
(stream (and ;; Check model-specific request-params for streaming preference
(let* ((model-params (gptel--model-request-params gptel-model))
(stream-spec (plist-get model-params :stream)))
;; If not present, there is no model-specific preference
(or (not (memq :stream model-params))
;; If present, it must not be :json-false or nil
(and stream-spec (not (eq stream-spec :json-false)))))
;; Check global and backend-specific streaming settings
gptel-stream
(gptel-backend-stream gptel-backend)))
(backend (buffer-local-value 'gptel-backend (plist-get info :buffer)))
(process (apply #'start-process "gptel-curl"
(generate-new-buffer "*gptel-curl*") "curl" args)))
Expand Down
20 changes: 17 additions & 3 deletions gptel-gemini.el
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@
(when params
(plist-put prompts-plist
:generationConfig params))
prompts-plist))
;; Merge request params with model and backend params.
(gptel--merge-plists
prompts-plist
(gptel-backend-request-params gptel-backend)
(gptel--model-request-params gptel-model))))

(cl-defmethod gptel--parse-buffer ((_backend gptel-gemini) &optional max-entries)
(let ((prompts) (prop)
Expand Down Expand Up @@ -230,6 +234,9 @@ Keys:
- `:cutoff-date': the knowledge cutoff date.
- `:request-params': a plist of additional request parameters to
include when using this model.
Information about the Gemini models was obtained from the following
source:
Expand All @@ -238,7 +245,8 @@ source:

;;;###autoload
(cl-defun gptel-make-gemini
(name &key curl-args header key (stream nil)
(name &key curl-args header key request-params
(stream nil)
(host "generativelanguage.googleapis.com")
(protocol "https")
(models gptel--gemini-models)
Expand Down Expand Up @@ -289,7 +297,12 @@ alist, like:
((\"Content-Type\" . \"application/json\"))
KEY (optional) is a variable whose value is the API key, or
function that returns the key."
function that returns the key.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for."
(declare (indent 1))
(let ((backend (gptel--make-gemini
:curl-args curl-args
Expand All @@ -300,6 +313,7 @@ function that returns the key."
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:key key
:url (lambda ()
(let ((method (if (and stream
Expand Down
1 change: 1 addition & 0 deletions gptel-kagi.el
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
(concat "\n\n" (mapconcat #'identity ref-strings "\n")))))
(concat output references)))

;; TODO: Add model and backend-specific request-params support
(cl-defmethod gptel--request-data ((_backend gptel-kagi) prompts)
"JSON encode PROMPTS for Kagi."
(pcase-exhaustive (gptel--model-name gptel-model)
Expand Down
22 changes: 14 additions & 8 deletions gptel-ollama.el
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ Intended for internal use only.")
:messages [,@prompts]
:stream ,(or (and gptel-stream gptel-use-curl
(gptel-backend-stream gptel-backend))
:json-false)))
;; TODO num_ctx chosen according to #330, make customizable
(options-plist (list :num_ctx 8192)))
:json-false))))
(when gptel-temperature
(setq options-plist
(plist-put options-plist :temperature
Expand All @@ -91,9 +89,11 @@ Intended for internal use only.")
(setq options-plist
(plist-put options-plist :num_predict
gptel-max-tokens)))
(when options-plist
(plist-put prompts-plist :options options-plist))
prompts-plist))
;; Merge request params with model and backend params.
(gptel--merge-plists
prompts-plist
(gptel-backend-request-params gptel-backend)
(gptel--model-request-params gptel-model))))

(cl-defmethod gptel--parse-buffer ((_backend gptel-ollama) &optional max-entries)
(let ((prompts) (prop)
Expand Down Expand Up @@ -177,7 +177,7 @@ If INJECT-MEDIA is non-nil wrap it with base64-encoded media files in the contex

;;;###autoload
(cl-defun gptel-make-ollama
(name &key curl-args header key models stream
(name &key curl-args header key models stream request-params
(host "localhost:11434")
(protocol "http")
(endpoint "/api/chat"))
Expand Down Expand Up @@ -227,13 +227,18 @@ KEY (optional) is a variable whose value is the API key, or
function that returns the key. This is typically not required
for local models like Ollama.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for.
Example:
-------
(gptel-make-ollama
\"Ollama\"
:host \"localhost:11434\"
:models \\='(\"mistral:latest\")
:models \\='(mistral:latest)
:stream t)"
(declare (indent 1))
(let ((backend (gptel--make-ollama
Expand All @@ -246,6 +251,7 @@ Example:
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:url (if protocol
(concat protocol "://" host endpoint)
(concat host endpoint)))))
Expand Down
43 changes: 33 additions & 10 deletions gptel-openai.el
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
(declare-function json-read "json")
(declare-function gptel-prompt-prefix-string "gptel")
(declare-function gptel-response-prefix-string "gptel")
(declare-function gptel--merge-plists "gptel")
(declare-function gptel-context--wrap "gptel-context")

(defmacro gptel--json-read ()
Expand Down Expand Up @@ -104,7 +105,8 @@ with differing settings.")
(gptel-backend (:constructor gptel--make-backend)
(:copier gptel--copy-backend))
name host header protocol stream
endpoint key models url curl-args)
endpoint key models url request-params
curl-args)

;;; OpenAI (ChatGPT)
(cl-defstruct (gptel-openai (:constructor gptel--make-openai)
Expand Down Expand Up @@ -140,8 +142,12 @@ with differing settings.")
(when gptel-temperature
(plist-put prompts-plist :temperature gptel-temperature))
(when gptel-max-tokens
(plist-put prompts-plist :max_tokens gptel-max-tokens))
prompts-plist))
(plist-put prompts-plist :max_completion_tokens gptel-max-tokens))
;; Merge request params with model and backend params.
(gptel--merge-plists
prompts-plist
(gptel-backend-request-params gptel-backend)
(gptel--model-request-params gptel-model))))

(cl-defmethod gptel--parse-buffer ((_backend gptel-openai) &optional max-entries)
(let ((prompts) (prop)
Expand Down Expand Up @@ -248,7 +254,7 @@ files in the context."

;;;###autoload
(cl-defun gptel-make-openai
(name &key curl-args models stream key
(name &key curl-args models stream key request-params
(header
(lambda () (when-let (key (gptel--get-api-key))
`(("Authorization" . ,(concat "Bearer " key))))))
Expand Down Expand Up @@ -298,7 +304,12 @@ alist, like:
((\"Content-Type\" . \"application/json\"))
KEY (optional) is a variable whose value is the API key, or
function that returns the key."
function that returns the key.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for."
(declare (indent 1))
(let ((backend (gptel--make-openai
:curl-args curl-args
Expand All @@ -310,6 +321,7 @@ function that returns the key."
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:url (if protocol
(concat protocol "://" host endpoint)
(concat host endpoint)))))
Expand All @@ -325,7 +337,7 @@ function that returns the key."
(protocol "https")
(header (lambda () `(("api-key" . ,(gptel--get-api-key)))))
(key 'gptel-api-key)
models stream endpoint)
models stream endpoint request-params)
"Register an Azure backend for gptel with NAME.
Keyword arguments:
Expand All @@ -334,7 +346,7 @@ CURL-ARGS (optional) is a list of additional Curl arguments.
HOST is the API host.
MODELS is a list of available model names.
MODELS is a list of available model names, as symbols.
STREAM is a boolean to toggle streaming responses, defaults to
false.
Expand All @@ -351,6 +363,11 @@ alist, like:
KEY (optional) is a variable whose value is the API key, or
function that returns the key.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for.
Example:
-------
Expand All @@ -361,7 +378,7 @@ Example:
:endpoint
\"/openai/deployments/DEPLOYMENT_NAME/completions?api-version=2023-05-15\"
:stream t
:models \\='(\"gpt-3.5-turbo\" \"gpt-4\"))"
:models \\='(gpt-3.5-turbo gpt-4))"
(declare (indent 1))
(let ((backend (gptel--make-openai
:curl-args curl-args
Expand All @@ -373,6 +390,7 @@ Example:
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:url (if protocol
(concat protocol "://" host endpoint)
(concat host endpoint)))))
Expand All @@ -392,7 +410,7 @@ CURL-ARGS (optional) is a list of additional Curl arguments.
HOST is where GPT4All runs (with port), typically localhost:4891
MODELS is a list of available model names.
MODELS is a list of available model names, as symbols.
STREAM is a boolean to toggle streaming responses, defaults to
false.
Expand All @@ -411,14 +429,19 @@ KEY (optional) is a variable whose value is the API key, or
function that returns the key. This is typically not required for
local models like GPT4All.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for.
Example:
-------
(gptel-make-gpt4all
\"GPT4All\"
:protocol \"http\"
:host \"localhost:4891\"
:models \\='(\"mistral-7b-openorca.Q4_0.gguf\"))")
:models \\='(mistral-7b-openorca.Q4_0.gguf))")

(provide 'gptel-openai)
;;; gptel-openai.el ends here
16 changes: 13 additions & 3 deletions gptel-privategpt.el
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,16 @@
(plist-put prompts-plist :temperature gptel-temperature))
(when gptel-max-tokens
(plist-put prompts-plist :max_tokens gptel-max-tokens))
prompts-plist))
;; Merge request params with model and backend params.
(gptel--merge-plists
prompts-plist
(gptel-backend-request-params gptel-backend)
(gptel--model-request-params gptel-model))))


;;;###autoload
(cl-defun gptel-make-privategpt
(name &key curl-args stream key
(name &key curl-args stream key request-params
(header
(lambda () (when-let (key (gptel--get-api-key))
`(("Authorization" . ,(concat "Bearer " key))))))
Expand Down Expand Up @@ -137,7 +141,12 @@ KEY is a variable whose value is the API key, or function that
returns the key.
CONTEXT and SOURCES: if true (the default), use available context
and provide sources used by the model to generate the response."
and provide sources used by the model to generate the response.
REQUEST-PARAMS (optional) is a plist of additional HTTP request
parameters (as plist keys) and values supported by the API. Use
these to set parameters that gptel does not provide user options
for."
(declare (indent 1))
(let ((backend (gptel--make-privategpt
:curl-args curl-args
Expand All @@ -149,6 +158,7 @@ and provide sources used by the model to generate the response."
:protocol protocol
:endpoint endpoint
:stream stream
:request-params request-params
:url (if protocol
(concat protocol "://" host endpoint)
(concat host endpoint))
Expand Down
Loading

0 comments on commit bcbbe67

Please sign in to comment.