この記事を作った動機

 LibreChat を使っているうちに、色々躓いたことがあったので記録したい。躓いたことでなくてもまとめておきたいことは書きたい。

前提条件

環境構築をしたディレクトリが以下のパスになっている

 LibreChat の Docker 関連のファイルが以下のディレクトリにある事を前提に進める。通常であれば、各個人に合わせて作業して良い。私の場合はあくまで以下のパスにあるというだけである。

~/LibreChat

LLM サーバの構成と、LibreChatの関係

 以下の図のような関係になっている事を前提にする。

LLM server configulation

MainDesktop エンドポイント

  • エンドポイントまでのアドレスとポート番号の仮定
    http://192.168.x.a:8080/v1
  • 詳細な役割の説明
     純粋に llama.cpp を動かして1つのモデルを読み込んでいる LLM サーバ専用(Gemma-4-31Bを動かす専用)に割り当てた PC である。LibreChat はここではホストしていない。Intel ARC の XPU 環境であり、LM Studio ではそのポテンシャルを引き出せないため、llama.cpp を専用にコンパイルしてセットアップしてある。OpenAI 互換 API 経由で利用可能にしてある。

DataServer エンドポイント

  • エンドポイントまでのアドレスとポート番号の仮定
    http://192.168.x.b:1234/v1
  • 詳細な役割の説明
     LM Studio を使って LLM を動かしている。こちらは、MainDesktop と異なり、NVIDIA の CUDA 環境であるため、LM Studio でポテンシャルを引き出すことができることから、LM Studio を使っている。LM Studio 標準の開発者機能から、OpenAI 互換 API 経由で利用可能にしてある。基本的に LM Studio の LLM サーバーが、LibreChat の要求に答えて選択されたモデルを自動的にロードし動かしてくれるため、いろんなモデルを動かすために使う。

その他諸々

  • Linux 環境である
  • docker、docker-composeパッケージが入っている
  • 全ては LAN 内で行われ、グローバル空間からのアクセスはできないようにしてある環境である。外出先からの利用はすべて VPN を通じて行う。

基本的な操作

設定ファイル保存場所

~/LibreChat/librechat.yaml

設定反映方法 (librechat.yaml)

 私の場合は、~/LibreChatにおいて以下のスクリプトをrestart.shとして配置し、実行することでlibrechat.yamlの変更内容を反映できる事を確認した。docker グループに入っていないユーザは、管理者権限を付与してコマンドを実行することで docker を操作できる。

#!/bin/bash
sudo docker compose down
sudo docker compose up -d

エンドポイント (OpenAI API 互換サーバ) の追加方法

 今回は、例として LM Studio の開発者モードで動かすことができる LLM サーバ (エンドポイント) を追加する例を以下に示す。前提として、既に LM Studio の LLM サーバーは動いていることがある。OpenAI 互換 APIサーバのエンドポイントは、custom セクションの中に記述する。利用可能なモデルは、LM Studio に対して、LibreChat が自動取得するように今回は設定しており、fetch: trueとしている。これについては注意点があり、lm-studio-のネットワーク設定の制限の引っかかっているを参照すること。

エンドポイントの追加前の設定例

# ...
endpoints:
  custom:
    - name: 'MainDesktop'
      apiKey: 'not-needed'
      baseURL: 'http://192.168.x.a:8080/v1'
      models:
        default: ['Gemma-4-31B']
        fetch: false
      titleConvo: true
      titleModel: 'Gemma-4-31B'
      modelDisplayLabel: 'Gemma-4-31B'

modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom"
        model: "Gemma-4-31B"
# ...

エンドポイントの追加後の設定例

# ...
endpoints:
  custom:
    - name: 'MainDesktop'
      apiKey: 'not-needed'
      baseURL: 'http://192.168.x.a:8080/v1'
      models:
        default: ['Gemma-4-31B']
        fetch: false
      titleConvo: true
      titleModel: 'Gemma-4-31B'
      modelDisplayLabel: 'Gemma-4-31B'
    - name: 'DataServer'
      apiKey: 'not-needed'
      baseURL: 'http://192.168.x.b:1234/v1'
      models: 
        default: ['test-model'] 
        fetch: true

modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom"
        model: "Gemma-4-31B"
# ...

躓いたこと

LM Studio の API サーバーを使いたい

エンドポイントの指定が間違っている (Linux 環境特有)

 Linux 環境の Docker では、host.docker.internal を Docker のホストマシンの localhost にアクセスするために使うことができない。私は単純にホストマシンの物理 NIC に割り当てられている IP(192.168.x.b) を直接指定することにした。

LM Studio のネットワーク設定の制限の引っかかっている

 Docker コンテナからのアクセスは別のネットワークからのアクセスとなるからか、以下の設定をしないと LM Studio のログにはアクセスできたように見えても、LibreChatは動作しなかった。動作に失敗したときのLibreChatの設定は、costomエンドポイントの設定をすべて無視して、デフォルトのOpenAIなどのリスティングしかしなくなる。つまりは、今まで正常に動いていたエンドポイントまで巻き添えにして、機能しなくなるので注意する。

LM Studio ネットワーク設定の様子

エンドポイントとモデル名を変更したら、過去のチャットを継続できなくなった

 LibreChat の場合は、既存のセッションに対して柔軟でないらしく、既存のLLM サーバに対するエンドポイント名とモデル名を変更すると、セッションを継続して利用できなくなってしまう。

 具体的には、設定を以下のように変更したあと、過去のセッションにアクセスすると、“モデル選択"と表示されそのままでは新しいプロンプトを受け付けず、かと行って新しく設定したセッションを選択しても、新しいセッションに飛ばされて、過去のセッションは継続できないということになった。

  • 古い設定の例 (librechat.yaml)
# ...
endpoints:
  custom:
    - name: 'Llama-CPP'
      apiKey: 'not-needed'
      baseURL: 'http://192.168.x.a:8080/v1'
      models:
        default: ['Local-Custom']
        fetch: false
      titleConvo: true
      titleModel: 'Local-Custom'
      modelDisplayLabel: 'Llama.cpp'

modelSpecs:
  list:
    - name: "Llama-CPP"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom"
        model: "Local-Custom"
# ...
  • 新しい設定の例 (librechat.yaml)
# ...
endpoints:
  custom:
    - name: 'MainDesktop'
      apiKey: 'not-needed'
      baseURL: 'http://192.168.x.a:8080/v1'
      models:
        default: ['Gemma-4-31B']
        fetch: false
      titleConvo: true
      titleModel: 'Gemma-4-31B'
      modelDisplayLabel: 'Gemma-4-31B'

modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom"
        model: "Gemma-4-31B"
# ...

 これに関しては、LibreChat が docker コンテナのスタックに含んでいる DB にアクセスして、古いセッションのエンドポイント名とモデル名を過去のものから新しいものに更新すること(Gemma4提案)で、古いセッションでも継続して利用できるようになる事を確認した。以下に DB の操作例を示す。

DB 操作例の前提

  • 古いモデル名
    Local-Custom
  • 新しいモデル名
    Gemma-4-31B
  • 古いエンドポイント名
    Llama-CPP
  • 新しいエンドポイント名
    MainDesktop
  • DB コンテナ名
    chat-mongodb

DB にアクセス

docker exec -it chat-mongodb mongosh

モデル名変更

use LibreChat;
db.conversations.distinct("model");
-- [
--   'Gemma-4-31B',
--   'Local-Custom',
--   'gemini-3-flash-preview',
--   'google/gemma-3n-e4b'
-- ]
db.conversations.updateMany(
  { model: "Local-Custom" }, 
  { $set: { model: "Gemma-4-31B" } }
);
-- {
--   acknowledged: true,
--   insertedId: null,
--   matchedCount: 486,
--   modifiedCount: 486,
--   upsertedCount: 0
-- }
db.conversations.distinct("model")
-- [ 'Gemma-4-31B', 'gemini-3-flash-preview', 'google/gemma-3n-e4b' ]

エンドポイント名変更

db.conversations.distinct("endpoint")
-- [ 'DataServer', 'Llama-CPP', 'MainDesktop', 'google' ]
db.conversations.updateMany(
  { endpoint: "Llama-CPP" }, 
  { $set: { endpoint: "MainDesktop" } }
);
-- {
--   acknowledged: true,
--   insertedId: null,
--   matchedCount: 486,
--   modifiedCount: 486,
--   upsertedCount: 0
-- }
db.conversations.distinct("endpoint")
-- [ 'DataServer', 'MainDesktop', 'google' ]

アプデしたらプロンプトが正しく送信されなくなることがあった (2026年9月27日追記)

 LibreChat のコンテナをアプデしたところ、1万コンテキスト程度の長さのテキストを添付すると、添付したファイルと本来一緒に送られるはずのユーザのセッション内のプロンプトが送信されないということになった。調査してみたところ、以下のlibrechat.yamlにおける設定が重要であることがわかった。最近の LibreChat では添付ファイルの扱いが変わっているらしく、以前はテキストとして送信するか、画像として送信するか、LLM エンドポイント先に送るか(プロバイダに送信するか)が選べたが、今はデフォルトでは出てこなくなるようになっている。その設定項目において、旧来の UI/UX を使おうとすると不具合が再現するようである。

 問題が再現すると、LLMは、添付したテキストしか受け取れず、ユーザが要約を求めているのだとして出力をし始めて、ユーザのプロンプトの指示に全くそぐわない見当違いのチグハグな出力をするようになる。

 色々試しているので厳密な対照実験とはなっていないが、私のケースでは、legacyFileUploadUXをtrueからfalseにすることで問題が解決されたように見受けられた。maxContextTokensなどのトークン数の制限に関しては、試しているテストプロンプトやテスト添付ファイルに対して、十分大きくなるようにしか設定しておらず、適切な設定をしているわけではないため注意する。以下の設定例におけるトークン数の設定は、あくまで問題の切り分けとして、LibreChat 側の制限に引っかからないようにするために、設定している。通常は適宜利用しているLLMエンドポイントの性能や運用上の都合に合わせて制限を設定する必要がある。以下の設定はあくまで自分用にしか使っていないので相当制限をゆるく怠惰に満足するくらいで設定しているというのもある。

現在の設定の一部の例

# ...
modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom"
        model: "Gemma-4-31B"
        maxContextTokens: 200000
        max_tokens: 500000

fileConfig:
  serverFileSizeLimit: 200
  endpoints:
    custom:
      fileLimit: 30
      fileSizeLimit: 200
      totalSizeLimit: 1000
      supportedMimeTypes:
        - "image/.*"
        - "text/*"
        - "application/pdf"
      legacyFileUploadUX: false  # 今回問題となった設定の部分である。これを true にすると、旧来の UI/UX として、テキストとして送信するか、プロバイダに送信するかなどを選ぶことができるようになる。ただ内部ロジックも古いものになってしまうようでバグが発生しているように見受けられる。
      fileTokenLimit: 100000
      fileContextCharLimit: 100000
      defaultLLMDeliveryPath:  # llama.cpp 対策。llama.cppは直接PDFをサポートしない
        overrides:
          'application/pdf': text
  ocr:
    supportedMimeTypes:
      - "^image/(jpeg|gif|png|webp|heic|heif)$"
      - "^application/pdf$"
      - "^application/vnd\\.openxmlformats-officedocument\\.(wordprocessingml\\.document|presentationml\\.presentation|spreadsheetml\\.sheet)$"
      - "^application/vnd\\.ms-(word|powerpoint|excel)$"
      - "^application/epub\\+zip$"
  text:
    supportedMimeTypes:
      - "^text/(plain|markdown|csv|json|xml|html|css|javascript|typescript|x-python|x-java|x-csharp|x-php|x-ruby|x-go|x-rust|x-kotlin|x-swift|x-scala|x-perl|x-lua|x-shell|x-sql|x-yaml|x-toml)$"
  stt:
    supportedMimeTypes:
      - "^audio/(mp3|mpeg|mpeg3|wav|wave|x-wav|ogg|vorbis|mp4|x-m4a|flac|x-flac|webm)$"
# ... 

fileConfigの設定項目が反映されていない (2026年9月27日追記)

 librechat.yamlの設定項目では、一度に添付できるファイルの数やサイズを制限する設定があり、設定していない場合デフォルト値が使われるということがある。アプデしたらプロンプトが正しく送信されなくなることがあったの調査過程より問題が発覚した。もっとデフォルとより大きくたくさんのファイルを添付したいとなると、設定が必要になるが、今まで正しく反映できていないことがわかり修正した。

 正しく設定を反映できていないときは、設定した通りの添付ファイル制限にならず、10個までしか添付できないなど、デフォルトのままになるという挙動になる。

問題がある例

# ...
modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom" # fileConfig の endpoints の項目において反映すべき名前
        model: "Gemma-4-31B"
        maxContextTokens: 200000
        max_tokens: 500000

fileConfig:
  serverFileSizeLimit: 200
  endpoints:
    assistants: # modelSpecs の項目で設定した endpoint 名にになっておらず、存在しないエンドポイント `assistants` に設定していることになっている。
      fileLimit: 30
      fileSizeLimit: 200
      totalSizeLimit: 1000
      supportedMimeTypes:
        - "image/.*"
        - "text/*"
        - "application/pdf"
      legacyFileUploadUX: false  
      fileTokenLimit: 100000
      fileContextCharLimit: 100000
      defaultLLMDeliveryPath:  # llama.cpp 対策。llama.cppは直接PDFをサポートしない
        overrides:
          'application/pdf': text
# ...

正しく反映されている例

# ...
modelSpecs:
  list:
    - name: "Main"
      label: "Default: Llama-CPP"
      description: "My primary local model"
      preset:
        endpoint: "custom" # fileConfig の endpoints の項目において反映すべき名前
        model: "Gemma-4-31B"
        maxContextTokens: 200000
        max_tokens: 500000

fileConfig:
  serverFileSizeLimit: 200
  endpoints:
    custom: # modelSpecs の項目で設定した endpoint 名になっている
      fileLimit: 30
      fileSizeLimit: 200
      totalSizeLimit: 1000
      supportedMimeTypes:
        - "image/.*"
        - "text/*"
        - "application/pdf"
      legacyFileUploadUX: false  
      fileTokenLimit: 100000
      fileContextCharLimit: 100000
      defaultLLMDeliveryPath:  # llama.cpp 対策。llama.cppは直接PDFをサポートしない
        overrides:
          'application/pdf': text
# ...

MCP サーバがタイムアウトする (2026年9月27日追記)

 最近 FastMCP を使った MCP サーバとして、hello30190f/Modular-MCP-Serverを作り、LibreChat にてフロントエンド側からエンドポイントを指定し、動かすということがあった。作ったMCP サーバは基本的に決まったスクリプトを書けばいくらでも MCP ツールを追加できるようになっているが、その一部のツールの実装において、画像などの処理に時間がかかり、LibreChatのデフォルトのタイムアウトの時間(多分1分くらい)を過ぎてしまい、結果失敗扱いになってしまうということがあった。

MCPのフロントエンドにおける設定画面.png

 タイムアウト時間は、フロントエンドからは設定できないらしく、librechat.yamlにて MCP サーバを直接明示し、その過程でタイムアウトを記述するという手法しか現状では取れていない。開発サーバとして MCP サーバを動かす際には、設定の存在を忘れたりするなどなにかと管理上不都合で不便だと思ったが、現状はその方法しか機能することやできることを確かめられていない。

現状の設定例

 MCP サーバのポート番号と IP アドレスは適宜設定すること。

# ...
mcpSettings:
  allowedAddresses:
    - "192.168.xxx.xxx:8000" 

mcpServers:
  MCP-dev:
    type: sse
    url: "http://192.168.xxx.xxx:8000/sse"
    timeout: 300000 # 5 * 60 * 1000 ms = 5分
# ...

関連する記事や外部サイトとか

使った画像とか

参考にしたサイトとか