跳到主要內容
Open In ColabOpen on GitHub

Ontotext GraphDB

Ontotext GraphDB 是一個圖形資料庫和知識探索工具,符合 RDFSPARQL 標準。

本筆記本展示如何使用 LLM 為 Ontotext GraphDB 提供自然語言查詢 (NLQ to SPARQL,也稱為 text2sparql)。

GraphDB LLM 功能

此處 所述,GraphDB 支援一些 LLM 整合功能

gpt-queries

  • magic predicates 使用知識圖譜 (KG) 中的資料,向 LLM 詢問文字、列表或表格
  • 查詢說明
  • 結果說明、摘要、改述、翻譯

retrieval-graphdb-connector

  • 在向量資料庫中為 KG 實體建立索引
  • 支援任何文字嵌入演算法和向量資料庫
  • 使用與 GraphDB 用於 Elastic、Solr、Lucene 的相同強大連接器 (索引) 語言
  • RDF 資料變更自動同步到 KG 實體索引
  • 支援巢狀物件 (GraphDB 10.5 版中不支援 UI)
  • 將 KG 實體序列化為文字,如下所示 (例如,針對葡萄酒資料集)
Franvino:
- is a RedWine.
- made from grape Merlo.
- made from grape Cabernet Franc.
- has sugar dry.
- has year 2012.

talk-to-graph

  • 使用已定義 KG 實體索引的簡單聊天機器人

在本教學中,我們不會使用 GraphDB LLM 整合,而是從 NLQ 產生 SPARQL。我們將使用您可以檢視的 Star Wars API (SWAPI) ontology 和資料集 此處

設定

您需要一個正在執行的 GraphDB 執行個體。本教學示範如何使用 GraphDB Docker 映像 在本機執行資料庫。它提供 Docker Compose 設定,可使用星際大戰資料集填入 GraphDB。所有必要檔案,包括本筆記本,都可以從 GitHub 儲存庫 langchain-graphdb-qa-chain-demo 下載。

docker build --tag graphdb .
docker compose up -d graphdb

您需要等待幾秒鐘,讓資料庫在 https://127.0.0.1:7200/ 上啟動。星際大戰資料集 starwars-data.trig 會自動載入到 langchain 儲存庫中。本機 SPARQL 端點 https://127.0.0.1:7200/repositories/langchain 可用於執行查詢。您也可以從您最愛的網頁瀏覽器 https://127.0.0.1:7200/sparql 開啟 GraphDB Workbench,您可以在其中互動式地進行查詢。

  • 設定工作環境

如果您使用 conda,請建立並啟動新的 conda 環境,例如

conda create -n graph_ontotext_graphdb_qa python=3.12
conda activate graph_ontotext_graphdb_qa

安裝以下程式庫

pip install jupyter==1.1.1
pip install rdflib==7.1.1
pip install langchain-community==0.3.4
pip install langchain-openai==0.2.4

使用以下命令執行 Jupyter

jupyter notebook

指定 ontology

為了讓 LLM 能夠產生 SPARQL,它需要知道知識圖譜結構描述 (ontology)。可以使用 OntotextGraphDBGraph 類別上的兩個參數之一來提供它

  • query_ontology:在 SPARQL 端點上執行的 CONSTRUCT 查詢,並傳回 KG 結構描述陳述式。我們建議您將 ontology 儲存在其自己的具名圖形中,這樣可以更輕鬆地僅取得相關的陳述式 (如下例所示)。不支援 DESCRIBE 查詢,因為 DESCRIBE 會傳回對稱簡潔有界描述 (SCBD),即輸入類別連結。在具有數百萬個執行個體的大型圖形的情況下,這效率不高。請查看 https://github.com/eclipse-rdf4j/rdf4j/issues/4857
  • local_file:本機 RDF ontology 檔案。支援的 RDF 格式為 TurtleRDF/XMLJSON-LDN-TriplesNotation-3TrigTrixN-Quads

在任一情況下,ontology 傾印都應

  • 包含關於類別、屬性、屬性附加到類別 (使用 rdfs:domain、schema:domainIncludes或 OWL 限制) 以及分類法 (重要個體) 的足夠資訊。
  • 不包含過於冗長且不相關的定義和範例,這些定義和範例無助於 SPARQL 建構。
from langchain_community.graphs import OntotextGraphDBGraph

# feeding the schema using a user construct query

graph = OntotextGraphDBGraph(
query_endpoint="https://127.0.0.1:7200/repositories/langchain",
query_ontology="CONSTRUCT {?s ?p ?o} FROM <https://swapi.co/ontology/> WHERE {?s ?p ?o}",
)
# feeding the schema using a local RDF file

graph = OntotextGraphDBGraph(
query_endpoint="https://127.0.0.1:7200/repositories/langchain",
local_file="/path/to/langchain_graphdb_tutorial/starwars-ontology.nt", # change the path here
)

無論哪種方式,ontology (結構描述) 都會以 Turtle 格式饋送至 LLM,因為具有適當前置詞的 Turtle 最精簡,且最容易讓 LLM 記住。

星際大戰 ontology 有點不尋常,因為它包含許多關於類別的特定三元組,例如物種 :Aleena 居住在 <planet/38> 上,它們是 :Reptile 的子類別,具有某些典型的特徵 (平均身高、平均壽命、膚色),並且特定個體 (角色) 是該類別的代表

@prefix : <https://swapi.co/vocabulary/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

:Aleena a owl:Class, :Species ;
rdfs:label "Aleena" ;
rdfs:isDefinedBy <https://swapi.co/ontology/> ;
rdfs:subClassOf :Reptile, :Sentient ;
:averageHeight 80.0 ;
:averageLifespan "79" ;
:character <https://swapi.co/resource/aleena/47> ;
:film <https://swapi.co/resource/film/4> ;
:language "Aleena" ;
:planet <https://swapi.co/resource/planet/38> ;
:skinColor "blue", "gray" .

...

為了簡化本教學,我們使用未受保護的 GraphDB。如果 GraphDB 受到保護,您應該在初始化 OntotextGraphDBGraph 之前設定環境變數 'GRAPHDB_USERNAME' 和 'GRAPHDB_PASSWORD'。

os.environ["GRAPHDB_USERNAME"] = "graphdb-user"
os.environ["GRAPHDB_PASSWORD"] = "graphdb-password"

graph = OntotextGraphDBGraph(
query_endpoint=...,
query_ontology=...
)

針對星際大戰資料集的問題解答

我們現在可以使用 OntotextGraphDBQAChain 來提出一些問題。

import os

from langchain.chains import OntotextGraphDBQAChain
from langchain_openai import ChatOpenAI

# We'll be using an OpenAI model which requires an OpenAI API Key.
# However, other models are available as well:
# https://langchain-python.dev.org.tw/docs/integrations/chat/

# Set the environment variable `OPENAI_API_KEY` to your OpenAI API key
os.environ["OPENAI_API_KEY"] = "sk-***"

# Any available OpenAI model can be used here.
# We use 'gpt-4-1106-preview' because of the bigger context window.
# The 'gpt-4-1106-preview' model_name will deprecate in the future and will change to 'gpt-4-turbo' or similar,
# so be sure to consult with the OpenAI API https://platform.openai.com/docs/models for the correct naming.

chain = OntotextGraphDBQAChain.from_llm(
ChatOpenAI(temperature=0, model_name="gpt-4-1106-preview"),
graph=graph,
verbose=True,
allow_dangerous_requests=True,
)

讓我們問一個簡單的問題。

chain.invoke({chain.input_key: "What is the climate on Tatooine?"})[chain.output_key]


> Entering new OntotextGraphDBQAChain chain...
Generated SPARQL:
PREFIX : <https://swapi.co/vocabulary/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?climate
WHERE {
?planet rdfs:label "Tatooine" ;
:climate ?climate .
}

> Finished chain.
'The climate on Tatooine is arid.'

以及更複雜的問題。

chain.invoke({chain.input_key: "What is the climate on Luke Skywalker's home planet?"})[
chain.output_key
]


> Entering new OntotextGraphDBQAChain chain...
Generated SPARQL:
PREFIX : <https://swapi.co/vocabulary/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

SELECT ?climate
WHERE {
?character rdfs:label "Luke Skywalker" .
?character :homeworld ?planet .
?planet :climate ?climate .
}

> Finished chain.
"The climate on Luke Skywalker's home planet is arid."

我們也可以提出更複雜的問題,例如

chain.invoke(
{
chain.input_key: "What is the average box office revenue for all the Star Wars movies?"
}
)[chain.output_key]


> Entering new OntotextGraphDBQAChain chain...
Generated SPARQL:
PREFIX : <https://swapi.co/vocabulary/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

SELECT (AVG(?boxOffice) AS ?averageBoxOfficeRevenue)
WHERE {
?film a :Film .
?film :boxOffice ?boxOfficeValue .
BIND(xsd:decimal(?boxOfficeValue) AS ?boxOffice)
}


> Finished chain.
'The average box office revenue for all the Star Wars movies is approximately 754.1 million dollars.'

鏈修改器

Ontotext GraphDB QA 鏈允許提示精細化,以進一步改善您的 QA 鏈並提升您的應用程式的整體使用者體驗。

「SPARQL 產生」提示

提示用於根據使用者問題和 KG 結構描述產生 SPARQL 查詢。

  • sparql_generation_prompt

    預設值

      GRAPHDB_SPARQL_GENERATION_TEMPLATE = """
    Write a SPARQL SELECT query for querying a graph database.
    The ontology schema delimited by triple backticks in Turtle format is:
    ```
    {schema}
    ```
    Use only the classes and properties provided in the schema to construct the SPARQL query.
    Do not use any classes or properties that are not explicitly provided in the SPARQL query.
    Include all necessary prefixes.
    Do not include any explanations or apologies in your responses.
    Do not wrap the query in backticks.
    Do not include any text except the SPARQL query generated.
    The question delimited by triple backticks is:
    ```
    {prompt}
    ```
    """
    GRAPHDB_SPARQL_GENERATION_PROMPT = PromptTemplate(
    input_variables=["schema", "prompt"],
    template=GRAPHDB_SPARQL_GENERATION_TEMPLATE,
    )

「SPARQL 修正」提示

有時,LLM 可能會產生具有語法錯誤或遺失前置詞等的 SPARQL 查詢。鏈將嘗試透過提示 LLM 修正來修正此問題一定的次數。

  • sparql_fix_prompt

    預設值

      GRAPHDB_SPARQL_FIX_TEMPLATE = """
    This following SPARQL query delimited by triple backticks
    ```
    {generated_sparql}
    ```
    is not valid.
    The error delimited by triple backticks is
    ```
    {error_message}
    ```
    Give me a correct version of the SPARQL query.
    Do not change the logic of the query.
    Do not include any explanations or apologies in your responses.
    Do not wrap the query in backticks.
    Do not include any text except the SPARQL query generated.
    The ontology schema delimited by triple backticks in Turtle format is:
    ```
    {schema}
    ```
    """

    GRAPHDB_SPARQL_FIX_PROMPT = PromptTemplate(
    input_variables=["error_message", "generated_sparql", "schema"],
    template=GRAPHDB_SPARQL_FIX_TEMPLATE,
    )
  • max_fix_retries

    預設值:5

「解答」提示

提示用於根據從資料庫傳回的結果和初始使用者問題來回答問題。根據預設,LLM 會被指示僅使用從傳回結果取得的資訊。如果結果集為空,LLM 應告知它無法回答問題。

  • qa_prompt

    預設值

      GRAPHDB_QA_TEMPLATE = """Task: Generate a natural language response from the results of a SPARQL query.
    You are an assistant that creates well-written and human understandable answers.
    The information part contains the information provided, which you can use to construct an answer.
    The information provided is authoritative, you must never doubt it or try to use your internal knowledge to correct it.
    Make your response sound like the information is coming from an AI assistant, but don't add any information.
    Don't use internal knowledge to answer the question, just say you don't know if no information is available.
    Information:
    {context}

    Question: {prompt}
    Helpful Answer:"""
    GRAPHDB_QA_PROMPT = PromptTemplate(
    input_variables=["context", "prompt"], template=GRAPHDB_QA_TEMPLATE
    )

一旦您完成 GraphDB QA 的操作,您可以從具有 Docker Compose 檔案的目錄執行 docker compose down -v --remove-orphans 來關閉 Docker 環境。


此頁面是否對您有幫助?