ASMR Vector Browser

asmr_works.jsonl からベクトル検索データを生成し、近い雰囲気のASMR作品を閲覧するWebUIです。

データ生成

依存なしで動くローカルハッシュベクトルを生成します。

uv run python scripts/build_vector_data.py --input asmr_works.jsonl --output-dir web/data

意味ベクトルで生成したい場合は semantic extra を有効にして実行します。

uv run --extra semantic python scripts/build_vector_data.py --method sentence-transformers --model intfloat/multilingual-e5-small

intfloat/multilingual-e5-small を使う場合は、生成スクリプト側で自動的に passage: prefix を付けます。

OpenAI互換のリモート埋め込みAPIで生成する場合:

uv run --extra remote python scripts/build_vector_data_remote.py

APIキーが必要な場合は EMBEDDING_API_KEY に設定します。

OpenAI互換APIで生成する場合:

EMBEDDING_API_KEY="..." uv run python scripts/build_vector_data_remote.py \
  --input asmr_works.jsonl \
  --output-dir web/data \
  --base-url https://reasonable-consensus-reproduce-cute.trycloudflare.com \
  --model text-embedding-qwen3-embedding-8b \
  --batch-size 32 \
  --concurrency 10

認証不要のAPIなら EMBEDDING_API_KEY は省略できます。小件数で試す場合は --limit 10 を付けます。 APIキーはコードに書かず、環境変数で渡してください。 --concurrency は同時リクエスト数です。API側が重い場合は 2 から 4 程度に下げてください。 remote生成では、通信切断やレスポンス途中切れが起きたbatchをデフォルトで成功するまで再試行します。止めたい場合は Ctrl+C、有限回で諦めたい場合は --no-retry-forever --retries 3 を指定します。

日次データ更新

最新順APIから新規作品だけを取得し、ローカルJSONL、フィルタ済みJSONL、web/data を更新します。

uv run python scripts/update_daily_asmr_data.py

web/data は manifest.json の remote-openai-compatible 設定を引き継ぎます。既存作品のembeddingは再利用し、新規または検索テキストが変わった作品だけembedding APIへ送ります。

ファイルを書かずに確認する場合:

uv run python scripts/update_daily_asmr_data.py --dry-run

dry-runでは新規作品、既存作品の更新、フィルタ差分、embedding APIへ送る作品と理由を表示します。各セクションの表示件数を変える場合:

uv run python scripts/update_daily_asmr_data.py --dry-run --diff-limit 100

全件表示する場合は --diff-limit 0 を使います。

新規作品がなくてもフィルタと web/data を作り直す場合は --force を付けます。

pull後のベクトル差分更新

Actions が更新した asmr_works.jsonl / asmr_works.filtered.jsonl を pull した後、ローカルの web/data だけを差分更新します。

git pull --rebase --autostash
uv run --extra remote python scripts/update_pulled_vector_data.py

このスクリプトは asmr_works.filtered.jsonl と web/data/works.json を比較し、既存作品のembeddingは web/data/embeddings.f32 からコピーして再利用します。新規作品、またはタイトル・タグ・声優が変わった作品だけembedding APIへ送ります。

ファイルを書かずに確認する場合:

uv run --extra remote python scripts/update_pulled_vector_data.py --dry-run

APIキーが必要な場合は EMBEDDING_API_KEY に設定します。接続先やモデルは web/data/manifest.json の remote-openai-compatible 設定を使います。

翻訳重複の修復

日本語原作と翻訳版が両方 asmr_works.filtered.jsonl / web/data に入ってしまった場合は、自動検出して翻訳版だけ除外できます。

uv run python scripts/prune_duplicate_works.py --dry-run

問題なければ実更新します。

uv run python scripts/prune_duplicate_works.py

このスクリプトは asmr_works.jsonl には触らず、asmr_works.filtered.jsonl、web/data/works.json、web/data/embeddings.f32、web/data/manifest.json を更新します。embeddings.f32 は既存ベクトルをコピーして再構築するため、embedding APIには送信しません。

WebUI起動

WebUIはAstroで動きます。初回は依存関係を入れます。

cd web
npm install

APIなしで静的UIだけ開発サーバーを起動する場合:

cd web
npm run dev

ブラウザで http://127.0.0.1:4321 を開きます。

ビルドする場合:

cd web
npm run build

サーバー計算つきで起動

ローカルの sentence-transformers で生成した web/data を検索する場合:

cd web && npm run build && cd ..
uv run --extra semantic python scripts/search_server.py

リモート埋め込みAPIで生成した web/data を検索する場合:

cd web && npm run build && cd ..
uv run --extra remote python scripts/search_server.py

APIキーが必要な場合:

EMBEDDING_API_KEY=xxx uv run --extra remote python scripts/search_server.py

このサーバーは起動時に web/data/works.json と web/data/embeddings.f32 を読み込みます。ブラウザはこれらのファイルを直接読み込まず、作品一覧は /api/works、作品詳細は /api/work、自然文検索は /api/search、作品ページのMyDNAは /api/similar から取得します。

リモート検索では web/data/manifest.json の baseUrl と model を使って、検索文を同じOpenAI互換APIへ送ります。必要なら起動時に上書きできます。

uv run --extra remote python scripts/search_server.py --remote-base-url https://example.com --remote-query-prefix "query: "

ブラウザで http://127.0.0.1:8000 を開くと、トップページには最近追加されたASMRが表示されます。検索欄に自然文を入れて「自然文検索」を押します。 検索結果の作品を開くと /work/?id=RJxxxx で作品ページに移動し、MyDNAとして近い作品を表示します。

例:

低音のお姉さんに囁かれながら寝落ちしたい
甘やかしてくれる耳かきで落ち着く作品
雨音と添い寝っぽい雰囲気

intfloat/multilingual-e5-small を使う場合、検索文にはサーバー側で自動的に query: prefix を付けます。リモート検索ではデフォルトでprefixを付けません。

推薦スコアは 0.8 * ベクトル類似度 + 0.2 * タグ一致 です。サークル・尺・年齢区分・NSFWは好みスコアには入れず、表示またはフィルタとして扱います。

S
Description
No description provided
Readme
757 MiB
Languages
Python 80.9%
JavaScript 11.2%
CSS 5.3%
Astro 2.6%