Resumen
Takes AI-generated contenido as entrada, usa un LLM to extraer verifiable factual claims, searches for cada claim via SERP API, y classifies claims as verified, contradicted, o unverifiable.
Desencadenador
On-demand (activado cuando AI-generated contenido es submitted for resena)
Programación
On-demand per contenido submission
Pasos del flujo de trabajo
Extraer factual claims
Pass el contenido to un LLM con un prompt to extraer todos verifiable factual claims as un JSON lista. Cada claim deberia be un single sentence.
Generar consulta de busqueda per claim
For cada claim, usar el LLM o un plantilla to generar un optimo consulta de busqueda (e.g., claim about un price -> '[producto] price 2026 sitio:official o resena sitio').
Search for cada claim
POST to Scavio search API for cada claim's consulta de busqueda. Retrieve top 5 resultados con fragmentos.
Clasificar claim contra resultados de busqueda
Pass claim + search fragmentos to LLM. Clasificar as: verified (fragmentos corroborate claim), contradicted (fragmentos contradict), o unverifiable (fragmentos don't address claim).
Annotate contenido con flags
Tag cada claim in el original contenido con its classification y el supporting o contradicting fuente URL.
Salida verification informe
Return JSON con: verified_count, contradicted_count, unverifiable_count, claims lista con classification y fuente, y un recommended_revision for contradicted claims.
Implementacion en Python
import requests
import json
import openai
SCRAVIO_KEY = "YOUR_API_KEY"
client = openai.OpenAI(api_key="YOUR_OPENAI_KEY")
def extract_claims(content: str) -> list[str]:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "user",
"content": f"Extract all verifiable factual claims from this text as a JSON array of strings. Only include claims that can be checked against external sources (prices, dates, statistics, product features). Text:\n\n{content}"
}],
response_format={"type": "json_object"},
temperature=0
)
return json.loads(resp.choices[0].message.content).get("claims", [])
def search_claim(claim: str) -> list:
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": SCRAVIO_KEY},
json={"query": claim, "platform": "google", "num": 5}
)
resp.raise_for_status()
return resp.json().get("results", [])
def verify_claim(claim: str, results: list) -> dict:
context = "\n".join(f"- {r.get('snippet', '')} ({r.get('url', '')})" for r in results[:5])
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "user",
"content": f"Claim: {claim}\n\nSearch results:\n{context}\n\nClassify as verified/contradicted/unverifiable. Return JSON: {{\"status\": \"\", \"source_url\": \"\", \"note\": \"\"}}"
}],
response_format={"type": "json_object"},
temperature=0
)
return json.loads(resp.choices[0].message.content)
def fact_check(content: str) -> dict:
claims = extract_claims(content)
results_list = []
for claim in claims:
search_results = search_claim(claim)
verification = verify_claim(claim, search_results)
results_list.append({"claim": claim, **verification})
counts = {"verified": 0, "contradicted": 0, "unverifiable": 0}
for r in results_list:
status = r.get("status", "unverifiable")
counts[status] = counts.get(status, 0) + 1
return {**counts, "claims": results_list, "total_credits_used": len(claims)}
if __name__ == "__main__":
sample = "Scavio costs $99/month and has been used by over 10,000 companies. It supports 15 search platforms."
report = fact_check(sample)
print(json.dumps(report, indent=2))
Implementacion en JavaScript
const fetch = require('node-fetch');
const OpenAI = require('openai');
const SCRAVIO_KEY = 'YOUR_API_KEY';
const client = new OpenAI({ apiKey: 'YOUR_OPENAI_KEY' });
async function extractClaims(content) {
const resp = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: `Extract verifiable factual claims as JSON array. Text: ${content}` }],
response_format: { type: 'json_object' }, temperature: 0
});
return JSON.parse(resp.choices[0].message.content).claims || [];
}
async function searchClaim(claim) {
const res = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCRAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: claim, platform: 'google', num: 5 })
});
return (await res.json()).results || [];
}
async function verifyClaim(claim, results) {
const context = results.slice(0, 5).map(r => `- ${r.snippet} (${r.url})`).join('\n');
const resp = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: `Claim: ${claim}\nResults:\n${context}\nClassify: verified/contradicted/unverifiable. Return JSON: {"status":"","source_url":"","note":""}` }],
response_format: { type: 'json_object' }, temperature: 0
});
return JSON.parse(resp.choices[0].message.content);
}
async function factCheck(content) {
const claims = await extractClaims(content);
const results = [];
for (const claim of claims) {
const searchResults = await searchClaim(claim);
const verification = await verifyClaim(claim, searchResults);
results.push({ claim, ...verification });
}
const counts = results.reduce((acc, r) => { acc[r.status] = (acc[r.status]||0)+1; return acc; }, {});
return { ...counts, claims: results };
}
factCheck('Scavio costs $99/month and supports 15 platforms.').then(r => console.log(JSON.stringify(r, null, 2)));
Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA