Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
nostrbuzzsのしくみ
Search
Yoji Shidara
March 10, 2023
Technology
620
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
nostrbuzzsのしくみ
Yoji Shidara
March 10, 2023
More Decks by Yoji Shidara
See All by Yoji Shidara
Searchnos & Search on Nostr
dara
0
350
searchnos について
dara
0
470
How nostrbuzzs works
dara
0
170
About searchnos
dara
0
160
HOME, GOPATH and me
dara
3
1.7k
The First Step for Building Groonga Bindings with Golang
dara
6
1.5k
まほうのひととき - The Magic Hour
dara
7
990
JDK CHRONICLE
dara
2
8.9k
Timelapse Introduction
dara
1
700
Other Decks in Technology
See All in Technology
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
19k
タクシーアプリ『GO』の実践的データ活用〜位置情報データの収集とStreamlitでの可視化〜
mot_techtalk
2
200
データ組織の転換期 一足飛びしない段階的戦略
leveragestech
PRO
0
150
第3回しろおびセキュリティスポンサーセッション
log0417
0
140
クラウドセキュリティ入門 ~安全なクラウド利用のための基礎知識~
lhazy
8
7.6k
20260608_Codexの可能性_ノンプログラマー向け_大城追記
doradora09
PRO
0
760
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
24k
モノリス Rails でも日中に rails db:migrate を走らせたい! / Daytime rails db:migrate on Monolithic Rails!
euglena1215
3
400
ガバメントクラウドでのランサムウェア対策
techniczna
1
760
LangfuseによるLLMOps基盤の構築と活用事例
zozotech
PRO
1
280
Issue設計から始める仕様駆動開発 / 20260731 Mizuki Hirata
shift_evolve
PRO
1
130
Webアクセシビリティ入門 2026
recruitengineers
PRO
1
260
Featured
See All Featured
Color Theory Basics | Prateek | Gurzu
gurzu
0
410
The agentic SEO stack - context over prompts
schlessera
0
860
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
920
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Designing for Performance
lara
611
70k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Tell your own story through comics
letsgokoyo
1
1k
Chasing Engaging Ingredients in Design
codingconduct
0
260
How to Ace a Technical Interview
jacobian
281
24k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Rails Girls Zürich Keynote
gr2m
96
14k
Transcript
nostrbuzzs のしくみ npub1q7qyk7rvdga5qzmmyrvmlj29qd0n45snmfuhkrzsj4rk0sm4c4psvqwt9c 2023-03-10 Nostr 勉強会 #1
@darashi Twitter のイマを切り取るサービス buzztter.com ( 運用終了) の作者です。 nostr の イマを切り取るサービス
nostrbuzzs をつくりました。 (NEW! Nostr 村放送局をつくりました。)
nostrbuzzs https://nostrbuzzs.deno.dev/
全体の構成 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
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 をつかっています。
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 でインデックスします。
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) で送ります。
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 に置いてありますが、静的な サイトです。
Analyzer の処理について、もうすこし詳しく
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.
Analyzer 2/2 -- スコア計算 5. 頻出フレーズの正規化(大文字小文字、NFKC )を行い、その結果が同一になるフ レーズ群の出現をまとめる。出現頻度が最大の表記を代表として採用する。 6. あるフレーズについて、同一
pubkey で複数の言及が有る場合は、最新の note に 代表させる。 7. 解析開始時刻とフレーズの出現時刻の差をみて、直近の出現が高い重みを持つよ うに重み付けする(ついでに解析窓の過去側の端がなめらかになるようにす る)。 8. Elasticsearch に問い合わせて、過去のフレーズの出現数を求め、直近の出現が多 く、過去の出現が少ないフレーズに高いスコアを与える。 9. 解析結果を relay に送信する。
Nostr 的おもしろポイント NIP-33 をつかった解析結果の受け渡し https://github.com/nostr-protocol/nips/blob/master/33.md
具体例 解析結果を 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" ] ] } ]
この構成のいいところ ブラウザに解析結果を返すための API サーバが不要です。 この API サーバでは、 新たにつなぎに来たブラウザには、キャッシュしてある最新の結果を即時で返す Analyzer から新たな結果が来たら、接続中のブラウザ全部に通知する
という処理が必要です。単純だけど、ストレージが必要だったりしてちょっと面倒。 (初期バージョンはそういう実装になっていました) これが NIP-33 で解決します。
NIP-33: Parameterized Replaceable Events 「kind, pubkey, d タグが同じイベントが来たら、古いイベントを置き換える」 要するに、 Relay
は最新の 1 件だけ保持して返してくれる。 めっちゃ便利。 しかも複数のリレーに publish するだけで冗長構成を取れます。
応用例 誰でもバズフレーズを受け取って表示するサイトを作れます。 予告なく仕様が変わるかもしれませんが... もし、誰かが別の解析エンジンを実装したとして、それが同じプロトコルを実装 していれば、ユーザは切り替えて使用できるかもしれません。 たとえば pubkey で区別できます。 何を以て「トレンド」とするか。誰でもトレンドを発信できる。 人と人のコミュニケーションするためのイベントが主流だけど、Nostr
を介してサービ スとサービスがやりとりする世界観のも面白いのでは。
専用リレーの運用 nostr-rs-relay を使うとすぐできる。 config.toml の [authorization] セクショ ンの pubkey_whitelist に
Analyzer の pubkey を追加するだけ。 自サービス専用だと思うと気が楽 吊るしで使えるリアルタイム API サーバー
まとめ Nostr の buzz を解析して、表示するサービス nostrbuzzs をつくりました。 Relay を活用することで、 Nostr
っぽいアーキテクチャでつくりました。