Git2PROV を例に W3C PROV オントロジー表現の基本を知る

本記事では、W3Cが勧告している PROV オントロジーの表現方法を Git2PROV ツールを例にみていきます。

【目次】

[1]はじめに

ネットで様々な情報が簡単かつ大量に得られるようになりました。

それはそれで良いのですが、同時に得られた情報が信用できる情報かどうかの判断も難しくなってきました。

昨今の生成系 AI などの事情を考えると、この傾向はますます進むような気がしますが、そもそも今まで何を根拠に「信頼」とか「信用」していたのか?と考えていくと、意外に根拠が薄そうな気がして、少々不安になります(笑)。

それはともかく、信用できる情報かどうかの判断基準として、データの来歴あるいは起源をみることは多いと思います。

W3C は、このような来歴あるいは起源を記述するための仕様である PROV を2013年に勧告しています。

崇高な概念をここで語ることはできませんが、来歴や起源をたどれるデータの表現方法は、一般のアプリ作成においても役立つことが多いと思いますので、本記事では、この PROV による情報の来歴あるいは起源に関する表現をみてみます。

ところで PROV 仕様をざっと概観するには、(英語ですが)以下のドキュメントが最適だと思います。

一方、本記事では開発者にとって身近な Git のコミット情報を PROV で表現するツール(Git2PROV)を例に、PROV の具体的な表現例をみていきます。

[2]PROV とは

(1)PROVの基本概念

PROV は「provenance」を表現する技術仕様です。

この「provenance」は、英辞郎 on the WEB に以下のように書かれています。
  1. 〔芸術作品などの〕来歴、起源、出どころ
  2. 〔動物・植物・酒などの〕原産地

以下では、「provenance」 を日本語で書く時は来歴と書くことにしておきます。

さて、PROV は「PROV Model Primer」に、以下のように書かれています。
  • The provenance of digital objects represents their origins.
    • デジタル オブジェクトの provenance(来歴) は、その起源を表します。
  • PROV is a specification to express provenance records, which contain descriptions of the entities and activities involved in producing and delivering or otherwise influencing a given object.
    • PROV は、来歴レコードを表現するための仕様であり、特定のオブジェクトの生産と配信、またはその他の影響を与えるエンティティとアクティビティの記述が含まれます。

詳細は以下のドキュメントを参照して下さい。

さて、PROV では「provenance」を表現するためのモデル(語彙)が定義されていますので、早速みていきます。

以下は PROV の主要な概念の説明によく出てくる図です。

PROV の主要概念


3つの概念(Entity、Activity、Agent)とそれらの関係(プロパティ)が5つ書かれています。

後ほど Git を題材にこれら概念の具体的な利用例を見ていきますが、その前に、それぞれの語彙についてごく簡単にみておきます。

なお、語彙定義は法律と同じで、高度に抽象化された表現になっているため、分かったような、分からないような表現になっていますが、後の具体例をみると、少しイメージしやすくなると思います。

また、私には語彙定義を納得できる日本語に訳す力量は無いため、仕様へのリンクと Google 翻訳を利用した日本語訳を利用します。

Entity

  • https://www.w3.org/TR/prov-o/#Entity
  • エンティティとは、物理的、デジタル的、概念的、またはいくつかの固定された側面を持つその他の種類のものです。 実体は実在する場合もあれば、架空の場合もあります。

Activity

  • https://www.w3.org/TR/prov-o/#Activity
  • アクティビティとは、一定期間にわたって発生し、エンティティに作用する、またはエンティティとともに作用するものです。 これには、エンティティの消費、処理、変換、変更、再配置、使用、または生成が含まれる場合があります。

Agent

  • https://www.w3.org/TR/prov-o/#Agent
  • エージェントとは、実行中のアクティビティ、エンティティの存在、または別のエージェントのアクティビティに対して何らかの形で責任を負うものです。

wasGeneratedBy

  • https://www.w3.org/TR/prov-o/#wasGeneratedBy
  • 生成(Generation)とは、アクティビティによる新しいエンティティの生成の完了です。 このエンティティは世代前には存在しませんでしたが、この世代の後に使用できるようになります。

used

  • https://www.w3.org/TR/prov-o/#used
  • 使用(Usage)は、アクティビティによるエンティティの利用の開始です。 使用前、アクティビティはこのエンティティの利用を開始しておらず、エンティティの影響を受けることはありませんでした。

wasDerivedFrom

  • https://www.w3.org/TR/prov-o/#wasDerivedFrom
  • 派生とは、エンティティを別のエンティティに変換すること、エンティティを更新して新しいエンティティを生成すること、または既存のエンティティに基づいて新しいエンティティを構築することです。

wasAssociatedWith

  • https://www.w3.org/TR/prov-o/#wasAssociatedWith
  • アクティビティの関連付け(activity association)とは、アクティビティに対するエージェントへの責任の割り当てであり、エージェントがアクティビティにおいて役割を持っていたことを示します。 さらに、このアクティビティのコンテキストでいくつかの目標を達成するためにエージェントが意図する計画を指定することもできます。

wasAttributedTo


(2)簡単な補足

私の場合、語彙定義を読んだだけではピンとこなかったので、自分の備忘録をかねて少し補足しておきます(下記内容はあまりあてにしないでください)。

語彙定義から具体的な表現を考えようとすると、迷うことが多いと思います。

例えば、私の場合、3つの概念「Entity」「Activity」「Agent」のうち、「Activity」と「Agent」は比較的とらえやすい概念だと感じますが、「Entity」は定義が広く、また、隠れた Entity が潜んでいたりして、意外に難しいです。

そこで、「Activity」と「Agent」以外は「Entity」と考えて進めておき、後でそれらの関係(プロパティ)を割り当てて再検討します。

ちなみに「Agent」は「人」だけでなく「組織」や「ソフトウェア」等も該当します。

関係(プロパティ)については、以下のように「定義域(domain)」と「値域(range)」が決まっています。
  • 「Entity」 wasGeneratedBy 「Activity」
  • 「Activity」 used 「Entity」
  • 「Entity」wasDerivedFrom「Entity」
  • 「Activity」 wasAssociatedWith 「Agent」
  • 「Entity」 wasAttributedTo 「Agent」

こう考えると、例えば、wasAssociatedWith と wasAttributedTo は、Agent に関係するものではありますが、関係付く対象が Activity か Entity かで違いがありますし、wasDerivedFrom は Entity 間の関係という事が分かります。

そして認識した「Entity」「Activity」「Agent」に対して、定義域と値域を意識してプロパティを当てはめると、考えたモデルの妥当性を考えやすいように思えました。

また、概念間の関係を割り当てたときに、不自然な感じがあれば、実は認識できていなかった Entity が見えることもあります。

ちなみに、PROV は何が起こるか?ではなく、何が起こったかという過去の事を記述するものなので、プロパティ名は過去形になっています。

ところで、これらの語彙をオントロジーとして深く考えようとすると、以前に紹介した下記の書籍が非常に参考になります。

また、これも以前紹介した書籍ですが、REA という設計パターンがあります。

REA とは Resource-Event-Agent のことです。

Resource=Entity、Event=Activity、Agent=Agent と対応させると、同じようなものを扱っているように思えます。

これを少し考えてみると、REA は PROV を具体的なビジネス上の取引の来歴に特化した視点と考えて、PROV に取引の双対性の考え方を加えると、REA と同様の表現が可能な気がします(非常に浅い考察ですが)。

(3)PROV のシリアライズ形式

PROV はシリアライズ形式が定義されています。

本記事では触れませんが、以下の形式が仕様化されています。

加えて、JSON あるいは JSON-LD へのシリアライズも提案されているようです。

(4)PROV グラフの可視化について

PROV 表現はグラフ構造であり、そのグラフを図示する際の推奨事項も公開されています。

ざっくりまとめてみます。
  • Agent は5角形の家の形(上向きの二等辺三角形でもよい)
  • Activity は青い四角形
  • Entity は黄色の楕円
なお、細かい色指定などは無視しています。

PROV における Agent、Activity、Entity の図形


これに関係(矢印)を加えてレイアウトする場合を考えます。

簡単のため、Entity 1 を利用する activity によって Entity 2 が生成される例を考えます。

水平方向に配置する場合は、過去から現在への時間軸を左から右へと考えます。すると、下図のように、右から左方向への矢印(関係)になります。

PROV グラフ要素の水平方向配置

垂直方向に配置する場合は、過去から現在への時間軸を上から下へと考えます。すると、下図のように、下から上方向への矢印(関係)になります。

PROV グラフ要素の垂直方向配置


(参考)

これらの図を Python を使って自動生成する記事『Python で W3C PROV オントロジーを可視化する(Python PROV)』を書きましたので、参考にしてください。

(5)拡張仕様について

はじめて PROV の仕様を読んだ時、直感的には、基本的な概念が意外に少ないので、十分な表現ができるのか?という素朴な疑問がありました。

少し理解が進むと、基本的な骨格の表現については十分な表現力があると思いますが、それでも不足する概念は多々あります。

不足する概念は、独自のものを考える前に、既存の他のオントロジーを組み合わせて利用すればよいのですが、PROV 自身も拡張性のある仕様になっており、拡張語彙も定義されています。

PROV 仕様の全体像の詳しい説明は、以下の仕様を参照して下さい。

[3]Git のコミット履歴を PROV で表現する

(1)Git2PROV

開発者にとって身近に来歴情報に接するのは Git を利用している時のように思います。

この Git のコミット情報を PROV で表現するツールが公開されています。

Git のコミット履歴を PROV で表現する意図などについては、上記論文などを参照して頂くとして、ここでは、PROV の利用例として Git2PROV が出力する表現をみていきます。

なお、ここでは PROV 表現の骨格をみることを主目的として、Git2PROV の出力そのままではなく、Namespace やファイル名、日時などの属性を省略して概念間の関係を中心に簡略化して書きます。

実際の Git2PROV による実際の出力方法は次節を参照して下さい。

以下では、Git にファイルを2つコミットするシナリオで PROV の例を図示します。

(2)ファイルのバージョン1をコミットしたとき

まず、テクノ大福(technodaifuku)がある「ファイル(file)」をコミットします。

この状況の PROV 表現を図示すると以下のようになります。


最初にファイルをコミットした時の PROV グラフ


コミット処理(commit_1)は Activity、テクノ大福(technodaifuku)は Agent です。

まずここで注意しておきたい点は、file と file_v1 の二つの Entity があるところです。

テクノ大福がコミット処理をしたことにより、物理的なファイルのバージョン1として file_v1 が作成されました。

このことは、file_v1 (Entity) が commit_1 (Activity) により生成された(wasGeneratedBy)と図示されます。

commit_1(Activity)には technodaifuku(Agent)が関与している(wasAssociatedWith)ことも図示されています。

ここで file と file_v1 についてですが、 file_v1 は、抽象的なファイル(file)の特殊化(specializationOf)の関係にあります。

ファイル(file)という抽象的な概念は、バージョンの変化(履歴)を追跡・集約するアンカーとして利用できます。

なお、この specializationOf 関係は、先の基本的な概念には含まれていませんが、PROV では以下のように仕様化されています。

  • specializationOf
    • https://www.w3.org/TR/prov-o/#specializationOf
    • 別のエンティティを専門化したエンティティは、後者のすべての側面を共有し、さらに、後者と同じもののより具体的な側面を示します。 特に、特殊化されるエンティティの存続期間には、あらゆる特殊化の存続期間が含まれます。 側面の例には、期間、抽象化、およびエンティティに関連付けられたコンテキストが含まれます。

詳しい説明は以下を参照して下さい。

(3)ファイルのバージョン2をコミットしたとき

続いて、テクノ大福(technodaifuku)が編集した「ファイル(file)」を再度コミットします。

この状況の PROV 表現を図示すると以下のようになります。

ファイルを更新した時の PROV グラフ


最初のコミットと同じ構造で、commit_2 (Activity)、file_v2(Entity)を下に追加します。

technodaifuku(Agent)と file(Entity)に対しては既存のインスタンスに接続されます。

ここで注意しておきたいのは、バージョン1のときには作られなかった関係が追加されていることです。

まず、「file_v2」は「commit_2」から生成された(wasGeneratedBy)関係は同じですが、「commit_2」から「file_v1」へ「used」という関係が作られています。

これにより、commit_2 は file_v1 を利用していることが分かります。(file_v2 は file_v1を利用して作成されたことも分かります。)

また、「commit_2」から「commit_1」へ「wasInformedBy」という関係も作られています。これにより、2つのコミット(Activity)間の依存関係が示されています。

この関係は基本的な概念には含まれていませんが、PROV で仕様化されています。
  • wasInformedBy
    • https://www.w3.org/TR/prov-o/#wasInformedBy
    • Communication は 2 つのアクティビティによるエンティティの交換であり、一方のアクティビティは他方のアクティビティによって生成されたエンティティを使用します。

続いて、「file_v2」 wasDerivedFrom 「file_v1」というリンクも作られています。

これにより物理的なファイルのバージョン間の依存あるいは改定順序が直接分かります。

最後に file_v2 からも file に対して specializationOf リンクがあります。

これにより、ファイルが二つのバージョンを持っていることも分かります。

(4)より詳細な Git のモデルや応用など

本記事では触れませんが、gitlab2prov というのもあります。

こちらはコミット以外の情報も含めたより詳細なモデルが定義されて、PROV への変換が行えるようです。(GitHub2PROVというのもあるようですが。)

ところで、Git を使ってソフトウェア開発を行っている開発当事者としては、わざわざ Git のコミット内容を PROV で表現する必要性は感じないのですが、上記に関係する論文などに少し目を通すと、プロジェクト管理的な面から有意なこともあるようです。

それとは別に、個人的に技術的な面白味として感じるのは、PROV は RDF のトリプルモデルなので、Semantic Web 系の各種ツールを利用した応用が可能になることです。

例えば、収集した Git の来歴情報をトリプルストアに取り込んでマージします。するとSPARQL クエリ等を利用して様々な角度から分析できそうです。(プロジェクト管理に限らず。)

[4]Git2PROVを実際に動かしてみる

ここでは、ローカルPC環境で実際に Git2PROV を使って、GitHub にあるリポジトリを PROV に変換する方法をメモします。

前節では簡略化した PROV 表現を書きましたが、Git2PROV を使うと、ファイル名やコミットに関する日時情報などの属性も見ることができます。

以下は Ubuntu 環境で、git コマンドと nvm を使って構築した Node.js 環境で動作を確認しています。

詳細な説明は、Git2PROVのサイトの説明を参照して下さい。

(1)インストール

以下のコマンドを実行します。
npm install git2prov

(2)ローカルサーバで実行

一番簡単な利用方法は、ローカルサーバを起動してブラウザからアクセスすることだと思います。

以下のコマンドでサーバを起動します。
npx git2prov-server

起動したらローカルホストのURLが表示されますので、ブラウザからアクセスします。

すると以下のような画面が表示されます。

Git2PROV の画面


上記の例は、GitRepo に GitHub 上の Git2PROV リポジトリを指定して「PROV-N」ボタンを押した例です。(PROV-N形式でテキストエリアに表示されます。ダウンロードすることも可能です。)

(3)コマンドラインから実行

コマンドラインから実行することもできますので、複数リポジトリから自動取得するような場合に便利だと思います。

ローカルサーバにある入力項目を以下の形式で指定して実行します。
npx git2prov git_url [serialization]

git_url は GitHub などのリポジトリのURLを指定します。

serialization には、PROV-N、PROV-JSON、PROV-O が指定可能なようです。
(省略した場合は、PROV-N 形式です。)

結果はリダイレクトを利用してファイルに保存できます。

コメント

このブログの人気の投稿

Google Document AIで画像から表形式データを抽出する(Vision API OCRとの違い)

VirtualBoxのスナップショット機能

Ubuntu/Colab環境でPDFファイルのページを画像化する(pdf2image、pdftoppm、pdftocairo)