その他

【Dify】HTTPリクエストで独自のAPIと繋いでみたら全然うまくいかんかった話

その他
この記事は約5分で読めます。

こんにちは、中川です。

初めて記事書きます。至らぬ点あるかと思いますがご了承願います。

早速本題。

Difyを使用してチャットボットの開発中、独自のAPIを分岐した処理に組み込みたかったのですがこれが全然うまくいかず、、、

先日ようやく解決できたので方法をまとめます。

環境

Windows10

WSL/Docker

Dify 0.6.12(アプリタイプ-チャットボット/BETA版chatflowを使用)

原因

HTTPリクエストに独自APIのURLを貼り接続を試すと以下のエラーを吐く。

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)

こちらはSSL証明書の信頼がなく起きるエラーです。

今回繋ぐAPIはSSL通信で、独自の証明書、いわゆるオレオレ証明書を使用しているためにDify側から信頼を得ることができず、このエラーが吐かれます。

解決策

Difyから信頼を得られずエラーが吐かれるのなら、Difyから信頼を得ればいいのです。

つまり、Difyを立てているDockerコンテナの認証局に独自証明書を配置し、信頼させます。

今回の手順、コードは全てこちらを参考にさせていただきました。

How to skip or fix SSL cert verification error · langgenius/dify · Discussion #4600
when i save openai provider with API Base(openai_api_base,base_url), got connection error, message is following httpx.ConnectError: certificate verify failed: ...

まずはAPIの証明書を用意しておきます。

ルート証明書と、中間証明書がある場合は中間証明書を含んだ証明書チェーンで発行することをおすすめします。2つのファイルでもできますが、面倒なので。

—–BEGIN CERTIFICATE—–

# ルート証明書

—–END CERTIFICATE——-

—BEGIN CERTIFICATE—–

# 中間証明書

—–END CERTIFICATE—–

こんな感じで2つとも1つのファイルに入っていると楽です。

証明書が用意できたらdify/docker配下に配置します。今回はdify/docker/certsというディレクトリを作成し格納しました。

証明書の格納ができたら、次はDockerfileを用意します。今回はdify/docker/直下にDockerfileを作成しました。

FROM langgenius/dify-api:0.6.12-fix1 # verによって異なるのでdocker-compose.yamlのapiのimageからコピペする

COPY ./certs/my_awesome_CA.crt /usr/local/share/ca-certificates/

RUN update-ca-certificates  # add to system CAs, probably not needed but can be useful
RUN cat /usr/local/share/ca-certificates/my_awesome_CA.crt >> /app/api/.venv/lib/python3.10/site-packages/certifi/cacert.pem # 要注意!!

WORKDIR /app/api

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

ここで注意点です。

RUN cat /usr/local/share/ca-certificates/my_awesome_CA.crt >> /app/api/.venv/lib/python3.10/site-packages/certifi/cacert.pem # 要注意!!

この行で証明書の中身を認証局(が参照する証明書がまとまったファイル)にコピーしているのですが、Difyのバージョンが異なるとコピー先が異なる可能性があります。(なんせ今まさに開発がガツガツ進んでいるホットな技術なので、、、私はこれにかなり振り回されました、、、お気をつけください、、)

実際に参考にしたコメントでは0.6.8を使用しているようですが、コピー先が異なります。

コピー先を確認する手段としては一度Difyを立ち上げたあとapiコンテナに入り以下を実行してみてください。

import certifi

certifi.where()

certifi.where()を実行するとパスが出てきます。そちらが実際の証明書の参照先になります。

パスが異なる場合は出力されたパスを貼り付けて実行してください。

次に、docker-compose.yamlを以下のように修正していきます。

services:
  # API service
  api:
    # image: langgenius/dify-api:0.6.12-fix1 # ここをコメントアウト
    build: # ここを追加
     context: . # ここを追加
     dockerfile: ./Dockerfile # ここを追加

先ほど作成したDockerfileでビルドするように変更しました。

ここまできたらあとはコンテナを立てるだけです。

通常はdocker compose up で立てますが、今回はDockerfileでのビルドに変更したのでdocker compose build --no-cache でビルドしたのち、docker compose up しましょう。

--no-cacheはたぶんなくても大丈夫ですが念の為です。念の為。

まとめ

ホットな技術についていこうとするのは大変ですね。。。

今回の手順はDockerfileの準備が必要だったり、ライブラリの下に証明書をコピーする必要があったりとあまりスマートな方法ではないらしいです。

環境変数で制御する方法があるようで検証したのですが、APIの接続はできるようになるものの、代わりにLLMなどで接続エラーが起きてしまいうまくいきませんでした。。。

こちらが解決したらまた記事にしたいと思います。

ここまでご覧いただきありがとうございました。