Bocha Search Provider Design
Date: 2026-06-25
Goal
将 Bocha 作为一等的 OpenSquilla 搜索 provider 加入,复用现有的搜索运行时、
provider catalog、onboarding、设置、诊断以及测试面。用户体验应当是:配置一个
Bocha key,随后正常的 web_search 与 web_discover 流程在 Bocha 是当前最佳可用
provider 时即可自动使用它。
本设计有意避免引入可见的中国区策略或 profile。Bocha 只是一个普通的 provider, 具备能力、凭据、排序与诊断。
Non-Goals
- 不添加可见的
cn、domestic或区域路由 profile。 - 不添加 Zhipu、独立的 reader 抽象,或多 provider 的结果融合。
- 不将
search_provider变成一个硬性的路由承诺。它仍然是search_api_key与search_api_key_env的凭据锚点。 - 在 MVP 中不添加面向用户的 provider 优先级控制。
- 默认情况下不将 fallback 扩大到空结果或低质量结果的重试。
Existing Runtime Boundaries
OpenSquilla 已经具备合适的扩展点:
- Provider specs 与 provider factories 位于
opensquilla.search.registry。 - 运行时可用性与 provider 排序位于
SearchRuntimeConfig与ResolvedSearchRuntime。 web_search使用规范的搜索 pipeline。web_discover拥有更轻量的 provider 路径,必须单独更新。- Onboarding 与设置消费 provider catalog payload。
search_fallback_policy当前支持off与network。
实现应当使用这些面,而不是引入第二个搜索 router。
Provider Behavior
在 src/opensquilla/search/providers/bocha.py 下添加 BochaSearchProvider。
预期的 API 形态:
- Endpoint:
https://api.bochaai.com/v1/web-search - Authentication:
Authorization: Bearer <api key> - Default environment variable:
BOCHA_SEARCH_API_KEY - Request options:
- query text
- max result count
- freshness mapping when
SearchOptions.recencyis set - summary enabled when supported
该 provider 应当将 Bocha 结果归一化为 SearchResult 字段:
- title from
name - url from
url - snippet from
snippet - provider content from
summarywhen present - published timestamp from
datePublished - source/site metadata from
siteName,displayUrl, or equivalent fields
Bocha 的 summaries 应当计为有用的 provider content,这样当 Bocha 已经返回了足够的 来源文本时,规范的 pipeline 就不会不必要地抓取页面。
Provider Spec
使用 SearchProviderSpec 注册 Bocha:
SearchProviderSpec(
provider_id="bocha",
requires_api_key=True,
env_key="BOCHA_SEARCH_API_KEY",
capabilities=frozenset({"web", "freshness", "content"}),
)
除非 Bocha API 支持等价的功能且有测试覆盖,否则不要声明 domain_filter。
Runtime Ordering
Bocha 应当参与现有的自动排序。建议的 MVP 排序:
_GENERAL_TIE_BREAKER = ("bocha", "tavily", "brave", "exa", "duckduckgo")
_TECHNICAL_TIE_BREAKER = ("exa", "bocha", "brave", "tavily", "duckduckgo")
_FRESHNESS_TIE_BREAKER = ("bocha", "tavily", "brave", "exa")
理由:
- 一般搜索与时效性搜索在配置了 Bocha 时应当优先使用它,因为它是针对可靠的 中国可访问搜索所做的有针对性的改进。
- 技术搜索应当保持 Exa 在前,因为它在语义与面向内容的研究中扮演的现有角色更强。
- 无 key 与部分 key 的用户由现有的可用性过滤器保护:不可用的有 key provider 会在返回排序之前被跳过。
Fallback Policy
保持 fallback 语义的狭窄:
off:最多发送一个 provider 的网络请求并呈现其错误;自动路由可以在任何请求 之前跳过一个缺 key 的候选。network:在一个被 provider 归类为瞬时的失败之后,最多再尝试一个额外的兼容 provider。自动路由优先选择下一个已配置凭据、排名靠前的 provider,当没有可用的 有 key fallback 时使用 DuckDuckGo。
不要在以下情况下 fallback:
- empty results
- low-quality results
- authentication or missing-key errors
- ordinary 4xx responses
- blocked/challenge responses
- parse errors
这为配置了多个付费 provider 的用户保留了成本、延迟与可预测性。
Configuration And Setup
受支持的 key 解析应当保持分层:
- active provider inline configured key
- active provider configured env var
- provider spec default env var
Bocha 应当支持所有现有的搜索设置路径:
- CLI configuration
- onboarding setup engine
- gateway setup payload
- desktop settings provider catalog
- web UI setup provider catalog
MVP 应当在 UI 拥有离线默认值的地方更新 fallback/静态 provider 列表,但唯一的 真相来源仍然是后端的 provider catalog。
Diagnostics
搜索运行时状态应当像其他 provider 一样展示 Bocha:
- available/unavailable
- credential source
- credential configured boolean
- skipped reason
- capabilities
诊断不得暴露原始 API key。
实时的 provider 探测可以稍后添加,但如果现有状态仍然基于可构建性/配置,则在 MVP 中并非必需。
Testing
必需的测试:
- 从一个有代表性的 Bocha payload 进行 provider 响应归一化。
- Bocha 的缺失 key 行为与凭据来源解析。
- 以下情形的运行时排序:
- no keyed providers
- only Bocha configured
- Bocha plus existing keyed providers
- technical mode
- freshness/news mode
web_search接受provider="bocha",且provider="auto"可以选择 Bocha。web_discover在配置后能接受并构建 Bocha。- Onboarding catalog 包含带
BOCHA_SEARCH_API_KEY的 Bocha。 - 文档与前端 catalog contract 测试包含 Bocha。
可选的实时测试:
- 一个使用
BOCHA_SEARCH_API_KEY的手动门控 Bocha smoke test。 - 该实时测试必须是 opt-in,且不得在正常 CI 中运行。
Documentation
更新:
docs/search.mddocs/configuration.md- relevant onboarding or setup docs if provider lists are repeated there
将 Bocha 文档化为一个普通的、运行时支持的 provider。避免将其描述为区域策略。
Acceptance Criteria
- 仅配置了
BOCHA_SEARCH_API_KEY的用户可以成功运行正常的自动 web 搜索。 - 仅拥有 Brave、Tavily、Exa 或 DuckDuckGo 的现有用户保持相同的行为,除了在可用时 Bocha 会出现在 provider catalogs 中。
- 所有当前的 fallback 语义保持不变。
- Bocha 出现在 CLI/onboarding/settings 的 provider 列表中。
- 测试覆盖 provider 映射、排序、配置与文档 contracts。