Add Serply web and Google Scholar retrievers - #2068
Conversation
Add two optional retrievers backed by the Serply SERP API, following the
existing per-provider pattern: RETRIEVER=serply for Google web results
(mirroring the serper retriever) and RETRIEVER=serply_scholar for Google
Scholar, which the project did not have. Both read SERPLY_API_KEY, normalize
to the standard {title, href, body} shape, and always return a list. No new
dependency and no change for users who do not opt in.
|
Reviewed properly — thanks, this is a clean PR. It applies to current Why this is not merged yet, and it isn't code quality.
That is a scope decision for @assafelovic, not a verdict on this patch. The sustainable answer is probably a documented plugin path — an entry-point group so a vendor ships and versions their own package — rather than accepting or rejecting each of these case by case, which is exactly why they have all been sitting. Not closing it. Flagging it so the decision gets made once instead of six times. |
Add Serply retrievers (web + Google Scholar)
This adds two optional retrievers backed by the Serply SERP API, following the existing per-provider pattern (one directory under
gpt_researcher/retrievers/, registered inretrievers/__init__.py,retrievers/utils.py, andactions/retriever.py):RETRIEVER=serply- Google web results, mirroring theserperretriever it sits next to.RETRIEVER=serply_scholar- Google Scholar results. GPT Researcher already has arXiv, Semantic Scholar, PubMed Central, and OpenAlex, but no Google Scholar, which spans publishers, theses, and citations across every field. This gives the research flow that coverage.Both read
SERPLY_API_KEYfrom the environment and normalize responses to the standard{title, href, body}shape. Like the sibling retrievers,search()always returns a list, neverNone.Why two
The repo already pairs same-vendor SERP wrappers (
serperandserpapi) and ships four academic retrievers, so both variants fit the existing surface. Each is small and self-contained; the file count comes from the per-provider scaffold applied twice, not from a large change to any one file.Optional and non-breaking
Nothing changes for anyone who does not set
RETRIEVER=serplyorserply_scholar. No new dependency is added (requestsis already required). Note: Serply sits behind Cloudflare, which rejects the defaultrequestsUser-Agent, so both retrievers send an explicit one.Testing
api.serply.io, confirming real web and scholar results normalize to the expected shape.tests/test_serply_returns_list.py, mirroringtest_serper_returns_list.py, covering the return-a-list error paths with the network mocked.Docs: added both entries to
docs/docs/gpt-researcher/search-engines/search-engines.md. More at serply.io/docs.Disclosure: I work with Serply. Happy to adjust scope, naming, or split the web and scholar retrievers into separate PRs if you prefer.