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

การสกัดเอนทิตีสำหรับกราฟความรู้

การรู้จำเอนทิตีที่มีชื่อ การสกัดความสัมพันธ์ และการเติมข้อมูลลงในกราฟ

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

การสกัดเอนทิตีคืออะไร

การสกัดเอนทิตี (การรู้จำเอนทิตีที่มีชื่อ, NER) คือการระบุสิ่งที่มีชื่อในข้อความ เช่น บุคคล องค์กร สถานที่ วันที่ และอื่น ๆ นี่เป็นขั้นตอนแรกในการสร้างกราฟความรู้จากข้อความที่ไม่มีโครงสร้าง

พื้นฐาน NER ของ spaCy

โมเดล en_core_web_sm ของ spaCy รู้จำประเภทเอนทิตีมาตรฐาน เช่น PERSON, ORG, GPE (เอนทิตีทางภูมิรัฐศาสตร์), DATE, MONEY และอื่น ๆ

import spacy

# Load English model (install: python -m spacy download en_core_web_sm)
nlp = spacy.load('en_core_web_sm')

text = 'Elon Musk founded SpaceX in 2002 in Hawthorne, California. Tesla is headquartered in Austin, Texas.'

doc = nlp(text)

for ent in doc.ents:
    print(f'{ent.text:30} {ent.label_:15} {spacy.explain(ent.label_)}')

# Output:
# Elon Musk                      PERSON          People, including fictional
# SpaceX                         ORG             Companies, agencies...
# 2002                           DATE            Absolute or relative dates
# Hawthorne, California          GPE             Countries, cities, states

การสกัดเอนทิตีเป็นข้อมูลที่มีโครงสร้าง

แปลงผลลัพธ์เอนทิตีจาก spaCy ให้อยู่ในรูปแบบที่มีโครงสร้างและเหมาะสำหรับจัดเก็บในกราฟความรู้ จัดกลุ่มเอนทิตีตามประเภทและกำจัดรายการซ้ำภายในเอกสาร

import spacy
from collections import defaultdict

nlp = spacy.load('en_core_web_sm')

def extract_entities(text: str) -> dict:
    doc = nlp(text)
    entities = defaultdict(set)
    
    for ent in doc.ents:
        entities[ent.label_].add(ent.text.strip())
    
    # Convert sets to lists for JSON serialization
    return {k: list(v) for k, v in entities.items()}

text = 'Apple CEO Tim Cook announced new products. The event was held in Cupertino on September 12, 2023.'
result = extract_entities(text)

import json
print(json.dumps(result, indent=2))
# {
#   "ORG": ["Apple"],
#   "PERSON": ["Tim Cook"],
#   "GPE": ["Cupertino"],
#   "DATE": ["September 12, 2023"]
# }

การสกัดความสัมพันธ์ด้วย LLM

spaCy ระบุเอนทิตีได้ แต่ไม่สามารถระบุความสัมพันธ์ระหว่างเอนทิตีเหล่านั้นได้ ให้ถาม LLM ว่า ความสัมพันธ์ระหว่าง X กับ Y คืออะไร เพื่อสกัดเส้นเชื่อมสำหรับกราฟความรู้

import openai
import json

client = openai.OpenAI(api_key='sk-...')

def extract_relations(text: str, entities: list) -> list:
    if len(entities) < 2:
        return []
    
    entity_list = ', '.join(entities)
    prompt = (
        f'Given this text and these entities: {entity_list}\n\n'
        f'Text: {text}\n\n'
        'Extract relationships between the entities. '
        'Return a JSON array of objects with fields: '
        'subject (string), relation (string), object (string). '
        'Use concise relation labels like FOUNDED_BY, WORKS_AT, LOCATED_IN, ACQUIRED_BY.'
    )
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    result = json.loads(response.choices[0].message.content)
    return result.get('relations', [])

text = 'Elon Musk founded SpaceX in Hawthorne, California.'
entities = ['Elon Musk', 'SpaceX', 'Hawthorne']
relations = extract_relations(text, entities)
print(relations)
# [{'subject': 'Elon Musk', 'relation': 'FOUNDED', 'object': 'SpaceX'},
#  {'subject': 'SpaceX', 'relation': 'LOCATED_IN', 'object': 'Hawthorne'}]

การทำให้เอนทิตีเป็นมาตรฐาน

เอนทิตีเดียวกันอาจปรากฏในรูปแบบที่แตกต่างกัน เช่น Elon Musk, Musk, E. Musk การทำให้เป็นมาตรฐานจะจับคู่รูปแบบเหล่านี้กับรูปแบบมาตรฐานเดียวกันก่อนเพิ่มลงในกราฟ

import openai
import json

client = openai.OpenAI(api_key='sk-...')

def normalize_entities(entity_mentions: list, entity_type: str) -> dict:
    '''
    Groups variations of the same entity together.
    Returns {canonical_name: [mention1, mention2, ...]}
    '''
    if len(entity_mentions) <= 1:
        return {m: [m] for m in entity_mentions}
    
    mentions_str = json.dumps(entity_mentions)
    prompt = (
        f'These are {entity_type} entity mentions from text: {mentions_str}\n'
        'Group mentions that refer to the same entity. '
        'Return JSON: {"groups": [["canonical", "alias1", "alias2"], ...]}'
    )
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    result = json.loads(response.choices[0].message.content)
    
    normalized = {}
    for group in result.get('groups', []):
        if group:
            canonical = group[0]
            for mention in group:
                normalized[mention] = canonical
    return normalized

mentions = ['Elon Musk', 'Musk', 'E. Musk', 'Tim Cook']
result = normalize_entities(mentions, 'PERSON')
print(result)

การกำจัดเอนทิตีซ้ำ

ก่อนแทรกข้อมูลลงในกราฟความรู้ ให้ตรวจสอบก่อนว่าเอนทิตีนั้นมีอยู่แล้วหรือไม่ ใช้การจับคู่แบบคลุมเครือหรือรหัสมาตรฐานเพื่อรวมรายการซ้ำจากแหล่งเอกสารหลายแห่ง

from difflib import SequenceMatcher

class EntityRegistry:
    def __init__(self, similarity_threshold=0.85):
        self.entities = {}  # {canonical_name: entity_data}
        self.threshold = similarity_threshold
    
    def similarity(self, a: str, b: str) -> float:
        return SequenceMatcher(None, a.lower(), b.lower()).ratio()
    
    def find_existing(self, name: str) -> str:
        for canonical in self.entities:
            if self.similarity(name, canonical) >= self.threshold:
                return canonical
        return None
    
    def add_entity(self, name: str, entity_type: str, metadata: dict = None) -> str:
        existing = self.find_existing(name)
        if existing:
            print(f'Merged "{name}" -> "{existing}"')
            return existing
        self.entities[name] = {'type': entity_type, 'metadata': metadata or {}}
        print(f'New entity: "{name}"')
        return name

registry = EntityRegistry()
registry.add_entity('OpenAI', 'ORG', {})
registry.add_entity('Open AI', 'ORG', {})   # Merged
registry.add_entity('OpenAI Inc', 'ORG', {})  # Merged
registry.add_entity('Microsoft', 'ORG', {})

การประมวลผลเอกสารหลายฉบับ

เมื่อสร้างกราฟความรู้จากชุดเอกสาร ให้ประมวลผลเอกสารตามลำดับและสะสมเอนทิตีกับความสัมพันธ์ไว้ ติดตามว่าแต่ละข้อเท็จจริงมาจากเอกสารใด (แหล่งที่มา)

import spacy
from typing import List, Dict

nlp = spacy.load('en_core_web_sm')

@dataclass
class KGFact:
    subject: str
    relation: str
    obj: str
    source_doc: str

def process_corpus(documents: List[Dict]) -> List:
    facts = []
    entity_registry = EntityRegistry()
    
    for doc in documents:
        doc_id = doc['id']
        text = doc['text']
        
        # Extract entities
        spacy_doc = nlp(text)
        persons = [ent.text for ent in spacy_doc.ents if ent.label_ == 'PERSON']
        orgs = [ent.text for ent in spacy_doc.ents if ent.label_ == 'ORG']
        
        # Register entities (deduplication)
        for p in persons:
            entity_registry.add_entity(p, 'PERSON')
        for o in orgs:
            entity_registry.add_entity(o, 'ORG')
        
        print(f'Processed doc {doc_id}: {len(persons)} persons, {len(orgs)} orgs')
    
    return entity_registry.entities

docs = [
    {'id': 'doc1', 'text': 'Sundar Pichai leads Google.'},
    {'id': 'doc2', 'text': 'Google CEO Sundar Pichai spoke at the conference.'}
]
entities = process_corpus(docs)

ประเภทเอนทิตีสำหรับกราฟความรู้

ออกแบบการจัดหมวดหมู่เอนทิตีของคุณก่อนสร้างกราฟ ประเภทที่พบได้บ่อยสำหรับกราฟความรู้ทางธุรกิจ ได้แก่ Person, Organization, Product, Location, Event, Technology ประเภทแบบกำหนดเองจะขึ้นอยู่กับโดเมนของคุณ

ENTITY_TYPES = {
    'PERSON': {
        'description': 'Individual human being',
        'properties': ['name', 'title', 'email'],
        'spacy_labels': ['PERSON']
    },
    'ORGANIZATION': {
        'description': 'Company, institution, or group',
        'properties': ['name', 'industry', 'founded'],
        'spacy_labels': ['ORG']
    },
    'LOCATION': {
        'description': 'Geographic place',
        'properties': ['name', 'country', 'coordinates'],
        'spacy_labels': ['GPE', 'LOC', 'FAC']
    },
    'PRODUCT': {
        'description': 'Product or service (custom, not in spaCy)',
        'properties': ['name', 'category', 'version'],
        'spacy_labels': ['PRODUCT']
    }
}

# Map spaCy labels to our types
def map_spacy_to_entity_type(spacy_label: str) -> str:
    for entity_type, config in ENTITY_TYPES.items():
        if spacy_label in config['spacy_labels']:
            return entity_type
    return 'UNKNOWN'

print(map_spacy_to_entity_type('ORG'))     # ORGANIZATION
print(map_spacy_to_entity_type('GPE'))     # LOCATION
print(map_spacy_to_entity_type('PERSON'))  # PERSON

การผสาน spaCy และ LLM

ใช้ spaCy เพื่อตรวจจับเอนทิตีอย่างรวดเร็วและประหยัดค่าใช้จ่าย ส่วน LLM ให้ใช้เฉพาะกับงานที่ยากกว่า เช่น การสกัดความสัมพันธ์ การแยกแยะเอนทิตี และการจัดการเอนทิตีเฉพาะด้านที่ spaCy ตรวจไม่พบ

import spacy
import openai

nlp = spacy.load('en_core_web_sm')
client = openai.OpenAI(api_key='sk-...')

def full_extraction_pipeline(text: str) -> dict:
    # Step 1: Fast spaCy extraction
    doc = nlp(text)
    entities = [
        {'text': ent.text, 'type': ent.label_}
        for ent in doc.ents
        if ent.label_ in ['PERSON', 'ORG', 'GPE', 'PRODUCT']
    ]
    
    if len(entities) < 2:
        return {'entities': entities, 'relations': []}
    
    # Step 2: LLM relation extraction (only when we have multiple entities)
    entity_names = [e['text'] for e in entities]
    relations = extract_relations(text, entity_names)
    
    return {
        'entities': entities,
        'relations': relations
    }

text = 'Satya Nadella of Microsoft acquired Activision Blizzard for $69 billion.'
result = full_extraction_pipeline(text)
print('Entities:', result['entities'])
print('Relations:', result['relations'])

การตรวจสอบข้อมูลที่สกัดได้

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

VALID_RELATIONS = {
    'FOUNDED_BY', 'WORKS_AT', 'LOCATED_IN', 'ACQUIRED_BY',
    'PARTNERED_WITH', 'INVESTED_IN', 'CEO_OF', 'PRODUCT_OF'
}

def validate_relation(relation: dict, known_entities: set) -> tuple:
    errors = []
    subject = relation.get('subject', '')
    relation_label = relation.get('relation', '')
    obj = relation.get('object', '')
    
    if not subject:
        errors.append('Missing subject')
    if not obj:
        errors.append('Missing object')
    if relation_label not in VALID_RELATIONS:
        errors.append(f'Unknown relation: {relation_label}')
    if subject and subject not in known_entities:
        errors.append(f'Unknown entity: {subject}')
    if obj and obj not in known_entities:
        errors.append(f'Unknown entity: {obj}')
    
    return len(errors) == 0, errors

known = {'Elon Musk', 'SpaceX', 'California'}
relation = {'subject': 'Elon Musk', 'relation': 'FOUNDED_BY', 'object': 'SpaceX'}
valid, errors = validate_relation(relation, known)
print('Valid:', valid, 'Errors:', errors)

การสร้างกราฟแบบเพิ่มทีละน้อย

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

def build_knowledge_graph_incremental(new_documents: list, graph_db, entity_registry):
    for doc in new_documents:
        print(f'Processing document: {doc["id"]}')
        
        # Extract
        extraction = full_extraction_pipeline(doc['text'])
        
        # Register and deduplicate entities
        canonical_entities = {}
        for entity in extraction['entities']:
            canonical = entity_registry.add_entity(
                entity['text'],
                entity['type']
            )
            canonical_entities[entity['text']] = canonical
            # Upsert node in graph
            graph_db.upsert_node(canonical, entity['type'])
        
        # Validate and insert relations
        for relation in extraction['relations']:
            # Map to canonical names
            subj = canonical_entities.get(relation['subject'], relation['subject'])
            obj = canonical_entities.get(relation['object'], relation['object'])
            valid, errors = validate_relation(
                {'subject': subj, 'relation': relation['relation'], 'object': obj},
                set(canonical_entities.values())
            )
            if valid:
                graph_db.upsert_edge(subj, relation['relation'], obj, doc['id'])
            else:
                print(f'Skipping invalid relation: {errors}')

print('Graph build pipeline defined')

ตรวจสอบความรู้: การสกัดเอนทิตี

ทดสอบความเข้าใจของคุณเกี่ยวกับการสกัดเอนทิตีสำหรับกราฟความรู้

สรุปการสกัดเอนทิตี

กระบวนการทำงานสกัดเอนทิตีสำหรับกราฟความรู้ที่สมบูรณ์ประกอบด้วย NER ของ spaCy สำหรับการตรวจจับเอนทิตีอย่างรวดเร็ว การสกัดความสัมพันธ์ด้วย LLM การทำให้เอนทิตีเป็นมาตรฐานเพื่อจับคู่รูปแบบที่ปรากฏกับชื่อมาตรฐาน การกำจัดรายการซ้ำเพื่อหลีกเลี่ยงโหนดซ้ำซ้อน การตรวจสอบก่อนแทรกข้อมูล และการติดตามแหล่งที่มาเพื่อทราบว่าแต่ละข้อเท็จจริงมาจากเอกสารใด

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

บทเรียน “การสกัดเอนทิตีสำหรับกราฟความรู้” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การสกัดเอนทิตีสำหรับกราฟความรู้”

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

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

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

บทเรียน “การสกัดเอนทิตีสำหรับกราฟความรู้” ใช้เวลานานแค่ไหน

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

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

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

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

  1. การสกัดเอนทิตีสำหรับกราฟความรู้
  2. การสืบค้น Neo4j จากเครื่องมือของเอเจนต์
  3. การผสานการค้นคืนแบบเวกเตอร์และกราฟ
  4. การสร้างเอเจนต์เสริมความรู้
← กลับไปที่ AI Agents