Ancrer un LLM avec des données SERP en direct signifie récupérer les résultats de recherche actuels pour une affirmation factuelle avant de générer une réponse, puis injecter les faits extraits dans le prompt comme contexte. Cela évite les hallucinations concernant les prix, les dates et la disponibilité.
Prérequis
- Python 3.9+
- Clé API Scavio
- SDK openai ou anthropic
Parcours
Étape 1: Rechercher sur SERP l'affirmation factuelle
Avant d'interroger le LLM, effectuez une recherche ciblée pour récupérer les faits actuels.
import requests
API_KEY = "your-scavio-api-key"
def fetch_grounding_context(claim_query: str, num_results: int = 5) -> str:
r = requests.post(
"https://api.scavio.dev/api/v1/search",
json={"query": claim_query, "num_results": num_results},
headers={"x-api-key": API_KEY},
timeout=15
)
r.raise_for_status()
results = r.json().get("organic_results", [])
lines = []
for i, res in enumerate(results, 1):
lines.append(f"{i}. {res.get('title')}\n {res.get('snippet')}\n Source: {res.get('link')}")
return "\n\n".join(lines)Étape 2: Injecter le contexte d'ancrage dans le prompt
Ajoutez les extraits SERP en tant que bloc [CONTEXT] pour que le LLM les utilise à la place des données d'entraînement.
def build_grounded_prompt(user_question: str, grounding_context: str) -> str:
return f"""[CONTEXT - Retrieved {__import__('datetime').date.today()}]
{grounding_context}
[INSTRUCTIONS]
Answer the question below using ONLY the context above. If the context does not contain the answer, say "I don't have current data on this."
Do not use information from your training data for prices, dates, or availability.
[QUESTION]
{user_question}"""
context = fetch_grounding_context("GPT-4o API pricing 2026")
prompt = build_grounded_prompt("What is the current price of GPT-4o per million tokens?", context)
print(prompt[:500])Étape 3: Appeler le LLM avec le prompt ancré
Transmettez le prompt ancré à n'importe quel LLM. La réponse du modèle est contrainte par les faits injectés.
import anthropic
client = anthropic.Anthropic(api_key="your-anthropic-key")
def grounded_answer(question: str, search_query: str = None) -> str:
query = search_query or question
context = fetch_grounding_context(query)
prompt = build_grounded_prompt(question, context)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
messages=[{"role": "user", "content": prompt}]
)
return message.content[0].text
answer = grounded_answer(
"What does GPT-4o cost per million input tokens?",
"GPT-4o API pricing per million tokens 2026"
)
print(answer)Exemple Python
import requests
import anthropic
from datetime import date
SCAVIO_KEY = "your-scavio-api-key"
ANTHROPIC_KEY = "your-anthropic-key"
def fetch_serp_context(query: str, n: int = 5) -> str:
r = requests.post(
"https://api.scavio.dev/api/v1/search",
json={"query": query, "num_results": n},
headers={"x-api-key": SCAVIO_KEY},
timeout=15
)
r.raise_for_status()
results = r.json().get("organic_results", [])
return "\n\n".join(
f"{i}. {r.get('title')}\n {r.get('snippet')}\n {r.get('link')}"
for i, r in enumerate(results, 1)
)
def grounded_answer(question: str, search_query: str | None = None) -> dict:
query = search_query or question
context = fetch_serp_context(query)
prompt = f"""[CONTEXT - {date.today()}]\n{context}\n\n[INSTRUCTIONS]\nAnswer using ONLY the context above. For prices, dates, or availability, cite the source number.\n\n[QUESTION]\n{question}"""
client = anthropic.Anthropic(api_key=ANTHROPIC_KEY)
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
messages=[{"role": "user", "content": prompt}]
)
return {"answer": msg.content[0].text, "context_used": context}
if __name__ == "__main__":
result = grounded_answer(
"How much does Firecrawl cost per month?",
"Firecrawl pricing 2026"
)
print(result["answer"])Exemple JavaScript
const SCAVIO_KEY = 'your-scavio-api-key';
const ANTHROPIC_KEY = 'your-anthropic-key';
async function fetchSerpContext(query, n = 5) {
const res = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': SCAVIO_KEY },
body: JSON.stringify({ query, num_results: n })
});
const data = await res.json();
return (data.organic_results ?? [])
.map((r, i) => `${i+1}. ${r.title}\n ${r.snippet}\n ${r.link}`)
.join('\n\n');
}
async function groundedAnswer(question, searchQuery) {
const context = await fetchSerpContext(searchQuery ?? question);
const prompt = `[CONTEXT - ${new Date().toISOString().slice(0,10)}]\n${context}\n\n[QUESTION]\n${question}`;
const res = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': ANTHROPIC_KEY,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-sonnet-4-6',
max_tokens: 512,
messages: [{ role: 'user', content: prompt }]
})
});
const msg = await res.json();
return msg.content[0].text;
}
const answer = await groundedAnswer('How much does Firecrawl cost per month?', 'Firecrawl pricing 2026');
console.log(answer);Sortie attendue
Based on the search results (source 2), Firecrawl offers:
- Free tier: 1,000 credits
- Starter: $16/month for 5,000 credits
- Scale: $83/month for 100,000 credits (annual billing)
These prices reflect annual billing rates as of 2026.