0Pricing
AI Agents · บทเรียน

การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน

การตรวจสอบโดยยึดแหล่งข้อมูล: ข้อกล่าวอ้างทุกข้อจะต้องย้อนกลับไปยังแหล่งข้อมูลที่ค้นคืนมาได้

การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

ปัญหาการกุเรื่องในเอเจนต์วิจัย

LLM สามารถสร้างข้อกล่าวอ้างที่ฟังดูน่าเชื่อถือแต่ไม่มีพื้นฐานจากแหล่งข้อมูลที่ดึงมา ในเอเจนต์วิจัย เรื่องนี้อันตรายเป็นพิเศษ เพราะผลลัพธ์ดูน่าเชื่อถือและนำเสนอพร้อมการอ้างอิงที่อาจไม่ได้สนับสนุนข้อกล่าวอ้างนั้นจริง

การป้องกันการกุเรื่องต้องได้รับการพิจารณาเป็นประเด็นสำคัญตั้งแต่แรก

การอ้างอิงแหล่งที่มา: ข้อกล่าวอ้างทุกข้อย้อนกลับไปยังแหล่งข้อมูลได้

หลักการสำคัญของการอ้างอิงแหล่งที่มาคือ ข้อกล่าวอ้างที่เป็นข้อเท็จจริงทุกข้อในผลลัพธ์สุดท้ายต้องสามารถย้อนกลับไปยังเอกสารที่ดึงมาอย่างน้อยหนึ่งฉบับได้ ข้อกล่าวอ้างที่ย้อนกลับไปตรวจสอบไม่ได้ถือเป็นข้อมูลหลอนหรือไม่มีหลักฐานรองรับ ซึ่งทั้งสองกรณีไม่อาจยอมรับได้ในรายงานการวิจัย

def check_grounding(claim: str, retrieved_docs: list[dict]) -> dict:
    doc_texts = '\n\n'.join(
        f'[DOC {i+1}] ({d["url"]})\n{d["text"][:800]}'
        for i, d in enumerate(retrieved_docs[:5])
    )
    return {
        'claim': claim,
        'docs':  doc_texts,
        'grounded': None   # to be filled by LLM verifier
    }

if __name__ == '__main__':
    docs = [{'url': 'https://example.com/geo', 'text': 'Paris is the capital of France.'}]
    result = check_grounding('Paris is the capital of France.', docs)
    print('Claim:', result['claim'])
    print('Supporting docs used:')
    print(result['docs'])

รูปแบบ LLM-as-Verifier

ใช้การเรียก LLM แยกต่างหาก ซึ่งทำหน้าที่เป็น ‘ตัวตรวจสอบ’ เพื่อตัดสินว่าข้อกล่าวอ้างมีแหล่งข้อมูลที่ให้มาเป็นหลักฐานรองรับหรือไม่ วิธีนี้สร้างการตรวจสอบถ่วงดุล โดยให้ตัวสร้างและตัวตรวจสอบเป็นการเรียกที่แยกจากกันอย่างอิสระ

import openai, json

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

def verify_claim(claim: str, source_texts: list[str]) -> dict:
    sources_block = '\n---\n'.join(source_texts[:3])
    prompt = (
        f'Is the following claim directly supported by the provided sources?\n'
        f'Claim: "{claim}"\n\n'
        f'Sources:\n{sources_block}\n\n'
        f'Return JSON: {{\n'
        f'  "supported": true/false,\n'
        f'  "confidence": 0.0-1.0,\n'
        f'  "reason": "one sentence explanation"\n'
        f'}}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)

ผลลัพธ์ที่คัดกรองตามระดับความเชื่อมั่น

กำหนดเกณฑ์สำหรับคะแนนความเชื่อมั่นของตัวตรวจสอบ ข้อกล่าวอ้างที่มีคะแนนสูงกว่า 0.85 จะเผยแพร่ได้ ส่วนข้อกล่าวอ้างที่อยู่ระหว่าง 0.5–0.85 จะเผยแพร่พร้อมข้อสงวนสิทธิ์ และข้อกล่าวอ้างที่ต่ำกว่า 0.5 จะถูกตัดออก

INCLUDE_THRESHOLD  = 0.85
DISCLAIMER_THRESHOLD = 0.50

def gate_claim(claim: str, source_texts: list[str]) -> dict:
    result = verify_claim(claim, source_texts)
    conf = result.get('confidence', 0.0)
    supported = result.get('supported', False)

    if not supported or conf < DISCLAIMER_THRESHOLD:
        return {'action': 'exclude', 'claim': claim, 'reason': result.get('reason')}
    elif conf < INCLUDE_THRESHOLD:
        return {
            'action': 'include_with_disclaimer',
            'claim': f'[LOW CONFIDENCE] {claim}',
            'reason': result.get('reason')
        }
    else:
        return {'action': 'include', 'claim': claim}

การตรวจจับรูปแบบข้อมูลหลอนที่เฉพาะเจาะจง

รูปแบบข้อกล่าวอ้างบางประเภทมีความเสี่ยงสูงที่จะเป็นข้อมูลหลอน ได้แก่ สถิติที่ระบุอย่างเจาะจง เช่น เปอร์เซ็นต์และจำนวนเงิน วันที่เฉพาะเจาะจง ชื่อบุคคล และความสัมพันธ์เชิงเหตุผล ควรตรวจสอบสิ่งเหล่านี้อย่างละเอียดเป็นพิเศษ

import re

def is_high_risk_claim(claim: str) -> bool:
    patterns = [
        r'\d+\.?\d*\s*%',            # percentages: 9.1%
        r'\$\s*\d+',                  # dollar amounts
        r'\b(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{4}',  # dates
        r'\b[A-Z][a-z]+\s+[A-Z][a-z]+\s+(said|stated|argued|claimed)',  # named quotes
        r'(caused?|led to|resulted in)',                                  # causal claims
    ]
    return any(re.search(p, claim) for p in patterns)

print(is_high_risk_claim('Inflation hit 9.1% in June 2022'))  # True
print(is_high_risk_claim('Inflation was elevated'))            # False

วงจรการตรวจสอบแบบแยกย่อย

สำหรับส่วนเนื้อหาที่ยาว ให้แยกข้อความออกเป็นข้อกล่าวอ้างแต่ละข้อ ตรวจสอบแต่ละข้ออย่างเป็นอิสระจากกัน จากนั้นประกอบส่วนเนื้อหากลับขึ้นใหม่โดยใช้เฉพาะข้อกล่าวอ้างที่ผ่านการตรวจสอบแล้ว

def decompose_into_claims(section_text: str) -> list[str]:
    prompt = (
        f'Break this text into individual verifiable factual claims.\n'
        f'Each claim should be a single sentence containing exactly one fact.\n'
        f'Return JSON: {{"claims": ["..."]}}\n\n'
        f'TEXT:\n{section_text}'
    )
    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('claims', [])

การประกอบข้อความที่ผ่านการตรวจสอบแล้วกลับขึ้นใหม่

หลังจากคัดกรองข้อกล่าวอ้างแต่ละข้อแล้ว ให้ประกอบส่วนเนื้อหาที่สะอาดและสอดคล้องกันจากเฉพาะข้อกล่าวอ้างที่ผ่านการตรวจสอบ ตัดข้อกล่าวอ้างที่มีความเชื่อมั่นต่ำออก และเรียบเรียงใหม่ให้อ่านง่าย

def reconstruct_section(verified_claims: list[str],
                        section_name: str) -> str:
    claims_text = '\n'.join(f'- {c}' for c in verified_claims)
    prompt = (
        f'Rewrite these verified facts as a coherent {section_name} section.\n'
        f'Do NOT add any new information not present in the claims.\n'
        f'Only use the facts provided.\n\n'
        f'VERIFIED CLAIMS:\n{claims_text}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return resp.choices[0].message.content

การตรวจจับความคลาดเคลื่อนของตัวเลข

บางครั้ง LLM อาจเปลี่ยนตัวเลขจากแหล่งข้อมูลเล็กน้อยโดยไม่รู้ตัว เช่น เปลี่ยน 9.1% เป็น 9.2% ให้ดึงตัวเลขจากทั้งข้อกล่าวอ้างและข้อความต้นฉบับ แล้วเปรียบเทียบกันอย่างชัดเจน

import re

def extract_numbers(text: str) -> list[float]:
    matches = re.findall(r'[-+]?\d*\.?\d+', text)
    return [float(m) for m in matches]

def check_numeric_drift(claim: str, source_text: str,
                        tolerance: float = 0.01) -> bool:
    claim_nums  = extract_numbers(claim)
    source_nums = extract_numbers(source_text)

    for cn in claim_nums:
        found_match = any(abs(cn - sn) <= tolerance for sn in source_nums)
        if not found_match:
            return True  # numeric drift detected
    return False

print(check_numeric_drift(
    'Inflation reached 9.2% in June 2022',
    'The CPI rose 9.1 percent in June 2022'
))  # True — 9.2 vs 9.1

การตรวจสอบการระบุแหล่งที่มา

หลังจากสร้างรายงานฉบับเต็มแล้ว ให้ตรวจสอบการระบุแหล่งที่มา โดยยืนยันว่าประโยคแต่ละประโยคในรายงานสามารถระบุได้ว่ามาจากแหล่งข้อมูลใดแหล่งหนึ่ง ทำเครื่องหมายประโยคใดก็ตามที่ไม่มีส่วนข้อความจากแหล่งข้อมูลที่ตรงกัน

def attribution_audit(report_text: str, sources: list[dict]) -> list[str]:
    sentences = [s.strip() for s in report_text.split('.') if len(s.strip()) > 20]
    unattributed = []

    for sentence in sentences:
        found = False
        for src in sources:
            if any(word in src.get('text', '') for word in sentence.split()[:5]):
                found = True
                break
        if not found:
            unattributed.append(sentence)

    return unattributed

# Flag unattributed sentences for manual review or re-verification

if __name__ == '__main__':
    report = ("Water boils at 100 degrees Celsius at sea level. "
              "The moon is made primarily of green cheese according to this document.")
    sources = [{'text': 'Water boils at 100C (212F) at standard atmospheric pressure.'}]
    unattributed = attribution_audit(report, sources)
    print('Unattributed sentences (need manual review):')
    for s in unattributed:
        print(' -', s)

การใช้ถ้อยคำแสดงความไม่แน่นอนกับข้อกล่าวอ้างที่ยังไม่แน่ชัด

ไม่ใช่ทุกข้อกล่าวอ้างที่จะตรวจสอบจนมีความเชื่อมั่นสูงได้ แทนที่จะตัดข้อกล่าวอ้างที่อยู่ก้ำกึ่งออกทั้งหมด ให้ใช้ถ้อยคำแสดงความไม่แน่นอน เช่น ‘นักวิเคราะห์บางรายเสนอว่า...’ ‘ตามข้อมูลของ X...’ หรือ ‘มีรายงานว่า...’ วิธีนี้ช่วยรักษาข้อมูลไว้พร้อมกับสื่อให้เห็นถึงความไม่แน่นอน

def hedge_claim(claim: str, confidence: float) -> str:
    if confidence >= 0.85:
        return claim  # state as fact
    elif confidence >= 0.65:
        hedges = ['Some sources suggest', 'According to available evidence',
                  'Analysts have noted']
        return f'{hedges[hash(claim) % len(hedges)]}, {claim.lower()}'
    else:
        return f'It has been reported (with low confidence) that {claim.lower()}'

print(hedge_claim('Inflation peaked at 9.1%', 0.90))
print(hedge_claim('Supply chain disruptions contributed to inflation', 0.72))
print(hedge_claim('Specific policy caused inflation', 0.45))

การติดตามอัตราการสร้างข้อมูลหลอน

ติดตามอัตราการสร้างข้อมูลหลอนตามเวลา โดยดูว่าข้อกล่าวอ้างที่สร้างขึ้นกี่เปอร์เซ็นต์ไม่ผ่านการตรวจสอบ และกำหนดเกณฑ์แจ้งเตือน หากอัตราดังกล่าวเพิ่มขึ้นอย่างรวดเร็ว แสดงว่าการออกแบบพรอมต์หรือคุณภาพการดึงข้อมูลของคุณลดลง

verification_log = []  # In production: a database

def log_verification(claim: str, supported: bool, confidence: float):
    verification_log.append({
        'claim':      claim[:100],
        'supported':  supported,
        'confidence': confidence
    })

def hallucination_rate() -> float:
    if not verification_log:
        return 0.0
    failed = sum(1 for v in verification_log if not v['supported'])
    return failed / len(verification_log)

def check_hallucination_alert(threshold: float = 0.15):
    rate = hallucination_rate()
    if rate > threshold:
        print(f'ALERT: Hallucination rate {rate:.1%} exceeds threshold {threshold:.1%}')
    return rate

if __name__ == '__main__':
    log_verification('The sky is blue', True, 0.95)
    log_verification('The moon is made of cheese', False, 0.2)
    log_verification('Water boils at 100C at sea level', True, 0.99)
    rate = check_hallucination_alert(threshold=0.15)
    print(f'Hallucination rate so far: {rate:.1%}')

จุดประสงค์หลักของรูปแบบ ‘LLM-as-verifier’ คืออะไร

รูปแบบ LLM-as-verifier เป็นรูปแบบสถาปัตยกรรมสำคัญสำหรับการป้องกันข้อมูลหลอน การทำความเข้าใจว่ารูปแบบนี้ตรวจสอบอะไร และเหตุใดจึงดำเนินการด้วยการเรียกที่แยกต่างหาก จึงเป็นสิ่งจำเป็น

สรุปการป้องกันข้อมูลหลอน

ป้องกันข้อมูลหลอนด้วยวิธีต่อไปนี้: การตรวจสอบการอ้างอิงแหล่งที่มา (ข้อกล่าวอ้างทุกข้อย้อนกลับไปยังแหล่งข้อมูลได้), LLM-as-verifier (การเรียกแยกต่างหากเพื่อตัดสินว่ามีหลักฐานรองรับหรือไม่), การคัดกรองตามระดับความเชื่อมั่น (ตัดข้อกล่าวอ้างที่ต่ำกว่าเกณฑ์ออก), การตรวจจับความคลาดเคลื่อนของตัวเลข, การใช้ถ้อยคำแสดงความไม่แน่นอนสำหรับกรณีที่อยู่ก้ำกึ่ง และ การติดตามอัตราการสร้างข้อมูลหลอนเพื่อตรวจจับการที่คุณภาพลดลง

คำถามที่พบบ่อย

บทเรียน “การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน”

การตรวจสอบโดยยึดแหล่งข้อมูล: ข้อกล่าวอ้างทุกข้อจะต้องย้อนกลับไปยังแหล่งข้อมูลที่ค้นคืนมาได้ คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม

ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การออกแบบวงจรการวิจัยหลายขั้นตอน
  2. การตรวจสอบแหล่งที่มาและการอ้างอิง
  3. การสร้างรายงานแบบมีโครงสร้าง
  4. การตรวจสอบข้อเท็จจริงและการป้องกันการหลอน
← กลับไปที่ AI Agents