LLM推論処理時間の長さに待てないDify

dify

最近、ドキュメントレビューツールを弄りつつしてると、こんなエラーが出るようになり、これの修正にかなりの時間を要したので備忘録としても記事化しときます。

Failed to transform agent message: req_id: 22f7893016 PluginInvokeError: {"args":{},"error_type":"Exception","message":"read llm model failed: read tcp 172.18.0.9:34414-\u003e172.18.0.14:5001: use of closed network connection\nfailed to read system header"}

見てると、丁度このタイミング。

ReactAgentが調査結果を出力してる途中。コンテナからは以下のようなエラーが plugin_daemon から出てました。

 2026-09-22T04:20:12.769290749Z ERROR dify-plugin-daemon generic.go:141 trace_id=e359e1ffabdae137037b6e3c3a560c5c tenant_id=7af8330a-9549-40af-b6e0-7b4b3e0267f0 plugin returned error response plugin=langgenius/agent:0.0.47@b14b5a5259094510a272e5b7facd09aa63352511c13fabcde36a4cac57d1da94 runtime_type=local error_type=Exception message="read llm model failed: read tcp 172.22.0.11:48240->172.22.0.14:5001: use of closed network connection\nfailed to read system header" args=map[] session_id=609eeaf7-4d2e-4ab9-85a5-712943cec63a action=invoke_agent_strategy

Plugin_Daemonの隠しパラメータ

実は、PluginDaemonだけに適用される環境変数というものがあります。plugin_daemon用のこのパラメータは、github上だと plugin_daemon 側の.envにしか情報がありません。

dify-plugin-daemon/.env.example at main ?? langgenius/dify-plugin-daemon
Contribute to langgenius/dify-plugin-daemon development by creating an account on GitHub.

具体的な項目と説明は下記の通りです。

環境変数説明
DIFY_BACKWARDS_INVOCATION_WRITE_TIMEOUTdifyの逆呼び出しにおける書き込みタイムアウト時間
DIFY_BACKWARDS_INVOCATION_READ_TIMEOUTdifyの逆呼び出しにおける読み込みタイムアウト時間
DIFY_BACKWARDS_INVOCATION_LLM_TOTAL_TIMEOUTLLM専用の逆呼び出し処理時間制限。これらはツール、埋め込みデータ、ストレージ、その他の逆呼び出しには影響しません。
値が0の場合は親プロセスから継承され、無制限を意味します。合計時間には接続設定/ヘッダー/ボディの処理時間も含まれ、呼び出し元からのキャンセル条件にも制限されます。
DIFY_BACKWARDS_INVOCATION_LLM_FIRST_RESPONSE_TIMEOUT最初にデコードされた応答フレームのタイムアウト時間。最終的な応答を待つブロック型 LLM 呼び出しのタイムアウト値としても機能します。
DIFY_BACKWARDS_INVOCATION_LLM_IDLE_TIMEOUT読み取りアイドルタイマーは最初のフレーム受信後に開始し、受信バイト数/フレーム数に応じてリセットされます。
デフォルト値は DIFY_BACKWARDS_INVOCATION_READ_TIMEOUT に設定されます。

何が問題だったのか?

今回、不具合が起きたのは以下のロジックです。

エージェントとしての推論リクエストを出すのはapiコンテナです。そのリクエストはPlugin_daemonに送られ、Plugin_daemonは内部のllama.cppにリクエストを出してLLMエンジンとしての推論結果をStreaming方式で応答するわけですが、plugin_daemonはこの応答処理の時間上限を240secと決めています。それは、直接的にはLLM_TOTAL_TIMEOUTです。

LLM_TOTAL_TIMEOUTは基本的にDIFY_BACKWARDS_INVOCATION_READ_TIMEOUTと言う環境変数から継承する仕組みになっており、そこが240sec(240,000ms)と規定しているために240secが上限となっています。今回、私はLLMから応答にかかった時間としては以下のようになっており、それ故にタイムアウトしてとエラーとなってしまったのだろうと考えられます。

 eval time =  280412.62 ms /  7033 tokens (   39.88 ms per token,    25.08 tokens per second)

実際、エラーが出たのはあくまでPlugin_daemon側のみで、api側では目立つ形でエラー発生の形跡はありませんでした。そして、240secでタイムアウトしたというのは、実際にllama.cppのログとapiログ、plugin_daemonログを並べて表示させて再試行してる最中に確認できたモノですので、タイミングに間違いはありませんでした。

今回、それなりに長文ドキュメントを処理してもらったため、それなりのトークン量を持って応答してもらう必要があったため、出力には280秒かかっていることが分かります。それ故にタイムアウトして処理が中断されたのだと考えられます。

値の修正は docker-compose.yaml への書込み

これらの値を修正するには、単純に.envを修正すれば良いということにはなりません。dify自体の docker-compose.yaml にはそれらは Build 時にしか適用されず、内的に規定された値に従って処理が行われるためです。なので、今回 docker-compose.yaml にこれらの設定を書込んであげる必要があります。

私はこの手の処理をローカルLLMを用いて行うため、そのことを踏まえたタイムアウト設定(240sec→900secに変更)を行い、保存することにしました。これにより、無事ドキュメントレビューツールは使えるようになったわけですが、推論時間がかかる場合の考慮というのは、クラウド外部型のLLMを使ったら確かにささっと出てくることを考えると、なかなか気づきにくいポイントなのかもしれません。

  # plugin daemon
  plugin_daemon:
    image: langgenius/dify-plugin-daemon:0.6.10-local
    deploy:
      replicas: 2
    restart: always
    env_file:
      - path: ./envs/core-services/shared.env
        required: false
      - path: ./envs/core-services/plugin-daemon.env
        required: false
      - path: ./envs/security.env
        required: false
      - path: ./envs/databases/db-postgres.env
        required: false
      - path: ./envs/databases/db-mysql.env
        required: false
      - path: ./envs/databases/redis.env
        required: false
      - ./.env
    networks:
      - ssrf_proxy_network
      - default
    environment:
      DB_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
      DB_SSL_MODE: ${DB_SSL_MODE:-disable}
      SERVER_PORT: ${PLUGIN_DAEMON_PORT:-5002}
      SERVER_KEY: ${PLUGIN_DAEMON_KEY:-**************************************}
      MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
      PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
      DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001}
      DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-***************************************}
      PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
      PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
      PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
      FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true}
      PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
      PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
      PLUGIN_STDIO_BUFFER_SIZE: ${PLUGIN_STDIO_BUFFER_SIZE:-1024}
      PLUGIN_STDIO_MAX_BUFFER_SIZE: ${PLUGIN_STDIO_MAX_BUFFER_SIZE:-5242880}
      PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
      PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
      PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
      PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
      PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
      PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
      PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
      S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
      S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
      S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
      S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
      AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
      AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
      AWS_REGION: ${PLUGIN_AWS_REGION:-}
      AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
      AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
      TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
      TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
      TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
      ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
      ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
      ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
      ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
      ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
      ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
      VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
      VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
      VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
      VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
      SENTRY_ENABLED: ${PLUGIN_SENTRY_ENABLED:-false}
      SENTRY_DSN: ${PLUGIN_SENTRY_DSN:-}
      DIFY_BACKWARDS_INVOCATION_WRITE_TIMEOUT: 10000
      DIFY_BACKWARDS_INVOCATION_READ_TIMEOUT: 900000
      DIFY_BACKWARDS_INVOCATION_LLM_TOTAL_TIMEOUT: 1200000
      DIFY_BACKWARDS_INVOCATION_LLM_FIRST_RESPONSE_TIMEOUT: 1200000
      DIFY_BACKWARDS_INVOCATION_LLM_IDLE_TIMEOUT: 900000
    #ports:
      #- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
    volumes:
      - ./volumes/plugin_daemon:/app/storage
    depends_on:
      db_postgres:
        condition: service_healthy
        required: false
      db_mysql:
        condition: service_healthy
        required: false
      oceanbase:
        condition: service_healthy
        required: false
      seekdb:
        condition: service_healthy
        required: false

参考になれば幸いです。

コメント

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