Practical Applications of Chatbot

Knowledge Graph Part 2: Information Extraction

Last Updated: 2025/05/06

王柳鋐

文本分析

Basis of Knowledge Graph: Text Analysis

文本分析基本任務: 斷詞、詞性標記、實體辨識 

"我和順仔早上5點登上「福建號」"

我和<person>順仔</person>早上5點登上「<ship>福建號</ship>

斷詞(tagger)

(命名)實體辨識NER
name-entity-recognition

原文

我  和  順仔  早上  5點   登上   福建號

          r   c    nr        t        t         v        nr

詞性標記PoS
part-of-speech

專業術語 + 分類

應用:索引、Hyperlink

中文文本分析開發工具 

中文文本分析開發工具2018之後

BERT

Bidirectional Encoder Representations from Transformers

中文文本分析開發工具2018之後 

文本分析的困難之處(1/3)

拜訪    普林斯    神學院    老同  學麥克  切斯  尼  先生    幾位  宣教  師 。 晚上 介紹 加拿大 , 哈巴  安德  醫師  翻譯

斷詞

困難: 斷詞錯誤    雜訊

"拜訪我普林斯頓(Princeton)神學院的老同學麥克切斯尼(McChesney)先生和幾位宣教師。晚上介紹加拿大,哈巴安德醫師翻譯。"

Icons made by Freepik from www.flaticon.com
Icons made by Eucalyp from www.flaticon.com

自訂辭典

停用字列表

普林斯頓

老同學

麥克切斯尼先生

哈巴安德醫師

宣教師

晚上

幾位

拜訪   普林斯  神學院    老同學   麥克切斯尼先生   宣教師 。 介紹 加拿大 , 哈巴安德醫師  翻譯

困難: 錯別字、同義詞(不同稱呼/不同翻譯)

Icons made by Eucalyp from www.flaticon.com

拜訪南勢番(南方的原住民),在包干李流(Li-lau),薄薄、斗蘭(Tau-lan)和七腳川拍了一些照片。

台灣堡圖

1904

我們拜訪流流、薄薄、里腦,又回到大社

問題:究竟是里腦,李流還是流流?

不同翻譯

回到五股坑,蔥仔在前往領事館費里德(A.Frater)先生那裡後和我們一起。

偕師母及閏虔益一起到五股坑,然後去洲裡,在晚上回來。

同義詞

專家

修正與建議

里漏社

自訂辭典

停用字列表

文本分析的困難之處(2/3)

訓練資料很難取得

文本分析的困難之處(3/3)

通用資訊擷取

Universal Information Extraction (UIE)

Universal IE

Universal Information Extraction(UIE,通用資訊擷取)

適用於多種任務、與多樣資料格式的統一模型或框架。

 

這些任務可能包括:

  • 命名實體辨識(Named Entity Recognition, NER)

  • 關係擷取(Relation Extraction, RE)

  • 事件擷取(Event Extraction)

  • 屬性擷取(Attribute Extraction)

  • 情感/意圖識別(Sentiment/Intent Extraction)

  • 半結構化資料的擷取(semi-structured sources like tables, forms)

「2024年,台積電在美國亞利桑那州設立了新晶圓廠。」

例句:

🟩 命名實體辨識(NER)

有意義的「實體」類別,例如人名、地名、組織名、時間等。

🔍 結果:

台積電 → ORG(組織)

美國亞利桑那州 → LOC(地點)

2024年 → DATE(時間)

 

NER 是基礎任務,通常其他任務都會依賴它的結果。

NER/關係擷取/事件擷取/屬性擷取

「2024年,台積電在美國亞利桑那州設立了新晶圓廠。」

例句:

🟦 關係擷取(Relation Extraction, RE)

在實體之間建立語意關係,如誰屬於誰、誰在何處、誰做了什麼

🔍 結果:

(台積電, 設廠地點, 美國亞利桑那州)

(事件時間, 設廠, 2024年)

 

系統需理解哪些實體之間存在特定語義上的「關聯」

NER/關係擷取/事件擷取/屬性擷取

🟨 事件擷取(Event Extraction, EE)

辨識事件的觸發詞(trigger)與其相關角色(arguments)

像是誰做了什麼、在什麼時間、在哪裡等。

🔍 結果:

  • 事件類型:設廠(建設/擴張型事件)
  • 觸發詞:設立
  • 角色參數:
    • 主體(Agent):台積電
    • 地點(Place):美國亞利桑那州
    • 時間(Time):2024年
    • 設施(Facility):新晶圓廠

這類任務通常會搭配「事件結構模板」,較接近語意理解。

NER/關係擷取/事件擷取/屬性擷取

🟧 屬性擷取(Attribute Extraction)

擷取產品資訊、知識圖譜、評論分析中的特定屬性或描述

例句:

「這間晶圓廠的產能為每月4萬片,專門生產3奈米晶片。」

🔍 結果:

產能:每月4萬片

製程技術:3奈米

用途:生產晶片

對象(主體):這間晶圓廠

NER/關係擷取/事件擷取/屬性擷取

📌 總結比較

          任務類型               問題定義                            結果範例

NER 實體是誰?在哪?是什麼? 台積電:ORG、亞利桑那州:LOC
RE 實體之間有什麼關係? 台積電 → 設廠地點 → 美國亞利桑那州
EE 發生了什麼事件?誰參與? 設立事件,主體:台積電,地點:亞利桑那
屬性擷取 對象有哪些屬性? 晶圓廠 → 產能:4萬片/月,製程:3奈米

NER/關係擷取/事件擷取/屬性擷取

Ckip Transformers安裝與使用

Ckip Transformers安裝與使用

使用方法ㄧ: 透過HuggingFace Transformers

圖片來源:Transformers, PyTorch, TensorFlow

pip install -U transformers

❶ 安裝transformers套件

❷ 安裝深度學習套件(擇一)

pip install -U torch
pip install -U tensorflow

* 後續以PyTorch為例

Ckip Transformers安裝與使用

使用方法二: CKIP_Transformers

圖片來源:Transformers, PyTorch, TensorFlow

pip install -U ckip-transformers
pip install -U torch

* 後續以PyTorch為例

from ckip_transformers.nlp import CkipWordSegmenter, CkipPosTagger, CkipNerChunker
## 將斷詞結果words與 part-of-speech結果pos打包在一起
def pack_ws_pos_sentece(words, pos):
   assert len(words) == len(pos), f'words{len(words)}和pos{len(pos)}長度必須一樣'
   result = []   # 最終結果串列
   for word, p in zip(words, pos):  # zip將words,pos對應位置鏈在一起
      result.append(f"{word}({p})")
   return "\u3000".join(result)  #\u3000是全形空白字元

# Input text
text = [
   "華氏80度,氣壓30-6,整天下雨。前進到奇武荖,聆聽朗誦。然後珍珠里簡和冬瓜山,晚間在珍珠里簡的禮拜有一百五十人,拔了七十六顆牙。",
   "相當涼爽舒適,與阿華出去鄉間拜訪他的一位老朋友,是一位農人。我們被看見,認出來,且受排斥。遭到兩隻大黑狗攻擊,孩童吼叫,狂暴的辱罵。 我們回家,在吃過飯之後,我們比過去更勤奮的研讀各自的功課。",
   "華氏84度,陰天,氣壓30-10。上午七點離開大里簡,大部分都用走的,上午時點三十分來到頭城,拔了一些牙。十一點到打馬煙,我們剛到雨就來了。禮德醫師在路上幫一個傢伙縫手指。新漆好的禮拜堂到處都是用藍色和紅色漆,全部由他們自費花了十二元。禮德醫師拍團體照。我們照顧了十四名病人,還拔了一些牙。主持聖餐禮,聆聽十七個人背誦。大家都做得很好,我們發禮物給他們。"
   ]

ws_driver = CkipWordSegmenter(model="bert-base") # 載入 斷詞模型
pos_driver = CkipPosTagger(model="bert-base")    # 載入 POS模型
ner_driver = CkipNerChunker(model="bert-base")   # 載入 實體辨識模型
print('all loaded...')

# 執行pipeline 產生結果
ws = ws_driver(text)   # 斷詞
pos = pos_driver(ws)   # 詞性: 注意斷詞-詞性是依序完成
ner = ner_driver(text) # 實體辨識

##列印結果
for sentence, word, p, n in zip(text, ws, pos, ner):
    print(sentence)
    print(pack_ws_pos_sentece(word, p))
    for token in n:
        print(f"({token.idx[0]}, {token.idx[1]}, '{token.ner}', '{token.word}')")
    print()

華氏80度,氣壓30-6,整天下雨。前進到奇武荖,聆聽朗誦。然後珍珠里簡和冬瓜山,晚間在珍珠里簡的禮拜有一百五十人,拔了七十六顆牙。


華氏(Na) 80(Neu) 度(Nf) ,(COMMACATEGORY) 氣壓(Na) 30-6(Neu) ,(COMMACATEGORY) 整(Neqa) 天(Nf) 下雨(VA) 。(PERIODCATEGORY) 前進(VA) 到(P) 奇武荖(Nc) ,(COMMACATEGORY) 聆聽(VC) 朗誦(VC) 。(PERIODCATEGORY) 然後(D) 珍珠里簡(Na) 和(Caa) 冬瓜山(Nc) ,(COMMACATEGORY) 晚間(Nd) 在(P) 珍珠里簡(Nc) 的(DE) 禮拜(Na) 有(V_2) 一百五十(Neu) 人(Na) ,(COMMACATEGORY) 拔(VC) 了(Di) 七十六(Neu) 顆(Nf) 牙(Na) 。(PERIODCATEGORY)


(0, 5, 'QUANTITY', '華氏80度')
(8, 12, 'QUANTITY', '30-6')
(37, 40, 'LOC', '冬瓜山')
(41, 43, 'TIME', '晚間')
(52, 56, 'CARDINAL', '一百五十')
(60, 63, 'CARDINAL', '七十六')

實體辨識

11類專有名詞

7類數量詞

Part-of-Speech(POS)

61種詞性

華氏80度,氣壓30-6,整天下雨。前進到奇武荖,聆聽朗誦。然後珍珠里簡和冬瓜山,晚間在珍珠里簡的禮拜有一百五十人,拔了七十六顆牙。


華氏(Na) 80(Neu) 度(Nf) ,(COMMACATEGORY) 氣壓(Na) 30-6(Neu) ,(COMMACATEGORY) 整(Neqa) 天(Nf) 下雨(VA) 。(PERIODCATEGORY) 前進(VA) 到(P) 奇武荖(Nc) ,(COMMACATEGORY) 聆聽(VC) 朗誦(VC) 。(PERIODCATEGORY) 然後(D) 珍珠里簡(Na) 和(Caa) 冬瓜山(Nc) ,(COMMACATEGORY) 晚間(Nd) 在(P) 珍珠里簡(Nc) 的(DE) 禮拜(Na) 有(V_2) 一百五十(Neu) 人(Na) ,(COMMACATEGORY) 拔(VC) 了(Di) 七十六(Neu) 顆(Nf) 牙(Na) 。(PERIODCATEGORY)


(0, 5, 'QUANTITY', '華氏80度')
(8, 12, 'QUANTITY', '30-6')
(37, 40, 'LOC', '冬瓜山')
(41, 43, 'TIME', '晚間')
(52, 56, 'CARDINAL', '一百五十')
(60, 63, 'CARDINAL', '七十六')

只辨識出1個實體

且分類錯誤

應為GPE

3個地名,共出現四次

珍珠里簡: 不同詞性?

Na:普通名詞,Nc: 地方詞

from ckip_transformers.nlp import CkipWordSegmenter, CkipPosTagger, CkipNerChunker
ws_driver = CkipWordSegmenter() # 初始化 CKIP 模型
pos_driver = CkipPosTagger()
ner_driver = CkipNerChunker()
text = ["2024年,台積電在美國亞利桑那州設立了新晶圓廠。"]
ws = ws_driver(text)
pos = pos_driver(ws)
ner = ner_driver(text)
print("🔎 命名實體:")
for sentence in ner:
    for entity in sentence:
        print(f"{entity.word} → {entity.ner}")
print("💥 事件擷取(簡易)")
trigger_words = ["設立", "成立", "開幕", "建設"]
for tokens, tags in zip(ws, pos):
    for i, word in enumerate(tokens):
        if word in trigger_words:
            subject = tokens[i-2] if i >= 2 else ""
            location = tokens[i-1] if i >= 1 else ""
            obj = tokens[i+1] if i+1 < len(tokens) else ""
            print(f"事件:{word}")
            print(f"  主體:{subject}")
            print(f"  地點:{location}")
            print(f"  對象:{obj}")
print("🔗 關係擷取(主詞-動詞-受詞邏輯)")
for tokens, tags in zip(ws, pos):
    for i in range(1, len(tokens)-1):
        if tags[i].startswith("V"):
            subj = tokens[i-1]
            obj = tokens[i+1]
            print(f"[主詞] {subj} —[動詞] {tokens[i]}→ [受詞] {obj}")

NER/關係擷取/事件擷取 CKIP_Transformers

Universal IE continue

🧠 核心概念

UIE 的目標是建構一個不同任務和領域的通用模型

UIE 強調:

  • 任務無關性:不需為不同任務設計不同模型

  • 資料格式通用性:能處理文本、表格、HTML 等格式。

  • 少樣本學習能力(few-shot / zero-shot learning)

    • 即使在新任務或新資料上也能快速適應。

Universal IE methodology

🔧 方法與技術

  1. 序列到序列(Seq2Seq)框架

    • 轉換成文字生成任務。例如,把「從句子中取出人名」變成「輸入:句子 + 指令,輸出:人名」。

    • 代表模型:T5, BART 等。

  2. Prompt-based Learning(提示學習)

    • 使用自然語言提示引導模型完成不同的抽取任務,常結合大型語言模型(如 GPT 系列、ChatGPT、T5、FLAN-T5)。

  3. Unified Schema/Framework

    • 如 OneIE、UIE、SpERT(Span-based Entity and Relation Transformer)等,把所有任務轉化為統一的「標註問題」。

  4. 多任務學習(Multi-task Learning)

    • 訓練一個模型解決多種任務,有助於學到更一般化的表示。

Universal IE methodology

🔬 代表性研究與模型

   名稱                                   發表單位                  年份      特點

UIE (DAMO Academy, Alibaba)

Alibaba

2022

提出 prompt-based 的 unified schema,支援多種任務(NER、RE、Event)。

OneIE

Columbia University

2020

將多任務建模視為 span-based sequence labeling 任務。

SpERT

IBM Research

2020

使用 transformer 擷取實體與關係,統一架構下進行 span prediction。

Text2Event

THU(清華)

2021

將事件擷取建模為序列生成任務。

TIE (Text-in-Text)

Facebook AI

2021

將所有任務統一成「子文字擷取」的問題。

Universal IE methodology

Universal IE Implementation

pip install paddlepaddle==2.6.1

非GPU版本

pip install -U paddlenlp
from paddlenlp.transformers import AutoTokenizer, AutoModelForTokenClassification
import paddle
# 使用 ERNIE 3.0 模型進行中文NER, 以7類為例(num_classes)
model_name = "ernie-3.0-base-zh"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForTokenClassification.from_pretrained(model_name, num_classes=7) 
# 自定義一段中文文本
text = "華氏80度,氣壓30-6,整天下雨。前進到奇武荖,聆聽朗誦。然後珍珠里簡和冬瓜山,晚間在珍珠里簡的禮拜有一百五十人,拔了七十六顆牙。"
# 將文本轉換為模型輸入格式
inputs = tokenizer(text, return_tensors="pd", padding=True, truncation=True, max_length=128)
# 模型預測
with paddle.no_grad():
    logits = model(**inputs)
    preds = paddle.argmax(logits, axis=-1).numpy()[0]
# 取出詞元與標籤
tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'][0].numpy())
label_map = {
    0: "O",       # 非實體
    1: "B-PER",   # 人名開頭
    2: "I-PER",   # 人名內部
    3: "B-ORG",   # 組織開頭
    4: "I-ORG",   # 組織內部
    5: "B-LOC",   # 地名開頭
    6: "I-LOC",   # 地名內部
}
# 顯示結果(只顯示非 'O' 的實體)
print("命名實體識別結果:")
for token, pred in zip(tokens, preds):
    label = label_map.get(pred, "O")
    if label != "O":
        print(f"{token}: {label}")

NER

from paddlenlp import Taskflow

# 醫療實體識別:診斷、症狀、藥物
schema = ['疾病', '症狀', '藥物']
ie_medical = Taskflow('information_extraction', model='uie-medical-base', schema=schema)

text = "患者出現高燒、咳嗽等症狀,診斷為流感,建議服用達菲。"

result = ie_medical(text)
print(result)

NER-醫療類

from paddlenlp import Taskflow

# 自訂實體類別
schema = ['學校名稱', '創辦人', '總部城市']
ie_custom = Taskflow('information_extraction', model='uie-base', schema=schema)

text = "真理大學是由牛津學堂發展而來,創辦人是馬偕,位於淡水。"

result = ie_custom(text)
print(result)

NER-自訂

from paddlenlp import Taskflow

# 自訂 schema(可根據任務調整)
schema = ['人物', '組織', '地點']
ie = Taskflow('information_extraction', model='uie-base', schema=schema)

# 多筆資料(List of strings)
texts = [
    "馬雲是阿里巴巴的創始人,總部位於杭州。",
    "劉德華出生於香港,是華語影壇的重要人物。",
    "鴻海總部在新北市,創辦人是郭台銘。"
]

# 批次預測
results = ie(texts)

# 顯示結果
for idx, res in enumerate(results):
    print(f"\n【第 {idx + 1} 筆輸入】")
    print(res)

NER-批次處理

PaddleNLP finetune

pip install paddlepaddle==2.6.1

非GPU版本

pip install -U paddlenlp
git clone https://github.com/PaddlePaddle/PaddleNLP.git
cd PaddleNLP/slm/model_zoo_uie

下載微調專案,前往微調樣板資料夾

PaddleNLP finetune

建議資料夾結構

uie/

訓練檔

驗證檔

{"content": "蔡英文是台灣的總統,住在台北。", "prompt": "人物", "result_list": [{"start": 0, "end": 3, "text": "蔡英文"}]}
{"content": "蔡英文是台灣的總統,住在台北。", "prompt": "地點", "result_list": [{"start": 9, "end": 11, "text": "台灣"}]}
{"content": "蔡英文是台灣的總統,住在台北。", "prompt": "地點", "result_list": [{"start": 16, "end": 18, "text": "台北"}]}

train.jsonl

{"content": "侯友宜是新北市市長,住在新北。", "prompt": "人物", "result_list": [{"start": 0, "end": 3, "text": "侯友宜"}]}
{"content": "侯友宜是新北市市長,住在新北。", "prompt": "地點", "result_list": [{"start": 6, "end": 9, "text": "新北市"}]}
{"content": "侯友宜是新北市市長,住在新北。", "prompt": "地點", "result_list": [{"start": 14, "end": 16, "text": "新北"}]}
{"content": "台灣大學是台灣最著名的高等教育機構之一,位於台北。", "prompt": "組織", "result_list": [{"start": 0, "end": 4, "text": "台灣大學"}]}
{"content": "台灣大學是台灣最著名的高等教育機構之一,位於台北。", "prompt": "地點", "result_list": [{"start": 21, "end": 23, "text": "台灣"}]}
{"content": "台灣大學是台灣最著名的高等教育機構之一,位於台北。", "prompt": "地點", "result_list": [{"start": 31, "end": 33, "text": "台北"}]}

dev.jsonl

PaddleNLP finetune


python finetune.py \
  --train_path train.jsonl \
  --dev_path dev.jsonl \
  --output_dir ./checkpoint/uie-taiwan-custom \
  --model_name_or_path uie-base \
  --max_seq_length 512 \
  --per_device_train_batch_size 16 \
  --per_device_eval_batch_size 16 \
  --learning_rate 1e-5 \
  --num_train_epochs 10 \
  --logging_steps 10 \
  --eval_steps 50 \
  --save_steps 50 \
  --do_train \
  --do_eval \
  --overwrite_output_dir \
  --device gpu

Preparation: Information Extraction

By Leuo-Hong Wang

Preparation: Information Extraction

  • 34