0Pricing
AI Agents · Pelajaran

Verifikasi Sumber dan Sitasi

Membandingkan klaim di berbagai sumber dan melampirkan URL sumber pada fakta.

Verifikasi Sumber dan Sitasi adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Mengapa Verifikasi Sumber Penting

Agen dapat mengambil klaim yang salah dari sumber berkualitas rendah dan menyajikannya sebagai fakta. Tanpa verifikasi, agen riset hanyalah mesin pencari canggih tanpa penyaring kualitas.

Verifikasi menambahkan lapisan yang memeriksa apakah klaim didukung oleh beberapa sumber independen.

Aturan Dua Sumber

Sebuah klaim dianggap terverifikasi jika muncul dalam setidaknya dua sumber independen. 'Independen' berarti berasal dari domain yang berbeda — menemukan klaim yang sama di dua situs yang sama-sama mengutip artikel asli yang sama tidak dihitung.

from urllib.parse import urlparse

def extract_domain(url: str) -> str:
    return urlparse(url).netloc.replace('www.', '')

def is_verified(fact: str, all_facts: list[dict]) -> bool:
    matching_domains = set()
    for f in all_facts:
        if fact.lower() in f['fact'].lower() or f['fact'].lower() in fact.lower():
            matching_domains.add(extract_domain(f['source']))
    return len(matching_domains) >= 2

# Example
facts = [
    {'fact': 'Inflation peaked at 9.1% in June 2022', 'source': 'https://bls.gov/cpi'},
    {'fact': 'US inflation hit 9.1% peak in mid-2022',  'source': 'https://reuters.com/article/a'}
]
print(is_verified('inflation peaked at 9.1%', facts))  # True

Pencocokan Semantik Berbasis LLM

Pencocokan string tidak dapat menangkap klaim yang diparafrasekan. Gunakan LLM untuk menilai apakah dua fakta setara secara semantik sebelum menghitungnya sebagai sumber yang saling menguatkan.

import openai, json

client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')

def claims_are_equivalent(claim_a: str, claim_b: str) -> bool:
    prompt = (
        f'Are these two statements making the same factual claim?\n'
        f'A: "{claim_a}"\n'
        f'B: "{claim_b}"\n'
        f'Answer JSON: {{"equivalent": true/false}}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content).get('equivalent', False)

print(claims_are_equivalent(
    'CPI hit 9.1% in June 2022',
    'US consumer prices rose 9.1 percent year-over-year in June 2022'
))  # True

Penilaian Kualitas Sumber

Tidak semua sumber memiliki kualitas yang sama. Nilai setiap sumber berdasarkan jenis domain, tanggal publikasi, dan tingkat keandalan yang diketahui. Sumber Tingkat 1 (statistik pemerintah, jurnal yang ditelaah sejawat) seharusnya memiliki bobot lebih besar daripada blog atau media sosial.

from datetime import datetime, timezone

HIGH_AUTHORITY_DOMAINS = [
    'gov', 'edu', 'nature.com', 'science.org', 'pubmed.ncbi.nlm.nih.gov',
    'reuters.com', 'bbc.com', 'apnews.com', 'who.int'
]

def score_source(url: str, publication_date: str | None) -> float:
    score = 0.5   # baseline
    domain = extract_domain(url)
    tld = domain.split('.')[-1]

    # Domain authority
    if any(ha in domain for ha in HIGH_AUTHORITY_DOMAINS):
        score += 0.3
    elif tld in ('gov', 'edu', 'org'):
        score += 0.1

    # Recency
    if publication_date:
        try:
            pub = datetime.fromisoformat(publication_date)
            days_old = (datetime.now(timezone.utc) - pub.replace(tzinfo=timezone.utc)).days
            if days_old < 365:
                score += 0.1
            elif days_old > 1825:  # 5 years
                score -= 0.1
        except ValueError:
            pass

    return min(1.0, max(0.0, score))

Mencocokkan Silang Klaim dengan Sumber

Untuk setiap klaim yang ingin disertakan agen dalam laporan akhir, cocokkan silang klaim tersebut dengan semua dokumen yang diambil untuk menemukan sumber pendukung terbaik.

def cross_reference(claim: str, all_facts: list[dict]) -> list[dict]:
    supporting = []
    seen_domains = set()

    for fact in all_facts:
        if claims_are_equivalent(claim, fact['fact']):
            domain = extract_domain(fact['source'])
            if domain not in seen_domains:  # only one per domain
                seen_domains.add(domain)
                supporting.append({
                    'source': fact['source'],
                    'domain': domain,
                    'fact':   fact['fact'],
                    'score':  score_source(fact['source'], fact.get('publication_date'))
                })

    return sorted(supporting, key=lambda x: x['score'], reverse=True)

Pemeriksaan Kredensial Penulis

Untuk klaim ilmiah atau medis, kredensial penulis penting. Studi dengan penulis yang disebutkan namanya dari institusi terakreditasi memiliki bobot lebih besar daripada tulisan blog anonim. Ekstrak informasi penulis dan tandai klaim dari sumber anonim.

def assess_authorship(url: str, page_text: str) -> dict:
    prompt = (
        f'From this webpage text, extract:\n'
        f'1. Author name(s) (or null)\n'
        f'2. Author affiliation/credentials (or null)\n'
        f'3. Publication name (or null)\n'
        f'Return JSON: {{"authors": [], "affiliation": null, "publication": null}}\n\n'
        f'TEXT:\n{page_text[:2000]}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)

Menandai Klaim yang Belum Terverifikasi

Klaim yang tidak dapat dicocokkan silang dengan dua sumber independen harus ditandai sebagai belum terverifikasi dalam keluaran. Bergantung pada tingkat risiko laporan, klaim yang belum terverifikasi dapat dikecualikan atau disajikan dengan penafian.

def classify_claims(claims: list[str], all_facts: list[dict]) -> list[dict]:
    classified = []
    for claim in claims:
        support = cross_reference(claim, all_facts)
        classified.append({
            'claim':       claim,
            'verified':    len(support) >= 2,
            'sources':     support[:3],  # top 3 supporting sources
            'confidence':  'high' if len(support) >= 3 else
                           'medium' if len(support) == 2 else
                           'low'
        })
    return classified

Format Sitasi: Daftar Dalam Teks dan Referensi

Laporan harus menyertakan sitasi dalam teks (superskrip bernomor) dan daftar referensi di bagian akhir. Hasilkan keduanya dari metadata sumber yang telah diverifikasi.

def format_citations(classified_claims: list[dict]) -> tuple[list[str], list[str]]:
    ref_list = []
    ref_map = {}   # url -> citation number
    inline_claims = []

    for item in classified_claims:
        nums = []
        for src in item['sources']:
            url = src['source']
            if url not in ref_map:
                ref_map[url] = len(ref_list) + 1
                ref_list.append(f'[{ref_map[url]}] {url}')
            nums.append(f'[{ref_map[url]}]')

        citation_str = ''.join(nums)
        prefix = '' if item['verified'] else '[UNVERIFIED] '
        inline_claims.append(f'{prefix}{item["claim"]} {citation_str}')

    return inline_claims, ref_list

if __name__ == '__main__':
    demo_claims = [
        {'claim': 'Revenue grew 12% year over year', 'verified': True, 'sources': [{'source': 'https://example.com/report'}]},
        {'claim': 'The CEO plans to step down', 'verified': False, 'sources': [{'source': 'https://example.com/rumor'}]},
    ]
    inline, refs = format_citations(demo_claims)
    for line in inline:
        print(line)
    print('References:')
    for r in refs:
        print(' ', r)

Mendeteksi Kontradiksi Antar-Sumber

Terkadang dua sumber tepercaya saling bertentangan. Deteksi kontradiksi dan sajikan kedua sisi, alih-alih memilih salah satunya secara diam-diam. Hal ini sangat penting terutama untuk klaim empiris yang masih diperdebatkan.

def find_contradictions(claim: str, all_facts: list[dict]) -> list[dict]:
    contradictions = []
    for fact in all_facts:
        if extract_domain(fact['source']) == extract_domain(claim):
            continue
        prompt = (
            f'Does fact B contradict fact A?\n'
            f'A: "{claim}"\nB: "{fact["fact"]}"\n'
            f'JSON: {{"contradicts": true/false}}'
        )
        resp = client.chat.completions.create(
            model='gpt-4o-mini',
            messages=[{'role': 'user', 'content': prompt}],
            response_format={'type': 'json_object'}
        )
        result = json.loads(resp.choices[0].message.content)
        if result.get('contradicts'):
            contradictions.append(fact)
    return contradictions

Kartu Ringkasan Verifikasi

Sebelum menghasilkan laporan akhir, buat ringkasan verifikasi: jumlah klaim yang terverifikasi, jumlah klaim yang belum terverifikasi, sumber utama berdasarkan skor otoritas, serta kontradiksi yang terdeteksi.

def verification_report_card(classified: list[dict]) -> dict:
    total     = len(classified)
    verified  = sum(1 for c in classified if c['verified'])
    all_sources = [
        src for c in classified for src in c['sources']
    ]
    top_domains = sorted(
        set(s['domain'] for s in all_sources),
        key=lambda d: max(s['score'] for s in all_sources if s['domain'] == d),
        reverse=True
    )[:5]
    return {
        'total_claims':    total,
        'verified':        verified,
        'unverified':      total - verified,
        'verification_rate': f'{verified/max(total,1)*100:.0f}%',
        'top_sources':     top_domains
    }

if __name__ == '__main__':
    demo_classified = [
        {'verified': True, 'sources': [{'domain': 'docs.python.org', 'score': 1.3}]},
        {'verified': False, 'sources': [{'domain': 'quora.com', 'score': 0.5}]},
    ]
    card = verification_report_card(demo_classified)
    for k, v in card.items():
        print(f'{k}: {v}')

Keluaran Berbasis Ambang Keyakinan

Tetapkan ambang verifikasi minimum sebelum menerbitkan laporan. Jika kurang dari 70% klaim terverifikasi, minta siklus riset menjalankan iterasi lain yang secara khusus menargetkan klaim yang belum terverifikasi.

MIN_VERIFICATION_RATE = 0.70

def should_run_more_research(classified: list[dict]) -> list[str]:
    unverified = [c for c in classified if not c['verified']]
    total = len(classified)
    if total == 0:
        return []
    rate = (total - len(unverified)) / total
    if rate >= MIN_VERIFICATION_RATE:
        return []  # Sufficient confidence — stop
    # Return search queries to verify remaining claims
    return [f'verify: {c["claim"]}' for c in unverified[:3]]

if __name__ == '__main__':
    demo_classified = [
        {'claim': 'A', 'verified': True},
        {'claim': 'B', 'verified': False},
        {'claim': 'C', 'verified': False},
    ]
    followups = should_run_more_research(demo_classified)
    print('Follow-up queries needed:', followups)

Apa yang menentukan dua sumber 'independen' dalam aturan verifikasi dua sumber?

Kriteria independensi mencegah verifikasi ruang gema ketika klaim yang sama ditelusuri kembali ke satu sumber asli yang dikutip oleh banyak penerbit.

Ringkasan Verifikasi Sumber

Riset yang terverifikasi memerlukan: penguatan oleh dua sumber dari domain yang berbeda, pencocokan semantik LLM untuk mendeteksi padanan yang diparafrasekan, penilaian kualitas sumber (otoritas domain + kemutakhiran), deteksi kontradiksi, dan keluaran berbasis ambang keyakinan yang memicu riset tambahan jika tingkat verifikasi terlalu rendah.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Verifikasi Sumber dan Sitasi” gratis?

Ya — teks lengkap “Verifikasi Sumber dan Sitasi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Verifikasi Sumber dan Sitasi”?

Membandingkan klaim di berbagai sumber dan melampirkan URL sumber pada fakta. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Verifikasi Sumber dan Sitasi” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Desain Putaran Riset Multi-Langkah
  2. Verifikasi Sumber dan Sitasi
  3. Pembuatan Laporan Terstruktur
  4. Pemeriksaan Fakta dan Pencegahan Halusinasi
← Kembali ke AI Agents