文芸的データベース - 文書の作成とそのデータベース化を同時に行なう手法
「文芸的データベース」とは、株式会社Helpfeelのshokai.iconが提唱している、 文書の作成とそのデータベース化を同時に行なう手法で、 文書とデータベースのフィールドをひとつの画面に混在させながら 追加したり修正したりして同時に構築していくことにより、 完全に整合性のとれた文書とデータベースを構築しようというもの
こんにちはshokai.icon
shokaiです
Cosense.icon Cosense プロダクトマネージャー
コンセプトと機能を考えて実装・運用をしています
これはHelpfeel Tech Conf 2024の発表資料です
右のメニューのStart presentationでスライドになります
今日の話
1. 文芸的データベースとは
2. 機能設計の工夫
3. 実装の面白い所を紹介
既に全てのprojectで使えます
が、もしAPI quota超えた場合はbusiness projectを優先します
文芸的データベースとは
各ページから抜き出す項目を宣言すると
関連ページリストがテーブル表示モードになる
せっかくなので実演しますshokai.icon
レシピ
https://gyazo.com/27108bf1a7ce89a23b122cd0c25e51a8
世によくあるやつ
人間が定型データを入力してテーブル作ると、ドキュメントが大量生成されるシステム
その逆です
人間がドキュメントと項目定義を用意すると、LLMがテーブルを生成してくれる
Infoboxとは
抜き出された項目をページの右側に表示したもの
本文を更新すると、Infoboxも自動的に更新される
https://gyazo.com/d331ab2f889a31f07d1c0ab2ffdbb578
名前とデザインの元ネタ
Wikipediaの機能である元祖Infobox
そちらはInfobox (wikipedia)を参照
2列目以降にプロンプトを書いて、正規化・ソートできる
https://gyazo.com/283da90609b4536c920a49d937cdb2ee
https://gyazo.com/e0f17f6f9e1473624b89678a5e6543d3
これちょっとわかりにくいですが、人間ではなくLLM向けの注釈や作業指示ですshokai.icon
何のために作ったのか
ドキュメントを各自が自由に元気よく書きつつ、
これは現状のCosenseの書き心地を維持したい
同時に、複数人でのコラボレーションも正確に行いたい
つまり
マネージャは、各ドキュメントに書いてほしい項目をしっかり定義しろ
ページを書く時は、そのページに書いてほしいと要望されている項目を意識しろ
面談や議事録、スペック表、仕様検討などに必要な項目をInfoboxの抜き出し項目として定義しておこう
使用例を見ながらデモします
使用例
/Nota/文芸的データベース開発タスク
ガチで書くとこうなる。2列目にプロンプトが書ける
/Nota/自由記述した本文からLLMでinfoboxを生成する
/Nota/Cosense名称変更に伴う開発タスク
「対応予定時期」を必ず書け
/Nota/shokai
1つのページに複数のInfoboxを設定できる
/Nota/増井研と関わりのある人物
人物名鑑の例
レシピ
用途
議事録
社内ミーティング、商談、面接、1on1
書き漏らし防止
必ず記載すべき事がずっと右側に表示されていて、書かないと空欄になっている
例:「次回までにやっておく事」
数値、日付、URLなども抜き出せる
タスク管理
未着手、実装中、完了、中止など
人物名鑑、プロダクト名鑑、機能リスト
ちゃんと抜き出されない場合は本文の書き方が悪い
LLMにすら解読不能な意味不明なドキュメントを書いた事を反省しよう
LLM可読ではないドキュメントを人間に読ませるのは失礼
項目定義やプロンプトではなく、本文を書き直すべきshokai.icon
例:システム運用のアイディア出しでは必ず仮説・検証方法・対策を書く
/Nota/デプロイ直後のMongoNetworkTimeoutErrorやMongoServerSelectionErrorの対策
機能設計の工夫
楽しく子機能を使っていたら、便利な親機能の準備が整う
子機能
ページから抜き出された右側がリアルタイムに更新される
抜け漏れチェックできて便利
親要素
抜き出した要素をテーブルにしてソート・フィルタできる
順不同に操作できる
4つの操作がある
1. 項目を宣言する
2. 本文を書く
3. 抜き出し結果を見る
4. テーブルを見る
どういう順番で操作しても破綻しないように作った
ドキュメント作成と項目定義は、どちらを先に行ってもよい
たくさんドキュメントを書いてから、項目定義してもよい
項目定義してから、ドキュメントを書いていってもよい
ドキュメントと項目定義が揃った時点で、即座にテーブルが生成される
強いUIはボタンを捨てる
保存ボタンも更新ボタンも無い
宣言を書くと抜き出される
宣言を削除すると消える
いつも通り本文を書くだけ
適当なタイミングでInfoboxは更新される
実装の面白い所
Infoboxの更新フロー
code:mmd
sequenceDiagram
participant ブラウザ
participant サーバー
ブラウザ->>サーバー: Infobox更新してください(HTTPリクエスト)
サーバー-->>ブラウザ: 更新しとくよ(HTTPレスポンス)
サーバー->>ブラウザ: 今更新してる(websocket)
ブラウザ->>ブラウザ: spinner回します
サーバー->>ブラウザ: できた(websocket)
ブラウザ->>ブラウザ: spinner止めます
ブラウザ->>サーバー: Infoboxください(HTTPリクエスト)
サーバー-->>ブラウザ: どうぞ(HTTPレスポンス)
「更新中」と「完了」のステータスがサーバーからwebsocketでpush通知される
Infoboxのテキストの取得は、websocketで通知されたブラウザ側からHTTPで取りに行く
なぜこうなっているか
Cosenseは1ページを複数人で同時編集する
ChatGPTからのレスポンス速度がまちまち
10秒近くかかる事もある
多重実行が起きると順番が入れ替わる
websocketにデカい文字列を流したくない
抜き出し結果のテキストは大きくなる可能性がある
websocketではあまり送りたくない
同時に1000人が見ているページかもしれない
サーバー側でmutex lockもかけて多重実行を防いでいる
ちょっと古い本文から作られたInfoboxが最終データとして残らないようにしてる
APIのcache
本文+プロンプトのMD5 hashを、cacheのkeyにしている
問題発生
Node.jsのメモリ使用量は大きくなっていないのに、サーバーのメモリ使用量が枯渇した
原因
デカい文字列のMD5 hash計算が重くてevent loopをロックしてしまう
1 msec 〜 10 msecの間CPUを専有し
HTTPリクエストが処理できなくなり
受信したHTTP / MongoDB / Redis接続のTCP socketは、kernel領域のメモリ空間にたまり続けてしまう
解決
chunkに分けて、細かくevent loopに処理を戻してあげながら、MD5計算するようにした
Infobox定義更新からの全ページ一括更新は、タスクマネジメントをブラウザ側でやってる
サーバーにqueueを持っていない
batch処理もしていない
以下をすべて満たす方法を考えていたら、そうなったshokai.icon
Infobox定義の変更をトリガーとした文芸的データベースの全件更新は
ユーザーの画面に表示されている順に、上から処理したい
負荷をランダムなNode.jsプロセスへ分散もしたい
並列数を上げて高速化もしたい
同時編集による多重実行も防ぎたい
実行中に追加の変更が来たら再実行もしたい
全件更新中のgraceful restartも対応させたい
両立させる
負荷分散・高速化・運用・ユーザー体験
パフォーマンスチューニング大変だった
おわり〜
文芸的データベースとInfoboxを使って、書いてほしい項目を宣言しよう
ドキュメントを各自が自由に元気よく書きつつ、複数人でのコラボレーションも正確にできるはずだ