Source code for evidence_fetcher.api

"""Public Python API."""

from __future__ import annotations

from evidence_fetcher._http import SearchHttpClient, UrlLibSearchHttpClient
from evidence_fetcher._providers.brave import BraveSearchProvider
from evidence_fetcher.models import Evidence, _canonical_url_key
from evidence_fetcher.ranking import EvidenceRanker, TfidfEvidenceRanker


[docs] def fetch_evidence( query: str, *, limit: int = 10, http_client: SearchHttpClient | None = None, ranker: EvidenceRanker | None = None, ) -> list[Evidence]: """Fetch normalized, deduplicated evidence for a search query. The first vertical slice uses Brave Search. Provider-specific request and response handling remain internal; callers receive only normalized :class:`Evidence` values. """ normalized_query = query.strip() if not normalized_query: raise ValueError("query must not be empty") if limit < 1: raise ValueError("limit must be at least 1") client = http_client if http_client is not None else UrlLibSearchHttpClient() provider = BraveSearchProvider(client) candidates = _deduplicate( provider.search(normalized_query, limit=limit), limit=limit, ) evidence_ranker = ranker if ranker is not None else TfidfEvidenceRanker() return evidence_ranker.rank(normalized_query, candidates)[:limit]
def _deduplicate(results: list[Evidence], *, limit: int) -> list[Evidence]: seen_urls: set[str] = set() deduplicated: list[Evidence] = [] for result in results: key = _canonical_url_key(result.url) if key in seen_urls: continue seen_urls.add(key) deduplicated.append(result) if len(deduplicated) >= limit: break return deduplicated