- hn.unlurker.com を作りながら書いた HN APIクライアント に、全 item を順番に取得する
scan 機能を追加し、Hacker News の全データをローカルにダウンロード
hn scan --no-cache --asc -c- -o full.json の実行中にダウンロードが何度か止まったが、再開可能な scan のおかげで数時間後に 20 GiB の JSON ファイルを確保
- DuckDB の
read_json_auto で JSON をテーブル化したあと、text ILIKE と 12週移動平均 の SQL で Python、JavaScript、Java、Ruby、Rust の言及比率を集計
- 単純な
grep だけでも “correct horse battery staple” という文句が Hacker News に 231回 登場したことを確認でき、DuckDB はこの規模の単発分析にとても向いていそう
- ローカルに全データができると Hacker News の過去コンテンツをさまざまな方法で分析できるが、このプロジェクトはここで区切りとし、次の段階は別の誰かが引き継ぐ余地として残される
Hacker News の全 item をダウンロード
- hn.unlurker.com を作るために HN APIクライアント を作成
- すでに複数のクライアントはあったが、新しいプロジェクトで最新の Go の機能 とリンターを試してみたかった
- HN API ではコメントとストーリーは item と呼ばれる
- クライアントはアクティブな item や item の一覧などを取得できる
- 実際のプロジェクトでは最近の item だけあれば足りたが、完成度のために
scan 機能を追加
scan は item を 0 から最新まで、または逆方向に順番にダウンロードする
- 全件ダウンロードは数万 GiB ではなく、数十 GiB の JSON 程度だろうと見込んで試した
hn scan --no-cache --asc -c- -o full.json
- ダウンロードが何度か止まり
CTRL-C で中断したが、scan は 再開可能 なので数時間後に完了
- 成果物は Hacker News で発生したあらゆる内容を含む 20 GiB の JSON ファイル
- 同じコマンドをもう一度実行すれば、最新データで再び埋められる
DuckDB でローカルデータを分析する
- 最初は単純に
grep で検索した
- その後 DuckDB で分析を試した
- DuckDB は埋め込み可能で高速な 分析実行エンジン であり、コマンドラインツールとしても提供される
- 新しい UI のおかげで初心者でも使いやすく、LLM が SQL クエリ作成の助けになった
- JSON データは DuckDB で次のように取り込む
CREATE TABLE items AS
SELECT *
FROM read_json_auto('/home/jason/full.json', format='nd', sample_size=-1);
- 例のクエリでは item を週単位でまとめ、全 item のうち特定の単語を含む比率を計算する
python、javascript、java、ruby、rust を text ILIKE で検索
- 各比率について 12週移動平均 を計算
- 同じ方法でデータベース関連の単語も可視化した
- 例のグラフには
mysql、postgres、mongo、redis、sqlite の 12週移動平均の言及比率が含まれる
- DuckDB はこの程度の規模のデータセットを分析するのにとても良さそうだった
- Hacker News の全コンテンツのローカルコピーを手に入れたが、プロジェクトはここで終わりにすることにした
1件のコメント
Hacker Newsのコメント
まずダウンロードしなくても分析を実行できる、更新済みの Hacker News テーブルを持つデータベースを2つ知っている
BigQuery は Google Cloud アカウントが必要で、クエリはおそらく無料枠で実行可能、
bigquery-public-data.hacker_news.fullを使えばよいClickHouse は登録不要で、ブラウザからすぐにクエリを実行できる: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...
clickhouseさえ見つけられる: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...ClickHouse の HN データベースを知る前に、すでに全 JSON をダウンロードする作業を自分でやってみたことがあった
以前、@fesshole の Twitter/Bluesky アカウントで似たようなことをやったことがある。アーカイブ全体をダウンロードしてモデルをファインチューニングし、さらに狂った告白を生成させた
かなり誇らしく思っていたが、結局は無垢な機械に 自慰と離婚 を教えただけだと気づいた
SF映画で、エイリアンや超知能 AI が人類の歴史を超高速で見て、私たちには救う価値がないと判断する場面みたいだった
そのデータに 外部世界との接続 がまったくないなら、その USB メモリに自慰と離婚に関するデータが入っていると、人間やモデルはどうやって分かるのだろう?
どちらも全体としては前向きなものだと思うし、こうしたことが普通になっている社会に生きられることに感謝している
Java のクエリには JavaScript のすべての事例も含まれるので、Java が過大に集計される
trust、antitrust、frustrationのような単語を大量に含んでしまうHacker Newsで起きたあらゆる出来事を収めた20GiBのJSONファイルがあったというのは、テキストしかないサイトだと考えると意外に大きい
HNが存在した18年間で、人々が200億バイトを超えるテキストを投稿したということか? 平均すると1日2MB超、毎秒約7.5KBになる
しかもそのかなりの量は人間ではないはず。
/newestはボットスパムだらけだJSONのメタデータや構文まで含まれているので、実際のテキスト量はそれよりさらに少ないはず。「1日2MB超」という計算は合っていた
[0] 実際の計算はChatGPTがやったけれど、正しそうではある: https://chatgpt.com/share/68124afc-c914-800b-8647-74e7dc4f21...
その多くはゴミだが、特により賢いボットが登場した2018〜2019年以前の初期データは見る価値がありそうだ
HNはFacebook以前の基準ではかなり大きなソーシャルネットワークだったはずで、規模がほどよく、活発に管理されていたおかげで価値も高い
2019年にGoogle+が終了したとき、そのサイトに投稿されたテキストデータがどれくらいあるのかモデル化してみたことがある
ここでいうテキストデータとは、画像・音声・動画のようなメディアや、HTMLの骨格、CSS、JSのような付随するページ要素を除いたものだ
参加率が非常に低く、投稿の平均が約120文字だったことを考えると、数千万のアクティブアカウントの7年分の記録でも数GiBにすぎなかった。登録プロフィールは40億件を超えていたが、実際の活動ははるかに少なかった
Archive TeamはInternet Archiveと協力しているが別組織としてGoogle+保存作業を行い、その成果は複雑だった。多くのコンテンツは保存されたが、さらに多くが失われ、コメントはほとんど残らず、スレッドは直近10件ほどで切られ、検索もなかったため概して使い物にならなかった。ランダムなハッシュではなく選んだアカウント名を使う「vanity accounts」はアクセス性がさらに悪かった
しかもページ全体をスクレイピングして、オンラインで見えていた形を再現しようとしていたため、保存要件は大幅に増える一方で、実際にそのサイトを面白くしていた要素は多く取りこぼしていた
大規模な人口集団のテキスト投稿を保存しようとする場合でも、保存要件はかなり控えめだ。たとえば1日の平均オンライン時間が45分、タイピング速度が45wpm、オンライン時間の半分だけが読むのではなく書く時間だとしても、1人あたり1日約1,000語、つまり約6KiBになる。1,000人あたり6MiB、100万人あたり6GiB、10億人あたり6PiBほどだ
実際の値はほぼ確実にもっと低い。書く時間は過大評価されていて、実際には10%に近いだろうし、モバイル入力速度も20〜30wpm程度の可能性が高い。たとえばFacebookには1日あたり約24.5億個の「コンテンツ片」が投稿され、その半分は動画だ。1投稿120文字と見積もれば、テキストデータは1日300GiBを大きく下回る、意外なほど小さい量になる
現在のデータ収集と監視資本主義システムの大半は、位置情報、動画、オンライン相互作用、商取引のような、人が直接入力していないデータが占めている
HNをダウンロードするときのネチケットは何だろう? サーバーに負荷をかける前にdangに先に聞くべきだろうか?
それとも、もう何十億ドル規模のテック企業が何度もやっているだろうから、目立ちもしないと考えていいのか?
https://console.cloud.google.com/marketplace/product/y-combi...
似たようなことをやったことがある。BigQueryデータセットを使うという抜け道を使ったのだが、なぜか継続的に更新されていて、データをParquetにエクスポートしてからダウンロードし、DuckDBでクエリした
「これで Hacker News の全コンテンツをローカルにダウンロードできたので、何百もの LLM ベースのボットを訓練して投稿者として回し、過去を永遠に反響・再利用する中国語の部屋の振動子の出力で、あらゆる人間のテキストをゆっくりと、しかし必然的に置き換えられる」という冗談ではあるが、いつか誰かが試しそうで怖い。
そうならないことを願うが、もし起きたら止められるだろうか?
解決すべき問題は多く、プライバシーもその一つだ。つながりそのものをユーザーに公開する必要はないが、素朴な実装ではサーバーには残ってしまう。
不信の経路を負の重みとして加えることもできる。直接または間接に誰かを信用しないなら、私とその人を結ぶ信頼の連鎖の値が下がる、という形だ。
ネットワークなので、システムを操作しようとする試みに対して自己調整できる可能性はあるが、どれほど堅牢かは依然として未知数だ。
長くて中身のあるコメントならたいてい見分けられるが、1〜2年前よりはるかに難しくなっている。短い1、2文のコメントなら、LLM はもう人間として通るのに十分なくらいうまくなったと思う。
一方で HN のコメントの多くは、平均的で大衆的な考えから外れた、かなりユニークな洞察だ。これを LLM に真似させようとすると、たわごとしか出てこないだろう。
そのたわごとに、筋が通ってもっともらしい返答だけを通すフィルターを付ければ、答えは退屈になり、それでもなおたわごとに近いままだ。
答えを正確かつ精密で、しかもユニークなものにするには、LLM ではない何かを使う必要がある。
サイトのカルマや速度に関するヒューリスティクスは、派手な機械学習に比べれば粗いが、コミュニティが Reddit や Twitter より小さく、運営が直接介入するので機能している。
LLM の偽アカウントの群れが人間のテキストを「置き換える」には、人々が本当に面白いと感じる投稿を出し続けなければならない。そうでなければ、そのはるか前に制限されるか、静かに排除されるだろう。
AI アカウントをいくつか生かしておくだけでも限界費用は高い。24時間、新しいスレッド数十本に推論を回すのは無料ではないし、出力がありふれた SEO ゴミに滑り落ちないよう維持するのも驚くほど難しい。
しかも収益は実質的にない。HN のトラフィックは現金化できず、カルマはボット運用者にとってはひどい通貨だ。
資源を持つ執拗な悪意ある行為者を止められるかといえば、おそらく可能だろうが、対策は今と同じになるだろう。強いレート制限、新規アカウント上限の強化、人間のモデレーターによる審査、そして場合によっては文体分析といったところだ。
正当な新規ユーザーには鬱陶しいだろうが、致命的ではない。結局のところ HN は、ここにいる人間がほかの人間の書いたものを読みたいから生き残っている。コメントが確率的オウムのように聞こえ始めたら、読者は無視するか通報するだろうし、ボット同士で会話するだけになるだろう。
GPT-3o が作成
「Metal Gear Solid 2 における Hideo Kojima の野心的な脚本は、ポストモダン・ビデオゲームの最初の事例として評価されることもあり、ポスト真実政治、フェイクニュース、エコーチェンバー、オルタナティブ・ファクトといった概念を予見していたとも評されている」
[0] https://en.wikipedia.org/wiki/Metal_Gear
[1] https://en.wikipedia.org/wiki/Dead_Internet_theory
今後数年のうちに、多くの API が単に DuckDB ファイルを返すオプションを提供し始める気がする。
どうせ JSON をデータベースにロードするのなら、レスポンスとしてデータベースを受け取れない理由はない。
積み上げチャートは使わないでほしい。読者の印象を歪めずに済ませるのがほとんど不可能だと思う。
特定のデータ点の高さをノイズの中から見積もるのが非常に難しく、たぶん存在しない依存関係を示唆してしまうからだ。
次は、地域ごとに1系列だけを含む複数の折れ線グラフを並べて積むやり方を考えている。
https://flowimmersive.com/ の取り組みを見ればよい。
[1]: https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PUBNOTES/ATL-...
以前これを1つ作ったことがあり、https://github.com/ashish01/hn-data-dumps、かなり面白かった
実装するとしたら格好いい機能は、最近の項目ほど時間の経過とともにより頻繁に更新されるので、最近ダウンロードした項目のほうが古い項目よりも早く古いキャッシュになる点を反映すること
私は古さを判断するのに経過時間ベースの関数を使っていた。最初は作成後1〜2分で古いとみなし、数日間は頻繁に更新し、その後は最初の1週間を過ぎると急速に頻度を下げて、約2週間後には不変として扱う
// DefaultStaleIf marks stale at 60 seconds after creation, then frequently for the first few days after an item is// created, then quickly tapers after the first week to never again mark stale items more than a few weeks old.const DefaultStaleIf = "(:now-refreshed)>" +"(60.0*(log2(max(0.0,((:now-Time)/60.0))+1.0)+pow(((:now-Time)/(24.0*60.0*60.0)),3)))"https://github.com/jasonthorsness/unlurker/blob/main/hn/core...