DifyのフローをChatbot UIから利用する(dify2openai)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/43c1bd2b-c2ea-cd9f-6c95-f58144bfab56.png)

作成日：2024年9月20日(金)

## １．はじめに
Dify（Do It For Yourselves）は非常に優れたローコード大規模言語モデルアプリケーション開発プラットフォームですが、少し残念な点があります。
それは作成したチャットボットのURLにハッシュコードのようなコードが含まれることと、チャットボットのWebインターフェースはシンプルなもので、チャットのスレッドの管理機能しかありません。
そこで、Difyで作成したチャットボット、ワークフローで設定が可能なAPIを使用して、外部からDifyを呼び出すことを考えました。
実際に調べてみるとDifyのAPIの固有のAPIに対応したチャットボットWeb UIを見つけることができず、OpenAI API Compatibleならば良かったのにと思っていたところ、[fatwang2/dify2opeai](https://github.com/fatwang2/dify2openai)を発見したので、使い方を含め紹介したいと思います。

![Dify_workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/eb1f1a9c-2a64-35cd-43c5-1b30d4e23023.png)

## ２．dify2openaiとは
dify2openaiは、DifyのフローをOpenAI互換のAPIとして利用できるようにするツールです。これにより、DifyのフローをChatbot UIなどの既存のOpenAI互換のインターフェースから簡単に利用することが可能になります。dify2openaiを使用することで、開発者はDifyの高度な機能を活用しつつ、使い慣れたOpenAI互換のAPIを介してアプリケーションを構築できます。
GitHubの[fatwang2/dify2opeai](https://github.com/fatwang2/dify2openai)を見てみると[0w0z/Dify2OpenaiApi](https://github.com/0w0z/Dify2OpenaiApi)からフォークしていて独自拡張をしているようで、2024年9月8日(日)時点で本家のスターが13なのに対して、[fatwang2/dify2opeai](https://github.com/fatwang2/dify2openai)は281です。
なかなかの人気だと思います。

```mermaid
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#FFD1DC', 'secondaryColor': '#E6E6FA', 'tertiaryColor': '#F0FFF0', 'mainBkg': '#FAFAFA', 'nodeBorder': '#FFB6C1', 'clusterBkg': '#FFF0F5', 'clusterBorder': '#FFB6C1', 'lineColor': '#FFB6C1', 'fontFamily': 'arial', 'fontSize': '14px'}}}%%
graph LR;
A["Chatbot UI"]:::pastelBlue --> |"OpenAI Compatible API"| B["dify2openai"]:::pastelGreen;
B --> |"Dify API"| C["Dify"]:::pastelPink;

classDef pastelBlue fill:#E6E6FA,stroke:#9370DB;
classDef pastelGreen fill:#F0FFF0,stroke:#98FB98;
classDef pastelPink fill:#FFE4E1,stroke:#FFB6C1;
```
上の図は、Chatbot UI、dify2openai、Difyの関係を示しています。Chatbot UIはOpenAI互換のAPIを使用してdify2openaiと通信し、dify2openaiはDify APIを使用してDifyと通信します。これにより、既存のChatbot UIからDifyの高度な機能を簡単に利用することができます。

https://github.com/fatwang2/dify2openai

### 2.1.サポート機能
[fatwang2/dify2opeai](https://github.com/fatwang2/dify2openai)の2024年9月8日(日)時点のサポート機能を以下にまとめます。
残念ながらマルチモーダルの中継に対応できていません。
但し、fatwang2氏はreadme.mdの中のRoadmapでマルチモーダル機能についてもサポート意思を表明していますので、期待しかありません。
Dockerもビルドが必要なので企業プロキシ配下では少しビルドの設定が面倒です。

| No | 機能 | サポート済み | 説明 |
| --- | --- | --- | --- |
| 1 | Dify APIをOpenAI APIに変換 | ✔ | OpenAI APIインタフェースをDify APIインタフェースに中継 |
| 2 | チャットのストリーミングとブロッキング | ✔ | チャット表示時のストリーミング（少しずつ表示される）サポート |
| 3 | Chat、Completion、Agent及び、Workflow botsの APIをサポート | ✔ | Difyで作成したチャットボットやワークフローのAPIをサポート |
| 4 | 変数のサポート | ✔ | Difyの変数をサポート（具体的なイメージが分かりませんでした） |
| 5 | Difyのメモリー機能(継続的な会話)サポート | ✔ | Dify側で過去の会話履歴を一時的に記憶し、継続的な会話をサポート  <bR<※殆どのチャットボットにはこの機能がありますので、チャットボットから使用する場合はメモリー機能をOffにしないと２重で聞いてしまいます。  <br>※プログラムなどから利用する場合は便利な機能かと思います |
| 6 | Docker | ✔ | Dockerfileによるビルド、Docker Composeによる起動をサポート  <br>※ビルド必須なので、企業プロキシ配下でビルドが面倒な場合は扱いにくいです。 |
| 7 | Zeabur、Vercelへのデプロイサポート | ✔ | 主要ホスティングサービスのZeabur、Vercelに対応 |
| 8 | 画像のサポート |  | マルチモーダルでチャットに画像をアップロードしたものを中継 |
| 9 | STT(Speach To Text)のサポート |  | マルチモーダルの音声ファイルをアップロードしてテキストを生成する機能 |
| 10 | TTS(Text to Speach)のサポート |  | テキストからマルチモーダルの音声ファイルを出力する機能 |

## ３．起動方法

### 3.1.Git Clone
**①推奨のGit Clone方法**
```bash
git clone https://github.com/fatwang2/dify2openai.git
```

※2024年5月4日(土)の V0.0.7のタグには2024年6月19日(水)～6月21日(金)のCommitのDockerfileのサポートが入っていないので注意が必要です。必ず最新版からCloneしましょう

**②非推奨のGit Clone方法**
```bash
git clone https://github.com/fatwang2/dify2openai.git -b V0.0.7 dift2openai_v0.0.7
```

### 3.2.ビルド

Dockerfileがあるdify2openaiフォルダでdocker buildします。

```bash
Q:\OneDrive\Docker>cd dify2openai

Q:\OneDrive\Docker\dify2openai>docker build -t dify2openai:latest .
[+] Building 1.8s (11/11) FINISHED                                                                 docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 421B                                                                               0.0s
 => [internal] load metadata for docker.io/library/node:16-alpine                                                  1.6s
 => [auth] library/node:pull token for registry-1.docker.io                                                        0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/5] FROM docker.io/library/node:16-alpine@sha256:a1f9d027912b58a7c75be7716c97cfbc6d3099f3a97ed84aa490be9dee  0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 98B                                                                                   0.0s
 => CACHED [2/5] WORKDIR /usr/src/app                                                                              0.0s
 => CACHED [3/5] COPY package*.json ./                                                                             0.0s
 => CACHED [4/5] RUN npm install                                                                                   0.0s
 => CACHED [5/5] COPY app.js ./                                                                                    0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:87f657f8d4eeaef6519afd4821282ecaea51d8d45600e38de0d586f7ecc0a5ce                       0.0s
 => => naming to docker.io/library/dify2openai:latest                                                              0.0s

View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/6cm5d3uty2u288qsuk1e8hu0p

Q:\OneDrive\Docker\dify2openai>
```

Dockerイメージを見てみるとdify2openai:latestが作成されています。

```bash
Q:\OneDrive\Docker\dify2openai>docker images
REPOSITORY                  TAG         IMAGE ID       CREATED         SIZE
langgenius/dify-web         0.7.3       100da9a2dbf7   4 days ago      234MB
langgenius/dify-api         0.7.3       095312d834cd   4 days ago      2.49GB
chatbotui-supabase          1.0         a8bf8d7cc01d   13 days ago     3.23GB
**dify2openai                 latest      87f657f8d4ee   2 weeks ago     134MB**
langgenius/dify-sandbox     0.2.6       112495cf3e96   2 weeks ago     513MB
ubuntu/squid                latest      c784fd269ca6   3 weeks ago     213MB
nginx                       latest      39286ab8a5e1   3 weeks ago     188MB
postgres                    15-alpine   fc9156a9e8b8   4 weeks ago     243MB
redis                       6-alpine    7de0dedd123b   3 months ago    30MB
semitechnologies/weaviate   1.19.0      8ec9f084ab23   16 months ago   52.5MB

Q:\OneDrive\Docker\dify2openai>
```

※企業プロキシの設定が面倒でビルドが簡単にできない方のためにビルドしたものを私のDockerHubにPushしておきます。

```bash
Q:\OneDrive\Docker\dify2openai>docker login -u potofo -p **********************
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded

Q:\OneDrive\Docker\dify2openai>docker tag dify2openai:latest potofo/dify2openai:latest

Q:\OneDrive\Docker\dify2openai>docker push potofo/dify2openai:latest
The push refers to repository [docker.io/potofo/dify2openai]
0d7b5e51122b: Pushed
d75e25e1bebb: Pushed
21796c863329: Pushed
b2e20e1a2ff5: Pushed
365ccd918307: Mounted from library/node
1bba629c69e9: Mounted from library/node
139c1270acf1: Mounted from library/node
4693057ce236: Mounted from library/node
latest: digest: sha256:23086c8fa7029adaf5af02cb7c8eef64d24d74b1916de02df24767dde45d8024 size: 1992

Q:\OneDrive\Docker\dify2openai>
```

https://hub.docker.com/repository/docker/potofo/dify2openai

### 3.3.docker-compose.ymlの編集
**①ビルドできた方向け**
　オリジナルのdocker-compose.ymlのDIFY_API_URLをDifyのAPIエンドポイントに修正します。
　ローカルで動かしている場合はhttp://localhost/v1です。

```plaintext
version: '3.5'
services:
  dify2openai:
    container_name: dify2openai
    build:
      context: .
      dockerfile: Dockerfile
    network_mode: bridge
    ports:
      - "3010:3000"
    restart: always
    environment: 
      - DIFY_API_URL=https://api.dify.ai/v1
      - BOT_TYPE=Chat
      - MODELS_NAME=dify
```

**②私のビルドしたイメージを使う方向け**
 　①のdocker-compose.ymlとの違いは「image: potofo/dify2openai:latest」行のみです。
　 potofo/dify2openaiは私のDockerHubリポジトリです。

```plaintext
version: '3.5'
services:
  # dify2openai API relay service
  dify2openai:
    image: potofo/dify2openai:latest
    container_name: dify2openai
    network_mode: bridge
    ports:
      - "3010:3000"
    restart: always
    environment: 
      - DIFY_API_URL=http://localhost/v1
      - BOT_TYPE=Chat
      - MODELS_NAME=dify
```

### 3.3.Docker Composeでの起動

**①ビルドできた方**

```bash
Q:\OneDrive\Docker\dify2openai>docker compose up -d
[+] Running 1/1
 ✔ Container dify2openai  Started                                                                                  0.6s

Q:\OneDrive\Docker\dify2openai>
```

```bash
Q:\OneDrive\Docker\dify2openai>docker ps
CONTAINER ID   IMAGE                              COMMAND                   CREATED         STATUS                  PORTS                                      NAMES
**68a6ad1226d8   dify2openai-dify2openai            "docker-entrypoint.s…"   4 minutes ago   Up 4 minutes            0.0.0.0:3000->3000/tcp                     dify2openai**
6e1854aada91   nginx:latest                       "sh -c 'cp /docker-e…"   11 hours ago    Up 11 hours             0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   docker-nginx-1
38bd486f4096   langgenius/dify-api:0.7.3          "/bin/bash /entrypoi…"   11 hours ago    Up 11 hours             5001/tcp                                   docker-api-1
a0dca28c8ec2   langgenius/dify-api:0.7.3          "/bin/bash /entrypoi…"   11 hours ago    Up 11 hours             5001/tcp                                   docker-worker-1
2b569c2073c9   ubuntu/squid:latest                "sh -c 'cp /docker-e…"   11 hours ago    Up 11 hours             3128/tcp                                   docker-ssrf_proxy-1
591ba2172ebb   redis:6-alpine                     "docker-entrypoint.s…"   11 hours ago    Up 11 hours (healthy)   6379/tcp                                   docker-redis-1
aa1b860a6af2   semitechnologies/weaviate:1.19.0   "/bin/weaviate --hos…"   11 hours ago    Up 11 hours
                                      docker-weaviate-1
5e7f62c4d619   langgenius/dify-sandbox:0.2.6      "/main"                   11 hours ago    Up 11 hours
                                       docker-sandbox-1
068e839f23e8   postgres:15-alpine                 "docker-entrypoint.s…"   11 hours ago    Up 11 hours (healthy)   5432/tcp                                   docker-db-1
72f39d066664   langgenius/dify-web:0.7.3          "/bin/sh ./entrypoin…"   11 hours ago    Up 11 hours             3000/tcp                                   docker-web-1

Q:\OneDrive\Docker\dify2openai>
```

**②私のビルドしたイメージを使う**
「[GitHub ActionsからDocker Hubに自動プッシュ](https://qiita.com/potofo/items/b8c55c4766dbc9abffc4)」の記事でdify2openaiのGitHubリポジトリをフォークして、GitHub Actionsのワークフロー機能でビルドしたものです。
dify2openaiの作者のfatwang2氏にはGitHub Actionの動かし方を
[CI): Setup GitHub Actions workflow for Docker image build and push #6](https://github.com/fatwang2/dify2openai/pull/6#issuecomment-2351218203)のスレッドで説明しているのですが、2024年9月20日時点で対応はしてくれていません。
従って私がビルドしたイメージをDockerHubの[porofo/dify2openai](https://hub.docker.com/repository/docker/potofo/dify2openai)に置いておきますのでそちらをお使いください。

※dify2openai Pulledとなっているのでインターネット経由でDockerHubの[porofo/dify2openai](https://hub.docker.com/repository/docker/potofo/dify2openai)をpullできていることが確認できます。
```bash
Q:\OneDrive\Docker\dify2openai>docker compose up -d
[+] Running 9/9
 ✔ dify2openai Pulled                                                                                              3.2s
   ✔ 7264a8db6415 Already exists                                                                                   0.0s
   ✔ eee371b9ce3f Already exists                                                                                   0.0s
   ✔ 93b3025fe103 Already exists                                                                                   0.0s
   ✔ d9059661ce70 Already exists                                                                                   0.0s
   ✔ 775eae708e53 Already exists                                                                                   0.0s
   ✔ 7e3bcf99b286 Already exists                                                                                   0.0s
   ✔ cf75303e4221 Already exists                                                                                   0.0s
   ✔ 8afefb2194aa Already exists                                                                                   0.0s
[+] Running 1/1
 ✔ Container dify2openai  Started                      ![Dify_Chatbot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/b72a1017-0c67-3b8b-9d0e-a9e592356838.png)
                                                            0.7s

Q:\OneDrive\Docker\dify2openai>
```
※docker-compose.ymlは3.3章②のものを使います。

```bash
Q:\OneDrive\Docker\dify2openai>docker ps
CONTAINER ID   IMAGE                              COMMAND                   CREATED          STATUS                  PORTS                                      NAMES
**14d094959023   potofo/dify2openai:latest          "docker-entrypoint.s…"   22 seconds ago   Up 21 seconds           0.0.0.0:3010->3000/tcp                     dify2openai**
6e1854aada91   nginx:latest                       "sh -c 'cp /docker-e…"   12 hours ago     Up 12 hours             0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   docker-nginx-1
38bd486f4096   langgenius/dify-api:0.7.3          "/bin/bash /entrypoi…"   12 hours ago     Up 12 hours             5001/tcp                                   docker-api-1
a0dca28c8ec2   langgenius/dify-api:0.7.3          "/bin/bash /entrypoi…"   12 hours ago     Up 12 hours             5001/tcp                                   docker-worker-1
2b569c2073c9   ubuntu/squid:latest                "sh -c 'cp /docker-e…"   12 hours ago     Up 12 hours             3128/tcp                                   docker-ssrf_proxy-1
591ba2172ebb   redis:6-alpine                     "docker-entrypoint.s…"   12 hours ago     Up 12 hours (healthy)   6379/tcp                                   docker-redis-1
aa1b860a6af2   semitechnologies/weaviate:1.19.0   "/bin/weaviate --hos…"   12 hours ago     Up 12 hours
                                       docker-weaviate-1
5e7f62c4d619   langgenius/dify-sandbox:0.2.6      "/main"                   12 hours ago     Up 12 hours
                                        docker-sandbox-1
068e839f23e8   postgres:15-alpine                 "docker-entrypoint.s…"   12 hours ago     Up 12 hours (healthy)   5432/tcp                                   docker-db-1
72f39d066664   langgenius/dify-web:0.7.3          "/bin/sh ./entrypoin…"   12 hours ago     Up 12 hours             3000/tcp                                   docker-web-1

Q:\OneDrive\Docker\dify2openai>
```

※こちらもIMAGEがporofo/dify2openai:latestとなっていることが確認できます。

## ４．Difyの設定

### 4.1.Difyでチャットボット(基本)を作成
LLMだけを呼び出すチャットボット(基本)を作成します。
![Dify_Chatbot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/f475a116-0b5b-165b-cd60-229c78486001.png)

### 4.2.APIシークレットキーを発行
[公開する]⇒[APIリファレンスにアクセス]を選び[新しいシークレットキーを作成]からAPIシークレットキーを作成します。
![Dify_SecretKey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/29448145-dc16-7a0f-3515-9ebd4ae111c4.png)

APIエンドポイントの例：http://localhost/v1
シークレットキーの例：app-JyGejMB9MKr2A6z54teCCqdQ

※APIエンドポイントは右上にAPIサーバとして表示されています。


## ５．Chatbot UIの設定
ここではChatbot UI legacyを使用しますが、OpenAI APIをサポートするWeb UIならばなんでも大丈夫です。
DifyのAPIはOpenAI APIのLLMとして、Chatbot UI legacyに登録しますので、以下の３ファイルの修正が必要です。

| No | ファイル | 修正内容 |
| --- | --- | --- |
| 1 | .env.local | Chatbot UI legacyのエンドポイントとAPIキー、デフォルトモデルを指定する |
| 2 | types/openai.ts | LLMの定義をする |
| 3 | utils/app/clean.ts | Chatbot UI初期化時にでデフォルトのモデルを設定 |

今回のChatbot UIのDify接続対応の変更差分は私のporofo/chatbot-uiのSupport_Dify_API_dify2openaiブランチに格納しておきます。

``` mermaid
gitGraph:
    commit id:"138950c5:Update README.md"
    branch feature-supports-azure-openai-api-2023-5-15-or-later
    checkout feature-supports-azure-openai-api-2023-5-15-or-later
    commit id:"e66b9bc9:feature-supports-azure-openai-api-2023-05-15-or-later"
    branch fixed
    checkout fixed
    commit id:"868e20e9:Added Azure current models"
    commit id:"36f0110d:Use custom max_tokens #316"
    commit id:"23486362:Bug fix for [DONE] is not valid JSON"
    branch Support_GPT-4o_and_GPT-4o_mini
    checkout Support_GPT-4o_and_GPT-4o_mini
    commit id:"23486362:Bug fix for DONE is not valid JSON"
    commit id:"ee5eda27:Supported GPT-4o/GPT-4o mini LLM"
    checkout fixed
    merge Support_GPT-4o_and_GPT-4o_mini
    branch Support_Dify_API_dify2openai
    checkout Support_Dify_API_dify2openai
    commit id:"afd01a40:Support Dify API(dify2openai)"
```

**①.env.localファイル編集**
　Chatbot UI Legacyでのモデル設定にdify2openaiで変換中継したDify APIのエンドポイントを設定します。
```bash
# Chatbot UI

OPENAI_API_TYPE=openai
OPENAI_API_HOST=http://localhost:3010
OPENAI_API_KEY=app-JyGejMB9MKr2A6z54teCCqdQ
DEFAULT_MODEL=dify
OPENAI_API_VERSION=2024-02-01

#NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT=You are ChatGPT, a large language model trained by OpenAI. Follow the user's instructions carefully. Respond using markdown.
NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT=You are a chatbot system called Chatbot UI lagacy, launched on April 20, 2023 by Mckay Wrigley. Using OpenAI's large-scale language model, you will carefully answer various questions based on pre-training knowledge up to the cutoff date. Please use Markdown format for your answers and make good use of code blocks Mermaid and tables to respond to user questions in an easy-to-understand manner.

# Google
GOOGLE_API_KEY=YOUR_API_KEY
GOOGLE_CSE_ID=YOUR_ENGINE_ID

```

※DEFAULT_MODEは以下のREST APIで「dify」であることが確認できます。

[localhost:3010/v1/models](http://localhost:3010/v1/models)

```bash
{
    "object": "list",
    "data": [
        {
            "id": "dify",
            "object": "model",
            "owned_by": "dify",
            "permission": null
        }
    ]
}
```

**②types/openai.tsの修正**
　Chatbot UIはOpenAIのモデルをopenai.tsファイルに定義して認識しているので、こちらも変更します。
　Chatbot UIはOpenAIモデルのエンドポイントを１つしか設定できないため、DEFAULT_MODELをOpenAIModelID.DIFYにすることでdify2openaiに接続したときは、
　Dify専用となります。

```bash
import { OPENAI_API_TYPE } from '../utils/app/const';

export interface OpenAIModel {
  id: string;
  name: string;
  maxLength: number; // maximum length of a message
  tokenLimit: number;
}

export enum OpenAIModelID {
  GPT_4O_AZ = 'gpt-4o-2024-05-13',
  GPT_4O_MINI_AZ = 'gpt-4o-mini-2024-07-18',
  DIFY = 'dify',
}

// in case the `DEFAULT_MODEL` environment variable is not set or set to an unsupported model
export const fallbackModelID = OpenAIModelID.DIFY;

export const OpenAIModels: Record<OpenAIModelID, OpenAIModel> = {
  [OpenAIModelID.GPT_4O_MINI_AZ]: {
    id: OpenAIModelID.GPT_4O_MINI_AZ,
    name: 'GPT-4o mini',
    maxLength: 512000,
    tokenLimit: 128000,
  },
  [OpenAIModelID.GPT_4O_AZ]: {
    id: OpenAIModelID.GPT_4O_AZ,
    name: 'GPT-4o',
    maxLength: 512000,
    tokenLimit: 128000,
  },
  [OpenAIModelID.DIFY]: {
    id: OpenAIModelID.DIFY,
    name: 'dify',
    maxLength: 512000,
    tokenLimit: 128000,
  },
};

```

**③utils/app/clean.tsの修正**
　Chatbot UIは画面の初期化時にconversation modelをリテラル値で設定しているので、ここも修正する必要があります。

```bash
import { Conversation } from '@/types/chat';
import { OpenAIModelID, OpenAIModels } from '@/types/openai';

import { DEFAULT_SYSTEM_PROMPT, DEFAULT_TEMPERATURE } from './const';

export const cleanSelectedConversation = (conversation: Conversation) => {
  // added model for each conversation (3/20/23)
  // added system prompt for each conversation (3/21/23)
  // added folders (3/23/23)
  // added prompts (3/26/23)
  // added messages (4/16/23)

  let updatedConversation = conversation;

  // check for model on each conversation
  if (!updatedConversation.model) {
    updatedConversation = {
      ...updatedConversation,
      model: updatedConversation.model || OpenAIModels[OpenAIModelID.DIFY],
    };
  }

  // check for system prompt on each conversation
  if (!updatedConversation.prompt) {
    updatedConversation = {
      ...updatedConversation,
      prompt: updatedConversation.prompt || DEFAULT_SYSTEM_PROMPT,
    };
  }

  if (!updatedConversation.temperature) {
    updatedConversation = {
      ...updatedConversation,
      temperature: updatedConversation.temperature || DEFAULT_TEMPERATURE,
    };
  }

  if (!updatedConversation.folderId) {
    updatedConversation = {
      ...updatedConversation,
      folderId: updatedConversation.folderId || null,
    };
  }

  if (!updatedConversation.messages) {
    updatedConversation = {
      ...updatedConversation,
      messages: updatedConversation.messages || [],
    };
  }

  return updatedConversation;
};

export const cleanConversationHistory = (history: any[]): Conversation[] => {
  // added model for each conversation (3/20/23)
  // added system prompt for each conversation (3/21/23)
  // added folders (3/23/23)
  // added prompts (3/26/23)
  // added messages (4/16/23)

  if (!Array.isArray(history)) {
    console.warn('history is not an array. Returning an empty array.');
    return [];
  }

  return history.reduce((acc: any[], conversation) => {
    try {
      if (!conversation.model) {
        conversation.model = OpenAIModels[OpenAIModelID.GPT_3_5];
      }

      if (!conversation.prompt) {
        conversation.prompt = DEFAULT_SYSTEM_PROMPT;
      }

      if (!conversation.temperature) {
        conversation.temperature = DEFAULT_TEMPERATURE;
      }

      if (!conversation.folderId) {
        conversation.folderId = null;
      }

      if (!conversation.messages) {
        conversation.messages = [];
      }

      acc.push(conversation);
      return acc;
    } catch (error) {
      console.warn(
        `error while cleaning conversations' history. Removing culprit`,
        error,
      );
    }
    return acc;
  }, []);
};

```

## ６．Chatbot UIの起動
Chatbot UIは「npm run dev」コマンドで起動しますので、以下のように起動します。

```bash
Q:\OneDrive\Docker\chatbot-ui_gpt4o>npm run dev

> ai-chatbot-starter@0.1.0 dev
> next dev

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - Loaded env from Q:\OneDrive\Docker\chatbot-ui_gpt4o\.env.local
Browserslist: caniuse-lite is outdated. Please run:
```

## ７．Difyの起動

Difyはgitのcheckout/pullコマンドでバージョンアップができますので今回はDify Ver8.3にアップして実行することにします。

```
Q:\OneDrive\Docker\dify>git checkout main
Previous HEAD position was 8986be0aa chore: Update versions to 0.7.3 (#7895)
Switched to a new branch 'main'
branch 'main' set up to track 'origin/main'.

Q:\OneDrive\Docker\dify>git pull origin main
remote: Enumerating objects: 6440, done.
remote: Counting objects: 100% (4290/4290), done.
remote: Compressing objects: 100% (934/934), done.
remote: Total 6440 (delta 3725), reused 3506 (delta 3353), pack-reused 2150 (from 1)
Receiving objects: 100% (6440/6440), 3.78 MiB | 22.88 MiB/s, done.
Resolving deltas: 100% (4411/4411), completed with 1174 local objects.
From https://github.com/langgenius/dify
 * branch                main       -> FETCH_HEAD
   b1918dae5..74f58f29f  main       -> origin/main
Updating files: 100% (1769/1769), done.
Updating b1918dae5..74f58f29f

...

 create mode 100644 web/app/components/workflow/nodes/iteration-start/types.ts
 delete mode 100644 web/app/components/workflow/nodes/iteration/insert-block.tsx
 rename web/public/logo/{logo-embeded-chat-avatar.png => logo-embedded-chat-avatar.png} (100%)
 rename web/public/logo/{logo-embeded-chat-header.png => logo-embedded-chat-header.png} (100%)
 create mode 100644 web/utils/format.spec.ts

Q:\OneDrive\Docker\dify>
Q:\OneDrive\Docker\dify>cd docker

Q:\OneDrive\Docker\dify\docker>docker compose down
Q:\OneDrive\Docker\dify\docker>
Q:\OneDrive\Docker\dify\docker>docker compose up -d
time="2024-09-29T06:42:46+09:00" level=warning msg="The \"CERTBOT_EMAIL\" variable is not set. Defaulting to a blank string."
time="2024-09-29T06:42:46+09:00" level=warning msg="The \"CERTBOT_DOMAIN\" variable is not set. Defaulting to a blank string."
[+] Running 7/9
 - web [⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                                     7.6s
 - db [⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                                         7.6s
 - weaviate [⠀⠀⠀⠀] Pulling                                                                                         7.6s
 - sandbox [⠀⠀⠀⠀⠀⠀] Pulling                                                                                        7.6s
 - nginx [⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                                         7.6s
 - redis [⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                                         7.6s
 - api Pulling                                                                                                     7.6s
 - worker [⣿⣿⣿⣿⣿⣿⣿⣤⠀⡀⠀⠀] Pulling                                                                                   7.6s
 - ssrf_proxy [⠀⠀⠀] Pulling                                                                                        7.6s

Q:\OneDrive\Docker\dify\docker>docker compose up -d
time="2024-09-29T06:42:46+09:00" level=warning msg="The \"CERTBOT_EMAIL\" variable is not set. Defaulting to a blank string."
time="2024-09-29T06:42:46+09:00" level=warning msg="The \"CERTBOT_DOMAIN\" variable is not set. Defaulting to a blank string."
[+] Running 71/9
 ✔ web Pulled                                                                                                     43.6s
 ✔ db Pulled                                                                                                      22.7s
 ✔ weaviate Pulled                                                                                                28.0s
 ✔ sandbox Pulled                                                                                                 50.1s
 ✔ nginx Pulled                                                                                                   27.9s
 ✔ redis Pulled                                                                                                   13.4s
 ✔ api Pulled                                                                                                    110.0s
 ✔ worker Pulled                                                                                                 110.0s
 ✔ ssrf_proxy Pulled                                                                                              34.1s
[+] Running 11/11
 ✔ Network docker_default             Created                                                                      0.1s
 ✔ Network docker_ssrf_proxy_network  Created                                                                      0.1s
 ✔ Container docker-sandbox-1         Started                                                                      3.4s
 ✔ Container docker-ssrf_proxy-1      Started                                                                      3.8s
 ✔ Container docker-db-1              Started                                                                      2.7s
 ✔ Container docker-web-1             Started                                                                      3.0s
 ✔ Container docker-weaviate-1        Started                                                                      3.5s
 ✔ Container docker-redis-1           Started                                                                      3.6s
 ✔ Container docker-worker-1          Started                                                                      3.1s
 ✔ Container docker-api-1             Started                                                                      3.3s
 ✔ Container docker-nginx-1           Started                                                                      3.6s

Q:\OneDrive\Docker\dify\docker>
```

## 7.1.Difyのチャットボット(基本)でAPI設定

　チャットボット(基本)を作成してシステムプロンプトに以下のような指示文を書いておきます。
　これはChatbot UIからdift2openai経由でチャットボット(基本)にAPI接続したときこのフローが動作しているのかを確認するために実施しておきます。

```
あなたは優秀なアシスタントです。
重要：返信時の応答の最後には必ず「かしこまりました。かしこ」と言ってください。
```

![Dify_chatbot_basic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/50fdcfac-f83c-255c-4150-6627c911222c.png)

![Dify_chatbot_basic_api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/4faa9949-5c29-cc65-75b2-e9f724b60565.png)

## ８．dify2openaiの起動

　[fatwang2/dify2openai](https://github.com/fatwang2/dify2openai)ではGitHubのワークフローを用いたDocker Imageの自動作成とDockerHubへの自動プッシュは対応されていないため、
　今回は私がミラーした[potofo/dify2openai](https://github.com/potofo/dify2openai)のGitHubのワークフローで構築した[potofo/dify2openai](https://hub.docker.com/repository/docker/potofo/dify2openai/general)を使用します。
　エディタでdocker-compose-image.ymlを作成して以下のように記載します。

■docker-compose-image.yml

```
version: '3.5'
services:
  # dify2openai API relay service
  dify2openai:
    image: potofo/dify2openai:latest
    container_name: dify2openai
    network_mode: bridge
    ports:
      - "3010:3000"
    restart: always
    environment: 
      #- DIFY_API_URL=http://localhost/v1
      - DIFY_API_URL=http://host.docker.internal/v1
      - BOT_TYPE=Chat
      - MODELS_NAME=dify
```

■docker-compose-image.ymlによるdify2openaiの起動

```
Q:\OneDrive\Docker\dify2openai>docker compose -f docker-compose-image.yml up -d
time="2024-09-29T06:50:18+09:00" level=warning msg="Q:\\OneDrive\\Docker\\dify2openai\\docker-compose-image.yml: `version` is obsolete"
[+] Running 9/9
 ✔ dify2openai Pulled                                                                                              5.5s
   ✔ 7264a8db6415 Already exists                                                                                   0.0s
   ✔ eee371b9ce3f Already exists                                                                                   0.0s
   ✔ 93b3025fe103 Already exists                                                                                   0.0s
   ✔ d9059661ce70 Already exists                                                                                   0.0s
   ✔ adeb2c16f58f Pull complete                                                                                    1.0s
   ✔ f7dd73f01723 Pull complete                                                                                    1.0s
   ✔ 4c4b6f6f3090 Pull complete                                                                                    2.4s
   ✔ ecd81bdf43a2 Pull complete                                                                                    2.4s
[+] Running 1/1
 ✔ Container dify2openai  Started                
```

ECONNREFUSEDエラーが発生する場合dify2openaiのdocker-compose-image.ymlのDIFY_API_URLの見直しをしてください。

```
dify2openai  | Error: FetchError: request to http://localhost/v1/chat-messages failed, reason: connect ECONNREFUSED 127.0.0.1:80
dify2openai  |     at ClientRequest.<anonymous> (file:///usr/src/app/node_modules/node-fetch/src/index.js:108:11)
dify2openai  |     at ClientRequest.emit (node:events:525:35)
dify2openai  |     at Socket.socketErrorListener (node:_http_client:494:9)
dify2openai  |     at Socket.emit (node:events:513:28)
dify2openai  |     at emitErrorNT (node:internal/streams/destroy:157:8)
dify2openai  |     at emitErrorCloseNT (node:internal/streams/destroy:122:3)
dify2openai  |     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
dify2openai  |   type: 'system',
dify2openai  |   errno: 'ECONNREFUSED',
dify2openai  |   code: 'ECONNREFUSED',
dify2openai  |   erroredSysCall: 'connect'
dify2openai  | }
dify2openai  | Request Method: GET
dify2openai  | Request Path: /v1/models
```

## ９．使ってみる
Chatbot UIのWeb画面にアクセスするには「http://localhost:3000」にブラウザからアクセスします。

![Chatbot-ui_with_dify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/3081a72e-d468-3615-51eb-92af930aa4cd.png)


※モデルのところにDefault(dify)と表示されればdify2openai経由でDifyのAPIに接続されています。

早速、カットオフデートを聞いてみます。
「カットオフデートはいつですか？」

![Chatbot-ui_with_dify_question.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764962/bdb845ac-0645-b8a3-432b-4c9a07be7963.png)

「カットオフデートは2023年10月です。かしこまりました。かしこ。」

カットオフデートを2023年10月と答えていることからgpt-4oかgpt-4o-miniが回答していることがわかります。
また、文末の「かしこまりました。かしこ」の回答から、Difyのチャットボット(基本)が動作していることがわかります。

## １０．関連記事

https://qiita.com/potofo/items/dce0a1532e111c1d0bf0

https://qiita.com/potofo/items/11a45260ee4121f00fea

https://qiita.com/potofo/items/85cad4d3cbf46dda317d