Resumen
A LangChain retrieval chain ese replaces vector almacenar retrieval con live SERP llamadas un API, injecting resultados de busqueda directamente en el LLM context window to produce grounded, citation-backed answers.
Desencadenador
Per usuario consulta (synchronous, one chain invocation per question)
Programación
Per usuario consulta (synchronous)
Pasos del flujo de trabajo
Recibir usuario question
Accept el user's question string as chain entrada. Optionally rewrite el consulta for search usando un query-expansion prompt.
Call SERP API as retriever
POST to Scavio search API con el user's question (o rewritten consulta). Retrieve top 5 resultados con titulo, fragmento, y URL.
Format retrieved context
Construir un context string de resultados de busqueda: '[Fuente 1: URL] titulo - fragmento'. Limit to 3,000 characters to stay dentro de token budget.
Construct grounding prompt
Combine system prompt (instruct to cite fuentes, admit uncertainty), retrieved context, y usuario question en el LLM entrada.
Generar grounded answer
Call LLM con el grounding prompt. El model produces un answer citing fuente URLs de el context.
Return structured respuesta
Return answer text y lista of cited fuente URLs extraido de el respuesta.
Implementacion en Python
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
import requests
SCRAVIO_KEY = "YOUR_API_KEY"
def scavio_retriever(query: str) -> str:
"""Fetch search results and format as context string."""
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": SCRAVIO_KEY},
json={"query": query, "platform": "google", "num": 5}
)
resp.raise_for_status()
results = resp.json().get("results", [])
context_parts = []
for i, r in enumerate(results[:5], start=1):
title = r.get("title", "")
snippet = r.get("snippet", "")
url = r.get("url", "")
context_parts.append(f"[Source {i}: {url}]\n{title}\n{snippet}")
return "\n\n".join(context_parts)[:3000]
SYSTEM_PROMPT = """You are a helpful assistant that answers questions using only the provided search results.
Always cite your sources using [Source N: URL] format.
If the search results don't contain enough information, say so — do not fabricate facts."""
prompt = ChatPromptTemplate.from_messages([
("system", SYSTEM_PROMPT),
("human", "Search results:\n{context}\n\nQuestion: {question}")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
# Build the chain
chain = (
RunnablePassthrough.assign(
context=RunnableLambda(lambda x: scavio_retriever(x["question"]))
)
| prompt
| llm
| StrOutputParser()
)
def grounded_answer(question: str) -> dict:
answer = chain.invoke({"question": question})
return {"question": question, "answer": answer}
if __name__ == "__main__":
result = grounded_answer("What does Scavio cost per month?")
print(result["answer"])
Implementacion en JavaScript
const { ChatOpenAI } = require('@langchain/openai');
const { ChatPromptTemplate } = require('@langchain/core/prompts');
const { StringOutputParser } = require('@langchain/core/output_parsers');
const { RunnablePassthrough, RunnableLambda } = require('@langchain/core/runnables');
const fetch = require('node-fetch');
const SCRAVIO_KEY = 'YOUR_API_KEY';
async function scavioRetriever(query) {
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, platform: 'google', num: 5 })
});
const results = (await res.json()).results || [];
return results.slice(0, 5).map((r, i) =>
`[Source ${i+1}: ${r.url}]\n${r.title}\n${r.snippet}`
).join('\n\n').slice(0, 3000);
}
const SYSTEM = 'Answer using only the provided search results. Cite sources as [Source N: URL]. Do not fabricate facts.';
const prompt = ChatPromptTemplate.fromMessages([
['system', SYSTEM],
['human', 'Search results:\n{context}\n\nQuestion: {question}']
]);
const llm = new ChatOpenAI({ model: 'gpt-4o-mini', temperature: 0.1 });
const chain = RunnablePassthrough.assign({
context: new RunnableLambda({ func: async (x) => scavioRetriever(x.question) })
}).pipe(prompt).pipe(llm).pipe(new StringOutputParser());
async function groundedAnswer(question) {
const answer = await chain.invoke({ question });
return { question, answer };
}
groundedAnswer('What does Scavio cost per month?').then(r => console.log(r.answer));
Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA