追加：GoogleDriveのPDFをnotionに自動登録できるようにし、notionからPDFの探索もできるようにしました）Notionを介し，ChatGPT plugin: Chat With Workspace を用いてChromeブックマークを探索する。～sumyによる抽出型要約や和訳を利用して～

# きっかけ

ChatGPT pluginにNotion内を検索できる「Chat With Workspace」が追加されました．
Chrome機能拡張「bookmarks to notion」を用いてChromeのブックマークをNotionと同期していたところですが，
ブックマーク先の文章の要約をNotionに追加しておけば，ChatGPTからChromeブックマークを探索しやすくなり，より有用にできるのでは，と考ました．

自分が蓄えてきた重要知識に対し、自分以外の知識を用いアクセスし、取り出す。
自分以外の視点をも含めた知識融合、それができえるかと期待するところです。

※　結果としては、ChatGPTからのアクセスに関しては、LangChainを用いた個人用ツールとして開発し直したほうが良いかな、という結果ではあります。　notion apiの出力制限が厳しくChatGPTに十分な情報が渡せないようです。結果、notionデータベースの情報量が大きくなるとどうにもならんみたいですね。
※　notionにブックマーク先の情報もPDF内の情報も自動登録できるシステムとできているところ、登録情報をより良く活用できれば、という動機は高まっています。notion標準の検索機能がいまいちであるところChatGPTで検索できればよかったところですが、ChatGPT以外の言語モデルを用いた検索でも良いところです。notion aiに期待。（202405頃、notion aiを用いた検索ができるようになったようです。が、今ひとつ日本語に弱いようで…）

# 環境
・Google Colab 2023/06/23

# 実施

## 1　準備
### 1.1　Chrome機能拡張　**bookmarks to notion**　のインストール
**bookmarks to notion**
https://chrome.google.com/webstore/detail/bookmarks-to-notion/lplcbopdbafpdcogfmgfhedhlpepljga?hl=ja

インストールしてsync to notionを実行してください．
NotionにBookmarksデータベースが作成されます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/a179edd4-0fc4-a528-4b8f-f06fc15478f3.png)


### 1.2　Notion APIを使用可能に・Internal Integration Token取得
Notion APIを使用可能にする方法は，次など参考ください

**Notion API を使用してデータベースを操作する**
https://zenn.dev/kou_pg_0131/articles/notion-api-usage

ついで，Internal Integration Tokenを取得しておきます．

### 1.3　NotionデータベースBookmarksにsummary列を追加・database_id取得・コネクトにintegration追加
NotionデータベースBookmarksに，プロパティsummaryを追加します．種類はテキストです．
このsummary列に，url先の文章の要約が入力されてゆくことになります．

ついで，アドレスから，database_idを取得しておきます．
https://www.notion.so/＜database_id＞?v=＜今回は使わない＞

ついで，右上の三点のメニューから，1.2で設定したintegrationをコネクトとして追加しておきます．（自分はintegration名をNotion-APIとしています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/6d4efeb5-2d8d-f0a6-4df9-e58c1cf4232a.png)


### 1.4　ChatGPT plugin　**Chat With Workspace**
**Chat With Workspace**を，ChatGPT pluginの選択画面からインストールします．
インストール時に，NotionのBookmarksデータベースをアクセス可能に選択しておきます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/1781891f-9c03-04bd-b3da-981757d6531d.png)

### 1.5　要約ライブラリ**sumy**のインストール
文章を要約する方法には様々ありますが，
今回はsumyを使用します．

```python:
pip install sumy
```

**miso-belica/sumy**
https://github.com/miso-belica/sumy
sumyでは複数の要約手法を選択可能ですが，今回はLsaSummarizerを用います．

※なお，文章要約には抽象型要約（生成型要約）と抽出型要約があるところですが，
今回は，元の文章の一部を抽出する，抽出型要約を採用します．
ChatGPTからNotionにアクセスするにあたり，その検索特性により，文章全体の意味の正しさよりも固有名詞（キーワード）が重要となりえるからです．
抽象型要約は固有名詞を失った要約を生成する傾向がありキーワード検索の対象となる文章をつくるにあまり向かない傾向にあります．上位概念で検索したいのか下位概念で検索したいかなど，どちらを選ぶかは用途次第ではあります．

抽象型要約を用いた場合の参考
https://qiita.com/kzuzuo/items/1f86f8a1e430447a6e22

### 1.6　Notionライブラリ**notion-client**のインストール
pythonからNotion API二アクセスするために，notion-clientを利用します．
```python:
pip install notion-client
```

**ramnes/notion-sdk-py**
https://github.com/ramnes/notion-sdk-py


## 2　コードと実行結果

### コード
細かい部分はお好みで．

・要約はあると便利なくても構わない．ところであるので，「動けばよかろうなのだァァァァッ!! 」という作成方針としています．
・言語選択は**langdetect**ライブラリを用いるなど，よりスマートな方法を採用すると良いでしょう．
・英語で抽出した場合には，**deep_translator**ライブラリなど用いて和訳しても良いですね．
・前処理をしておくとより良いです．けれど目的は読める要約を作ることではなく検索キーワード作成に近いのであまり重要ではないでしょう．
・tryでリンク切れなどまとめて排除していますが，きちんとエラーを拾うべきです．（予期しないキャンセルがあるようなので後日ちょっと確かめてみます→punktが必要でした）
・コメントは全て消しました．分からなければChatGPTさんにコメント求めれば足りますからね・・・

```python:
from notion_client import Client
from sumy.parsers.html import HtmlParser
from sumy.nlp.tokenizers import Tokenizer
from sumy.summarizers.lsa import LsaSummarizer
from tqdm.notebook import tqdm

import nltk
nltk.download('punkt')

notion = Client(auth="<Internal Integration Token>")
database_id = "<database_id>"

params = {"database_id": database_id}

while True:
    database = notion.databases.query(**params)
    summarizer = LsaSummarizer()

    counter = 0
    for page in tqdm(database["results"]):
        counter += 1
        if page["properties"]["summary"]["rich_text"]==[]:
            page_id = page["id"]
            url = page["properties"]["url"]["url"]

            try:
                parser = HtmlParser.from_url(url, Tokenizer("japanese"))
                summary = summarizer(parser.document, 10) 
                if len(summary)==0:
                    parser = HtmlParser.from_url(url, Tokenizer("english"))
                    summary = summarizer(parser.document, 10)

                summary_text = " ".join(str(sentence) for sentence in summary)
                if summary_text=='':
                    summary_text = 'non'

                notion.pages.update(
                    page_id=page_id,
                    properties={
                        "summary": {"rich_text": [{"text": {"content": summary_text}}]}
                    }
                )
                print(counter, page_id, url, summary_text)
            except:
                pass
        
    if "next_cursor" in database and database["next_cursor"]:
        params["start_cursor"] = database["next_cursor"]
    else:
        break
```

- GPT-4さんによるコード解説
> このPythonコードは、Notionの特定のデータベースからウェブページの情報を取得し、それを自動的に要約し、その要約を元のページ情報に追加するためのものです。
主な動作は以下の通りです：
Notion APIを使って特定のデータベースにアクセスします（Notionはノート、タスク、データベースなどを統合的に管理できるツールです）。
そのデータベースから全てのページを取得します。それぞれのページは独自のIDとURLを持ち、またそれぞれのページには要約（summary）というプロパティがあるようです。
それぞれのページのURLにアクセスし、そのウェブページの内容を自動的に要約します。この要約には、Sumyというテキスト要約ライブラリが使用されています。このライブラリは自然言語処理の一部で、大量のテキストを短く要約する機能があります。
得られた要約をNotionの元のページ情報に追加します。
このプロセスは、特定のデータベースの全ページを処理し終えるまで繰り返されます。
なお、このコードは内部統合トークンとデータベースIDが必要で、これらを指定しなければ動作しません。また、エラーハンドリングのために、要約プロセス中に何らかの問題が発生した場合にはそのページはスキップされます。
このコードはPython言語で書かれており、リクエスト処理、HTMLのパース、自然言語処理、プログレスバー表示など、様々なライブラリを活用しています。

- GPT-4さんによるコード批判
> このコードは基本的には良く構成されていますが、いくつかの改善点や考慮すべき事項があります。
エラーハンドリング：このコードでは try / except ブロックを使用していますが、具体的な例外をキャッチしていません。これによりすべての例外が無視され、どのような問題が発生したのか特定が難しいです。例外の種類によって適切な対処を行うためには、可能な限り具体的な例外を捕捉することを推奨します。また、ログを出力することで後で問題を解析できるようにすると良いでしょう。
エラーハンドリングの継続性：現在の設計では、あるページでエラーが発生するとそのページの処理がスキップされますが、その後も処理が続行されます。しかし、一部のエラー（ネットワーク接続の問題やNotion APIの一時的な問題など）は一時的なもので、再試行によって解決できる可能性があります。リトライロジックを実装すると、一時的なエラーから回復できる可能性が高まります。
セキュリティ：このコードは Notion API のトークンとデータベースIDを直接コードに書き込む形になっています。この情報は重要な認証情報なので、セキュアな方法で管理すべきです。環境変数を用いてこれらの値を管理する方法を検討すると良いでしょう。
テキストの要約が生成されない場合：要約が生成されない場合（日本語と英語のパーサーの両方で失敗した場合や要約が空文字列の場合）に、単に 'non' という文字列をセットしています。ただし、そのような場合には何が問題だったのかを示すエラーメッセージを設定する方が良いでしょう。

あ，はい


### コードの実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/22f993f2-fcdc-2693-cbf0-eab2dd9735d1.png)

### NotionデータベースBookmarkのsummaryへ追記された要約
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/ceaf73d3-32bd-c37a-249c-f18699afd8e5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/8c1d30cd-e17b-cc08-0a28-4a2c715c6e7f.png)


### ChatGPT pluginを用いた探索例 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/00a56df2-f10c-643a-a49f-f35c099f7ec6.png)

面白げな記事をブラウザにブックマークしたのは良いけれど，見直すこともないまたは見直すことが難しかったりします。
このように探索できるようになっていると嬉しいですよね．

- ただし、今のところ，ChatGPTを用いた探索では見逃しやエラーが多く、またChatGPTからNotionにアクセスできること以上の価値は見いだせていません。

ChatGPT pluginはどれも言語モデルの利点を活かしきれていませんよねいまのところ．

**ChatGPT pluginには，外部データベースに対する「概念検索」と，「検索結果と既存知識を融合させた結果提示や提案」，これらはできて欲しいと期待しています．**
データベースに対する概念検索については，キーワードを増やし関連度順に評価を繰り返す指示をすることである程度は対応できえますが，自ら解像度を変えながら検索を繰り返してほしいところです．
検索結果と既存知識を融合させた結果提示や提案については，なぜか融合できず独立にしか出力できないようで？，如何ともしがたい印象です．出力を一度プールし処理しなすことはできなくはないと思うのですが…pluginの設計がそうできないようになっているのでしょうか?

可能性はあり得るのに、まだまだうまくゆかない、という心象ですね。

LangChainを用いて１から組み直したほうが手っ取り早いかもしれません。
openai APIを用いることになりそうでありコストがかかりますが。
（前者は全データに対し類似度を求めれば良いけれど…トークン数を考えれば現実的にはopenai embeddingを用いることになる。後者も同様。うーむ。）

※次のエラーにより実行できないことも多いようです。Notion APIの限界ですね…

```
{
  "ADDITIONAL_INSTRUCTIONS_FOR_CHATGPT": "Response character limit exceeded. You can't retrieve the blocks list because it will cause an error \"Message too long\". Reduce the page_size parameter and try again.Message character count: 28570. Limit: 15000. ",
  "notion_response": {}
}
```

# その他
### Notionのアプリをスマホにインストールすると共有機能が使えるようになります．この共有機能を用いると，ブラウザなどの記載内容をNotionデータベースに保存でき，Notionから検索容易とできます．デスクトップではChrome機能拡張の「Notion Web Clipper」で同じことができますね．

共有により記載内容は指定のNotionデータベースの子ページに保存されます．その要約や翻訳をプロパティに入れても良いですね．

### Google Driveに保存しているPDFに対し，GASを用いたOCR処理を行い，PDFの記載内容をNotionデータベースに保存し，Notionから検索できるようにしました．

Google Driveに保存しているPDFは自動的にOCR処理されており，Google Driveでそれを対象にした検索ができはするのですが，結構検索に引っかかってこないこともあります．この原因は多分，OCRの読み取り不良です．手持ちのデータでは2-5%ほど不良があったでしょうか（一時に比べると素晴らしい進歩ではありますが）
NotionでOCRの読み取り不良の有無を確認し明示的に補正しておけば，検索改善ができます．

つぎの記事で紹介されているライブラリのコードを一部変更し使用しています．

　　**Notion で Google Drive の OCR を簡単に使えるんですか！？**
　　https://zenn.dev/hankei6km/articles/easily-use-google-drive-ocr-with-notion
　　https://github.com/hankei6km/gas-gocr2notion/tree/main

変更点は，
・API取得可能文字数制限エラーの回避　2箇所
・文字化けの除去　2箇所
・エラー対応容易化のため、for内で都度setDescriptionするように変更　1箇所
・for内で都度setDescriptionするように変更したことによるリクエスト増加に対し，Utilities.sleepで対応　1箇所
・scanFolderIdによるフォルダ内ファイル取得時における取得件数制限に対し、pageTokenで対応　1箇所
```javascript:
```
・大きなファイルがある場合にDrive.Files.copyの処理終了を待つため，例外処理とUtilities.sleepで対応　1箇所
```javascript:
```
・Notion API非対応のエスケープシーケンスの修正　1箇所
ですね。

なお、上記修正をする過程で、Google Application Script APIの実行時間制限6分の中で多量のデータに対しバランスよく処理効率化とエラー対応を行うことはなかなか厄介だ、と認識しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/03a09d8a-47b5-1266-59aa-fd9db2295110.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/570c758d-31a0-ec76-3581-988792a5f982.png)
和訳を加えて，
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/375448b5-9c0e-971b-ad6e-e9a1f1616e2c.png)

・Notionでの論文管理をサポートするツールを作りました
https://qiita.com/issakuss/items/2e69f2da040cb35ed0d3
上記ではPDF一般で使えますが、論文に限定すればこちらのPapntを用いても良さそうです。


### 現在殆どのデータをNotionに移行しています．
いや本当に便利です。
欲を言えば，検索機能を強化してくれないかな・・・

### ChatGPTは，Voice control for ChatGPTと組み合わせることで会話の自動翻訳や自動構成を含めた議事録の作成や文字起こしを行えうるなど，非常に面白いですよね本当に．
GPT-3.5では途中から設定の忘却が始まりますし、セキュリティ対策をしなければいけませんが。
→　Custom instructions機能により，設定の忘却を気にする必要はなくなりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/667ad560-a129-680c-ed72-0f9097824000.png)

### sumyをLangChainの途中で用い、エージェントを動かす際のコストを低減させるなども有り得そうです。
LangChainは基本的なところしか触っておらず、特許母集団から特定の特許について質問する、などしか用いていませんが、外部接続とメモリの有効利用など、できることは多いでしょう。
コストもある程度下がりましたしGPT-4 APIも使えるようになりました。新規昨日の公開もある程度落ち着き、情報も揃ってきました。
そろそろ要求を整理し何らか作りたいと思います。
特許と製品とニーズと法律と判例が連携できればよいのですがねぇ。

# GPTs Actionsを用いnotion API経由でGPTsからnotionデータベースを検索することにしました

しました。
いや便利。

GPTsでNotion APIを叩くようにしてみたらやばかった
https://zenn.dev/yutakobayashi/articles/gpts-notion-api

![Screenshot_20231114-212742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/88c7e5c5-c91d-0c58-a74a-67bfba79ed32.png)

複数のnotionデータベースの複数のページから情報を抽出し、まとめ直すこともできるようです。
リレーショナルデータベースもういらないかもな．再現率は低いとは思うけど
![Screenshot_20231114-220820.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284074/60a9f967-4672-fb9e-b027-94276a41c05e.png)