ろんJ 実況~論文をなんJ風に解説&実況~

自然言語処理

論文は難しそうで読むのが億劫だと感じたことはありませんか?でもそんな人でも、「ろんJ」を使えば論文の内容が面白おかしく理解できるかもしれません。

「ろんJ」は、アップロードした論文の内容を、あの有名な2ちゃんねるの「なんでも実況J」(通称:なんJ)のスレッド風に解説・実況してくれる画期的なサービスです。難解な論文の内容を、親しみやすいなんJのノリで楽しく理解することができます。


こちらの記事もおすすめ

ろんJ (V1.4)~論文をなんJ風に解説!専門家と初心者の活発な議論が面白い~
論文は難しそうで読むのが億劫...。でもそんな人でも、「ろんJ GPTs」を使えば論文の内容が面白おかしく理解できるかもしれません。「ろんJ GPTs」は、アップロードした論文の内容を、あの有名な2ちゃんねるの「なんでも実況J」(通称:なん...
Claudeを使用してなんJのスレを作成してみた
最近話題のAIチャットボット「Claude」を使って、なんJ風の架空のスレッドを自動生成してみました。Claudeの高度な言語理解と文脈把握能力により、各キャラクターの口調や性格を見事に再現できていると思います。のんのんびよりのキャラクター...

特徴

  • 論文の内容をなんJスレッド風に自動解説
  • 音声合成による臨場感あふれる実況
  • シンプルで直感的なユーザーインターフェース
  • Dockerを使用した簡単なセットアップ

セットアップ

ろんJを使用するには、まずこのリポジトリをクローンし、Dockerコンテナを起動します。以下の手順に従ってセットアップを行ってください。

リポジトリのクローン

ターミナルを開き、以下のコマンドを実行してリポジトリをクローンします。

git clone https://github.com/Sunwood-ai-labs/RonJ.git
cd ronj

Dockerコンテナの起動

クローンしたリポジトリのディレクトリ内で、以下のコマンドを実行してDockerコンテナを起動します。

docker-compose up -d

このコマンドにより、以下のサービスが起動します。

  • style-bert-vits2-api: Style-Bert-VITS2モデルのAPIサーバー
  • ron-j: ろんJのStreamlitアプリケーション

アプリケーションへのアクセス

セットアップが完了したら、ブラウザで http://localhost:8502/ にアクセスしてください。ろんJのStreamlitアプリケーションが表示されます。

使い方

ろんJを使用するには、以下の手順に従ってください。

JSONファイルの準備

なんJ風に解説したスレッドの情報をJSONファイルで準備します。JSONファイルのフォーマットは以下の通りです。

[
  {
    "name": "風吹けば名無し",
    "text": "論文の内容を面白おかしく解説するで!",
    "number": "1",
    "header": "1番セカンド",
    "replies": []
  },
  {
    "name": "風吹けば名無し",
    "text": "著者らは新しい手法を提案しとるな。画期的やと思うで!",
    "number": "2",
    "header": "2番セカンド",
    "replies": [">>1"]
  }
]

ろんJのwebページにアクセス

ブラウザで http://localhost:8502/ にアクセスし、ろんJのwebページを開きます。

設定の入力

Streamlitのサイドバーで、以下の情報を入力します。

  • JSONファイルのパス
  • 絵文字のテキストファイルのパス(デフォルト: assets/emojis.txt
  • 音声生成のAPIエンドポイント(デフォルト: http://style-bert-vits2-api:5000/voice

実況の開始

「再生」ボタンをクリックすると、style-bert-vits2によるなんJスレッド風の実況が始まります。

論文の理解

実況を楽しみながら、論文の内容を理解していきましょう!

style-bert-vits2 APIの動作確認

style-bert-vits2 APIのデモを実行するには、以下のコマンドを実行してください。

docker-compose exec ron-j python demo/demo_style_bert_api.py

ろんJのDocker部分の解説

ろんJをDockerで実行するための docker-compose.yml ファイルと Dockerfile が用意されています。以下の手順に従ってDockerコンテナを起動し、ろんJを使用することができます。

前提条件

  • Dockerがインストールされていること
  • docker-composeがインストールされていること

使用方法

Dockerコンテナの起動

docker-compose.yml ファイルがあるディレクトリ内で、以下のコマンドを実行してDockerコンテナを起動します。

docker-compose up -d

このコマンドにより、以下のサービスが起動します。

  • style-bert-vits2-api: Style-Bert-VITS2モデルのAPIサーバー
  • ron-j: ろんJのStreamlitアプリケーション

ろんJの使用

コンテナが正常に起動したら、以下のURLにアクセスしてろんJを使用できます。

  • ろんJ: http://localhost:8502/
  • Style-Bert-VITS2 API: http://localhost:5000/

Dockerコンテナの停止

ろんJの使用が終了したら、以下のコマンドでDockerコンテナを停止します。

docker-compose down

設定

docker-compose.yml ファイルには、各サービスの設定が記載されています。

  • style-bert-vits2-api サービスは、Style-Bert-VITS2モデルのAPIサーバーを起動します。
  • ron-j サービスは、ろんJのStreamlitアプリケーションを起動します。

Dockerfile には、ろんJのStreamlitアプリケーションを実行するためのDockerイメージの構成が記載されています。必要なPythonパッケージのインストールなどが行われます。

ボリュームのマウント

docker-compose.yml ファイルでは、ホストマシンのディレクトリをコンテナ内にマウントしています。

  • ./Style-Bert-VITS2 ディレクトリは、Style-Bert-VITS2モデルの関連ファイルを格納するために使用されます。
  • ./ ディレクトリは、ろんJのアプリケーションファイルを格納するために使用されます。
  • ./.cache ディレクトリは、キャッシュファイルを格納するために使用されます。
  • ./.streamlit ディレクトリは、Streamlitの設定ファイルを格納するために使用されます。

注意事項

  • .env ファイルには、必要な環境変数を設定してください。
  • コンテナを起動する前に、必要なディレクトリとファイルが存在することを確認してください。

ろんJ Streamlitアプリケーション部分の解説

app.py は、ろんJのメインアプリケーションを構成するStreamlitアプリケーションです。論文の内容をなんJスレッド風に解説・実況するための機能を提供します。

インポートと設定

まず、必要なライブラリをインポートし、Streamlitアプリケーションの基本設定を行います。

import streamlit as st
import json
import time
import streamlit.components.v1 as components
import random
from modules.tts_module import TextToSpeech
import base64
import os
from pydub import AudioSegment
import re

st.set_page_config(
    page_title="RonJ",
    page_icon="📚",
    initial_sidebar_state="expanded",
    menu_items={
        'Get Help': 'https://github.com/Sunwood-ai-labs/RonJ.git',
        'About': "RonJ~論文を面白おかしく理解するツール~"
    }
)

ここでは、Streamlitの基本設定として、ページタイトル、アイコン、サイドバーの初期状態、ヘルプリンクとアプリケーションの説明を設定しています。

サイドバーの設定

次に、Streamlitのサイドバーを使用して、アプリケーションのパラメータを設定します。

with st.sidebar:
    st.markdown("""
<p align="center">
    <h1 align="center">Ron J</h1>
    <img src="https://raw.githubusercontent.com/Sunwood-ai-labs/RonJ/main/docs/icon_mini.png" width="100%">
    <br>
</p>

    """, unsafe_allow_html=True)

json_file_path = st.sidebar.text_input("JSONファイルのパス", "data/ViTAR_KANA.json")
emoji_file_path = st.sidebar.text_input("絵文字のテキストファイルのパス", "assets/emojis.txt")
api_url = st.sidebar.text_input("音声生成のAPIエンドポイント", "http://style-bert-vits2-api:5000/voice")

サイドバーには、アプリケーションのロゴと説明を表示し、JSONファイルのパス、絵文字のテキストファイルのパス、音声生成のAPIエンドポイントを入力するためのテキストボックスを配置しています。

音声合成の設定

TextToSpeechクラスを使用して、音声合成のインスタンスを作成します。

tts = TextToSpeech(api_url=api_url)

データの読み込み

チャットデータの読み込み

load_chat_data関数を使用して、指定されたJSONファイルからチャットデータを読み込みます。

def load_chat_data(json_file_path):
    """チャットデータをJSONファイルから読み込む"""
    try:
        with open(json_file_path, "r") as f:
            chat_data = json.load(f)
        return chat_data
    except FileNotFoundError:
        st.error(f"JSONファイルが見つかりません: {json_file_path}")
        return []

絵文字データの読み込み

load_emojis関数を使用して、指定されたテキストファイルから絵文字のリストを読み込みます。

def load_emojis(emoji_file_path):
    """絵文字のリストをテキストファイルから読み込む"""
    try:
        with open(emoji_file_path, "r", encoding="utf-8") as f:
            emojis = [line.strip() for line in f]
        return emojis
    except FileNotFoundError:
        st.warning(f"絵文字のテキストファイルが見つかりません: {emoji_file_path}")
        return []

マッピングの生成

名前と絵文字のマッピング

generate_name_emoji_map関数を使用して、登場人物の名前と絵文字のマッピングを生成します。

def generate_name_emoji_map(chat_data, emojis):
    """名前と絵文字のマッピングを生成する"""
    unique_names = list(set([message["name"] for message in chat_data]))
    name_emoji_map = {name: random.choice(emojis) for name in unique_names}
    return name_emoji_map

名前と音声IDのマッピング

generate_name_voice_map関数を使用して、登場人物の名前と音声IDのマッピングを生成します。

def generate_name_voice_map(chat_data):
    """名前と音声IDのマッピングを生成する"""
    unique_names = list(set([message["name"] for message in chat_data]))
    name_voice_map = {name: random.randrange(0, 7, 1) for name in unique_names}
    return name_voice_map

チャットの表示

display_chat関数を使用して、チャットを表示します。

def display_chat(chat_data, name_emoji_map, name_voice_map):
    """チャットを表示する"""
    chat_container = st.container()

    # JavaScriptコードを1回だけ実行
    components.html(
        """
        <script>
            window.onload = function() {
                setInterval(function() {
                    window.parent.document.querySelector('section.main').scrollTo(0, window.parent.document.querySelector('section.main').scrollHeight);
                }, 100);
            };
        </script>
        """,
        height=0
    )

    # チャットの表示
    for message in chat_data:
        name = message["name"]
        text = message["text"]
        number = message["number"]
        header = message["header"]

        # 名前に応じた絵文字を取得
        emoji = name_emoji_map.get(name, "👤")

        # チャットコンテナにメッセージを追加
        with chat_container:
            # メッセージの表示
            with st.chat_message("user", avatar=emoji):
                st.markdown(f"**{header}**")

                # 返信先の処理
                if message["replies"]:
                    reply_to = message["replies"][0][2:]
                    st.write(f">> {reply_to}")

                # テキストを "。"、"!"、"!" で分割
                sentences = re.split(r'[。!!]', text)
                for sentence in sentences:
                    if sentence:
                        st.write(sentence)
                        play_audio(sentence, name_voice_map.get(name, 1))

        time.sleep(2)

ここでは、チャットコンテナを作成し、各メッセージを順番に表示します。また、JavaScriptを使用してチャットメッセージが自動的にスクロールするようにしています。

音声の再生

play_audio関数を使用して、音声を再生します。

def play_audio(text, voice_id):
    """音声を再生する"""
    # 音声ファイルを生成
    output_filename = f"{text}.wav"
    audio_path = f"output/{output_filename}"
    try:
        voice_data = tts.generate_audio(text, output_filename=output_filename, model_id=voice_id)
    except Exception as e:
        st.error(f"音声生成エラー: {str(e)}")
        return

    # 音声ファイルを読み込む
    with open(audio_path, "rb") as audio_file:
        voice_data = audio_file.read()

    if voice_data:
        audio_str = "data:audio/wav;base64,%s" % (base64.b64encode(voice_data).decode())
        audio_html = f"""
            <audio autoplay=True>
                <source src="{audio_str}" type="audio/wav" autoplay=True>
                Your browser does not support the audio element.
            </audio>
        """
        st.markdown(audio_html, unsafe_allow_html=True)

    # 音声ファイルの読み込み
    sound = AudioSegment.from_file(audio_path, "wav")
    audio_duration = sound.duration_seconds

    time.sleep(audio_duration)

    # 生成された音声ファイルを削除
    os.remove(audio_path)

ここでは、指定されたテキストと音声IDを使用して音声ファイルを生成し、再生します。また、再生後に生成された音声ファイルを削除します。

メイン関数

main関数を使用して、アプリケーションのメイン処理を実行します。

def main():
    st.title("解説求む!新しいVision Transformerアーキテクチャ「ViTAR」")

    if st.button("再生"):
        chat_data = load_chat_data(json_file_path)
        emojis = load_emojis(emoji_file_path)
        name_emoji_map = generate_name_emoji_map(chat_data, emojis)
        name_voice_map = generate_name_voice_map(chat_data)

        display_chat(chat_data, name_emoji_map, name_voice_map)

if __name__ == "__main__":
    main()

ここでは、「再生」ボタンがクリックされたときに、チャットデータと絵文字データを読み込み、マッピングを生成し、チャットを表示します。

以上が、ろんJのStreamlitアプリケーションの構成と機能の説明です。このアプリケーションを使用することで、論文の内容をなんJスレッド風に解説・実況することができます。初心者の方でも、コードを読むことで処理の流れを理解し、必要に応じてカスタマイズや拡張を行うことができます。

ろんJのリポジトリには、論文の内容を面白おかしく理解するためのツールが含まれています。Dockerを使用して簡単にセットアップできるので、誰でも手軽に使い始めることができます。

セットアップ手順に従ってDockerコンテナを起動し、ろんJのwebページにアクセスすれば、すぐに論文の実況を楽しむことができます。JSONファイルを用意し、Streamlitのサイドバーで設定を入力するだけで、なんJスレッド風の解説が自動的に生成されます。

ろんJのStreamlitアプリケーションは、チャットデータと絵文字データを読み込み、登場人物の名前と絵文字・音声IDのマッピングを生成します。そして、チャットを表示しながら音声合成による実況を行います。JavaScriptを使用してチャットメッセージが自動的にスクロールするようにしているので、まるで実際になんJのスレッドを閲覧しているかのような臨場感を味わえます。

ろんJは、論文の内容を親しみやすいなんJのノリで解説することで、難解な論文でも楽しく理解することができます。プルリクエストや改善案も大歓迎なので、みんなで協力してろんJをさらに便利で面白いツールにしていきましょう!

さあ、ろんJを使って論文の実況を楽しみながら、新しい知識を身につけていきましょう!

リポジトリ

GitHub - Sunwood-ai-labs/RonJ
Contribute to Sunwood-ai-labs/RonJ development by creating an account on GitHub.

GPTs

ChatGPT - ろんJ (V1.4)
なんJ スレ風に論文を解説してくれます(*文量によっては全体を把握できない可能性がることをご承知おきください)

コメント

タイトルとURLをコピーしました