Opt-in provider fallback: a list of provider specs, tried in order until one answers, such as free first and paid last:
Perplexed.search("zoning setbacks", provider: [:searxng, :ceramic, :firecrawl])Perplexed.Search.run/3 comes here whenever the provider spec is a
list, so the same list works in Perplexed.search/2, Perplexed.answer/2
(its :provider) and the provider setting. A single provider behaves as
it always has.
A provider's answer moves the chain on when its outcome is in
:fallback_on: :error (it failed or timed out) and :empty (it
answered with no hits, often how a quiet block looks) by default. Each
provider runs in a task under Perplexed.TaskSupervisor and gets
:provider_timeout_ms, capped by what is left of the chain's
:deadline_ms; one that overruns is shut down and counts as an error.
Once the deadline passes, the providers left are recorded as :deadline
and not called.
The Perplexed.Search.Result names the provider that answered, carries
every attempt in attempts, and costs what all of them cost (a paid
provider that answered empty still bills). When every provider fails, an
empty answer from one of them is still returned as the result; with no
answer at all the chain is {:error, {:upstream, %{reason: :all_providers_failed, attempts: attempts}}}. Each provider's call still
emits its own [:perplexed, :search, ...] span. Every attempt also
emits [:perplexed, :search, :attempt] with duration (ms) and cost, and
metadata provider, outcome and billable.
Summary
Functions
Runs query down chain.
Types
@type attempt() :: %{ provider: Perplexed.Search.spec(), outcome: outcome(), cost: float(), duration_ms: non_neg_integer() }
@type outcome() :: :ok | :empty | :timeout | :deadline | {:error, term()}
Functions
@spec run([Perplexed.Search.spec(), ...], String.t(), keyword()) :: {:ok, Perplexed.Search.Result.t()} | {:error, Perplexed.error()}
Runs query down chain.
Options
:provider_timeout_ms- each provider's limit, default 15000.:deadline_ms- the whole chain's limit, default 30000.:fallback_on- outcomes that move on to the next provider, any of:errorand:empty, default[:error, :empty].
Other options go to every provider.