15%

5.6 Information Provenance and Multi-Source Synthesis

Information Provenance คืออะไร

Information Provenance คือการ track ว่าข้อมูลแต่ละชิ้นมาจากไหน — เมื่อ agent ใช้หลาย sources (documents, APIs, databases, web search) ต้องระบุได้ว่า claim แต่ละ claim มาจาก source ไหน verified เมื่อไหร่ และ reliable แค่ไหน ป้องกันปัญหา “agent บอกว่ารู้ แต่ไม่รู้ว่ารู้มาจากไหน”

ทำไม Provenance สำคัญ

  • Hallucination detection — ถ้า claim ไม่มี source = อาจเป็น hallucination
  • Conflict resolution — เมื่อ 2 sources ขัดกัน ต้องรู้ว่าไหน authoritative กว่า
  • Freshness — ข้อมูลเก่า 6 เดือนอาจ outdated
  • Accountability — เมื่อ output ผิด trace back ได้ว่า source ไหนให้ข้อมูลผิด

Source Tracking Pattern

from dataclasses import dataclass
from datetime import datetime
from enum import Enum

class SourceType(Enum):
    DOCUMENT = "document"
    API = "api"
    DATABASE = "database"
    WEB = "web"
    HUMAN_INPUT = "human_input"
    MODEL_GENERATION = "model_generation"  # Claude generated — no external source

@dataclass
class SourceCitation:
    source_type: SourceType
    location: str          # URL, file path, or API endpoint
    retrieved_at: datetime
    reliability: float     # 0-1 confidence in source
    excerpt: str           # The actual text cited

@dataclass
class Claim:
    statement: str
    sources: list[SourceCitation]
    confidence: float
    
    @property
    def is_grounded(self):
        """A claim is grounded if it has at least one non-model source"""
        return any(s.source_type != SourceType.MODEL_GENERATION for s in self.sources)

Multi-Source Synthesis

เมื่อ Sources เห็นตรงกัน (Agreement)

def synthesize_agreement(claims_from_sources):
    """Multiple sources agree — high confidence"""
    common_claims = find_common(claims_from_sources)
    
    for claim in common_claims:
        claim.confidence = min(1.0, 0.5 + 0.2 * len(claim.sources))
        # More sources agree = higher confidence
    
    return common_claims

เมื่อ Sources ขัดกัน (Conflict)

def resolve_conflict(claim_a, claim_b):
    """Two sources disagree — need resolution strategy"""
    
    strategies = {
        "recency": lambda a, b: a if a.retrieved_at > b.retrieved_at else b,
        "authority": lambda a, b: a if a.source_reliability > b.source_reliability else b,
        "specificity": lambda a, b: a if a.is_more_specific else b,
    }
    
    # Apply hierarchy: official docs > API response > web > model generation
    authority_rank = {
        SourceType.DOCUMENT: 4,    # Official docs
        SourceType.API: 3,         # Live API data
        SourceType.DATABASE: 3,    # Internal data
        SourceType.WEB: 2,         # Web search
        SourceType.HUMAN_INPUT: 2, # User said
        SourceType.MODEL_GENERATION: 1,  # Claude generated
    }
    
    a_rank = max(authority_rank[s.source_type] for s in claim_a.sources)
    b_rank = max(authority_rank[s.source_type] for s in claim_b.sources)
    
    if a_rank != b_rank:
        winner = claim_a if a_rank > b_rank else claim_b
        return {
            "resolved": winner,
            "conflict_note": f"Conflict between sources. Chose {winner.sources[0].location} (higher authority)",
            "discarded": claim_b if a_rank > b_rank else claim_a
        }
    
    # Same authority — flag for human review
    return {
        "resolved": None,
        "conflict_note": "Equal authority sources disagree — human review needed",
        "options": [claim_a, claim_b]
    }

Provenance in Practice

Annotated Output

def generate_report_with_provenance(topic, sources):
    """Generate a report where every claim has a citation"""
    
    report = client.messages.create(
        system="""Generate a report. For EVERY factual claim, add a citation 
        in [Source N] format. At the end, list all sources with their details.
        If you are not sure about a claim, mark it as [UNVERIFIED].""",
        messages=[{"role": "user", "content": f"""
        Topic: {topic}
        
        Available sources:
        {format_sources(sources)}
        
        Write a report with citations for every claim.
        """}]
    )
    
    # Verify citations actually exist in sources
    claims = extract_claims_with_citations(report)
    for claim in claims:
        if not verify_citation_exists(claim.citation, sources):
            claim.flag = "CITATION_NOT_FOUND"  # Possible hallucination
    
    return report, claims

Source Freshness Check

def check_freshness(source: SourceCitation, max_age_days=30):
    age = (datetime.now() - source.retrieved_at).days
    
    if age > max_age_days:
        return {
            "fresh": False,
            "age_days": age,
            "recommendation": "Re-fetch this source — data may be outdated"
        }
    return {"fresh": True, "age_days": age}

Key Concepts

  • Grounded vs Ungrounded claims — grounded = มี external source; ungrounded = Claude generated (potential hallucination)
  • Source authority hierarchy — official docs > API > database > web > model generation
  • Freshness — ข้อมูลเก่าอาจ outdated; ต้อง re-verify periodically
  • Conflict resolution — เมื่อ sources ขัดกัน ใช้ authority + recency + specificity
  • Citation verification — ตรวจว่า citation ที่ Claude ใส่มา match กับ source จริง

Exam Tips

  • ข้อสอบจะถาม: เมื่อ 2 sources ขัดกัน ทำอย่างไร — ตอบ: ดู authority hierarchy, recency, escalate ถ้า equal
  • Hallucination detection = claim ที่ไม่มี source citation = suspect
  • Model-generated content มี reliability ต่ำสุด — ต้อง verify กับ external source เสมอ
  • ข้อสอบอาจให้ scenario ที่ Claude assert ข้อมูลผิด — ถามว่าป้องกันอย่างไร → citation + verification
  • Source freshness check สำคัญ: ข้อมูลเทค 6 เดือนอาจ outdated (เช่น API versions, pricing)
  • Multi-source synthesis ≠ เอาทุก source มา merge — ต้อง detect conflicts และ resolve