Repository navigation
Feature Search
事实来源:主仓
pr-88@a312645的src/souwen/facade/search.py、src/souwen/cli/search.py、src/souwen/server/routes/search.py。
SouWen 把"搜索"统一为按 (domain, capability) 的派发。门面层从 registry 挑默认源,业务层 Client 各自实现 search 方法,门面用 MethodSpec.param_map 把统一参数映射到各 Client 的实参。
| Capability | 中文 | 源数量 | 默认源 |
|---|---|---|---|
search |
通用搜索 | 72 | openalex+arxiv(paper)/ google_patents(patent)/ duckduckgo+bing(web) |
search_news |
新闻搜索 | 1 | duckduckgo_news |
search_images |
图片搜索 | 1 | duckduckgo_images |
search_videos |
视频搜索 | 1 | duckduckgo_videos |
search_users / search_articles
|
用户 / 专栏文章 | 1 / 1 | bilibili |
非标准命名空间能力(exa:find_similar / unpaywall:find_oa)需显式指定 sources=[...]。
souwen search paper "transformer" -s openalex,arxiv -n 5
souwen search patent "quantum" -s uspto_odp -n 5
souwen search web "python asyncio" -e duckduckgo,bing -n 10
souwen search images "diagram"
souwen search videos "AI agent"curl "http://localhost:8000/api/v1/search/paper?q=transformer&sources=openalex,arxiv&per_page=5"
curl "http://localhost:8000/api/v1/search/web?q=python&engines=duckduckgo,bing&per_page=10"
curl "http://localhost:8000/api/v1/search/images?q=diagram&max_results=20&safesearch=off"from souwen.facade import search, search_all
# 单 domain
papers = await search("transformer", domain="paper", limit=5)
# 跨 domain
mixed = await search_all("quantum", domains=["paper", "web", "knowledge"])
# 指定 capability
news = await search("AI policy", domain="web", capability="search_news", limit=10)
# 命名空间能力(须显式源)
oa = await search("10.1038/nature12345", domain="paper",
capability="unpaywall:find_oa", sources=["unpaywall"])每个源在 SourceAdapter 上有 default_for: frozenset[str]。registry.defaults_for(domain, capability) 按声明顺序返回所有标了 <domain>:<capability> 的源。
-
paper:search默认:openalex + arxiv(CLI 兼容旧版给 5 源) -
patent:search默认:google_patents -
web:search默认:duckduckgo + bing
高风险源(带
tags={"high_risk"})必须default_for=frozenset(),不进默认集——tests/registry/test_consistency.py::test_high_risk_not_default强制校验。
-
per-event-loop Semaphore:channel
search默认 10 个并发。 -
每源独立限流:Token Bucket + 滑动窗口;触发
RateLimitError。 -
异常隔离:单源失败 →
meta.failed,不阻塞其他源。 -
HTTP 端点:所有源失败返
502 bad_gateway;超过timeout返504。
import asyncio
from souwen.facade import search
async def find_papers(query: str):
resp = await search(query, domain="paper",
sources=["openalex", "semantic_scholar", "arxiv"], limit=5)
seen = set()
for sr in resp:
for r in sr.results:
if r.doi and r.doi not in seen:
seen.add(r.doi)
print(f"{r.year} | {r.title[:80]} | {r.doi}")
asyncio.run(find_papers("graph neural network"))Last calibrated:2026-05-04 · 主仓 pr-88 @ a312645`
Home · Quick Start · Architecture · FAQ · Troubleshooting · Coverage Manifest · Contributing
权威技术文档以主仓 docs/ 与 src/ 为准。本项目仅供 Python 学习与技术研究使用,禁止用于违反法律法规或第三方服务条款的用途。