返回文章列表

知識圖譜問答系統建構與效能評估

本文探討如何建構根據知識圖譜的問答系統,並利用 Sentence Transformers 計算 cosine 相似度評估系統效能。文章涵蓋了從樹狀結構到圖形資料函式庫的轉換、維基百科資料擷取、Pipeline 流程設計、以及效能指標計算與分析等關鍵步驟。同時也探討了效能最佳化策略和未來發展方向。

知識圖譜 自然語言處理

現代問答系統仰賴知識圖譜的建構與有效查詢。本文探討如何從維基百科等來源建構知識圖譜,並結合 LlamaIndex 和 OpenAI 技術,開發高效能的問答系統。文章詳細介紹了資料收集、清理、轉換的流程,並使用 Python 和相關函式庫實作圖形資料函式庫的建構。此外,利用 Sentence Transformers 計算 cosine 相似度,結合人工回饋,對系統效能進行了全面評估,並提出了最佳化策略和未來發展方向。

建構客製化增強生成式 AI 知識函式庫

從樹狀結構到圖形資料函式庫的實踐

在深入程式碼之前,我們先來探討如何將樹狀結構轉換為圖形結構。圖形是由節點(或頂點)和邊(或弧)組成的集合。節點代表實體,邊代表這些實體之間的關係或連線。例如,在本案例中,節點可以代表各種行銷策略,邊則可以顯示這些策略之間的相互關聯。這有助於新客戶理解不同的行銷策略如何協同工作以達成整體業務目標,促進更清晰的溝通和更有效的策略規劃。

您可以參考 GitHub 上的 Tree-2-Graph.ipynb 檔案,這個程式使用 NetworkX 和 Matplotlib 以視覺化方式呈現樹狀結構中的關係。它可以根據給定的節點對建立有向圖,檢查並標記朋友關係,然後顯示具有自定義視覺屬性的樹狀圖。

程式首先定義了以下主要函式:

  • build_tree_from_pairs(pairs):從節點對列表構建有向圖(樹),並識別根節點。
  • check_relationships(pairs, friends):檢查並列印每對節點的朋友關係狀態。
  • draw_tree(G, layout_choice, root, friends):使用 Matplotlib 視覺化樹狀圖,根據朋友關係狀態應用不同的邊緣樣式,並提供不同的節點佈局選項。

接著,程式執行從樹到圖的轉換過程:

  1. 定義節點對和朋友關係資料。
  2. 根據節點對構建樹狀圖。
  3. 根據朋友關係資料檢查節點關係。
  4. 使用選定的佈局繪製樹狀圖,並使用不同樣式標記朋友關係。

例如,程式首先定義一組節點對及其朋友關係:

# 節點對
pairs = [('a', 'b'), ('b', 'e'), ('e', 'm'), ('m', 'p'), ('a', 'z'), ('b', 'q')]
# 朋友關係
friends = {('a', 'b'), ('b', 'e'), ('e', 'm'), ('m', 'p')}

內容解密:

以上程式碼定義了節點對及其朋友關係。節點對代表樹狀結構中的父子關係,而朋友關係則代表節點之間的一種特殊關係,例如社交網路中的朋友。friends 集合包含了具有朋友關係的節點對。

程式接著構建樹狀圖並檢查節點關係:

# 構建樹狀圖
tree, root = build_tree_from_pairs(pairs)
# 檢查關係
check_relationships(pairs, friends)

輸出顯示哪些節點對是朋友關係,哪些不是:

Pair ('a', 'b'): friend
Pair ('b', 'e'): friend
Pair ('e', 'm'): friend
Pair ('m', 'p'): friend
Pair ('a', 'z'): not friend
Pair ('b', 'q'): not friend

內容解密:

輸出結果顯示了每對節點之間的關係。如果一對節點存在於 friends 集合中,則它們被視為朋友關係,否則被視為非朋友關係。

程式接著使用 spring 佈局繪製圖形:

# 繪製樹狀圖
layout_choice = 'spring'  # 定義佈局選項
draw_tree(tree, layout_choice=layout_choice, root=root, friends=friends)

spring 佈局模擬彈簧效果,使邊緣吸引節點,同時確保所有節點相互排斥以避免重疊。您可以深入研究 draw_tree 函式以探索和選擇其他佈局選項,還可以修改顏色和線條樣式。在這個例子中,朋友關係用實線表示,非朋友關係用虛線表示,如下圖所示:

圖表翻譯: 此圖表展示了樹狀結構中的節點關係。實線表示朋友關係,虛線表示非朋友關係。節點 A 與 B、E、M、P 之間存在朋友關係,而 A 與 Z、B 與 Q 之間則不存在朋友關係。

Pipeline 1:收集和準備檔案

本文中的程式碼將從維基百科擷取我們需要的後設資料、擷取檔案、清理資料,並將其彙總以準備插入 Deep Lake 向量資料函式庫。此過程如下圖所示:

圖表翻譯: 此圖表描述了 Pipeline 1 的流程。首先,從維基百科擷取資料。如果頁面存在,則擷取其摘要和 URL。接著,對資料進行清理和預處理,最後彙總資料。

Pipeline 1 包含兩個筆記本:

  • Wikipedia_API.ipynb:我們將使用維基百科 API 擷取與我們選擇的主題根頁面相關的頁面 URL,包括每個頁面的參照。
  • Knowledge_Graph_Deep_Lake_LlamaIndex_OpenAI_RAG.ipynb:我們將在其中實作所有三個流程。在 Pipeline 1 中,它將擷取 Wikipedia_API 筆記本提供的 URL,清理它們,並載入和彙總它們以進行更新。

擷取維基百科資料和後設資料

讓我們開始構建一個程式,與維基百科 API 互動以擷取有關特定主題的資訊、對擷取的文字進行分詞,並管理維基百科文章的參照。您可以參考 GitHub 儲存函式庫中的 Wikipedia_API.ipynb 檔案。

程式首先安裝我們需要的 wikipediaapi 函式庫:

try:
    import wikipediaapi
except:
    !pip install Wikipedia-API==0.6.0
import wikipediaapi

內容解密:

以上程式碼嘗試匯入 wikipediaapi 函式庫。如果該函式庫尚未安裝,則使用 pip 安裝它。這是確保我們可以使用維基百科 API 的必要步驟。

下一步是定義將被呼叫以計算摘要中標記數量的分詞函式,如下列程式碼片段所示:

import nltk
from nltk.tokenize import word_tokenize

def nb_tokens(text):
    # 更精細的分詞,包含標點符號
    tokens = word_tokenize(text)
    return len(tokens)

內容解密:

此函式接受一個字串作為輸入,並使用 NLTK 函式庫進行更精細的分詞(包含標點符號),傳迴文字中的標記數量。這對於評估文字的大小和複雜度非常有用。

要開始擷取資料,我們需要使用指定的語言和使用者代理設定維基百科 API 的執行個體:

# 使用詳細的使用者代理建立維基百科 API 的執行個體
wiki = wikipediaapi.Wikipedia(
    language='en',
    user_agent='Knowledge/1.0 ([USER AGENT EMAIL)'
)

內容解密:

在這裡,我們建立了一個維基百科 API 的執行個體,並指定了語言為英文 (en)。同時,我們需要提供一個使用者代理字串,這通常包含您的電子郵件地址,以便維基百科能夠識別請求的來源。

我們現在可以定義與感興趣的維基百科頁面相關聯的主題和檔案名稱:

topic = "Marketing"  # 主題
filename = "Marketing"  # 儲存輸出的檔案名稱
maxl = 100  # 設定最大連結數量

內容解密:

這裡定義了三個重要的變數:主題 (topic)、儲存輸出的檔案名稱 (filename),以及我們希望擷取的最大連結數量 (maxl)。

接下來,我們需要擷取指定維基百科頁面的摘要,檢查頁面是否存在,並列印其摘要:

import textwrap  # 用於換行文字並以段落顯示

page = wiki.page(topic)
if page.exists():
    print("頁面 - 存在: %s" % page.exists())
    summary = page.summary
    # 標記數量
    nbt = nb_tokens(summary)
    print("標記數量: ", nbt)
    # 使用 textwrap 將摘要文字換行到指定的寬度
    wrapped_text = textwrap.fill(summary, width=60)
    # 列印預換行後的摘要文字
    print(wrapped_text)
else:
    print("頁面不存在")

內容解密:

這段程式碼首先檢查指定的維基百科頁面是否存在。如果存在,則擷取其摘要並計算摘要中的標記數量。接著,使用 textwrap 將摘要文字換行到指定的寬度,以方便閱讀。

輸出提供所請求的控制資訊,包括頁面是否存在、標記數量以及頁面的摘要內容。

現在,我們可以從目標頁面擷取 URL、連結和摘要:

# 從頁面擷取所有連結
links = page.links
# 印出每個連結和摘要
urls = []
counter = 0
maxl = 10  # 設定最大連結數量
for link in links:
    try:
        counter += 1
        print(f"連結 {counter}: {link}")
        summary = wiki.page(link).summary
        print(f"連結: {link}")
        print(wiki.page(link).fullurl)
        urls.append(wiki.page(link).fullurl)
        print(f"摘要: {summary}")
        if counter >= maxl:
            break
    except wiki.exceptions.PageError:
        # 忽略不存在的頁面
        pass

內容解密:

這段程式碼遍歷目標頁面的所有連結,並嘗試擷取每個連結頁面的摘要。如果某個連結頁面不存在,則捕捉 PageError 例外並忽略它。這樣,我們可以獲得與目標主題相關的多個頁面的資訊。

從維基百科建構知識圖譜問答系統:效能評估與指標分析

在建構根據知識圖譜的問答系統後,評估其效能至關重要。玄貓將透過一系列指標和實際案例,深入解析如何評估根據維基百科和 LlamaIndex 構建的知識圖譜問答系統的效能。

評估指標與案例分析

為了評估知識圖譜索引的查詢引擎,玄貓執行了十個案例,並追蹤其分數。rscores 紀錄了人工回饋分數,而 scores 則紀錄了相似度函式分數:

import numpy as np
from sentence_transformers import SentenceTransformer, util

# 使用 Sentence Transformer 計算 cosine similarity
model = SentenceTransformer('all-mpnet-base-v2')

# 省略部分程式碼以保持簡潔

內容解密:

此段程式碼的主要功能是載入預訓練的 Sentence Transformer 模型,用於計算文字之間的相似度。Sentence Transformer 是一種根據 BERT 的模型,能夠將文字對映到向量空間,從而計算文字之間的語義相似度。

評估流程

圖表翻譯: 此流程圖展示了評估知識圖譜問答系統的流程。首先載入 Sentence Transformer 模型,接著計算查詢結果與參考答案之間的相似度分數。然後,紀錄人工回饋分數。最後,分析評估指標以判斷系統的效能。

指標計算與結果分析

玄貓計算了人工回饋分數和相似度函式分數的平均值、標準差、最小值和最大值等統計指標:

# 計算統計指標
rscores_mean = np.mean(rscores)
rscores_std = np.std(rscores)
# ...

內容解密:

這些統計指標有助於瞭解系統效能的分佈情況和穩定性。例如,平均值可以反映整體效能,而標準差則可以衡量結果的離散程度。

效能最佳化策略

玄貓認為,要進一步提升知識圖譜問答系統的效能,可以從以下幾個方面著手:最佳化查詢引擎的引數、提升知識圖譜的品質、以及改進相似度計算方法等。此外,還可以結合使用者回饋,不斷迭代最佳化系統。

隨著知識圖譜技術的不斷進步,玄貓預計未來將出現更多創新應用。例如,結合多模態資料構建更豐富的知識圖譜、以及利用強化學習技術最佳化查詢引擎等。這些發展將進一步提升知識圖譜問答系統的效能和實用性。

使用 Sentence Transformers 評估問答系統效能

前言

本篇文章將介紹如何使用 sentence_transformers 函式庫來評估問答系統的效能。我們將透過計算兩個文字之間的 cosine 相似度來評估系統回覆的品質,並使用各種指標來分析結果。

Cosine 相似度計算函式

def calculate_cosine_similarity_with_embeddings(text1, text2):
    embeddings1 = model.encode(text1)
    embeddings2 = model.encode(text2)
    return util.cos_sim(embeddings1, embeddings2)[0][0].item()

內容解密:

此函式使用 sentence_transformers 模型將輸入的兩個文字轉換為向量表示(embeddings),然後計算這兩個向量之間的 cosine 相似度。Cosine 相似度是一種衡量兩個向量之間相似程度的指標,值越接近 1,表示兩個向量越相似。

問答系統評估流程

# 建立空陣列儲存人工回饋分數
rscores = []
# 建立空陣列儲存相似度函式分數
scores = []

# 範例查詢與回覆
user_queries = [
    "哪些專家通常與行銷理論相關?",
    "B2B 和 B2C 之間的區別是什麼?",
    "農業行銷服務 (AMS) 維持哪些商品計畫?"
]

responses = [
    "心理學家、文化人類學家和其他行為科學專家通常與行銷理論相關。",
    "B2B 企業將產品和服務銷售給其他公司,而 B2C 企業則直接銷售給客戶。",
    "農業行銷服務 (AMS) 在五個商品領域維持計畫:棉花和菸草、乳製品、水果和蔬菜、牲畜和種子,以及家禽。"
]

for i in range(len(user_queries)):
    user_query = user_queries[i]
    response = responses[i]

    # 計算相似度分數
    similarity_score = calculate_cosine_similarity_with_embeddings(str(response), user_query)
    print(f"Cosine Similarity Score with sentence transformer: {similarity_score}")
    scores.append(similarity_score)

    # 模擬人工回饋
    human_feedback = [0.75, 0.8, 0.9][i]  # 範例分數
    rscores.append(human_feedback)

內容解密:

此段程式碼模擬了一個問答系統的評估流程。首先,我們定義了一些範例查詢和對應的回覆。然後,對於每一對查詢和回覆,我們計算它們之間的 cosine 相似度,並將結果儲存在 scores 列表中。同時,我們也模擬了人工回饋的分數,並將其儲存在 rscores 列表中。

結果分析

print(len(scores), scores)
print(len(rscores), rscores)

# 計算指標
mean_score = np.mean(scores)
median_score = np.median(scores)
# ... 其他指標計算 ...

內容解密:

我們列印出了 scoresrscores 的長度和內容,以便檢視計算出的相似度分數和人工回饋分數。然後,我們計算了一些統計指標,如平均值和中位數,以評估系統的效能。

案例分析

此圖示呈現了查詢、回覆、cosine 相似度分數和人工回饋之間的關係。

@startuml
skinparam backgroundColor #FEFEFE

title 知識圖譜問答系統建構與效能評估

|開發者|
start
:提交程式碼;
:推送到 Git;

|CI 系統|
:觸發建置;
:執行單元測試;
:程式碼品質檢查;

if (測試通過?) then (是)
    :建置容器映像;
    :推送到 Registry;
else (否)
    :通知開發者;
    stop
endif

|CD 系統|
:部署到測試環境;
:執行整合測試;

if (驗證通過?) then (是)
    :部署到生產環境;
    :健康檢查;
    :完成部署;
else (否)
    :回滾變更;
endif

stop

@enduml

圖表翻譯: 此圖表展示了問答系統評估的流程。首先,使用者提出查詢,系統給出回覆。然後,計算回覆與查詢之間的 cosine 相似度分數。同時,人工評估回覆的品質並給出回饋分數。最後,結合 cosine 相似度分數和人工回饋分數來評估系統的整體效能。