branch: externals/llm
commit d5085859d22efb57c4d5c95ec8a5a9e54d112cc5
Author: Andrew Hyatt <[email protected]>
Commit: GitHub <[email protected]>
Add reasoning output for Gemini (#210)
---
NEWS.org | 2 ++
llm-vertex.el | 51 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/NEWS.org b/NEWS.org
index 8283847ce5..d7dce6ee11 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -1,3 +1,5 @@
+* Version 0.27.3
+- Add reasoning output for Gemini.
* Version 0.27.2
- Add JSON response capabilities to Gemini, which had a non-standard API.
- Add Claude 4.1 to supported models
diff --git a/llm-vertex.el b/llm-vertex.el
index 31677de833..b587e9ebf7 100644
--- a/llm-vertex.el
+++ b/llm-vertex.el
@@ -153,7 +153,23 @@ the key must be regenerated every hour."
(assoc-default 'content
(aref (assoc-default 'candidates
response) 0)))))
(when parts
- (assoc-default 'text (aref parts (- (length parts)
1)))))))))
+ (assoc-default 'text (seq-find (lambda (part)
+ (not (assoc-default
'thought part)))
+ parts))))))))
+
+(cl-defmethod llm-provider-extract-reasoning ((provider llm-google) response)
+ (if (vectorp response)
+ (llm-provider-extract-reasoning provider (aref response 0))
+ ;; In some error cases, the response does not have any candidates.
+ (when (assoc-default 'candidates response)
+ (when-let* ((parts (assoc-default
+ 'parts (assoc-default
+ 'content
+ (aref (assoc-default 'candidates response)
0))))
+ (thought-part (seq-find (lambda (part)
+ (assoc-default 'thought part))
+ parts)))
+ (assoc-default 'text thought-part)))))
(cl-defmethod llm-provider-extract-tool-uses ((provider llm-google) response)
(if (vectorp response)
@@ -254,12 +270,12 @@ the key must be regenerated every hour."
(setq inner-plist
(plist-put inner-plist
prop
(llm-vertex-transform-response-format prep-def))))
- v)
+ v)
inner-plist))
((eq k :items)
(llm-vertex-transform-response-format v))
(t v))))))
- format)
+ format)
result))
(cl-defmethod llm-provider-chat-request ((provider llm-vertex) prompt _)
@@ -287,18 +303,23 @@ which is necessary to properly set some paremeters."
(setq params-plist (plist-put params-plist :response_schema
(llm-vertex-transform-response-format
(llm-provider-utils-convert-to-serializable format))))))
- (when-let ((budget (llm-chat-prompt-reasoning prompt))
- (max-budget (if (eq model 'gemini-2.5-pro) 32768 24576)))
- (when (member 'reasoning (llm-model-capabilities (llm-models-by-symbol
model)))
- (if (and (eq model 'gemini-2.5-pro) (eq budget 'none))
- (display-warning 'llm :warning "Cannot turn off reasoning in
Gemini 2.5 Pro, ignoring reasoning setting")
- (setq params-plist (plist-put params-plist :thinkingConfig
- `(:thinkingBudget
- ,(pcase budget
- ('none 0)
- ('light 1024)
- ('medium (/ max-budget 2))
- ('maximum max-budget))))))))
+ (let* (thinking-plist
+ (model-data (llm-models-by-symbol model)))
+ (when (and model-data (member 'reasoning (llm-model-capabilities
model-data)))
+ (setq thinking-plist '(:includeThoughts t))
+ (when-let ((budget (llm-chat-prompt-reasoning prompt))
+ (max-budget (if (eq model 'gemini-2.5-pro) 32768 24576)))
+ (if (and (eq model 'gemini-2.5-pro) (eq budget 'none))
+ (display-warning 'llm :warning "Cannot turn off reasoning in
Gemini 2.5 Pro, ignoring reasoning setting")
+ (setq thinking-plist (plist-put thinking-plist
+ :thinkingBudget
+ (pcase budget
+ ('none 0)
+ ('light 1024)
+ ('medium (/ max-budget 2))
+ ('maximum max-budget)))))))
+ (when thinking-plist
+ (setq params-plist (plist-put params-plist :thinkingConfig
thinking-plist))))
(when params-plist
`(:generationConfig ,params-plist))))