Les pipelines RAG LangChain utilisent couramment TavilySearchResults comme récupérateur de recherche web. Après l'acquisition par Nebius, passer à un fournisseur indépendant réduit le risque lié au fournisseur. Scavio s'insère dans le même emplacement du pipeline : définissez un outil personnalisé avec la même interface, et votre chaîne continue de fonctionner. Ce tutoriel montre les modifications de code exactes pour LangChain RetrievalQA, create_retrieval_chain et les modèles RAG basés sur des agents.
Prérequis
- Python 3.9+ installé
- Paquets langchain et langchain-core installés
- Une clé API Scavio depuis scavio.dev
- Une clé API LLM (OpenAI ou Anthropic)
Parcours
Étape 1: Créer le récupérateur de recherche Scavio
Construisez un récupérateur compatible LangChain qui appelle l'API Scavio. Il renvoie des objets Document avec page_content et metadata, correspondant à ce que fournit TavilySearchResults.
import os, requests
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
from typing import List
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
class ScavioRetriever(BaseRetriever):
api_key: str = ''
num_results: int = 5
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.api_key = self.api_key or SCAVIO_KEY
def _get_relevant_documents(self, query: str) -> List[Document]:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': self.api_key, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': self.num_results})
resp.raise_for_status()
docs = []
for r in resp.json().get('organic_results', []):
docs.append(Document(
page_content=f"{r['title']}\n{r.get('snippet', '')}",
metadata={'source': r['link'], 'title': r['title']}
))
return docs
retriever = ScavioRetriever(num_results=5)
docs = retriever.invoke('LangChain RAG tutorial 2026')
for d in docs:
print(f'{d.metadata["title"][:50]}\n {d.metadata["source"]}')Étape 2: Remplacez TavilySearchResults dans votre chaîne
Échangez TavilySearchResults contre un outil Scavio dans le RAG basé sur des agents. Le wrapper d'outil maintient la même interface afin que votre configuration d'agent reste inchangée.
from langchain_core.tools import tool
@tool
def web_search(query: str) -> str:
"""Search the web for current information. Returns relevant results with titles, snippets, and URLs."""
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': 5})
results = resp.json().get('organic_results', [])
return '\n\n'.join(
f'Title: {r["title"]}\nContent: {r.get("snippet", "")}\nSource: {r["link"]}'
for r in results
)
# BEFORE:
# from langchain_community.tools.tavily_search import TavilySearchResults
# tools = [TavilySearchResults(max_results=5)]
# AFTER:
tools = [web_search]
result = web_search.invoke('LangChain vs LlamaIndex 2026')
print(result[:300])Étape 3: Mettre à jour une chaîne RetrievalQA
Si vous utilisez RetrievalQA avec Tavily comme récupérateur, remplacez-le par ScavioRetriever. L'interface de la chaîne reste identique.
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
# BEFORE:
# from langchain_community.retrievers import TavilySearchAPIRetriever
# retriever = TavilySearchAPIRetriever(k=5)
# AFTER:
retriever = ScavioRetriever(num_results=5)
# The rest of your chain stays exactly the same
llm = ChatOpenAI(model='gpt-4o-mini', temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type='stuff',
retriever=retriever,
return_source_documents=True
)
# Run a query
result = qa_chain.invoke({'query': 'What are the best RAG frameworks in 2026?'})
print(f'Answer: {result["result"][:200]}')
print(f'\nSources:')
for doc in result['source_documents'][:3]:
print(f' - {doc.metadata["source"]}')Étape 4: Ajouter la récupération multi-plateforme pour un RAG plus riche
Allez au-delà de ce que Tavily offrait en ajoutant des sources Reddit et YouTube à votre pipeline RAG. Cela donne au LLM des opinions de la communauté et des références vidéo en plus des résultats web.
class MultiPlatformRetriever(BaseRetriever):
api_key: str = ''
platforms: list = ['google', 'reddit']
results_per_platform: int = 3
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.api_key = self.api_key or SCAVIO_KEY
def _get_relevant_documents(self, query: str) -> List[Document]:
docs = []
site_map = {'reddit': 'reddit.com', 'youtube': 'youtube.com'}
for platform in self.platforms:
q = f'site:{site_map[platform]} {query}' if platform in site_map else query
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': self.api_key, 'Content-Type': 'application/json'},
json={'query': q, 'country_code': 'us', 'num_results': self.results_per_platform})
for r in resp.json().get('organic_results', []):
docs.append(Document(
page_content=f'[{platform.upper()}] {r["title"]}\n{r.get("snippet", "")}',
metadata={'source': r['link'], 'title': r['title'], 'platform': platform}
))
return docs
retriever = MultiPlatformRetriever(platforms=['google', 'reddit', 'youtube'])
docs = retriever.invoke('best python web framework 2026')
for d in docs:
print(f'[{d.metadata["platform"]}] {d.metadata["title"][:50]}')
print(f'\nCost: {len(set(d.metadata["platform"] for d in docs))} API calls = ${len(set(d.metadata["platform"] for d in docs)) * 0.005:.3f}')Exemple Python
import os, requests
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
from typing import List
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
class ScavioRetriever(BaseRetriever):
api_key: str = ''
num_results: int = 5
def __init__(self, **kw):
super().__init__(**kw)
self.api_key = self.api_key or SCAVIO_KEY
def _get_relevant_documents(self, query: str) -> List[Document]:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': self.api_key, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': self.num_results})
return [Document(page_content=f"{r['title']}\n{r.get('snippet','')}",
metadata={'source': r['link']}) for r in resp.json().get('organic_results', [])]
retriever = ScavioRetriever(num_results=5)
docs = retriever.invoke('RAG frameworks 2026')
for d in docs:
print(f"{d.page_content[:60]}\n {d.metadata['source']}")Exemple JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function searchForRAG(query, num = 5) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, country_code: 'us', num_results: num })
});
const data = await resp.json();
return (data.organic_results || []).map(r => ({
pageContent: `${r.title}\n${r.snippet || ''}`,
metadata: { source: r.link, title: r.title }
}));
}
searchForRAG('RAG frameworks 2026').then(docs => {
docs.forEach(d => console.log(`${d.pageContent.slice(0, 60)}\n ${d.metadata.source}`));
});Sortie attendue
LangChain RAG Tutorial: Complete Guide 2026
https://example.com/langchain-rag-tutorial
Building Production RAG with LangChain
https://docs.langchain.com/rag-guide
[google] Best RAG Frameworks Comparison 2026
[reddit] r/LangChain - RAG framework recommendations 2026
[youtube] RAG Tutorial: LangChain vs LlamaIndex
Cost: 3 API calls = $0.015