examples/citation-verification-agent.mjs
Rama master · réplica de lectura del repositorio original.
#!/usr/bin/env node
// Example: agent({ verifyCitations }) — citation verification on generate().
//
// Configure the agent with an embedder + a retriever, and every call to
// agent.generate() returns its response with a `grounding` field
// containing per-claim verdicts. No separate verifier.verify(text, sources)
// step required. The sources are fetched after the model answers and are
// used only to score the answer; they are not added to the prompt.
//
// Usage:
// export OPENAI_API_KEY="sk-..." # the model call is real; the embedder and retriever are mocks
// node examples/citation-verification-agent.mjs
import { agent, formatVerifiedResponse } from '../dist/index.js';
// --- Mock embedder + retriever for the example ---
function mockEmbed(texts) {
return Promise.resolve(
texts.map((t) => {
const vec = new Array(64).fill(0);
for (let i = 0; i < t.length; i++) vec[i % 64] += t.charCodeAt(i) / 1000;
const mag = Math.sqrt(vec.reduce((s, v) => s + v * v, 0));
return mag > 0 ? vec.map((v) => v / mag) : vec;
}),
);
}
const FACTS = [
{ content: 'Tokyo is the capital and seat of government of Japan.', url: 'https://example.com/japan' },
{ content: 'The population of Tokyo proper is approximately 14 million.', url: 'https://example.com/tokyo' },
];
async function mockRetrieve(query) {
// In a real flow you'd hit your vector store or RAG pipeline here.
return FACTS;
}
// --- Build an agent with citation verification wired in ---
const docsAgent = agent({
provider: process.env.AGENTOS_PROVIDER || 'openai',
verifyCitations: {
embedFn: mockEmbed,
retrieve: mockRetrieve,
supportThreshold: 0.6,
unverifiableThreshold: 0.3,
},
});
// --- Generate and inspect the grounding result ---
const result = await docsAgent.generate('Tell me about Tokyo.');
console.log('=== Generated text ===');
console.log(result.text);
console.log();
if (result.grounding) {
console.log('=== Grounding ===');
console.log(formatVerifiedResponse(result.grounding));
console.log(`overallGrounded: ${result.grounding.overallGrounded}`);
for (const claim of result.grounding.claims) {
const icon =
claim.verdict === 'supported' ? '✓' :
claim.verdict === 'weak' ? '~' :
claim.verdict === 'contradicted' ? '✗' : '?';
console.log(` ${icon} [${claim.verdict}] (${(claim.confidence * 100).toFixed(0)}%) ${claim.text}`);
}
}