ぽっぺんしゃんにょろりんこ

匿名・非追跡型アダルト動画検索エンジンの設計ノート

イメージ画像から検索用タグを自動生成するというお話:②MythoMax日本語変換編

こんにちは、にょろりんこの技術備忘録ブログです。

今回は、前回の『BLIPで画像から自然文のキャプションを生成する』編の続きとなる第2ステップ──英語キャプションを、日本語の自然な一文に変換する「MythoMax日本語変換編」です。

  • AIが画像から文章をつくる(BLIP)
  • 英語キャプションを日本語に翻訳(MythoMax)←今回はこれ。
  • 形態素解析で語句を抽出(SudachiPy)
  • フィルタ&整形して、検索タグとして格納

翻訳じゃない、「キャッチコピー生成」なんです

なぜ「翻訳」ではなく「日本語変換」なのか?

それは、この処理が翻訳ではないからです。

正確には、「意味を保ちつつ、検索しやすく、自然に読めるように書き直す」──
いわばキャッチコピー生成です。

翻訳に失敗した過去と、原点回帰

当初は、ローカルLLMで普通に翻訳させていました。

※LLM(Large Language Model/大規模言語モデル

しかし、いざ実行してみると──

  • 説明っぽい文章になる
  • 長すぎて検索に使えない
  • カタカナが不自然
  • 妙にドラマチックで誇張された文になる

といった問題が発生し、翻訳としてもコピーとしても中途半端な結果になりがちでした。

原点に立ち返って気づいたのは、私は検索エンジンを作っているのであって、そのためには検索クエリと整合性のある素材(=日本語の短文)が必要だということです。

となると、直訳的な翻訳ではなく、「検索に役立つ自然な日本語」に変換することが本質であるとわかりました。

なぜ MythoMax なのか?

そうした試行錯誤の末にたどり着いたのが、LLMを「キャッチコピー専用エンジン」として制御する構成です。

Sae-Porns のタグ生成パイプラインでは、BLIP によって生成された英語キャプション(例:a blonde girl smiling in a sunlit room)を、そのままでは使いません。英語では、日本語ユーザーにとって検索利便性がありません。

そこで登場するのが、ローカルで動かせる LLaMA 系 LLM である MythoMax です。

GPTのような自然文生成能力を持ちながら、API制限や課金もなく、自由にカスタマイズして使えるのが特長です。

Sae-Pornsでは、この MythoMax を活用して、AV風の自然なキャッチコピーを自動生成しています。

ティアラ_手を前に出す

LLMを通さない「賢いスキップ処理」

次に重要なのが、タイトルが存在せず、IDやハッシュ値のみが表示されているケースの除外です。

例えば、以下のようなタイトル:

  • 3ffjd9r3JDKdjslfwX2p49  
  • ABCD1234EFGH5678  
  • Xv123456

これらはおそらくファイル名や内部IDであり、翻訳もキャッチコピーも不要です。このような文字列は、is_gibberish()(ジバリッシュ)という関数で除外しています。

※ただし、こういった文字列はそのまま検索クエリとして重要なキーになるため、翻訳はせずとも、DBにはそのまま保存しておくことが大切です。

無意味な文字列を除外する処理

■generate.py より抜粋

def is_gibberish(text):
    """
    意味不明な英数字の羅列を判定
    - アルファベット+数字のみ
    - 長さ15文字以上
    """
    return bool(re.fullmatch(r'[A-Za-z0-9]{15,}', text))

正規表現を使って、「英数字のみ・15文字以上」の文字列をLLMに送らずスキップしています。これは「翻訳しない勇気」の設計です。

キャッチコピー生成プロンプト部分

次に、キャッチコピー生成に使っているプロンプト部分をご紹介します。

このプロンプトは、MythoMaxに渡す“指示文”であり、生成される出力の品質を決定づける重要なポイントです。

■generate.py より抜粋


def call_mythomax(foreign_title):
    """LLMへプロンプトを送信してキャッチコピー生成"""
    prompt = f"""次のアダルト動画のタイトルを、日本語のAV風キャッチコピーに翻訳してください。
- タイトルは英語・フランス語・スペイン語・中国語・韓国語など、外国語全般が対象です。
- 意味や語順をなるべく保ってください。
- 外国語の人名(例: Lily, Jihye, Meiling)は自然なカタカナに変換してください。
- 曖昧な表現でも、意味を汲み取り自然な日本語にしてください。
- 誇張や脚色、説明調は禁止です。
- 意味不明な記号・英数字の羅列はそのまま出力してください。
- 出力は35文字以内の自然な1文のみとし、それ以外は書かないこと。

タイトル: {foreign_title}
日本語キャッチコピー:"""

このように、プロンプトでは生成ルールを細かく指定しています。

特に重要なのは以下のような点:

  • 「人名を自然なカタカナに」
  • 「説明調は禁止」
  • 「35文字以内・一文のみ」
  • 「意味不明なコードはそのまま出力」

これらの制約を明示することで、LLMの出力が暴走せず、安定して“ちょうどいい一文”を出してくれるようになります。

プロンプト調整は繰り返しが命

プロンプトは一度作って終わりではありません。生成結果を見ながら、表現や条件を何度も調整していくことで、精度が上がっていきます。

たとえば:

「意味を汲み取って自然な日本語にしてください」

「出力は35文字以内の自然な一文のみ」

こういった曖昧さと制約のバランスをとることで、はじめて使えるコピーが出てくるわけです。

レスポンス処理と例外時の対策

■generate.py より抜粋


response.raise_for_status()
data = response.json()
result = data.get("copy") or data.get("text") or ""
return result.strip().splitlines()[0]

この部分では、MythoMax APIから返ってきたJSONを読み取り、copy または text キーに格納された文字列の1行目だけを抽出しています。

通信失敗などが起きた場合は例外をキャッチして、元のタイトルをそのまま返します。

■generate.py より抜粋


except requests.RequestException as e:
    print(f"[ERROR] API呼び出しエラー: {e}", file=sys.stderr, flush=True)
    return foreign_title

LLMは毎回「生成処理」が走るため、まれにエラーが起きることもあります。

ですが、この except 処理によって、処理が途中で止まることなく、安全にスキップできるようになっています。

全体の流れを振り返ると…

  1. 無意味な文字列のスキップ処理(is_gibberish)
  2. 日本語プロンプトでキャッチコピーを生成(MythoMax)
  3. 失敗時はスキップして処理継続

この一連のフローにより、BLIPで生成された英語キャプションが、日本語の検索クエリとして意味のある短文へと変換されていくわけです。

最後に

ただ、ここで使っているLLMやプロンプト設計の技術は日進月歩です。今後さらに良い方法が出てきたら、柔軟に取り入れていく予定です。

それでは皆さま、よき開発ライフを。

にょろりんこでした。

※このコードが実際に使われている「追跡されないアダルト動画の検索エンジンSae-Porns」はこちら!よかったら見ていってください。(18歳未満の方はご利用できません。)

sae-porns.org