Creates a tool that lets any model search the web while it answers. Pass it to
chat() with .tools, and the model decides when to search and what to search
for. It works the same way with every provider that supports tools, including
local models through ollama() or llamacpp() that have no web access of their
own.
The model only chooses the search query. Everything else, such as how many
results come back and whether full page text is included, is fixed when you
create the tool, so a model cannot run up your search bill by asking for more.
The arguments are the same as for websearch(), which runs a single search
directly and returns the results as a tibble.
Usage
websearch_tool(
.backend = c("tavily", "searxng"),
.server = NULL,
.max_results = 5,
.include_content = FALSE,
.max_chars = 4000,
.timeout = 30,
...
)Arguments
- .backend
The search service to use:
"tavily"(the default) or"searxng". See the section on search services below.- .server
The address of your SearXNG server, such as
"http://localhost:8888". IfNULL, theSEARXNG_SERVERenvironment variable is used. Only for.backend = "searxng".- .max_results
How many results each search returns, between 1 and 20.
- .include_content
If
TRUE, each result also carries the text of the page, cut to.max_charscharacters. This helps with questions a short excerpt cannot answer, but it makes every tool result much longer. Only Tavily can do this.- .max_chars
The maximum number of characters of page text per result when
.include_content = TRUE. UseInfto keep the whole page.- .timeout
Seconds to wait for each request to the search service. Busy or failing services are asked up to three times, for at most a minute in total.
- ...
Further search options passed to the search service by name. The options each service accepts are listed in the section on search services below; a misspelled option is an error.
Value
A tool object to pass to the .tools argument of chat().
Details
Each search returns one block of text to the model: the query, the date of the search, and a numbered list of results with title, URL, publication date where the service knows it, and an excerpt. The tool asks the model to cite the URLs it relies on.
If a search fails, for example because the key is wrong or the monthly credits are used up, the model receives the error message as the search result instead of the conversation stopping. It will usually tell you what went wrong.
The tool is named tidyllm_web_search, which is the name you will see in
the tool calls of a conversation. The Tavily key or SearXNG address is read
once, when the tool is created: set it before calling websearch_tool(),
and create the tool again after changing it. The key is stored inside the
tool, so do not save the tool object to a file you share.
Search services
Tavily is a paid search API with a free plan of 1,000 credits per month,
no credit card needed; one basic search costs one credit. It needs a
TAVILY_API_KEY environment variable. Options: search_depth ("basic",
"advanced", "fast" or "ultra-fast"; "advanced" costs two credits),
topic ("general", "news" or "finance"), time_range ("day",
"week", "month" or "year", or the short forms "d", "w", "m" and
"y"), start_date and end_date
("YYYY-MM-DD"), include_domains, exclude_domains, country,
include_answer and others from Tavily's search API.
SearXNG is a free search engine you run yourself, which collects results
from Google, Brave and other engines. Use your own server: public SearXNG
servers usually refuse programs. Its settings.yml must list json under
search: formats:, and for a server only you use, server: limiter: false
stops it from blocking repeated searches. Set the address with .server or
the SEARXNG_SERVER environment variable. SearXNG returns no page text.
Options: categories (such as "general" or "news"), engines (such as
c("google", "brave")), language (such as "de"), time_range ("day",
"week", "month" or "year"), safesearch (0, 1 or 2) and
pageno (which page of results, for more than one page). A search fails if
it finds nothing and at least one engine did not answer, for example because
it asked for a CAPTCHA.
Examples
if (FALSE) { # \dontrun{
llm_message("What changed in the latest R release?") |>
chat(ollama(), .tools = websearch_tool())
news_search <- websearch_tool(.max_results = 8, topic = "news", time_range = "week")
llm_message("Summarise this week's news on EU AI regulation.") |>
chat(claude(), .tools = news_search)
} # }
