feat: update the web_search_coyote tool to attempt to use the current model first then fallback to the configured model for web searches
This commit is contained in:
1 file changed
+65
-13
@@ -8,10 +8,17 @@ set -e
|
|||||||
|
|
||||||
# @meta require-tools coyote
|
# @meta require-tools coyote
|
||||||
|
|
||||||
# @env WEB_SEARCH_MODEL=gemini:gemini-2.5-flash The model for web-searching.
|
# @env WEB_SEARCH_MODEL=gemini:gemini-2.5-flash The fallback model for web-searching.
|
||||||
#
|
#
|
||||||
# supported coyote models:
|
# Model selection: when WEB_SEARCH_USE_CURRENT_MODEL is true (the default) and
|
||||||
# - gemini:gemini-2.0-*
|
# the running session's model (COYOTE_CURRENT_MODEL, injected by coyote for
|
||||||
|
# every tool call) natively supports web search, the search runs on the current
|
||||||
|
# model first. If the current model is unsupported, or if the search fails at
|
||||||
|
# runtime, the tool falls back to WEB_SEARCH_MODEL. If that also fails, the
|
||||||
|
# tool fails.
|
||||||
|
#
|
||||||
|
# supported coyote models (native web search):
|
||||||
|
# - gemini:*
|
||||||
# - vertexai:gemini-*
|
# - vertexai:gemini-*
|
||||||
# - perplexity:*
|
# - perplexity:*
|
||||||
# - ernie:*
|
# - ernie:*
|
||||||
@@ -20,29 +27,74 @@ set -e
|
|||||||
# client — the codex OAuth path uses the
|
# client — the codex OAuth path uses the
|
||||||
# Responses API where this parameter
|
# Responses API where this parameter
|
||||||
# does not exist)
|
# does not exist)
|
||||||
|
# @env WEB_SEARCH_USE_CURRENT_MODEL=true Prefer the running session's model when it natively supports web search.
|
||||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# Returns 0 when the model natively supports web search via a known mechanism.
|
||||||
main() {
|
supports_native_search() {
|
||||||
client="${WEB_SEARCH_MODEL%%:*}"
|
case "$1" in
|
||||||
|
gemini:* | vertexai:gemini-* | perplexity:* | ernie:* | claude:*) return 0 ;;
|
||||||
|
openai:gpt-4o*search-preview*) return 0 ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "$client" == "gemini" ]]; then
|
# Exports the request-body patch that enables native web search for the
|
||||||
|
# given model's client (clearing any patch left over from a prior attempt).
|
||||||
|
export_search_patch() {
|
||||||
|
unset COYOTE_PATCH_GEMINI_CHAT_COMPLETIONS \
|
||||||
|
COYOTE_PATCH_VERTEXAI_CHAT_COMPLETIONS \
|
||||||
|
COYOTE_PATCH_ERNIE_CHAT_COMPLETIONS \
|
||||||
|
COYOTE_PATCH_CLAUDE_CHAT_COMPLETIONS \
|
||||||
|
COYOTE_PATCH_OPENAI_CHAT_COMPLETIONS
|
||||||
|
|
||||||
|
case "${1%%:*}" in
|
||||||
|
gemini)
|
||||||
export COYOTE_PATCH_GEMINI_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"google_search":{}}]}}}'
|
export COYOTE_PATCH_GEMINI_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"google_search":{}}]}}}'
|
||||||
elif [[ "$client" == "vertexai" ]]; then
|
;;
|
||||||
|
vertexai)
|
||||||
export COYOTE_PATCH_VERTEXAI_CHAT_COMPLETIONS='{
|
export COYOTE_PATCH_VERTEXAI_CHAT_COMPLETIONS='{
|
||||||
"gemini-1.5-.*":{"body":{"tools":[{"googleSearchRetrieval":{}}]}},
|
"gemini-1.5-.*":{"body":{"tools":[{"googleSearchRetrieval":{}}]}},
|
||||||
"gemini-2.0-.*":{"body":{"tools":[{"google_search":{}}]}}
|
"gemini-2.0-.*":{"body":{"tools":[{"google_search":{}}]}}
|
||||||
}'
|
}'
|
||||||
elif [[ "$client" == "ernie" ]]; then
|
;;
|
||||||
|
ernie)
|
||||||
export COYOTE_PATCH_ERNIE_CHAT_COMPLETIONS='{".*":{"body":{"web_search":{"enable":true}}}}'
|
export COYOTE_PATCH_ERNIE_CHAT_COMPLETIONS='{".*":{"body":{"web_search":{"enable":true}}}}'
|
||||||
elif [[ "$client" == "claude" ]]; then
|
;;
|
||||||
|
claude)
|
||||||
export COYOTE_PATCH_CLAUDE_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"type":"web_search_20250305","name":"web_search","max_uses":5}]}}}'
|
export COYOTE_PATCH_CLAUDE_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"type":"web_search_20250305","name":"web_search","max_uses":5}]}}}'
|
||||||
elif [[ "$client" == "openai" ]]; then
|
;;
|
||||||
|
openai)
|
||||||
# Chat Completions native search exists only on the search-preview
|
# Chat Completions native search exists only on the search-preview
|
||||||
# models; the regex scopes the patch so other OpenAI models run
|
# models; the regex scopes the patch so other OpenAI models run
|
||||||
# unpatched instead of erroring on an unsupported parameter.
|
# unpatched instead of erroring on an unsupported parameter.
|
||||||
export COYOTE_PATCH_OPENAI_CHAT_COMPLETIONS='{"gpt-4o.*search-preview.*":{"body":{"web_search_options":{}}}}'
|
export COYOTE_PATCH_OPENAI_CHAT_COMPLETIONS='{"gpt-4o.*search-preview.*":{"body":{"web_search_options":{}}}}'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
run_search() {
|
||||||
|
export_search_patch "$1"
|
||||||
|
coyote -m "$1" "$argc_query" >>"$LLM_OUTPUT"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local fallback="${WEB_SEARCH_MODEL:-gemini:gemini-2.5-flash}"
|
||||||
|
local current="${COYOTE_CURRENT_MODEL:-}"
|
||||||
|
local primary=""
|
||||||
|
|
||||||
|
if [[ "${WEB_SEARCH_USE_CURRENT_MODEL:-true}" == "true" && -n "$current" && "$current" != "$fallback" ]] &&
|
||||||
|
supports_native_search "$current"; then
|
||||||
|
primary="$current"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
coyote -m "$WEB_SEARCH_MODEL" "$argc_query" >> "$LLM_OUTPUT"
|
if [[ -n "$primary" ]]; then
|
||||||
}
|
if run_search "$primary"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "web_search: search with current model '$primary' failed; falling back to '$fallback'" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_search "$fallback"
|
||||||
|
}
|
||||||
Reference in new issue
Block a user