簡単に簡素なデジタルアーカイブを構築するにあたってIIIF対応も簡単に

今回は、ここ2回続いた生成AIの話はちょっと横に置いておきまして、「簡単に簡素なデジタルアーカイブを構築するにあたってIIIF対応も簡単に」する方法です。それができるサンプルプログラムをしばらく前に作って紹介しましたので、それをご紹介する記事です。そして、この記事は、初心者向けの記事ではなく、そういうことができるシステムをすでに作っていたり、これから作ろうと思っている方々に、「もう一手間かけるとIIIF対応にできる」ことを知っていただくことを目的としたものです。ですので、そういう方々は、ここで紹介するプログラムを見て、ぜひ色々と可能性をご検討ください。

デジタルアーカイブ構築用のシステムは、このところどんどん高度化していて、高いものでは1億を超えるものもあるようです。ある程度費用をかけると、データの管理機能も備えた、大変利便性の高いシステムを利用できるようですね。

一方で、画像はJPEG、目録情報(メタデータ)はエクセルやGoogle Spreadsheetで用意したけど、これをなるべくお金も手間もかけずに公開したい。。。というニーズも依然として存在しているようです。そのようなデータを簡素にデジタルアーカイブとして公開しようとする取組みとして、ネットでぱっと検索してみると、たとえば以下のようなものが見つかります。

  • 移行しやすく使いやすいデジタルアーカイブの構築:教育図書館貴重資料デジタルコレクションの経験から https://doi.org/10.2964/jsik_2019_016 情報知識学会誌 2019 年 28 巻 5 号 p. 367-370

  • DAKit: 低コストなデータ共有のための 静的デジタルアーカイブジェネレータの提案 https://doi.org/10.2964/jsik_2022_035 情報知識学会誌 2022 年 32 巻 4 号 (こちらのジェネレータでは、IIIF v2/Miradorに対応していたようです。)

商用サービスでも探してみると色々ありそうです。 (このあたりのことをより抽象的に捉えようとする論考も色々あるのですが、今回はとりあえず、「どうやって作ればいいのか」に限定した話です。)

こういった簡素なデジタルアーカイブも、この簡素なレベルでIIIF対応画像として公開することが可能です。。。と言っても、画像の切り出しや回転のようなことはできなくなってしまうので、できれば、それもできるようなサーバを用意していただきたいと切に思うところなのですが、どうしてもそういうサーバを用意できないという場合でも、それ以外の様々なIIIFの「つなぐ」機能の恩恵を受けられる方法を、ここではご紹介します。

IIIF対応で画像や目録情報(メタデータ)を公開するための一般的な方法は、『IIIFで拓くデジタルアーカイブ』(オープンアクセス本)に詳細に書いてありますので、そちらをご覧ください。

この本で紹介する方法では、基本的に、サーバコンピュータ上でIIIF対応画像サーバソフトを実行して、画像切り出しなどの要請がきたらそれにあわせて画像をいつでも送り出せるようにしておく必要があります。この方法は、サーバ環境が充実していれば特に難しいことではないのですが、しかし、そのようなサーバソフトを自由に立ち上げられないが、しかし、HTMLや画像ファイルなどの静的なファイルだけは置くことができる、という環境でデジタルアーカイブを公開しなければならない状況もあろうかと思います。今回ご紹介するのは、そのような状況で、しかし、IIIFに対応することで少しでも利便性を高めたい、という人のための方法です。つまり、「静的なHTMLや画像ファイルなどを自由にサーバに載せて公開できる環境」は最低限のものとして必要になります。

そのような環境があり、かつ、公開できる画像とJPGで、そしてそれと紐付けられた目録情報(メタデータ)がある、という場合に、この記事で紹介する方法は有効になります。

それから、プログラミング言語Pythonを動作させられる環境が必要です。Pythonを動かせる環境というのはよくわからない…という人向けの話ではないのですが、最近は、そういうことはChatGPTに聞けばなんとかなるかもしれません。

これを実現するためのプログラムは、以下のURLに置いてあります。使い方もそこに書いてあります。そんなに親切な書き方ではないですが、Pythonを使ったことがある人はすぐにわかると思います。

https://github.com/knagasaki/simple_iiif

ここで紹介している方法は、画像とメタデータを用いてIIIF Manifestファイルを自動的に作成して、さらに各資料のランディングページにビューワへのリンクを表示させて、利用者は好きなIIIFビューワを選んでその画像を閲覧できる、というものです。これによって、各コマ送りをしたり一覧表示をしたり…といった色々な表示方法に関して、世界で開発されている最先端のIIIFビューワを利用できますので、システム開発の手間に比した利用者への利便性の高さは圧倒的です。もちろん、IIIF Curation Viewerで表示させれば、そこから様々なアノテーションが可能になり、動的なWebの世界も利用者が自由に堪能できます。

そして、IIIF Presentation APIの version2とversion3の両方を出力することで互換性に配慮した上で、各IIIF対応ビューワに読み込ませるものはversion3としております。

上記のURLにて公開しているプログラムをみていただければ、拍子抜けするほど簡単にIIIF対応できることをご理解いただけるかと思います。これを持っていって、ご自身のサービスに組込んでいただいても結構ですし、自分でもっときれいなものを書く、ということならそれでもかまいません。ぜひご利用ください。

見本は以下のような感じで、佐藤秀峰先生の『ブラックジャックによろしく』を使わせていただいております。

www.dhii.jp

このまだと見た目などはなんとも微妙ですが、CSSを工夫すれば結構みられるものになると思います。静的なHTMLを出力しているだけなので、できあがったHTMLファイル群をあとから検索置換で修正したり、プログラム自体にちょこっと手をいれたりしていただくのもアリだと思います。

それから、プログラミングはしないけどなんとか頑張ってここまでお付合いしてくださった皆様におかれましては、自分の周囲で、あるいは自分が依頼しようと思っている人がIIIF対応に難色を示している場合は、このブログ記事と上記のプログラムをご紹介してください。

IIIFを通じて、世界のデジタルアーカイブがより有機的に連携し、より豊かな知識社会の基盤を形成していくことを願っております。

生成AIの新展開!?―学術研究支援用ボットを作ってみた。その(2)

前回記事の続きです。生成 AI が、いつの間にか新しい局面を迎えているように思います。問い合わせをするための文字数制限(正確に言えばトークンの制限)が大幅に増え、問い合わせの際に、前提知識として学術論文数十本、あるいは新書10冊くらいを読み込ませてから回答させることができるようになっています。これまでは「生成 AI が持つ知識」を問い合せる形になっていましたが、これによって、「こちらが持つ知識や情報を生成 AI に考えさせる」ことができるようになりつつあります。この流れがさらに進めば、今まではできなさそうだった有用性を発揮することができるようになるかもしれない、ということで、とりあえず今試せることをちょこちょことやってみています。

で、前回記事をみた人から、J-STAGEからPDFをダウンロードする方法についてのリクエストがありましたので、ちょこっと書いてみます。

生成AIに読み込ませる信頼できる情報源としての学術論文ですが、現在はJ-STAGEでたくさんのオープンアクセス論文が公開されています。これを雑誌単位でまるっと利用できれば、その学会が扱っている分野に関する比較的専門性の高い生成AIのRAGが構築できそうな感じです。なお、国際ジャーナルでやればもっと楽だ、とか、その方がよいのではないか、という話もあるのですが、J-STAGEに載っている学術雑誌には固有の良さがありますので、これはこれで重要なことです。

J-STAGEはAPIでのデータ公開を行っています。雑誌一つをまとめてまるっとダウンロードしたい時は、これを使うのが便利です。

というわけで、J-STAGEのAPIを使って、任意の雑誌の論文PDFをざっくりダウンロードするスクリプトを書いてみます。 J-STAGEに迷惑がかからないように、特に、利用規約はよく読んでからご利用ください。規約では大量ダウンロードは禁じられていますので、大量にならないように、サーバに大きな負荷がかかってしまわないように、よく気をつけてください。

import requests
from bs4 import BeautifulSoup
import urllib.parse
import os
import re
import sys
import time

def save_pdf(link, save_path):
        pdf_response = requests.get(link)
        content_disposition = pdf_response.headers.get('content-disposition')
        if content_disposition and 'filename=' in content_disposition:
                filename = content_disposition.split('filename=')[1]
                filename = filename.strip('"')  
        pdf_filename = filename
        pdf_save_path = os.path.join(save_path, pdf_filename)
        #print (pdf_save_path)
        if not os.path.isfile(pdf_save_path):
          with open(pdf_save_path, 'wb') as pdf_file:
            pdf_response = requests.get(link)
            pdf_file.write(pdf_response.content)
            print(f"Downloaded: {pdf_filename}")
        else:
            print ('skip:')
        


if len(sys.argv) > 2:
    save_directory = sys.argv[2]
    if not os.path.exists(save_directory):
        os.makedirs(save_directory)
else:
    print ("保存フォルダ名を2番目の引数に指定してください。")
    sys.exit()

journalurlapi = 'https://api.jstage.jst.go.jp/searchapi/do?service=2&cdjournal='+sys.argv[1]
response = requests.get(journalurlapi)
soup = BeautifulSoup(response.content, 'xml')

entries = soup.select("entry")
for entry in entries:
    eachvol = entry.find_all('volume')[0].get_text()
    volurl = 'https://api.jstage.jst.go.jp/searchapi/do?service=3&cdjournal=jpbs&vol='+eachvol
    eresponse = requests.get(volurl)
    eachsoup = BeautifulSoup(eresponse.content, 'xml')
    eentries = eachsoup.select('entry')
    for eentry in eentries:
        elink = eentry.select('link')[0].get('href')
        pdflink =  re.sub(r'_article/',r'_pdf/',elink)
        print (pdflink)
        save_pdf(pdflink, save_directory)
        time.sleep(1)

このスクリプトは、以下のように利用します。

$ python このスクリプト 雑誌のID 保存先フォルダ名

これで、PDFファイルは一通り入手できるはずです。そうしましたら、次は、OCRをかけるために、このPDFからJPG画像を全部取り出します。 こういうのは Pythonで一括処理するのが楽ですね。

from pdf2image import convert_from_path
import os
import glob
import re

pdfs = glob.glob("*.pdf")
for pdf in pdfs:
    pdfpath = 'jpgs/'+os.path.splitext(pdf)[0]
    if not os.path.isdir(pdfpath):
        os.mkdir(pdfpath)
    images = convert_from_path(pdf)
    for i, image in enumerate(images):
            image_path = f"{pdfpath}/p_{i+1}.jpg"
            image.save(image_path, "JPEG")
            print(f"Page {i+1} saved as {image_path}")

さあ、ここまでできたら、次はOCRですね。。。というのはまた次回に。

生成AIの新展開!?―学術研究支援用ボットを作ってみた。その(1)

先週末、カリフォルニア大学バークレー校にて、ご招待をいただいて発表をしてきました。AIと仏教研究の未来、というテーマのイベントで、世界中から関連研究者が招待されて発表をしていました。要するに、世界のデジタル仏教研究者が集まって発表をする、という会で、年に数回、こういうことが世界の各地で行われているのですが、私はもうなかでも古株というか古参というか、20年近くこの界隈にコミットしてきております。最近はAIの進展でこの世界も新しい展開を見せつつあり、また新しい人が参入してきています。

イベント自体は、生成AIを作っている話とか使ってみた話とか、そこからAIのあり方や利用方法などについて色々な議論が行われていて、とても面白いものでした。私はと言えば、今回はトリをつとめることになったので、面白いネタを、と思いまして、一つはこれまであちこちで話をしてきた(そしてこのブログでもご紹介している)AI-OCRとIIIFを使った木版仏典画像の超効率的なcollationという話だったのですが、もう一つ、RAG (Retrieval-Augmented Generation) を使った生成AI学術研究支援ボットのようなものを作って紹介してみたところ、これもなかなか好評でした。今回の記事は、ここで作ってみた経験を通じて、このRAGというものが、これまでは結構使いにくかったものから急に極めて使いやすくなったという、一大転換点が生じているように思いましたので、これをぜひみなさまにお知らせしなければと思って書いているものです。

この件については、学会発表のようなことをするよりも、まずは自分のやり方を公表してしまって皆で色々試してみることができた方が面白いと思いましたので、とりあえずやり方をお知らせして、少しでも試行する人を増やそうと思って、ブログに書いてしまうことにしました。

RAG、つまり、Retrieval-Augmented Generationは、簡単に言えば、生成AIにあらかじめ専門知識を与えることで良い回答を出させようとするものです。つまり、専門知識の情報を含むプロンプトを作って問い合せるものです。ということはつまり、プロンプトに渡すための「関連する専門知識のデータ」を作らねばならないことになります。これは、生成AIの仕組みを活かすなら、質問文を受け取った時に「関連する専門知識のデータ」を生成して、それをさらに生成AIに渡す、という流れになります。関連する専門知識のデータは、なんらかのデータベースやナリッジベースのようなものから取り出すことになりますが、生成AIが受け取れる分量(トークン数)まで絞り込まねばなりません。そして、生成AIがハルシネーションを起こさずに適切な回答を出力できるようにするためには、おそらくは、文脈を保ちつつ適切な専門用語が含まれている「関連する専門知識のデータ」を生成する必要があるでしょう。これを実現するには、テーマによっては結構な長さの「関連する専門知識のデータ」を生成せざるを得ない場合もあるでしょう。

一方で、少し前までは、一度に読み込めるトークン数は、ChatGPTで8kや32k、という感じでかなり短いものでした。これは、読み込んだそばから時間のかかる計算処理を行わねばならないため、短くても仕方がないと考えられてきたところで、それをなんとかするための技術開発も様々に行われてきました。

しかし、ここにきて、一度に使えるトークン数が急に増えました。Gemini1.5で、100万トークンまでいけるとのことです。トークン数、と、いきなり言われてもなんだかよくわからないかもしれませんが(私も明確にはわからなかったのですが)、一応、それを数えてくれるツールがあるようです。

これによれば、以下のように、英語だと大体1単語1トークンという感じなのですが、

日本語では単語区切りをできているわけではないようで、1300字に対して900トークン、といった案配です。

2割くらい引いた数と考えるとして、1トークン1文字と考えても、100万文字一度に扱えることになりそうです。なお、ここでのトークン制限は、生成AIのAPIに渡すものだけでなく、戻されるトークンなども含まれるので、100万トークンをそのまま送信できるわけではないようです。とはいえ、戻ってくる回答のトークン数などは、100万トークンという数の前ではあまり気にするようなものではなさそうです。

100万字を一気に生成AIに送り込めるとなると、新書なら10冊分くらいになりますね。ただ、今回は新書はターゲットではないので、学術論文で考えてみましょう。そうすると、1つあたり2万字くらいだとしたら、50本の論文が読み込めることになります…というのは料金(従量制の場合)も大変になりますし、ちょっとやりすぎかもしれませんが、20本くらいはまあ楽勝と考えていいでしょうか。そうすると、20本の論文を生成AIに渡して、そこから質問文に対する回答をまとめてもらう、ということになります…としたら、結構いい感じになるのではないでしょうか。

こうなる前には、Claude 3が20万トークンのコンテキストウィンドウを提供し始めた(3/4)という話があり、その後のさらなる発展を予感させたところですが、そこに至る前は8000トークンとか32000トークンに落とし込んでから生成AIに送り込むという話だったため、これはなかなか大変なものがありました。32000トークンだと論文1本か2本でせいぜいなので、そうすると、論理的整合性のある文章を読み込ませようとすると、結局、一つか二つの論文を探してきて渡すことになってしまい、その立場を代弁する(というかその要約になってしまう)か、それに加えて謎の知識が謎に追加されるというやや困った事態になることもありました。あるいは、もっと細かく文章を分割して適合する箇所(章や段落など)のみを様々なソースから抜き出してまとめて生成AIに送るという方法もありましたが、それも断片的な情報に基づいて生成AIが判断をするということになってしまって、向き不向きをかなり選ぶ感じになっていました。 他にもいくつかの方法がありましたが、いずれにしても、生成AIに渡すために短めのテキストを適切に作成するというのが一つの重要な技術開発になっていました。

このような状況で、論文20本読み込んでも問題ない、というようなものが登場したのです。これは、少なくとも学術情報に適切に回答できる生成AIを期待する側としては考えられないくらいありがたいことだ、と思ってしまって、とりあえず実際に作ってみることにしました。

これまでのところ、RAGは、上記のようなトークン数制限(事実上の文字数制限)という事情や、質問文(自然文)から回答を生成しようとするために、生成AIに送るための「関連する専門知識のデータ」も質問文から作成しようとする、といった事情から、ベクターストアというタイプの(単語検索をするのではなく)文書類似度に基づく文書検索ソフトを使うことが多かったようです。いくつかのソフトがフリーで使えるようになっていますが、特に Chroma DBというのがPythonのモジュールで簡単に使えるようになっているため、とりあえずこれを試してみることにするか…と思ったのですが、まず、その前に、「論文20本を読み込ませたら実際にどうなるのか」ということを試してから前に進みたいところです。

ですので、やや迂遠ですが、まずは任意の論文20本を簡単に取り出せる状況を作ってみることにしました。

任意の論文20本を取り出せるようにするためには、論文の全文テキストのようなものが必要になります。そこで、とりあえずJ-STAGEですね。気になる雑誌(ここでは『印度学仏教学研究』という雑誌の約14000本の論文を試してみています。)のPDFファイルを少しインターバルを置きながらダウンロードして、ついでに、論文DOI/URLを含むメタデータも全部タブ区切りでまとめてPDFのファイル名と紐付けられるようにしておきます。(J-STAGEのAPIで取得できる値にはPDFのファイル名が入っていないのでここは(なぜか)手動対応が必要になります)。このあたりは目新しいことではないですし生成AIが作ってくれるプログラムでもいけると思いますので省略します。(リクエストがあれば別途記事を書くかもしれません)

さて、PDFがそろったところでOCRです。ここでのOCRには、もしGPU付きのPCを持っているなら国立国会図書館のOCRソフトがおすすめです。精度が非常に高いのがまず良い点ですが、それ以外に、スクリプトによるバッチ処理ができるので確実にはやくできるという点もなかなかです。でも、GPU付きのPCがなかったり、上記のソフトの使い方がよくわからない…というような場合には、たとえばABBYのFinereaderでも「指定したフォルダ内のPDFファイルを全部OCR」という処理はできるようです。ただ、PDFが異様に重くなったりするのと、一度にたくさんのファイルを予約しておくと固まって動かなくなったりするので(体験談)、小分けにするなどといった工夫が必要かもしれません。

OCRが全部できたら、メタデータのリスト(これはタブ区切りテキストやCSVなどになっていると使いやすいでしょうか)に、この全文テキストをくっつけます。一行一論文(本文入り)のタブ区切りテキストファイル、で、論文本文を1カラムに押し込み、これを1チャンクとします。

さて、ここまでくれば、まあおおむね準備はできたと言えるでしょうか。とりあえずはgrepなどで適当に20本取り出すことにするという前提で次(生成AIのAPIに送り込む)に行きましょう。

生成AIのAPIに送り込むにあたり、今回は100万トークンまでいけるGemini 1.5 proで試してみます。(Flushの方が安いからそっちを使えば、というアドバイスをUCバークレーの会合でグーグルの人にいただきましたが、proの方が精度は高いらしく、とりあえず精度が高い方で試したいのでここではproでいきます)。APIに送り込むためには、まず契約が必要です。契約の仕方はGeminiが教えてくれるのでそちらに聞いてください。「Gemini 1.5 proにAPIでデータを送り込みたいので契約手続きの仕方を教えてください」と問い合せれば喜んで(?)教えてくれます。私の場合は(多分みなさんもそうなるのではないかと思いますが)、Vertex AIというサービスに申し込んで、そこからGemini 1.5 proのAPIを使う形になっています。使用開始までに色々クリックしなければならないので、変だなと思ったらその都度Geminiに詳しく状況と疑問を伝えれば色々教えてくれます。

APIの認証に関してなのですが、Gemini 1.5 proのAPIを実際に使うには、認証キーファイルのようなものを取得しておくのが楽です。「サービスアカウントキーファイル」のような名前のjsonファイルを、Vertex AIのサービスの設定(?)画面でダウンロードできるようになっていますので、ダウンロードして適切なフォルダに入れて、ファイル名を控えておいてください。

ということで、まあ大体準備は終了のはずです。次に、APIに論文データを送り込むためのスクリプトです。

ここで、RAG用のフレームワークとして名高いLangchainを使うのが一般的のようなのですが、今回は、なるべくプリミティブに、処理を一つずつ追いかけていきたいので、ごく単純な「データをAPI送り込んで戻ってきたテキストを見る」というだけのものを作ってみます。

今回は、「送り込むための論文データ」は別ファイルとした上で、そのファイル名をコマンドラインで指定すると読み込めるようにします。つまり、

$ python rag_content.py 論文データファイル名(20本/20行くらいのTSVファイル)

ということになります。 それで、 rag_content.pyの中身ですが、これはGeminiに頼んでもなぜかうまく書いてくれなかったので、別のところで情報を得てなんとかしました。それが以下のものです。 (「サービスアカウントキーファイルのパス」のところには、自分がダウンロードしたファイルのパスを入れておいてください。)

import os
import sys
from google.oauth2 import service_account
from vertexai import init
#from vertexai.preview.language_models import TextGenerationModel
from vertexai.generative_models import GenerativeModel, Part, SafetySetting

# サービスアカウントキーファイルのパス
SERVICE_ACCOUNT_KEY_FILE = 'gen-lang-client-07hogehoge-hogehoge.json'

# サービスアカウントキーを読み込む
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_KEY_FILE)

# プロジェクトIDとリージョンを初期化
init(
    project="gen-lang-client-hogehoge",         # プロジェクトIDを指定
    location="us-central1",            # リージョンを指定
    credentials=credentials
)

with open(sys.argv[1]) as f:
    search_results = f.read()

generation_config = {
    "max_output_tokens": 8192,
    "temperature": 1,
    "top_p": 0.95,
}


# モデルの初期化
model = GenerativeModel(
        "gemini-1.5-pro-002",
    )
safety_settings = [
    SafetySetting(
        category=SafetySetting.HarmCategory.HARM_CATEGORY_HATE_SPEECH,
        threshold=SafetySetting.HarmBlockThreshold.OFF
    ),
    SafetySetting(
        category=SafetySetting.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
        threshold=SafetySetting.HarmBlockThreshold.OFF
    ),
    SafetySetting(
        category=SafetySetting.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
        threshold=SafetySetting.HarmBlockThreshold.OFF
    ),
    SafetySetting(
        category=SafetySetting.HarmCategory.HARM_CATEGORY_HARASSMENT,
        threshold=SafetySetting.HarmBlockThreshold.OFF
    ),
]

search_results = '以下の質問を、「内容」の内容を踏まえて回答してください。回答のフォーマットはHTMLとしてください。それから、引用したチャンクにおけるURLは必ず明示
し、クリックすると新しいウインドウで開くようにしてください。\n質問:ナーガールジュナの中論における中心的課題について教えてください。\n内容:'+search_results

responses = model.generate_content(
    [search_results],
    generation_config=generation_config,
    safety_settings=safety_settings,
    stream=True,
)

for response in responses:
    print(response.text, end="")
これに読み込ませるための20本の論文を、とりあえずは対象となる論文全文テキストのタブ区切りファイルがありますのでgrepなどで適当に集めて「送り込むための論文データ」を作り、上記のようにpythonで動かしてみると、まあ大体以下のような回答を得られます。

ナーガールジュナの中論における中心的課題

ナーガールジュナ(龍樹, Nāgārjuna, Nagarjuna)の『中論』(根本中頌, Madhyamakaśāstra, Madhyamakasastra, Madhyamaka-śāstra, Madhyamaka-sastra, Mūlamadhyamakakārikā, Mulamadhyamakakarika, Mūlamadhyamaka-kārikā, Mulamadhyamaka-karika)における中心的課題は、あらゆる存在は実体を持たない「空」であることを論証し、縁起の真義を明らかにすることです。実体(自性, svabhāva)とは、それ自身で存在し、他のものに依存せずに成立する性質を指します。ナーガールジュナは、あらゆる現象は相互依存的に生起する縁起によって成立するため、独立した実体を持つことはないと主張します。

空の論証

ナーガールジュナは、帰謬法を用いて空を論証します。帰謬法とは、ある命題の否定を仮定し、そこから矛盾を導き出すことで、元の命題が真であることを証明する方法です。彼は、あらゆる存在が実体を持つと仮定すると、そこから「生」「滅」「一」「異」「来」「去」といった概念に関して矛盾が生じることを示します。例えば、もし実体があれば、それは不変であるはずなので、生じることも滅することもありません。しかし、現実にはあらゆるものは生滅変化を繰り返します。このように、実体の存在を仮定すると矛盾が生じるため、あらゆる存在は空であると結論づけます。

木村秀雄氏(文學的立場より見たるナーガールジュニコンダの彫刻美術, 1961)は、ナーガールジュニコンダの彫刻美術に見られる様々な主題と、当時の文学作品との関連を論じています。中でも「火中捨身布施の兎」の彫刻は、ジャータカ物語における菩薩の転生である兎が、自らの身を燃やして布施を行う場面を描写しています。この物語は、利他の実践を象徴するものであり、大乗仏教の精神に通じるものと言えるでしょう。一方で、木村氏は、ミトゥナ彫刻に見られる官能表現が、カーマスートラのような世俗文学と関連付けられる一方で、仏教徒の自制も表現していると指摘しています。これは、ナーガールジュナが『中論』で説く空の思想が、世俗的な価値観を否定するものではなく、むしろそれを包含するものであることを示唆していると言えるかもしれません。

縁起の真義

ナーガールジュナは、空の論証を通じて、縁起の真義を明らかにしようとします。縁起とは、あらゆる現象は互いに依存し合って生起することを意味します。彼は、実体があると仮定すると、縁起が成立しないことを示します。なぜなら、もし実体があれば、それは他のものに依存せずに存在するはずだからです。しかし、現実にはあらゆるものは他のものに依存して存在します。例えば、種子は土や水、日光などに依存して芽を出します。このように、実体の存在を否定することで、縁起の真義が明らかになると彼は考えます。

金子宗元氏(中観派二諦説の思想的展開, 1999)は、ナーガールジュナの二諦説が、後世の唯識思想や如来蔵思想の影響を受けて変容していったことを指摘しています。特にチャンドラキールティは、弥勒系論書の影響を受け、「実義」とそれを覆い隠すものとの二項対立で理論を構築しました。この「実義」とは、ナーガールジュナが『中論』で説く「空」に近い概念と言えるでしょう。チャンドラキールティは、この「実義」を覆い隠すものとして、世俗的な認識を挙げ、それを乗り越えることで「実義」に到達できると主張します。これは、ナーガールジュナが縁起の真義を明らかにすることで、迷いを超えた悟りの境地に至ることができるとする主張と通じるものと言えるでしょう。

中論の中心的課題の意義

ナーガールジュナが『中論』で示した空と縁起の思想は、後世の大乗仏教に大きな影響を与えました。彼の思想は、あらゆる存在に固執する心を離れ、執着から生じる苦しみから解放されるための指針となります。また、空を理解することで、あらゆる存在は相互依存的に存在していることを認識し、他者への慈悲心を育むことができます。この慈悲心は、大乗仏教の根幹をなす菩薩行の実践へとつながります。

岸根敏幸氏(ナーガールジュナとチャンドラキールティ, 2000)は、ナーガールジュナの空の思想と、大乗仏教の利他行との関連性について論じています。ナーガールジュナ自身は、空の思想と大乗仏教との関係を明確にはしていませんでしたが、後世のチャンドラキールティは、空の思想を菩薩行の実践と結びつけることで、大乗仏教の理論的基盤を確立しようとしました。これは、ナーガールジュナが『中論』で示した空の思想が、単なる理論にとどまらず、実践的な意味を持つものであることを示唆していると言えるでしょう。

このように、ナーガールジュナの中論における中心的課題は、単なる形而上学的な議論にとどまらず、人間の苦しみを根本から解決するための実践的な道を開くものでした。彼の思想は、現代社会においてもなお、重要な示唆を与え続けていると言えるでしょう。

このように、「送り込むための論文データ」の内容に回答が大きく左右されますので、あとは、「どうやって質問文にフィットする論文を選び出すか」ということになります。ここで、とりあえずchroma DBを使ってみたのですが、専門的な論文から探そうという場合、chroma DBだとうまく専門用語にたどりつかず、かえって関係の薄い論文を取り出してしまうことが散見されました。

そこで、Apache Solrでもキーワード検索に持ち込めば文書類似度検索もできる、という風に前向きに考えて、

  1. 質問文をSpacyでトークナイズして名詞と固有名詞だけをとりだし、
  2. 固有名詞は専門用語シソーラスで展開して OR検索できるようにして
  3. 「(同義語1 OR 同義語2 OR 一つ目の名詞 ) AND 二つ目の名詞 AND 三つ目の名詞」というような感じでApache Solrで検索して20本の論文を取り出してみる…
ということをしてみたところ、意外とよい感じになりました。たとえば以下のような感じです。なかなか良い感じであるような気がします。

質問:

日本の寺社における聖教資料の保存の状況について教えてください。

回答:

日本の寺社における聖教資料の保存の状況

日本の寺社における聖教資料の保存状況は、複雑な歴史的経緯を反映し、一様ではありません。廃仏毀釈の影響や、その後の復興運動、さらには各宗派、寺院の個別事情が絡み合い、多様な状況を生み出しています。

廃仏毀釈の影響

明治維新期の廃仏毀釈は、仏教寺院、仏像、そして聖教資料に甚大な被害をもたらしました。松井孝純「法華宗が種子島に於て被つた廃仏毀釈と復興」(1976、URL)によれば、種子島では薩摩藩の政策に基づき、寺領没収、寺宝・什器の破壊、僧侶の強制還俗が行われました。この壊滅的な状況は、種子島における法華宗寺院の過去帳や石塔群の残存状況からも伺い知ることができます。仏教関連資料の焼却や破壊は各地で起こっており、聖教資料の散逸、喪失という結果をもたらしました。

聖教資料の隠匿と保護

廃仏毀釈の嵐の中で、全ての聖教資料が失われたわけではありません。僧侶や信徒の中には、危険を冒してまで貴重な資料を隠匿し、保護しようとした人々がいました。松井孝純(前掲論文)は、種子島において釈迦・多宝・日蓮・鬼子母神像などの仏像や、日蓮、日隆の真筆マンダラなどが掘り出され、現在も大切に保管されていることを報告しています。このように、散逸を免れた聖教資料は、その後の仏教復興に大きな役割を果たしました。

復興運動と聖教資料

廃仏毀釈後、信教の自由が認められると、各地で仏教復興運動が起こりました。松井孝純(前掲論文)は、種子島において法華宗寺院の復興が、両本山からの巡教や信徒の活動によって進められたことを示しています。この復興運動の中で、隠匿されていた聖教資料は再び日の目を見ることとなり、信仰の拠り所として、また宗門再建の指針として重要な役割を果たしました。大本山では、教団の再興を願う強い思いが記録されています。

寺院における聖教資料の保存と管理

寺院は、古来より聖教資料の保存と管理を担ってきました。下田正弘「大乗仏教起源論再考」(2013、URL)は、律蔵の記述に基づき、経典の書写、保存、管理は在家信者も重要な役割を担っていたことを指摘しています。また、蓑輪顕量「東大寺所蔵の法会に関する写本 -経釈と論義から-」(2004、URL)は、東大寺図書館に、法会に関する写本資料、論義や唱導に関する資料が豊富に所蔵されていることを紹介し、これらが当時の仏教教学の実態を知る上で貴重な資料となっていることを示しています。これらの資料は、寺院における聖教資料の継承と研究の営みを物語るものです。宮地廓慧「『歎異抄』の「大切の証文」について」(1970、URL)では、『歎異抄』の「大切の証文」に関する議論を紹介していますが、これも聖教資料の解釈と伝承をめぐる重要な問題提起です。椎名宏雄「『万善同帰集』の文献史的考察」(2007、URL)は、『万善同帰集』の刊行と流通の歴史を明らかにし、各時代の版の違いや、版本に記された情報が、当時の社会状況や仏教界の動向を知る上で貴重な資料となることを示しています。古賀克彦「河内国壺井通法寺に就いて」(2006、URL)は、通法寺という特定の寺院の歴史と変遷を通して、聖教資料の伝来と散逸、そしてその保存に関わる問題を浮き彫りにしています。

聖教資料研究の意義

聖教資料は、過去の仏教思想、教学、信仰を知る上で不可欠の資料です。椎名宏雄「『禅門拈頌集』の資料価値」(2002、URL)は、『禅門拈頌集』に収録された公案や著語が、当時の禅宗における思想動向を知る上で貴重な資料となることを指摘しています。山崎龍明「柘植信秀の真宗論」(2003、URL)は、柘植信秀という近代真宗僧侶の思想を通して、近代仏教が社会問題とどのように関わってきたかを考察しています。菊池武「近世における俳諧師と遊行家-特に北陸地方での安楽坊春波法師の活動について-」(1974、URL)は、俳諧師と遊行家の活動を通して、仏教文化が民衆の生活に浸透していく過程を明らかにしています。笠松直「ミャンマー所伝南方仏教古写本調査報告」(2014、URL)は、ミャンマーの寺院に所蔵される南方仏教の写本調査を通して、聖教資料の保存と研究の国際的な連携の重要性を示しています。奈良弘元「空也伝にみられる慈善事業」(1987、URL)は、空也の伝記から、古代における仏教と社会事業との関わりを考察しています。朴鎔辰「元代『科註妙法蓮華経』の刊行と流通」(2016、URL)は、『科註妙法蓮華経』の刊行と流通の歴史を通して、東アジアにおける仏教文化の交流と伝播を明らかにしています。都河陽介「長沼賢海写『華厳経論』断簡について」(2021, URL)は、『華厳経論』の断簡を通して、経典の伝来と受容の歴史を考察しています。秋津秀彰「初期曹洞宗教団における『正法眼蔵』の伝来について」(2022、URL)は、『正法眼蔵』の伝来と受容の歴史を通して、初期曹洞宗の教団形成を考察しています。Shobha Rani Dash「文化史の観点から見るコロフォン研究の重要性――オディシャー州の宗教系貝葉写本を事例として――」(2019、URL)は、インドの貝葉写本のコロフォン(奥書)に着目し、そこに記された情報が、写本の歴史や文化的な背景を知る上で重要であることを示しています。田戸大智「身延文庫蔵「大乗義章抄」所引の文献・逸文について」(2019、URL)は、「大乗義章抄」に引用された文献や逸文を分析することで、院政期の学問研究の状況を明らかにしています。金子寛哉「日本における群疑論の引用 (二)」(1982、URL)は、『群疑論』の引用状況を分析することで、浄土教思想の受容と伝播の過程を明らかにしています。早島鏡正「自然・風土的基盤と原始佛教思想」(1960、URL)は、原始仏教思想とインドの自然・風土との関係を考察しています。高橋秀榮「鎌倉時代の仏名会」(2004、URL)は、鎌倉時代の仏名会という仏教行事を通して、当時の信仰や社会状況を考察しています。宇治谷祐顕「南海の仏教遺跡ボロブドール」(1978、URL)は、ボロブドール遺跡の調査を通して、仏教美術や建築様式、そしてその背後にある思想を考察しています。これらの研究は、聖教資料が単なる過去の遺物ではなく、現代社会を理解するための重要な手がかりとなることを示しています。

あとは、これをさっくり簡単にWebから使えるようにすれば、まあ大体OKですね。なお、Apache Solrの使い方については、このブログの過去記事にさんざん書いてありますが、リクエストが多ければこの記事の続編ということで改めて少し書くかもしれません。

JADH2024の豪華な基調講演をご紹介(まだ参加申込みは間に合います!)

日本デジタル・ヒューマニティーズ学会 (JADH) の年次国際学術大会、JADH2024が、本年は9/18-20に東京大学本郷キャンパスで開催されます。JADHは、国際デジタル・ヒューマニティーズ学会連合 (ADHO) の構成組織として、国際的なデジタル・ヒューマニティーズの潮流と日本の研究動向の交流の場として2012年の設立以来、毎年国際会議を開催するという形で活動を続けてきています。基調講演には国内外の有力なデジタル・ヒューマニティーズ研究者に講演をしていただくことになっていますが、今回は、ポーランド科学アカデミーのポーランド語研究所で所長をしつつクラクフ教育大学の教員でもあるMaciej Eder先生と、オランダ・マーストリヒト大学の教員であり、この9月からは欧州連合の人文学向けデジタルインフラプロジェクトDARIAHのトップをつとめておられるSusan Schreibman先生が基調講演を引き受けてくださいました。

Maciej Eder先生は、コンピュータ文学研究の第一人者であり、StyloというRベースのオープンソースソフトウェアを開発・公開しておられます。このソフトは、コンピュータで文体を分析して類似度を測ったり系統樹を作成したりしてくれる便利なソフトウェアで、この分野ではよく用いられる著者推定の手法である John BurrowsのDeltaも実装されて簡単に使えるようになっている大変便利なソフトウェアです。このMaciej Eder先生のお話をじっくり聞ける貴重な機会が、今回のJADH2024では提供されます。

一方、Susan Schreibman先生はアイルランド文学の研究者であり、かつデジタル・ヒューマニティーズの研究者でもいらっしゃいますが、デジタル・ヒューマニティーズ分野では知らぬ人のいない大物で、デジタル・ヒューマニティーズという分野名が使われることになった直接の理由である『A Companion to Digital Humanities』という2004年に出た分厚い共著本の3人の編纂者のうちの一人です。というのは、この本で Digital Humanitiesという言葉が用いられる以前は、この分野は Humanities ComputingやComputers and the Humanities等と呼ばれていたのですが、この本でDigital Humanitiesという言葉が使われ、さらに、学会連合やカンファレンスの名称、政府の助成機関等で用いるようになったため、デジタル・ヒューマニティーズという言葉が広く人口に膾炙することになりました。なお、この本に関しては、2015年に新版が刊行されたため、2004年版はオープンアクセスとして公開されています。

このような多大な影響力を持つ本の編纂者であったというだけでも相当なことですが、その後もSusan Schreibman先生は各地で活躍をしてこられました。日本で比較的よく知られているものとしては、TEIガイドラインに準拠して構築した校訂テキストをWebブラウザ上で見やすく表示するためのソフトウェア、Versioning Machine関連論文)を米国・メリーランド大学時代に開発したことでしょうか。その後、アイルランドの大学で、アイルランドでは初めてのパブリック・ヒューマニティーズであるイースター蜂起に関する手紙を文字起こしするプロジェクト Letters of 1916 に取組まれ、さらにそれをアイルランド内戦の時期まで広げたLetters 1916-1923)を現在も率いておられます。

また、近年、オランダに移られてからは、3Dを学術的に扱えるようにするための研究、3D Scholarly Editionに取り組んでおられ、PURE3Dという国際的なプロジェクト(関連論文)を率いておられます。このプロジェクトは、内容やコンセプトが素晴らしいのはもちろんですが、それだけでなく、学術編集版として3D環境を編集・操作するためのコンピュータ環境を、オランダの学術インフラ上で、オランダの学術インフラプロジェクトDANSの協力を得ながら構築しているという点でも素晴らしいものがあります。人文学のプロジェクトに対してここまで深く政府の学術インフラプロジェクトが関わってくれるという体制には、我々としても学ぶべきことが色々あるように思われます。なお、この3D Scholarly Editionの話を聞きたい人は、9/17(火)に慶応大学三田キャンパスで講演とワークショップがありますので、ぜひそちらにご参加ください。

こういった先進的なプロジェクトを着々と立ち上げ推進される一方で、基本図書の編纂にも注力しておられ、上述の2冊に加えて、デジタル文学研究の教科書、『A Companion to Digital Literary Studies』も編纂されました。そして、現在も、新たに重要な基本図書の編纂をしておられるのだそうです。

このような流れで、この9月からは、欧州連合の人文学向けデジタルインフラプロジェクトDARIAHのDirectorに就任されました。様々な国際的なプロジェクトを率いる中での知見を踏まえ、JADH2024では、人文学におけるデジタルインフラのあり方についての講演をしてくださるようです。日本ではそのあたりはなかなかうまくいっていないところですが、欧州でも必ずしもうまくいっているわけではありません。とはいえ、難しさのポイントはまったく異なっているはずです。というのは、欧州ではデジタル学術研究基盤を構築するプロジェクトが欧州連合全体として推進されており、人文学もそのなかにきちんと位置づけられ、内容に応じた複数のプロジェクトが立ち上げられているからです。そのあたりのことを聞いてみることで、日本の今後がどういう風に展開していくのか、検討するための材料を色々といただけるのではないかと期待しております。

JADH2024は、まだ参加申込みできますので、有料になってしまうのが恐縮ですが、基調講演以外にも興味深い一般発表がたくさんありますので、ご興味がおありの方は、今からでもぜひお申し込みください。参加申込みについては以下の頁をご覧ください。

JADH2024 - Registration

Apache Solrをローカルで使う時にCORSエラーを回避する方法

表題のとおりです。これができると、ローカルのHTMLファイルに書き込んだJavaScriptでApache Solrから検索して結果を表示できるようになります。 ある種の用途には非常に便利です。

やり方ですが、以下の頁を参照しています。

Going Cross-Origin with Solr - OpenSource Connections

が、Solrのver. 9.6.1の時点では、ここに書いてあるように jetty-servletsやjetty-utilsを持ってくる必要はなく、単に、

server/solr-webapp/webapp/WEB-INF/web.xml

の中に以下の情報を追加して、Solrを再起動するだけでいいようです。

<filter>
   <filter-name>cross-origin</filter-name>
   <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
   <init-param>
     <param-name>allowedOrigins</param-name>
     <param-value>*</param-value>
   </init-param>
   <init-param>
     <param-name>allowedMethods</param-name>
     <param-value>GET,POST,OPTIONS,DELETE,PUT,HEAD</param-value>
   </init-param>
   <init-param>
     <param-name>allowedHeaders</param-name>
     <param-value>origin, content-type, accept</param-value>
   </init-param>
 </filter>

 <filter-mapping>
   <filter-name>cross-origin</filter-name>
   <url-pattern>/*</url-pattern>
 </filter-mapping>

上記のXMLエレメントを追加する場所は、以下のエレメントの次で大丈夫でした。

  <listener>
   <listener-class>org.apache.solr.servlet.CoreContainerProvider</listener-class>
  </listener>

How to Set Up DHconvalidator with Docker

This blog is usually written in Japanese, but I will write it in English because I think people who set up DHconvalidator can usually at least read English tutorials.

DHconvalidator is a very cool tool that, in conjunction with Conftool (https://www.conftool.net/en/index.html), automatically retrieves the list of authors and affiliations of the papers presented and finally makes the presenters create abstracts in TEI/XML format.

A huge amount of files of papers in TEI/XML format are already accumulated in various locations (mainly on Github) and can be used in various ways. Statistical analysis is also expected, but for now, an easy-to-understand way to use the data is to go to The Index of Digital Humanities Conferences, which is a very straightforward site. You can search for papers (mainly abstracts) presented at past DH conferences in various regions. For example, a search using my name returns 26 results.

The DHconvalidator, which makes all these wonderful things possible, is very easy to set up if you keep a few points in mind. I would be able to set it up in 20 minutes with the following tutorial.

However, it took me about three days because I had overlooked one of the following points I decided to write this tutorial so that you all do not have to go through this unnecessary suffering of mine.

0. Check the secure pass of the Conftool for your conference

A Google search on this matter may turn up old documents. In the current Conftool, go to Overview > Data Import and Export > Integrations With Other Systems and look at the bottom and see "Enable General REST Interface ". Select Yes here and note the REST Interface Password. Also note the URL of the REST API. This URL is probably something like https://www.conftool.net/[your conference name]/rest.php.

Here, let's assume the server name running DHconvalidator is dhconv.dhii.jp.

1. Configure the virtual server

(This is the case for Redhat Linux operating systems including Alma, Rocky, etc. For Debian, Ubuntu, etc., please modify the settings according to the OS settings.)

To set up a virtual server, I can assign a new hostname using CNAME on the DNS server and then configure it on the HTTP server. In this case, I used the hostname dhconv.dhii.jp using Bind and Apache, so it looks like this

Configuration for Bind under chroot environment:

Edit "[chroot]/etc/DNS/dhii.jp":

dhconv  IN      CNAME   parentserver.dhii.jp.

(Don't forget to increase the value of serial)

Restart Bind

# systemctl restart named-chroot

As for Apache, I configured virtual hosts and then Certbot to support https.

Edit "/etc/httpd/conf.d/vhost.conf" or "[Apache home]/conf.d/vhost.conf"

<VirtualHost *:80>
ServerName dhconv.dhii.jp
DocumentRoot /var/www/html/
DirectoryIndex index.html index.php
ErrorLog logs/dhconv-error_log
CustomLog logs/dhconv-access_log combined env=!no_log
</VirtualHost>

Restart Apache

# systemctl restart httpd

Run Certbot

# certbot -d dhconv.dhii.jp
2. Set up a reverse proxy

Edit "/etc/httpd/conf.d/vhost-le-ssl.conf" or "[Apache home]/conf.d/vhost-le-ssl.conf":

<VirtualHost *:443>
ServerName dhconv.dhii.jp
(snip)
<Proxy *>
        Require all granted
</Proxy>

        ProxyRequests Off
        ProxyPreserveHost On
        ProxyPass / http://localhost:8080/ keepalive=On
        ProxyPassReverse / http://localhost:8080/
        RequestHeader set X-Forwarded-Proto "https"
(snip)
</VirtualHost>

Restart Apache

# systemctl restart httpd
3. Clone the GitHub repository
% git clone https://github.com/ADHO/dhconvalidator
4. Edit template files

Edit the docx and ott file templates in the following directories as appropriate for your meeting. Be careful not to change too much or the conversion to TEI/XML may not work.

$ ls dhconvalidator/src/main/resources/template/
DH_template_DH2016_en.docx  DH_template_DH2018_es.docx   DH_template_DHd2016_en.docx  old_DH_template_DH2018_en.docx
DH_template_DH2016_en.ott   DH_template_DH2018_es.ott    DH_template_DHd2016_en.ott
DH_template_DH2018_en.docx  DH_template_DHd2016_de.docx 
DH_template_DH2018_en.ott   DH_template_DHd2016_de.ott   

In this case, the following two files were created. Note how the files are named.

 DH_template_JADH_en.docx DH_template_JADH_en.ott
5. Edit the Dockerfile

Next, here is the most important part. Write the required information in the following file.

dhconvalidator/Dockerfile

The contents of this file will look like this. Rewrite the "jadh-2024" value as appropriate for your conference environment and some other values. In particular, do not forget the [REST Interface Password]. (This Dockerfile is a slight modification of the one on GitHub, so if you edit it based on this one, you can eliminate errors during Docker builds..)

# First step: build the war file
FROM gradle:5.4 as builder

WORKDIR /home/gradle/dhconvalidator
USER root:root
COPY . .
RUN gradle war  --no-daemon

# step 2: run the application server
FROM jetty:alpine
USER root
RUN apk add --no-cache curl

ENV dhconvalidator_base_url=http://dhconv.dhii.jp/dhconv \
    dhconvalidator_conftool_login_url=https://www.conftool.net/jadh-2024/ \
    dhconvalidator_conftool_rest_url=https://www.conftool.net/jadh-2024/rest.php \
    dhconvalidator_conftool_shared_pass=[REST Interface Password on the Conftool] \
    dhconvalidator_defaultSubmissionLanguage=ENGLISH \
    dhconvalidator_encodingDesc='<encodingDesc xmlns="http://www.tei-c.org/ns/1.0"><appInfo><application ident="DHCONVALIDATOR" version="{VERSION}"><label>DHConvalidator</label></application></appInfo></encodingDesc>' \
    dhconvalidator_html_address_generation=true \
    dhconvalidator_html_to_xml_link=true \
    dhconvalidator_image_min_resolution_height=50 \
    dhconvalidator_image_min_resolution_width=100 \
    dhconvalidator_logConversionStepOutput=true \
    dhconvalidator_oxgarage_url=https://teigarage.tei-c.org/ege-webservice/ \
    dhconvalidator_performSchemaValidation=true \
    dhconvalidator_publicationStmt='<publicationStmt xmlns="http://www.tei-c.org/ns/1.0"><publisher>Japanese Association for Digital Humanities</publisher><address><addrLine>5-26-4-11F, Hongo, </addrLine><addrLine>Bunkyo-ku, Tokyo</addrLine><addrLine>Japan</addrLine><addrLine>Japanese Association for Digital Humanities</addrLine></address></publicationStmt>' \
    dhconvalidator_showOnlyAcceptedPapers=false \
    dhconvalidator_showOnlyAcceptedUsers=true \
    dhconvalidator_tei_image_location=/Pictures \
    dhconvalidator_templateFileEN=template/DH_template_JADH_en \
    dhconvalidator_paperProviderClass=org.adho.dhconvalidator.conftool.ConfToolClient \
    dhconvalidator_userProviderClass=org.adho.dhconvalidator.conftool.ConfToolClient

COPY --from=builder /home/gradle/dhconvalidator/build/libs/*.war /tmp/
COPY entrypoint.sh /entrypoint.sh

USER root:root
RUN mkdir -p ${JETTY_BASE}/webapps/ROOT \
    && unzip /tmp/*.war -d ${JETTY_BASE}/webapps/ROOT \
    && chown -R jetty:jetty ${JETTY_BASE}/webapps/ROOT

Especially the following two lines are very important, so I will show them again for confirmation.

dhconvalidator_paperProviderClass=org.adho.dhconvalidator.conftool.ConfToolClient
dhconvalidator_userProviderClass=org.adho.dhconvalidator.conftool.ConfToolClient
6. Build the Docker image

Now that you've made it this far, you're almost ready to build Docker, as described in the GitHub tutorial.

# docker build -t dhconvalidator .
7. Run the Docker container

Then, run the Docker container

# docker run -d --rm -p8080:8080 --name dhconvalidator dhconvalidator 
8. Access your DHconvalidator with your Web browser

Access your DHconvalidator with your Web browser. If your paper has been accepted, your name will be displayed after you log in, and the title of your paper will be displayed when you go beyond that, and so on. If your paper is not accepted, you may want to create an accepted temporary user on Conftool, for example. In any case, I hope you are logging in successfully.

歌合絵巻テキスト構造化&IIIF画像連携の成果が公開されました

この数年、お手伝いをしていたお仕事の一つに、『十番虫合絵巻』(ホノルル美術館所蔵)のデジタル化、という仕事がありました。 このコンテンツについてはまったくの素人で、正確な説明はこちらのページをご覧いただきたいのですが、簡単に述べますと、

  • 時は江戸時代、天明2年(1782)8月。隅田川のほとりのお寺、木母寺(もくぼじ)。
  • 元々、当時は、和歌を詠みあって対戦する「歌合」というゲームが流行っていた。
  • 一方で、秋の夕方、鈴虫・松虫などの声を愛でるために御座(ござ)や酒を携えて名所を訪れる「虫聴」も流行っていた。
  • 和歌だけで対戦するのでは飽き足らなくなり、生きた松虫・鈴虫を組込んだジオラマ(州浜、と呼ばれるそうです)も作って展示して、それをテーマにした和歌を詠むことにした/詠もうとする和歌にあわせたジオラマを作って展示することにした
  • 対戦で詠む和歌の元ネタは主に平安時代の作品(=当時から見ても古いもの。王朝の古典。)

という楽しいことが起きていたそうです。

そして、そのジオラマと、詠まれた和歌、さらには、その評価(判詞)と勝敗までが、巻物に書き込まれたもの、それが『十番虫合絵巻』なのだそうです。

しかし、この絵巻を見ても、絵がきれいなのはいいけど、文字はよくわからないし、文字が読めても内容は古文でわかりにくいし、そもそもそういうことだとどこがなんなのかもよくわからない…

…という、残念な状況がありました。

これを一気に解決してくれるのが、今回ご紹介する虫合絵巻ビューワです。

このビューワでは、上の図のように、現代語訳に加えて英訳まで、対応する箇所をハイライト表示してくれます。これで、「何が書いてあるのか」を現代日本語で読んで知ることができるのです。また、和歌に対応するジオラマも、和歌の横の画像アイコンをクリックすると表示してくれるようになっています。

しかし、これだけだと、文章を理解することはできても、歌合という対戦の構造はなんだかちょっとわかりにくいです。それをわかりやすくしてくれるのが、 右側の「和歌」タブです。

ここでずらっとリストされている「一番左歌」「一番右歌」…というのが、本文中の和歌なのですが、このうちのいずれかをクリックすると、その和歌についての対戦情報がずらっと出てきます。

ここでの「左歌」は、詠まれた和歌で、「虫判」はジオラマに対する評価、「歌判」は和歌に対する評価、そして、「歌判勝敗」は、その歌が勝ちであることを書いています。 これは古文だからよくわからない…という人は、それぞれのテキストにカーソルをあわせてみましょう。そうすると以下のように…

現代語訳の対応箇所にスクロールしてくれて、ハイライトもされます! 英訳も同様に表示されますので、英語圏の人にも同じようにおすすめすることができますね。

そして、「左歌」の隣にある画像アイコンをクリックすると、その歌の対応するジオラマの絵も表示されます。

そして、この画像はIIIF対応で公開されていますので、たとえば以下のような感じで、「虫」がどこにいるのか、拡大して探してみることもできます。

では次に、この会に参加したり歌を詠んだりした人たちはどういう人たちだったんだろう…?と思った時には、「人物」タブをクリックしてみましょう。

今度は、人物のリストが表示されます。各人物の名前をクリックしてみると、その項目が開いて、その人物の詳細情報が表示されます。たとえば、以下のような感じです。

そして、人物情報の下の方に、「参照している箇所」という項目があり、そこにカーソルをあわせると以下のように、その人物が登場する場所にスクロールされます。

と、まあ、このような形で、読みやすく、かつ、虫合という対戦を色々な角度から楽しめるいビューワが公開されたのでした。

このプロジェクトには多くの人が関わり、校訂本文・現代語訳・英訳を作成され、また、テキストはTEIに準拠した歌合向けのマークアップとIIIF画像向けのマークアップが行われ、さらにそのTEI準拠テキストとIIIF画像を連携させつつ同時にうまく表示させるビューワの開発も行われました。詳細はこちらをご覧いただければと思います。

そのようなことで、ぜひこの虫合絵巻ビューワをお試しして、虫合の世界を堪能してみてください。