branch: elpa/gptel
commit ead44a2891f4c384546c2032c8bb488ca0e8b890
Author: Trannie Carter <[email protected]>
Commit: Karthik Chikmagalur <[email protected]>
gptel-ollama: Handle streaming tool calls
* gptel-ollama.el (gptel-curl--parse-stream): Handle streaming
tool calls. The handling is identical to the non-streaming case,
as it appears Ollama sends the entire tool call in one response
chunk.
* gptel-request.el (gptel-request): Don't block streaming when
using Ollama + tools.
---
gptel-ollama.el | 18 +++++++++++++++---
gptel-request.el | 3 ---
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/gptel-ollama.el b/gptel-ollama.el
index c17e8b4150d..abecfb6c551 100644
--- a/gptel-ollama.el
+++ b/gptel-ollama.el
@@ -55,9 +55,22 @@ Intended for internal use only.")
(setq pt (point))
(let ((done (map-elt content :done))
(reasoning (map-nested-elt content '(:message :thinking)))
- (response (map-nested-elt content '(:message :content))))
+ (response (map-nested-elt content '(:message :content)))
+ (tool-calls (map-nested-elt content '(:message :tool_calls))))
(when (and response (not (eq response :null)))
(push response content-strs))
+ (when (and tool-calls (not (eq tool-calls :null)))
+ (gptel--inject-prompt
+ (plist-get info :backend) (plist-get info :data)
+ `(:role "assistant" :content :null :tool_calls ,(vconcat
tool-calls)))
+ (cl-loop
+ for tool-call across tool-calls ;replace ":arguments" with
":args"
+ for call-spec = (copy-sequence (plist-get tool-call :function))
+ do (plist-put call-spec :args
+ (plist-get call-spec :arguments))
+ (plist-put call-spec :arguments nil)
+ collect call-spec into tool-use
+ finally (plist-put info :tool-use tool-use)))
(if (and reasoning (not (eq reasoning :null)))
(plist-put info :reasoning
(concat (plist-get info :reasoning) reasoning))
@@ -124,8 +137,7 @@ Store response metadata in state INFO."
(when (and gptel-use-tools gptel-tools)
;; TODO(tool): Find out how to force tool use for Ollama
(plist-put prompts-plist :tools
- (gptel--parse-tools backend gptel-tools))
- (plist-put prompts-plist :stream :json-false))
+ (gptel--parse-tools backend gptel-tools)))
;; if the temperature and max-tokens aren't set as
;; backend/model-specific, use the global settings
(when (and gptel-temperature (not (plist-get options-plist :temperature)))
diff --git a/gptel-request.el b/gptel-request.el
index dc193be7894..955f1c09217 100644
--- a/gptel-request.el
+++ b/gptel-request.el
@@ -2050,9 +2050,6 @@ Initiate the request when done."
;; TODO(tool) Limit tool use to capable models after documenting
:capabilities
;; (gptel-use-tools (and (gptel--model-capable-p 'tool-use)
gptel-use-tools))
(stream (and (plist-get info :stream) gptel-use-curl gptel-stream
- ;; HACK(tool): no stream if Ollama + tools. Need to
find a better way
- (not (and (eq (type-of gptel-backend) 'gptel-ollama)
- gptel-tools gptel-use-tools))
;; Check model-specific request-params for streaming
preference
(let* ((model-params (gptel--model-request-params
gptel-model))
(stream-spec (plist-get model-params
:stream)))