Llama3.1 軽量版 8B の日本語能力を高める方法 (Dify の DSL あります)

ローカル LLM で満足のいくレベルの日本語を使うことは大きなチャレンジであり、研究機関や企業、高校生などによって、日々研究開発が行われています。海外の大手企業などが新たな LLM をリリースするたびに、日本語に対応していると正式に謳っているか、実際に使い物になるか、等という情報が LLM 界隈に行き交い、様々なテストが行われます (X とかの SNS をやってないので想像含む)。同じ質問を投げかけてどのような回答があるか、日本語は正しいか、英語や中国語が混じっていないか、回答は正しいか、内容は充実しているか、というあたりはブログなどの結果を見ると判断できますが、実際に使って思うのは、文法や言葉遣いは二の次で、本当に欲しいのは内容の充実度とその応答速度である、というところです。また、長文を翻訳させたいとか、LLM を切り替えるときの読み込み時間がイヤということもあり、ボクがここしばらくチャットで使っているローカル LLM は、llama3.1:8b-instruct-fp16 一本です。実サイズ 16GB なので、32GB しかメモリがない Mac でコンテキスト長を 3万トークンにしても高速で動いてくれます。

日本語能力の高い LLM を調べる

さて、LLM の日本語能力を機械的に多角的に評価され、信頼性が高そうなサイトに「Nejumi LLMリーダーボード3」さん (リンクは下記) があります。更新頻度は高く、商用/オープン・パラメータ数・リリースのタイミング・instruct/chat/text 等のバージョン違いを含めた非常に多くの LLM を評価されているようで、細かい内容まではわかりませんが、とにかく信頼してよさそうな情報量です。

リンク: https://wandb.ai/wandb-japan/llm-leaderboard3/reports/Nejumi-LLM-3–Vmlldzo3OTg2NjM2?accessToken=wpnwc9whr96pxm40dfe4k3xq513f9jc4yhj7q6pnvj4jtayoefbc77qhzbsrztgz

こちらの Nejumi さんでの Llama3.1 の順位はというと、2024/09/28 現在 8位で、オープンなモデルでは Alibaba 社の Qwen 2.5 に次いで 2番目です。すばらしいですね。ただし、パラメータ数は Llama3.1 最上位の 405B なので、ボクの持っている 32GB RAM の Mac では動かせません。8B モデルの順位はというと、次のページの真ん中よりちょっと上あたりにやっと登場。他の選択肢の多さを考えたら選ぶ理由は無い、というレベルです。

でも、個人の感想ですが、実際に使っているとそんなに大きな問題は感じません。元々学習に使ったソースの質が高かったのでしょう、405B を 8B に蒸留してもある程度の質が高い状態で保たれていると感じます。Dify でコンテキスト長を 32,768 トークンにしてもトータルで 22GB に収まるため、32GB RAM でも処理は 100% GPU で行えます (つまり速い。14TPS 以上)。問題となるのは単純な知識の量ですので、必要なら英語で質問すればより多い知識から回答が得られます。そもそも対応言語に日本語が無いんですから、日本語でチャットができても、日本語での知識は乏しくても仕方ないんです。

HuggingFace: https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct

結論、英語で推論してもらえば良い

前置きが長くなりました。というわけで、この記事で紹介するのは、Llama3.1 に英語で推論して日本語で回答してもらう方法です。知識は英語で蓄えているのですから、知識を引き出すところだけ英語にしてもらえば、日本語の回答の精度や内容の質が高まるはずです。他の日本語対応を正式には謳っていない LLM でも同様の手法は有効だと思います。下記する方法を試したところ、プロトタイプ二つを経て、最終的には極めて簡単なプロンプトでほぼ期待したような結果が得られるようになりました。むしろ、20B 以下の少ないパラメータ数の LLM の場合、多言語対応だと浅く広くの知識にならざるを得ないでしょうから、「日本語での会話」がそれなりにでき、知識は英語やらフランス語やらの限られた言語で多く・深く収集された LLM の方が利用価値は高いと思います。

紹介する方法の使い方

Mac で Dify と Ollama で作ったので、同環境でしかテストしていません。ただ、最適化バージョンと、見える化バージョンは、実質システムプロンプトのみなので、LM Studio 等の System Prompt を設定できる AI ツールを使っても簡単に利用できると思います。Ollama 単体でも template を書き換えるか、毎回質問するときに記入すれば同様のことは実現できるかもしれません。

以下に Dify 用 DSL と System プロンプトを貼っておきます。Dify なら適当な名前.ymlとしてファイルに保存してから「DSL をインポート」で読み込んでください。LM Studio 等のツールで試すなら、DSL の後に貼ってある System prompt の内容をコピペしてください。LLM にはモデルプロバイダ Ollama でダウンロードした llama3.1:8b-instruct-fp16 を使用しています。Dify で別のものを使用する際には適宜変更してください (使用する LLM によっては期待した効果は得られない可能性があります)。

効果を見るには、System prompt を何も指定していない (デフォルト) の状態と、最適化したものを使った場合とで出力を比較してみてください。日本人なら当然知っているであろうこと (「漫画家鳥山明の代表作は」等) も日本語で聞くとハルシネーションを起こしがちですが、英語で推論されると正しい答えが得られるケースが多いです。また、海外から日本を見た第三者的解釈による回答が得られやすいのも良い側面だと思います。対して難点としては、英訳・和訳の処理が挟まるため微妙なニュアンスが変わってしまったり、固有名詞が間違った漢字やローマ時表記になることがあります。

まずは評価を簡単にしたかったので、回答内容に大きなブレや遊びが出ないように、Temperature と Top_P のそれぞれを 0.2 にしています。もっと厳密に評価・比較する場合は数値を下げたり、実際に運用フェーズで多様な生成を行いたいという場合には 1に近い値を採用するなど、目的に応じて工夫して使ってください。

また、Size of context window は 32GB RAM Mac で最大になるように32768にしてしまっています。GPU 使用率がマックスにならない場合はこの値が大きすぎる可能性があるので、チェックを外すなり小さな値にするなり、使用する LLM やご自身の RAM サイズに合わせて調整してください。参考:

日本語能力を高めたチャットボットの紹介

適当な名前.ymlとして保存した DSL を Dify の「DSL ファイルをインポート」でインポートすると現れるチャットボット

最適化バージョン

最終バージョンです。日本語で質問すると、内部的に英語で推論し、日本語で回答してくれます。一行のシステムプロンプトのみなので、レスポンスタイムに影響はありません。

★ Dify 用 DSL (クリックして表示する) ★:
app:
  description: Llama3.1 の持つ豊富な英語の知識を日本語で回答してくれる。日本語の固有名詞の変換が苦手なところは、日本語ペラペラなアメリカ人インテリも漢字はニガテ、みたいでかわいい
  icon: male-student
  icon_background: '#FFE4E8'
  mode: advanced-chat
  name: Llama3.1 最適化 (脳内処理バージョン)
  use_icon_as_answer_icon: true
kind: app
version: 0.1.1
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
        number_limits: 3
        transfer_methods:
        - local_file
        - remote_url
    opening_statement: ''
    retriever_resource:
      enabled: false
    sensitive_word_avoidance:
      enabled: false
    speech_to_text:
      enabled: false
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: true
    text_to_speech:
      enabled: false
      language: ''
      voice: ''
  graph:
    edges:
    - data:
        sourceType: start
        targetType: llm
      id: 1727272665783-llm
      source: '1727272665783'
      sourceHandle: source
      target: llm
      targetHandle: target
      type: custom
    - data:
        sourceType: llm
        targetType: answer
      id: llm-answer
      source: llm
      sourceHandle: source
      target: answer
      targetHandle: target
      type: custom
    nodes:
    - data:
        desc: ''
        selected: false
        title: 開始
        type: start
        variables: []
      height: 54
      id: '1727272665783'
      position:
        x: 80
        y: 282
      positionAbsolute:
        x: 80
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: false
          variable_selector: []
        desc: ''
        memory:
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 10
        model:
          completion_params:
            keep_alive: 30m
            num_ctx: 32768
            temperature: 0.2
            top_p: 0.2
          mode: chat
          name: llama3.1:8b-instruct-fp16
          provider: ollama
        prompt_template:
        - id: d80ef4de-35f3-4106-87af-ff57023b2649
          role: system
          text: Infer question in English, generate rich answer, and output in the
            language used to ask.
        selected: true
        title: LLM
        type: llm
        variables: []
        vision:
          enabled: false
      height: 98
      id: llm
      position:
        x: 379
        y: 282
      positionAbsolute:
        x: 379
        y: 282
      selected: true
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        answer: '{{#llm.text#}}'
        desc: ''
        selected: false
        title: 回答
        type: answer
        variables: []
      height: 107
      id: answer
      position:
        x: 680
        y: 282
      positionAbsolute:
        x: 680
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    viewport:
      x: -111
      y: 197
      zoom: 1

System prompt (LM Studio 等で使用する場合はこちらをどうぞ):

Infer question in English, generate rich answer, and output in the language used to ask.

見える化バージョン

質問の英訳、英語での推論、最終的な和訳、の全てが表示されるバージョンです。それぞれの処理は一つの LLM ブロックで実施しています。上の最終バージョンでは本当に英語で推論したのかわかりませんが、こちらは途中経過もはっきり見て取れます。英語の勉強にも使えるかもしれません。

★ Dify 用 DSL (クリックして表示する) ★:
app:
  description: Llama3.1 が、質問を英訳し、推論し、日本語で返す、全てのプロセスを透明化したバージョン。冗長だが、英語の知識を使って回答していることがわかる。英語の勉強にもなるかも?
  icon: two_men_holding_hands
  icon_background: '#E4FBCC'
  mode: advanced-chat
  name: Llama3.1 英語で推論 (見える化バージョン)
  use_icon_as_answer_icon: true
kind: app
version: 0.1.1
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
        number_limits: 3
        transfer_methods:
        - local_file
        - remote_url
    opening_statement: ''
    retriever_resource:
      enabled: false
    sensitive_word_avoidance:
      enabled: false
    speech_to_text:
      enabled: false
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: true
    text_to_speech:
      enabled: false
      language: ''
      voice: ''
  graph:
    edges:
    - data:
        sourceType: start
        targetType: llm
      id: 1727270833994-llm
      source: '1727270833994'
      sourceHandle: source
      target: llm
      targetHandle: target
      type: custom
    - data:
        sourceType: llm
        targetType: answer
      id: llm-answer
      source: llm
      sourceHandle: source
      target: answer
      targetHandle: target
      type: custom
    nodes:
    - data:
        desc: ''
        selected: false
        title: 開始
        type: start
        variables: []
      height: 54
      id: '1727270833994'
      position:
        x: 80
        y: 282
      positionAbsolute:
        x: 80
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: false
          variable_selector: []
        desc: ''
        memory:
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 10
        model:
          completion_params:
            keep_alive: 30m
            num_ctx: 32768
            temperature: 0.2
            top_p: 0.2
          mode: chat
          name: llama3.1:8b-instruct-fp16
          provider: ollama
        prompt_template:
        - id: 342e3642-d8b5-42c8-b003-7816a8ec7f3a
          role: system
          text: 'You are a skilled AI translator. Since your knowledge is best in
            English, translate any question into English for inference and generate
            answer. Follow the steps described below.


            ### Steps:

            1. You translate {{#sys.query#}}directly into English. Try maintaining
            the original format without omitting or adding any information.

            2. Generate response in English.

            3. Translate the response literary back into the language originally used
            by the user and output.'
        selected: true
        title: LLM
        type: llm
        variables: []
        vision:
          enabled: false
      height: 98
      id: llm
      position:
        x: 381
        y: 282
      positionAbsolute:
        x: 381
        y: 282
      selected: true
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        answer: '{{#llm.text#}}'
        desc: ''
        selected: false
        title: 回答
        type: answer
        variables: []
      height: 107
      id: answer
      position:
        x: 680
        y: 282
      positionAbsolute:
        x: 680
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    viewport:
      x: -205
      y: 134
      zoom: 1

System prompt (LM Studio 等で使用する場合はこちらをどうぞ):

You are a skilled AI translator. Since your knowledge is best in English, translate any question into English for inference and generate answer. Follow the steps described below.

### Steps:
1. You translate the query directly into English. Try maintaining the original format without omitting or adding any information.
2. Generate response in English.
3. Translate the response literary back into the language originally used by the user and output.

ステップバイステップバージョン

質問の英訳、英語での推論、最終的な和訳、のそれぞれを個別の LLM ブロックで実行しています。最終的にユーザに返ってくるのは和訳されたものだけなので余計な情報は含まれませんが、ブロック毎にどういう処理をしたのかが調べられるのでデバッグ向きです (最初に作った PoC バージョン)。回答の質は高い傾向があります。これが最終バージョンでは無いのは、3回LLM が動くので単純に時間がかかるからです。Dify のフローを利用しているため、こちらに限っては LM Studio にシステムプロンプトに指示を投げるという使い方では実現できません。

★ Dify 用 DSL (クリックして表示する) ★:
app:
  description: 質問の英訳、推論、和訳、と 3つのパートそれぞれに Llama3.1 を使用したバージョン。無駄に時間がかかる、PoC 版
  icon: family
  icon_background: '#FEF7C3'
  mode: advanced-chat
  name: Llama3.1 開発途上 (3倍労力バージョン)
  use_icon_as_answer_icon: true
kind: app
version: 0.1.1
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
        number_limits: 3
        transfer_methods:
        - local_file
        - remote_url
    opening_statement: ''
    retriever_resource:
      enabled: false
    sensitive_word_avoidance:
      enabled: false
    speech_to_text:
      enabled: false
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: true
    text_to_speech:
      enabled: false
      language: ''
      voice: ''
  graph:
    edges:
    - data:
        isInIteration: false
        sourceType: start
        targetType: llm
      id: 1726927256338-source-1727251929525-target
      source: '1726927256338'
      sourceHandle: source
      target: '1727251929525'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: llm
        targetType: answer
      id: 1727252264986-source-answer-target
      source: '1727252264986'
      sourceHandle: source
      target: answer
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: llm
        targetType: llm
      id: 1727251929525-source-1727252519406-target
      source: '1727251929525'
      sourceHandle: source
      target: '1727252519406'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: llm
        targetType: llm
      id: 1727252519406-source-1727252264986-target
      source: '1727252519406'
      sourceHandle: source
      target: '1727252264986'
      targetHandle: target
      type: custom
      zIndex: 0
    nodes:
    - data:
        desc: ''
        selected: false
        title: 開始
        type: start
        variables: []
      height: 54
      id: '1726927256338'
      position:
        x: 80
        y: 282
      positionAbsolute:
        x: 80
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        answer: '{{#1727252264986.text#}}'
        desc: ''
        selected: false
        title: 回答
        type: answer
        variables: []
      height: 107
      id: answer
      position:
        x: 1278.680492089227
        y: 282
      positionAbsolute:
        x: 1278.680492089227
        y: 282
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: true
          variable_selector:
          - sys
          - query
        desc: ''
        memory:
          query_prompt_template: ''
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 50
        model:
          completion_params:
            keep_alive: 30m
            num_ctx: 32768
            temperature: 0.2
            top_p: 0.2
          mode: chat
          name: llama3.1:8b-instruct-fp16
          provider: ollama
        prompt_template:
        - id: 7e4cffec-808f-4f8b-968d-945955648c2b
          role: system
          text: You are a skilled translator in English. You translate {{#sys.query#}}directly
            into English so the entire output can be used as a replacement of the
            original text. Based on the content, maintaining the original format without
            omitting or adding any information.
        - id: d152eb91-5a38-4d31-97d9-c57c4b18ed51
          role: user
          text: '{{#context#}}'
        selected: false
        title: Translation to English
        type: llm
        variables: []
        vision:
          enabled: false
      height: 98
      id: '1727251929525'
      position:
        x: 380
        y: 275.68049208922713
      positionAbsolute:
        x: 380
        y: 275.68049208922713
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: false
          variable_selector: []
        desc: ''
        memory:
          query_prompt_template: ''
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 50
        model:
          completion_params:
            keep_alive: 30m
            num_ctx: 32768
            temperature: 0.2
            top_p: 0.2
          mode: chat
          name: llama3.1:8b-instruct-fp16
          provider: ollama
        prompt_template:
        - id: 9e13c0fb-e680-48da-8270-2d8ed2f8b676
          role: system
          text: You are a skilled translator in Japanese. You translate {{#1727252519406.text#}}directly
            into Japanese so the entire output can be used as a replacement of the
            original text. Based on the content, maintaining the original format without
            omitting or adding any information.
        - id: be046c8d-1d48-47f4-91d0-1c6bb7fc3909
          role: user
          text: '{{#1727252519406.text#}}'
        selected: true
        title: translation to japanese
        type: llm
        variables: []
        vision:
          enabled: false
      height: 98
      id: '1727252264986'
      position:
        x: 980
        y: 282
      positionAbsolute:
        x: 980
        y: 282
      selected: true
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: false
          variable_selector: []
        desc: ''
        memory:
          query_prompt_template: ''
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 50
        model:
          completion_params:
            keep_alive: 30m
            num_ctx: 32768
            temperature: 0.2
            top_p: 0.2
          mode: chat
          name: llama3.1:8b-instruct-fp16
          provider: ollama
        prompt_template:
        - id: 5a722de8-e6f9-48df-81cb-86cfa183f447
          role: system
          text: Generate rich answer in English.
        - id: a3587e3e-84f3-41c9-a45d-ea5fb8392c73
          role: user
          text: '{{#1727251929525.text#}}'
        selected: false
        title: inference and generation
        type: llm
        variables: []
        vision:
          enabled: false
      height: 98
      id: '1727252519406'
      position:
        x: 684
        y: 275.68049208922713
      positionAbsolute:
        x: 684
        y: 275.68049208922713
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    viewport:
      x: -270.21689933279276
      y: 120.80412637177352
      zoom: 0.8083334534373365

まとめ

プロンプトには改善の余地はあるでしょうし、対象とする LLM によって最適な方法も変わると思います。ただいずれにせよ、英語の情報が豊富な代わりに日本語で学習した情報が少ないという LLM には有効な手法だと思います。すぐに試せるはずなので、具体的な実行例は載せませんでした。そのまま使わなくても、アイディアは流用できるでしょう。ぜひお気に入りの LLM の知識を最大限に活用できる方法を生み出してください。そして、ぜひボクや世の中に共有してください。

(蛇足) センシティブな情報と情報発信

アメリカの大手企業が作った LLM である Llama (Meta 社) や Phi (Microsoft 社)、Gemma (Google 社) は、ローカルにダウンロードして利用できるオープンソース・オープンウェイトではありますが、それぞれの企業のコンプライアンスポリシーに従ってセンシティブな情報は回答してくれません。つまり、エロいこと、差別的なこと、暴力的なこと、犯罪に関わること、等を答えさせようとしても、ことごとく、かたくなに、徹底的に拒否されてしまいます。ところが、中国産の LLM は大手がリリースしたものであっても制限がゆるいようです。特にパラメータ数の小さいモデルほど、質問の仕方によってはかなりの部分まで回答してくれます。例えば Nejumi さんのリーダーボードで 20位以内に入っている Qwen 2.5 14B Instruct はかなり寛容な感じです。

これは、「危ないことを教えてくれるぜ、えへへ」ということではなく、どのような LLM を使ってどのような文章 (絵や映像、音声も同じです) が得られたとしても、それを使用して外部に何かを発信する前には注意が必要、ということです。注意すべきは LLM 自体のライセンスだけではありません。文法、誤字脱字、ファクトチェックも重要ですが、誰かを傷つけたり、権利を侵害するようなことが無いよう、十分気をつけましょう。

本ブログでは LLM が生成した文章をそのまま注釈無しで使用しないようにしていますが、何か不備がございました、ご指摘いただけると幸いです。

また、気に入った記事には文末のイイネボタンをクリックしていただけるとうれしいです。

Image by Stable Diffusion

アメリカ人大学教授が寿司の作り方を教えている授業の風景を想定してお願いしてみました。

Date:
2024年9月29日 0:21:23

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
white male american college professor in formal suit teaching how to make sushi

Exclude from Image:

Seed:
1340386485

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & GPU

【Mac 専用】OpenVoice で音声クローン

音声クローン技術の OpenVoice を Mac にインストールして使ってみました。作業を始めてから実際に使えるようになるまで結構大変だったので、やり方をまとめます。また、OpenVoice V2 は日本語ネイティブ対応ということですが、TTS (Text-To-Speech) に使われている MeloTTS の日本語能力がよろしくないので、macOS に標準搭載されている say コマンドで生成した音声を元にクローン音声を生成するスクリプトを書きました。そちらはなかなかの成果が出たので、合わせて紹介します。

OpenVoice (オフィシャル GitHub): https://github.com/myshell-ai/OpenVoice/

Weel さんの紹介記事 (こちらで知りました): https://weel.co.jp/media/tech/openvoice

注意点

OpenVoice v2 は MIT ライセンスで公開されているので、ソースコードも生成された音声も商用利用可能です。ただし、クローン元となる音声を利用する権利を有していない場合は、商用か否かにかかわらず生成された音声を公開する権利はありません。現在の法律がどうであれ、AI の進歩と共に法整備も進んでいくはずです。声やしゃべりで生計を立てている方々もいる以上、許可無く誰かの音声を使用することは何らかの形で罰せられる可能性があります。そのことを理解した上で本記事を読み進めてください。また、ご自身の音声データを公開する場合においても、ライセンスの明記は行うようにしましょう。

免責事項:
このサイトで提供される情報や方法を使用して行われた行為については、私たちは一切の責任を負いません。特に、他人の無断使用または違法な手段によって得られた音声データを使用して音声クローンを作成し、公開することは完全に利用者の自己責任であり、その結果として生じるあらゆる問題やトラブルについても当方は何ら関知せず、一切の責任を負わないものとします。

法律により保護された著作権やパブリシティ権等が侵害される可能性のある行為を行う際には、利用者は事前に適切な法的措置を講じ、自己のリスクにおいて行動するものとし、当方はその結果生じる一切の損害について責任を負わないものとします。

なお、この免責事項は日本国の法律に基づいて解釈されるものとし、適用されるべき法域については当事者の本拠地が所在する国または地域の法律ではなく、日本国の法律を選択的に適用することに同意するものとします。

以上のご理解とご了承をいただきますようお願い申し上げます。

環境

動作確認ができた環境

macOS: 14.5
ffmpeg version 7.0.1
pip version 24.2

環境構築手順

入っていなければ、ffmpeg をインストール (もちろん brew が必要です):

brew update
brew install ffmpeg

ディレクトリを作って OpenVoice リポジトリをクローン。ディレクトリ名はお好きにどうぞ:

mkdir OpenVoice
cd OpenVoice
git clone https://github.com/myshell-ai/OpenVoice.git .

仮想環境を構築して入る。ボクは得意のpipenvですが、これもお好きなのをお使いください。Python は 3.9 必須らしいです:

pipenv --python 3.9
pipenv shell

pipを最新にし、torchchardet、そして OpenVoice をインストール:

python -m pip install --upgrade pip
pip install torch chardet
pip install -e .

OpenVoice V2 をダウンロードして展開:

※ チェックポイントの最新版 (unzip の対象) は、https://github.com/myshell-ai/OpenVoice/blob/main/docs/USAGE.md の Download the checkpoint from here and extract it to the checkpoints_v2 folder. で確認のこと!

wget https://myshell-public-repo-host.s3.amazonaws.com/openvoice/checkpoints_v2_0417.zip
unzip checkpoints_v2_0417.zip
rm checkpoints_v2_0417.zip

以下に従ってファイル openvoice/se_extractor.py を編集 (22行目のcudacpuにし、float16float32に変更):

[[[IMPORTANT]]] modify OpenVoice source for Apple Silicon Mac: https://github.com/reid-prismatic/OpenVoice-Scribe/commit/f681f5bcbc18df3f356953928a78ba6dcff9de99

def split_audio_whisper(audio_path, audio_name, target_dir='processed'):
    global model
    if model is None:
        model = WhisperModel(model_size, device="cpu", compute_type="float32")
    audio = AudioSegment.from_file(audio_path)
    max_len = len(audio)

(ここは必要な場合のみ) OpenVoice V2 オフィシャルでは、音声生成 (TTS、Text-To-Speech) に MeloTTS を使用しているため、別途インストールする手順が示されています。個人的に日本語の能力は不十分だと思いますが、気になる方、オフィシャルの方法でまずは進めたい方は以下も実施してください:

git clone https://github.com/myshell-ai/MeloTTS
cd MeloTTS
pip install -e .
python -m unidic download

(MeloTTS のテストをしたい場合のみ) 以下にテスト用のサンプルコードを貼っておきます (★ MeloTTS テストコード ★をクリックするとコードが開きます)。python japanese.py で実行し、生成された jp.wav をファインダで QuickLook もしくは Terminal からafplay jp.wav で再生できます。テキストの文面は上で紹介した Weel さんの記事の一部ですが、アルファベット表記の “OpenVoice” がガン無視されたり、音引きが部分的にスルーされたり、読点で溜めが無かったり、なんとなく中国語っぽい癖があったり、という感じで、実用するにはきびしいです。ちなみに初回実行時はファイルのダウンロードが発生するので時間がかかります。

★ MeloTTS テストコード ★
from melo.api import TTS
import time

# Speed is adjustable
speed = 1.0
device = 'cpu' # 'mps' にしても動くが、速くはならない

start = time.time()

text = """
OpenVoiceは、正確なトーンカラーのクローニング、柔軟な声のスタイル制御、ゼロショット多言語クローニングを可能にする音声クローニング技術です。

OpenVoiceを使用すると、リファレンス スピーカーの音色を複製するだけでなく、感情、アクセント、リズム、ポーズ、イントネーションなどの音声スタイルをきめ細かく制御できます。

これを使用するとこのような音声が生成できます。
"""
model = TTS(language='JP', device=device)
speaker_ids = model.hps.data.spk2id

output_path = 'jp.wav'
model.tts_to_file(text, speaker_ids['JP'], output_path, speed=speed)

print(f'\nかかった時間: {round(time.time()-start, 2)} 秒\n')

OpenVoice を使う

クローンしたい音声を準備

環境の準備ができたら、クローンしたい音声ファイルを準備します。なるべく高品質で、他の人の声や雑音、BGM 等が入っていない、10秒以上の音声がよさそうです。参考まで、ffmpegで MP4 の映像ファイルから MP3 の音声を書き出すなら、こんな感じで行えます:

ffmpeg -i input.mp4 -vn -acodec libmp3lame myvoice.mp3

OpenVoice/resources フォルダに入れておきます (ファイル名 myvoice.mp3はサンプルコードで使用しているので、そのまま使いましょう):

cp myvoice.mp3 resources

まずはオフィシャルのテストコードで試す (MeloTTS 必須)

オフィシャルのサンプルコード (demo_part3.ipynb GitHub で見るならこちら) を適当にいじって日本語だけ生成するようにし、かかった時間を表示するようにしたものがこちらです。上の手順で MeloTTS をダウンロードした場合はこれでクローンのテストが行えます。OpenVoice ディレクトリ直下においてpython test.pyで実行します:

import os
import torch
from openvoice import se_extractor
from openvoice.api import ToneColorConverter
from melo.api import TTS
import time

home_dir = './'
ckpt_converter = home_dir + 'checkpoints_v2/converter'
device = "cuda:0" if torch.cuda.is_available() else "cpu"
output_dir = 'outputs'

start = time.time()

tone_color_converter = ToneColorConverter(f'{ckpt_converter}/config.json', device=device)
tone_color_converter.load_ckpt(f'{ckpt_converter}/checkpoint.pth')

os.makedirs(output_dir, exist_ok=True)

reference_speaker = home_dir + 'resources/myvoice.mp3' # This is the voice you want to clone
target_se, audio_name = se_extractor.get_se(reference_speaker, tone_color_converter, vad=False)

texts = {
    'JP': "彼は毎朝ジョギングをして体を健康に保っています。"
}

src_path = f'{output_dir}/tmp.wav'

# Speed is adjustable
speed = 1.0

for language, text in texts.items():
    model = TTS(language=language, device=device)
    speaker_ids = model.hps.data.spk2id

    for speaker_key in speaker_ids.keys():
        speaker_id = speaker_ids[speaker_key]
        speaker_key = speaker_key.lower().replace('_', '-')

        source_se = torch.load(f'checkpoints_v2/base_speakers/ses/{speaker_key}.pth', map_location=device)
        model.tts_to_file(text, speaker_id, src_path, speed=speed)
        save_path = f'{output_dir}/output_v2_{speaker_key}.wav'

        # Run the tone color converter
        encode_message = "@MyShell"
        tone_color_converter.convert(
            audio_src_path=src_path,
            src_se=source_se,
            tgt_se=target_se,
            output_path=save_path,
            message=encode_message)
 
print(f'\nかかった時間: {round(time.time()-start, 2)} 秒\n')

生成された音声は outputs に保存されます。afplay outputs/output_v2_jp.wav で再生しましょう。サンプルの文章がちょうど良いのか悪くない感じがするものの、文章をいろいろ変えて試すと結構きびしいことがわかってきます。でもこれって、OpenVoice の問題じゃないんです。

OpenVoice はボイスチェンジャーである

outputs ディレクトリには output_v2_jp.wav 以外に、tmp.wav ファイルがあるのがわかります。実はこれは MeloTTS で作られた、ベースとなる音声ファイルです。OpenVoice はその音声を、ユーザが用意した音声の特徴で置き換える、つまり乱暴に言うとボイスチェンジャー的なことをしています。音楽で言えばピアノで弾いた曲の音色をギターに変えるようなことをしているので、ベースのアクセントを踏襲しますし、他の言語でもしゃべれてしまう、というわけです。

ええぃ、MeloTTS はキツい!Siri さん、お願いします!

我らが macOS にはいにしえ (Mac OS 9?) より音声合成技術が備わっております。Siri さんなんかは iPhone の普及も相まって、なかなかに鍛わっています。面倒なインストール作業も必要なく、ファイルへの書き出しにも対応しています。というわけでボクはあまり使えない MeloTTS を捨て、音声合成部分に macOS 標準搭載のsayコマンドを使用することにしました。簡単なオプションも追加したスクリプトを書いたので紹介します。名付けて clonesay (クローンせい!) です。やかましいですね。

python clonesay.py でとりあえず動きます (-hを付けると、利用できるオプションの一覧を表示します)。macOS で指定されている音声で、テスト用に入れているデフォルトのテキストを音声合成し、myvoice.mp3 の声色にクローンして outputs/output_jp.mp3 として書き出してくれます。実行中にはごちゃごちゃと英文が表示されますが、最終的に「かかった時間」が表示されればおそらく問題無いはずです。

import os
import torch
from openvoice import se_extractor
from openvoice.api import ToneColorConverter
import time
import subprocess
import argparse

# macOS の 'say' コマンドを使用して、ベースとなる音声ファイルを生成
def text_to_speech(text, output_file):
    command = ['say', '-o', output_file, text]
    subprocess.run(command)

# 引数を解析するための設定
parser = argparse.ArgumentParser(description='OpenVoice を利用して音声のクローニングを行います。事前にクローンしたい音声ファイルを resources/myvoice.mp3 \
                                 として保存してから実行してください。macOS の "say" コマンドを利用しています。\
                                 https://github.com/myshell-ai/OpenVoice/')
parser.add_argument('-i', '--input', type=str, required=False, help='しゃべらせたいテキストを直接入力します。例 -i "こんにちは、おげんきですか"')
parser.add_argument('-f', '--file', type=str, required=False, help='しゃべらせたいテキストが入力されたファイルを指定します。同時に指定した場合は -i が優先されます。')
parser.add_argument('-s', '--source', type=str, required=False, help='テキストから音声を生成せずに、指定した既存の音声ファイルを元にクローンを作成します。\
                    同時に指定した場合は -i、-f が優先されます。')
parser.add_argument('-o', '--output', type=str, required=False, help='出力するファイル名を指定します。利用できるフォーマット: mp3(デフォルト), aiff, wav.')
parser.add_argument('-r', '--reference', type=str, required=False, help='クローン元となる音声ファイルを指定します。\
                    初回指定時には必要なデータが processed ディレクトリに作成されます。')
parser.add_argument('-p', '--play', action='store_true', required=False, help='生成された音声を自動再生します。')
args = parser.parse_args()

home_dir = './'
device = 'cpu'
ckpt_converter = home_dir + 'checkpoints_v2/converter'
tone_color_converter = ToneColorConverter(f'{ckpt_converter}/config.json', device=device)
tone_color_converter.load_ckpt(f'{ckpt_converter}/checkpoint.pth')
output_dir = 'outputs'
language = 'jp'
src_path = f'{output_dir}/tmp.aiff'

os.makedirs(output_dir, exist_ok=True)
start = time.time()

# クローン元となる音声ファイルの指定
if args.reference:
    reference_speaker = args.reference
else:
    reference_speaker = home_dir + 'resources/myvoice.mp3' # クローン元となる音声ファイル

target_se, audio_name = se_extractor.get_se(reference_speaker, tone_color_converter, vad=False)

# 発声するテキストを指定もしくは、既存の音声ファイルを指定
if args.input:
    input_text = args.input
#elif os.path.isfile(args.file) and os.path.getsize(args.file) > 0:
elif args.file and os.path.isfile(args.file):
    with open(args.file, 'r', encoding='utf-8') as file:
        input_text = file.read()
elif args.source:
    src_path = args.source
    input_text = ''
else:
    input_text = """
    しゃべらせたい文章を、ダッシュアイで指定してください。その他利用可能なオプションは、ダッシュエイチで確認できます。
    """

# 発声するテキストの元となる音声ファイルを生成
if input_text != '':
    text_to_speech(input_text, src_path)

source_se = torch.load(f'checkpoints_v2/base_speakers/ses/{language}.pth', map_location=device)
save_path = f'{output_dir}/output_{language}.mp3' # デフォルトの出力ファイル

# 出力ファイル名の指定がある場合
if args.output:
    output_extension = os.path.splitext(args.output)[1].lower()
    if output_extension in {'.mp3', '.aiff', '.wav'}:
        save_path = args.output
    else:
        save_path = os.path.splitext(args.output)[0] + '.aiff'
else:
    save_path = f'{output_dir}/output_{language}.mp3'

# OpenVoice processing part
# Run the tone color converter
encode_message = "@MyShell"
tone_color_converter.convert(
    audio_src_path=src_path,
    src_se=source_se,
    tgt_se=target_se,
    output_path=save_path,
    message=encode_message)
 
print(f'\nかかった時間: {round(time.time()-start, 2)} 秒\n')

# Play the generated MP3 file using the default media player
if args.play and os.path.isfile(save_path):
    # Use afplay for macOS, which is a simple command-line audio player
    print(f'ファイル: {save_path}')
    if input_text !="":
        print(input_text)
    subprocess.run(['afplay', save_path])
else:
    print("The output file does not exist.")

簡単にいろいろ試すなら、-iオプションでテキストを入力し、-pで生成後に再生するようにするのが良いと思います。例えばこんな感じ:

python clonesay.py -p -i "本日皆さんに集まっていただいたのは、\
新しいエーアイ活用の方法を議論するのが目的です。どうぞ、よろしくお願いします。"

(“AI” は “エーアイ” にするなど、工夫は必要です)

macOS の音声を変えてみる

多分 macOS デフォルトの音声は Siri (声 2) ですが、さすがに男性の声に寄せるのはきびしいと思います。そのような場合には、システム設定で変更しましょう。コマンドでのやり方はみつかりませんでした (声の管理… から、追加もできるようです)。

システム設定… → アクセシビリティ → 読み上げコンテンツ → システムの声

感想

AI による音声のクローニング手法はいくつかあるようで、以前 GPT-SoVITS というのをいじったときには結構衝撃的な結果でした。数秒の音声からかなり高い再現度だったからです。今回はたまたま Weel さんで見つけた OpenVoice を試したわけですが、正直クローニングのクオリティとしては劣っていると感じています。ベースの音声 (Siri さん) に寄りすぎだな、と。ただ、今後ベースの TTS (Text-To-Speech) の性能がとんでもなく高く、自分がクローンしたい声質に近いものが現れたときには TTS だけ乗り換えれば良いわけで、将来性はあるのかもしれない、とも思っています。また、OpenVoice は TTS に頼らない技術です。なので、ボクのサンプルスクリプトの-sオプションでリアルの人物がしゃべった音声ファイルをソースとして指定すれば、ナチュラルな結果が得られるでしょう。何か使い道はありそうですよね。mac ユーザの方は遊んでみてください。

Image by Stable Diffusion (Mochi Diffusion)

今回の画像は何のひねりも無いプロンプトで描いてもらいました。ステップ数が高ければキレイになったりリアルになったりするわけでも無いんですよね。ランダムでしばらく回し、めぼしい Seed 値が見つかった後は何度か Steps の増減を繰り返し、指と女性の顔が一番ブキミじゃなかった、マシだった、という一枚に決めました。

Date:
2024年9月23日 23:14:52

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
human voice clone technology

Exclude from Image:

Seed:
85304328

Steps:
25

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

Ollama 単体では速い LLM が、なぜか Dify や Continue から使うと遅い、という時の解決方法

最近のオープンソース・オープンウェイトの LLM のパフォーマンスは本当にすごくて、コーディング補助なら DeepSeek Coder V2 Lite Instruct (16B)、日本語と英語のチャットや翻訳なら Llama 3.1 Instruct (8B) で十分です。Ollama をターミナルアプリから実行してチャットすると、その内容と回答スピードには本当に驚かされますね。インターネットが止まっても当分生きていける感じがします。

ところが、Dify や Visual Studio Code 用 LLM 拡張機能 Continue から Ollama の同じモデルを API で使用すると、使い物にならないくらい遅いという状況が発生しました。今回はその解決方法を紹介します。あなたの問題の原因は別のところにあるかもしれませんが、簡単に確認・修正できるので、まずは本記事の【結論】の内容を試してみることをオススメします。

確認できた環境

OS やアプリのバージョン

macOS: 14.5
Ollama: 0.3.8
Dify: 0.6.15
Visual Studio Code - Insiders: 1.93.0-insider
Continue: 0.8.47

LLM とサイズ

モデル名モデルサイズコンテキストサイズOllama ダウンロードコマンド
llama3.1:8b-instruct-fp1616 GB131072ollama pull llama3.1:8b-instruct-fp16
deepseek-coder-v2:16b-lite-instruct-q8_016 GB163840ollama run deepseek-coder-v2:16b-lite-instruct-q8_0
deepseek-coder-v2:16b-lite-instruct-q6_K14 GB163840ollama pull deepseek-coder-v2:16b-lite-instruct-q6_K
mac で 32GB 以上の RAM なら楽勝で動くはずのモデルサイズ

【結論】コンテキストサイズを見直そう

API 経由で Ollama のモデルを利用する側のアプリ、例えば Dify で設定する「Size of context window」を十分に小さくすることで解決します。モデル自体が対応しているから、とか、将来のためになるべく多くのトークンを処理できるキャパにしておきたいから、という理由で大きな数字を割り振るのはやめましょう。デフォルト値 (2048) または 4096 程度に変更し、短い文章のチャットでテストしてみてください。本来のスピードに近いパフォーマンスが出れば、ビンゴです。

コンテキストサイズとは: 英語では context size、他にコンテキストウィンドウ (context window)、コンテキスト長 (context length)、とも呼ばれる値で、LLM が一度のやりとりで処理できるトークン数の合計です。トークン数とは、日本語ならほぼ文字数、英語ならほぼ単語数とイコールです。上の表の Llama 3.1 を見ると 131072 となっていますので、単純に LLM への入力と生成されるテキストが同じ量であると想定すると入力に使えるのは半分なので、Llama 3.1 は約 6万5千文字の日本語の文章を入力に使用できる、そのキャパシティがあるということです。

コンテキストサイズを変更するところ

Dify

スタジオのアプリ内にある LLM ブロックを開き、モデル名をクリックすると細かい設定が行えます。下にスクロールすると Size of cont… (Size of content window) があるので、そこのチェックを外すか、「4096」を入力します。

無効化したときのデフォルト値は 2048

Continue (VS Code 用拡張機能)

コンフィグファイル config.json の LLM の設定内、contextLengthmaxTokens それぞれを 40962048 に変更します (maxTokensは LLMで生成されるトークンの最大値なので、半分にしています)。コンフィグファイルは Continue ペインのギアアイコンから開けます。

    {
      "title": "Chat: llama3.1:8b-instruct-fp16",
      "provider": "ollama",
      "model": "llama3.1:8b-instruct-fp16",
      "apiBase": "http://localhost:11434",
      "contextLength": 4096,
      "completionOptions": {
        "temperature": 0.5,
        "top_p": "0.5",
        "top_k": "40",
        "maxTokens": 2048,
        "keepAlive": 3600
      }
    }

LLM のコンテキストサイズを調べる

一番簡単なのは、Ollama のコマンドollama show <modelname>を使う方法です。context length として表示されます。実行例:

% ollama show llama3.1:8b-instruct-fp16
  Model                                          
  	arch            	llama 	                         
  	parameters      	8.0B  	                         
  	quantization    	F16   	                         
  	context length  	131072	                         
  	embedding length	4096  	                         
  	                                               
  Parameters                                     
  	stop	"<|start_header_id|>"	                      
  	stop	"<|end_header_id|>"  	                      
  	stop	"<|eot_id|>"         	                      
  	                                               
  License                                        
  	LLAMA 3.1 COMMUNITY LICENSE AGREEMENT        	  
  	Llama 3.1 Version Release Date: July 23, 2024

アプリケーションにモデルを追加する時のコンテキストサイズ指定

Dify のモデルプロバイダー Ollama

Dify に Ollama の LLM を追加する際、デフォルトで 4096 になっているところを上書きすることで、モデルのキャパシティ (Model context size) と生成されるトークンの上限 (Uper bound for max tokens) を設定できます。ただ上限をここでかけてしまうと作った AI アプリ側で不具合が出たときにデバッグしづらいので、追加の際にはどちらもモデルのコンテキストサイズ (context length の値) を入れておくのが良いと思います。そして、AI アプリ側の Size of content window で後述するほどよいコンテキストサイズを指定しましょう。

Continue の “models”

Continue の場合、設定内容はモデルを選択したときに使われるので、titleにコンテキストサイズに関する説明 (Fastest Max Size とか 4096 とか) を入れて、同じモデルで複数の異なったコンテキストサイズの設定を用意しておいても良いかもしれません。以下は、ボクが実際に 32GB RAM の M2 Max で試して Llama 3.1 (8B) の高速動作が確認できた値を入れてあります。Dify とは異なり、maxTokenscontextLengthと同じ値だとエラーになるため、半分にします。

    {
      "title": "Chat: llama3.1:8b-instruct-fp16 (Fastest Max Size)",
      "provider": "ollama",
      "model": "llama3.1:8b-instruct-fp16",
      "apiBase": "http://localhost:11434",
      "contextLength": 24576,
      "completionOptions": {
        "temperature": 0.5,
        "top_p": "0.5",
        "top_k": "40",
        "maxTokens": 12288,
        "keepAlive": 3600
      }
    }

LLM の処理が重いとき、何が起こっているか (状況からの想定)

ollama runで使用すると速いのに他のアプリから Ollama サーバ経由で使用すると重いのは、上記の通りコンテキストサイズが大きいことが原因のひとつです。実際に LLM が動作しているときに、ollama psコマンドを叩いてみましょう。以下は実行例ですが、上がモデルのコンテキストサイズ最大値を設定して反応が重い時、下がサイズを小さくして反応が速い時の出力です。SIZEPROCESSORの下に書かれている内容に注目してください。

% ollama ps
NAME                     	ID          	SIZE 	PROCESSOR      	UNTIL               
llama3.1:8b-instruct-fp16	a8f4d8643bb2	49 GB	54%/46% CPU/GPU	59 minutes from now	

% ollama ps
NAME                     	ID          	SIZE 	PROCESSOR	UNTIL              
llama3.1:8b-instruct-fp16	a8f4d8643bb2	17 GB	100% GPU 	4 minutes from now

重い時のSIZEは実モデルのサイズ (16 GB) よりもかなり大きい 49 GB となり、処理は CPU で 54%、GPU で 46% 行っています。ウラを取っていませんが、Ollama は実際に処理しているトークン数にかかわらず API で大きなコンテキストサイズを受け取ると、LLM のサイズ自体を大きく処理するようです。そのため、GPU の VRAM サイズを超えたモデルを動かしていると認識されるので (ユニファイドメモリの Mac ではほぼ意味がないですが) CPU とその配下の RAM も動員し、場合によってスワップも使用して処理するのでとてつもなく遅くなる、のであろうと考えています。そういう仕様なのだろうと。

ほどよいコンテキストサイズの値を見つける

さて、状況証拠からおおよその理由がわかったので、対策を取ります。4096トークンでまかなえるのであればそれで構いませんが、可能な限り大きなトークンを処理したいですよね。Ollama の仕様を見つけられれば良かったのですが諦め、手作業コンテキストサイズを 4096 の倍数で増減させながらチャットを繰り返し、PROCESSOR 100% GPUになる値を見つけ出しました。それが、24576 (4096*6) です。Llama 3.1 8B の F16 と DeepSeek-Corder-V2-Lite-Instruct の Q6_K なら 100% GPU で動きます。32 GB 以外のユニファイドメモリの方は、同様の方法で見つけ出してください。使った感じ、CPU 10%、GPU 90% くらいでも十分な速度が得られましたが、4096 の倍数以外の数字を使うと文字化けが発生したので、そこはご注意ください (DeepSeek-Corder-V2-Lite-Instruct の Q8_0 が該当)。また、Dify で同じコンテキストサイズを使った場合、Continue よりもSIZEが小さくなります。欲張ればもう少し増やせるかもしれませんので、必要に応じて試す価値はありそうです。時間はかかっても良いので長文を処理したい、原文を分割したくない、なんてケースでは、LLM の持つキャパを最大限使うという選択肢もアリだと思います。

Ollama、疑ってごめんね (読まなくて良い話)

Ollama 自体で動かしたら速いのに、API 経由で使うととてつもなく遅くなるんだから、Ollama のバグに違いない!サーバの処理がおかしいんだ!と決めつけて調べていたのですが、Windows 版で GPU を使ってくれないという Issue のやりとりにあった「context size を 4096 にして試したまえ」というアドバイスにハッとし、実際に試してみるとウソのように解決しました。Ollama さん、盛大に疑ってごめんなさい。

一番大きいモデルサイズは DeepSeek-Corder-V2236BLlama 3.1 にもなると 405B と完全なる貴族仕様で、利用可能なコンテキストサイズはそのまま小さな庶民サイズのモデルにも適用されています。もしかしたら将来的に Ollama サーバでは違う処理がされるのかもしれませんが、 少なくとも 2024年の晩夏現在、一般庶民 (レベルの RAM 容量) で快適に LLM を使うには、コンテキストサイズを自分で調整する必要がある、ということを学びました。

Image by Stable Diffusion (Mochi Diffusion)

小さなバイクが、ゴージャスなバンだかキャンピングカーだかピックアップトラックだかを抜き去る画像が欲しかったんですけど、バイク vs バイクだったり、逆車線で単純にすれ違っただけだったり、バンが見切れてたり、ただただバイクがかっこよく走ってるだけだったり、と非常に苦戦!疾走感が無いですが、小さい方が速い感を出せてるこれにキメタ!

Date:
2024年9月1日 2:57:00

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
A high-speed motorcycle overtaking a luxurious van

Exclude from Image:

Seed:
2448773039

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
All

© Peddals.com