การสกัดเอนทิตีสำหรับกราฟความรู้
การรู้จำเอนทิตีที่มีชื่อ การสกัดความสัมพันธ์ และการเติมข้อมูลลงในกราฟ
การสกัดเอนทิตีสำหรับกราฟความรู้ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสกัดเอนทิตีสำหรับกราฟความรู้
- การสืบค้น Neo4j จากเครื่องมือของเอเจนต์
- การผสานการค้นคืนแบบเวกเตอร์และกราฟ
- การสร้างเอเจนต์เสริมความรู้