Upgrade to Pro — share decks privately, control downloads, hide ads and more …

nostrbuzzsのしくみ

 nostrbuzzsのしくみ

Yoji Shidara

March 10, 2023
Tweet

More Decks by Yoji Shidara

Other Decks in Technology

Transcript

  1. nostrbuzzs
    のしくみ
    npub1q7qyk7rvdga5qzmmyrvmlj29qd0n45snmfuhkrzsj4rk0sm4c4psvqwt9c
    2023-03-10 Nostr
    勉強会 #1

    View Slide

  2. @darashi
    Twitter
    のイマを切り取るサービス buzztter.com (
    運用終了)
    の作者です。
    nostr
    の イマを切り取るサービス nostrbuzzs
    をつくりました。
    (NEW! Nostr
    村放送局をつくりました。)

    View Slide

  3. nostrbuzzs
    https://nostrbuzzs.deno.dev/

    View Slide

  4. 全体の構成
    deno deploy
    fly.io
    nostrverse
    kind:1
    kind:1
    recent notes
    phrase frequency
    kind:38225 kind:38225
    static assets
    nostrbuzzs.deno.dev
    indexer analyzer
    ElasticSearch nostr-rs-relay
    relay.damus.io
    nos.lol
    web-browser

    View Slide

  5. Indexer
    deno deploy
    fly.io
    nostrverse
    kind:1
    kind:1
    recent notes
    phrase frequency
    kind:38225 kind:38225
    static assets
    nostrbuzzs.deno.dev
    indexer analyzer
    ElasticSearch nostr-rs-relay
    relay.damus.io
    nos.lol
    web-browser
    リレーに接続して kind1
    を収集します。
    content
    の言語推定を行い、日本語と推定されたものだけ Elasticsearch
    にイン
    デックスします。
    言語推定には https://github.com/pemistahl/lingua-go
    をつかっています。

    View Slide

  6. Elasticsearch
    deno deploy
    fly.io
    nostrverse
    kind:1
    kind:1
    recent notes
    phrase frequency
    kind:38225 kind:38225
    static assets
    nostrbuzzs.deno.dev
    indexer analyzer
    ElasticSearch nostr-rs-relay
    relay.damus.io
    nos.lol
    web-browser
    https://www.elastic.co/
    をそのまま使っています。
    Indexer
    から送られたデータを保持します。
    Analyzer
    が分析するために必要な情報を提供します。
    解析のため、形態素等でトークナイズせず N-gram
    でインデックスします。

    View Slide

  7. Analyzer
    deno deploy
    fly.io
    nostrverse
    kind:1
    kind:1
    recent notes
    phrase frequency
    kind:38225 kind:38225
    static assets
    nostrbuzzs.deno.dev
    indexer analyzer
    ElasticSearch nostr-rs-relay
    relay.damus.io
    nos.lol
    web-browser
    Elasticsearch
    からデータをとって buzzphrases
    を求めます。
    解析結果を Relay
    に Parameterized Replaceable Events (NIP-33)
    で送ります。

    View Slide

  8. Web UI
    deno deploy
    fly.io
    nostrverse
    kind:1
    kind:1
    recent notes
    phrase frequency
    kind:38225 kind:38225
    static assets
    nostrbuzzs.deno.dev
    indexer analyzer
    ElasticSearch nostr-rs-relay
    relay.damus.io
    nos.lol
    web-browser
    いわゆる SPA
    です。
    Fresh https://fresh.deno.dev/
    で書きました。
    当初は API
    サーバも実装していたので deno deploy
    に置いてありますが、静的な
    サイトです。

    View Slide

  9. Analyzer
    の処理について、もうすこし詳しく

    View Slide

  10. Analyzer 1/2 --
    頻出フレーズ抽出
    1. Elasticsearch
    から直近2
    時間分の note
    を取得する。
    2. SimHash [1] (
    実装は https://crates.io/crates/simhash)
    を用いて note
    間の類似性を
    計算し、類似度の高い note
    は 1
    つを残して削除する。
    3. Sudachi
    で形態素に分解する。
    4. PrefixSpan [2] (
    自前実装)
    を用いて、頻出フレーズを求める。
    [1] Charikar, Moses S. "Similarity estimation techniques from rounding algorithms."
    Proceedings of the thiry-fourth annual ACM symposium on Theory of computing. 2002.
    [2] Han, Jiawei, et al. "Prefixspan: Mining sequential patterns efficiently by prefix-
    projected pattern growth." Proceedings of the 17th international conference on data
    engineering. IEEE, 2001.

    View Slide

  11. Analyzer 2/2 --
    スコア計算
    5.
    頻出フレーズの正規化(大文字小文字、NFKC
    )を行い、その結果が同一になるフ
    レーズ群の出現をまとめる。出現頻度が最大の表記を代表として採用する。
    6.
    あるフレーズについて、同一 pubkey
    で複数の言及が有る場合は、最新の note

    代表させる。
    7.
    解析開始時刻とフレーズの出現時刻の差をみて、直近の出現が高い重みを持つよ
    うに重み付けする(ついでに解析窓の過去側の端がなめらかになるようにす
    る)。
    8. Elasticsearch
    に問い合わせて、過去のフレーズの出現数を求め、直近の出現が多
    く、過去の出現が少ないフレーズに高いスコアを与える。
    9.
    解析結果を relay
    に送信する。

    View Slide

  12. Nostr
    的おもしろポイント
    NIP-33
    をつかった解析結果の受け渡し
    https://github.com/nostr-protocol/nips/blob/master/33.md

    View Slide

  13. 具体例
    解析結果を JSON
    で content
    に入れます。
    kind
    は 38225
    で buzz-phrases:jp
    というタグをつけています。
    自前のリレーに送っています。
    ❯ echo '["REQ", "_", {"kinds": [38225] }]' | nostcat --stream wss://example.com | jq .
    [
    "EVENT",
    "_",
    {
    "content": "{\"phrases\":[{\"text\":\"bluesky
    といえば\"},
    ...
    中略...
    ,{\"text\":\"Windows100\"}],\"created_at\":\"2023-02-26T08:36:14.559572950+00:00\",\"language\":\"ja\"}",
    "created_at": 1677400574,
    "id": "789cdedc73c7472428c40a39ada18177fa44a1996c30783f0ec0b194ca676cb8",
    "kind": 38225,
    "pubkey": "fe295340106bb7b8f5b08f8b7c22000862abc9731dbb86f2f141301e13b4d024",
    "sig": "f5c6aaf310cd0b6c631bdaf1f909563b1ebf7f45c5db8cced25ab3fced93fba6d8337a03277f23e2e58a1e7aaf1c94cf9996daa58d97a6e80bbde64829fda4f9",
    "tags": [
    [
    "d",
    "buzz-phrases:ja"
    ]
    ]
    }
    ]

    View Slide

  14. この構成のいいところ
    ブラウザに解析結果を返すための API
    サーバが不要です。
    この API
    サーバでは、
    新たにつなぎに来たブラウザには、キャッシュしてある最新の結果を即時で返す
    Analyzer
    から新たな結果が来たら、接続中のブラウザ全部に通知する
    という処理が必要です。単純だけど、ストレージが必要だったりしてちょっと面倒。
    (初期バージョンはそういう実装になっていました)
    これが NIP-33
    で解決します。

    View Slide

  15. NIP-33: Parameterized Replaceable Events
    「kind, pubkey, d
    タグが同じイベントが来たら、古いイベントを置き換える」
    要するに、 Relay
    は最新の 1
    件だけ保持して返してくれる。
    めっちゃ便利。
    しかも複数のリレーに publish
    するだけで冗長構成を取れます。

    View Slide

  16. 応用例
    誰でもバズフレーズを受け取って表示するサイトを作れます。
    予告なく仕様が変わるかもしれませんが...
    もし、誰かが別の解析エンジンを実装したとして、それが同じプロトコルを実装
    していれば、ユーザは切り替えて使用できるかもしれません。
    たとえば pubkey
    で区別できます。
    何を以て「トレンド」とするか。誰でもトレンドを発信できる。
    人と人のコミュニケーションするためのイベントが主流だけど、Nostr
    を介してサービ
    スとサービスがやりとりする世界観のも面白いのでは。

    View Slide

  17. 専用リレーの運用
    nostr-rs-relay
    を使うとすぐできる。 config.toml
    の [authorization]
    セクショ
    ンの pubkey_whitelist
    に Analyzer
    の pubkey
    を追加するだけ。
    自サービス専用だと思うと気が楽
    吊るしで使えるリアルタイム API
    サーバー

    View Slide

  18. まとめ
    Nostr
    の buzz
    を解析して、表示するサービス nostrbuzzs
    をつくりました。
    Relay
    を活用することで、 Nostr
    っぽいアーキテクチャでつくりました。

    View Slide