Dify Code interpreter Pythonのモジュール追加制限　解除する方法

## 記事の要約
DifyのSandbox環境では、使用できるPythonモジュール※1に制限があります。ダミーモジュールに差し替えることで制限を無効化します。

※1:標準対応モジュールは次を参照してください。
https://github.com/langgenius/dify/blob/main/api/core/helper/code_executor/python3/python3_transformer.py

## 前提条件
以下の前提条件を満たしていることを確認してください：
- Dify 0.6.11をローカル環境にインストール済み
- 基本的なDockerの知識がある
- Linuxの知識がある
- gcc,make インストール済み

## 注意事項
- 制限を解除することは、セキュリティレベルを下げるため、本番環境での使用は推奨されません。開発やテスト環境での利用に留めてください
- 本番環境ではCodeInterpreter処理をコンテナ化しHTTP Requestで処理することを推奨します

## ダミーモジュール作成手順

### 1. ダミーモジュール用のソースコード作成
以下のコードを使用して`dummy_python.c`ファイルを作成します。

```c
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

// DifySeccomp関数のプロトタイプ宣言
void DifySeccomp(uint32_t arg1, uint32_t arg2, bool arg3);

// DifySeccomp関数の実装
void DifySeccomp(uint32_t arg1, uint32_t arg2, bool arg3) {
    // 関数が正しく呼び出されたことを確認するための単純な出力
    printf("DifySeccomp called with arg1: %u, arg2: %u, arg3: %s\n", 
           arg1, 
           arg2, 
           arg3 ? "true" : "false");
}
```
### 2. Makefileの作成
以下の内容をコピーして、Makefileファイルを作成します。

```make:Makefile
# 出力ファイル名とソースファイル名
TARGET = python.so
SOURCE = dummy_python.c

# コンパイラとコンパイルオプション
CC = gcc
CFLAGS = -Wall -Werror -fpic

# リンクオプション
LDFLAGS = -shared

# 'make'を実行した場合に最初に呼ばれるターゲット
all: $(TARGET)

# 共有ライブラリをビルド
$(TARGET): $(SOURCE)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

# 'make clean'で不要なファイルを削除
clean:
	rm -f $(TARGET)
```

### 3. ダミーモジュールのコンパイル
makeコマンドを実行して、ダミーモジュールpython.soを作成します。
```bash:
$ make
gcc -Wall -Werror -fpic -shared -o python.so dummy_python.c
```

### 4. ダミーモジュールのテストプログラム作成
以下のPythonコードを使用して、ダミーモジュールが正しく動作するかテストします。
```python:test_dummy.py
# test_dummy.py
import ctypes

# ダミーモジュールのロード
dummy = ctypes.CDLL('./python.so')

# 関数の引数と戻り値の型を設定
# DifySeccomp関数の引数の型（uint32, uint32, bool）を指定します
dummy.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_bool]

# 戻り値の型をNone（void）に設定します
dummy.DifySeccomp.restype = None

# ダミーモジュールの関数を呼び出し
dummy.DifySeccomp(65537, 1000, 1)
```

### 5. テストプログラムの実行
以下のコマンドを実行して、テストプログラムを実行します。
ダミー関数が正常に呼ばれていることを確認します。
```bash:
$ python3 test_dummy.py
DifySeccomp called with arg1: 65537, arg2: 1000, arg3: true
```

### 6. 所有者をrootに変更
コンパイルしたpython.soの所有者をrootに変更します。
```bash:
$ sudo chown root:root python.so
```

### 7. Code interpreterに使用したいモジュールを追加
以下のpathのpython-requirements.txtにモジュールを追加した後、
docker-sandbox-1を再起動します。
```text:dify/docker/volumes/sandbox/dependencies/python-requirements.txt
pandas
```

### 8. ダミーモジュールをsandboxにコピーします
以下のコマンドを実行して、docker-sandbox-1にダミーモジュールをコピーします。
この操作は、docker-sandbox-1の起動後数秒後に行い、再起動の度に必要です。
```bash:
$ docker cp python.so docker-sandbox-1:/var/sandbox/sandbox-python/
```

### 9.Code interpreterテスト
Code interpreterに以下をコピーし実行し、
正常に実行でることを確認します。

```python:
import pandas as pd

def main(arg1: int, arg2: int) -> dict:
    return {
        "result": str(arg1 + arg2),
    }

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12112/b193f11f-13b2-bff2-f075-481ad5813df5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12112/41723270-f2f2-2a82-ee09-4b94de99076a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12112/2dd44abd-6d0e-e6d4-44e9-68c31a7de4df.png)

以上になります

## 結論
DifyのSandbox環境でPythonの制限を解除するために、ダミーモジュールを作成し、適用する方法を紹介しました。これにより、開発が捗ると思います。