├── README.md └── demo-upload.yml /README.md: -------------------------------------------------------------------------------- 1 | # dify_code_node_get_image 2 | 如何让 dify工作流的 code 节点拿到图片的信息 3 | 本仓库为AI带路党Pro视频准备[如何在dify的code节点中访问图片文件-dify二次开发 4 | ](https://www.bilibili.com/video/BV1BRPNeLEDv/?vd_source=e60241d08fb6eeea3c6a0e9196f65bc0) 5 | #### clone源码 6 | clone源码,并git checkout 0.15.3,避免使用 main 分支代码进行build,因为 main 分支不稳定 7 | #### 修改api源码 8 | 1. api/services/file_service.py 中 FileService类upload_file函数中,在storage.save之前新增代码 9 | ``` 10 | # 新增此行 11 | source_url = '/app/api/storage/' + file_key if not source_url else source_url 12 | # save file to storage 13 | storage.save(file_key, content) 14 | ``` 15 | #### 修改沙盒配置 16 | 1. 修改 docker/volumes/sandbox/conf/config.yaml,为什么加这个请看 up 主之前沙盒的视频 17 | ``` 18 | allowed_syscalls: [0,1,2,3,4,5,6,7,8,9,14,15,21,22,25,26,29,30,31,32,33,34,35,38,39,43,44,45,46,56,57,61,62,63,64,71,72,79,80,94,98,101,131,132,134,135,139,144,146,172,215,222,226,318,334,307,262,16,8,217,1,3,257,0,202,9,12,10,11,15,25,105,106,102,39,110,186,60,231,234,13,16,24,273,274,334,228,96,35,291,233,230,270,201,14,131,318,56,258,83,41,42,49,50,43,44,45,51,47,52,54,271,63,46,307,55,5,72,138,7,281] 19 | ``` 20 | #### 修改 docker-compose.yaml 21 | 1. api节点修改不用 image而是通过 build(为什么请参考 up 主往期视频) 22 | ``` 23 | api: 24 | build: ../api 25 | restart: always 26 | ``` 27 | 2. 修改 sandbox 节点中的volumes 28 | ``` 29 | volumes: 30 | - ./volumes/sandbox/dependencies:/dependencies 31 | - ./volumes/sandbox/conf:/conf 32 | - ./volumes/app/storage:/var/sandbox/sandbox-python/usr/local/storage 33 | ``` 34 | 3. 修改后分别执行 docker compose down、docker compose build、docker compose up。拉不到镜像,无法安装包等问题请自习挂代理等方式解决 35 | #### 导入 仓库中 demo-upload.yml工作流进行测试 36 | 返回示例,result 为文件大小,url 为存储于 dify-api中的图片路径,在 37 | ``` 38 | { 39 | "result": 227683, 40 | "name": "test-3.png", 41 | "url": "/app/api/storage/upload_files/13e6c543-0996-4c9e-853f-5c023ee48c6d/d5d0aab0-02af-41ed-abab-bac2076f49fb.png" 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /demo-upload.yml: -------------------------------------------------------------------------------- 1 | app: 2 | description: '' 3 | icon: 🤖 4 | icon_background: '#FFEAD5' 5 | mode: workflow 6 | name: demo-upload 7 | use_icon_as_answer_icon: false 8 | kind: app 9 | version: 0.1.5 10 | workflow: 11 | conversation_variables: [] 12 | environment_variables: [] 13 | features: 14 | file_upload: 15 | allowed_file_extensions: 16 | - .JPG 17 | - .JPEG 18 | - .PNG 19 | - .GIF 20 | - .WEBP 21 | - .SVG 22 | allowed_file_types: 23 | - image 24 | allowed_file_upload_methods: 25 | - local_file 26 | - remote_url 27 | enabled: false 28 | fileUploadConfig: 29 | audio_file_size_limit: 50 30 | batch_count_limit: 5 31 | file_size_limit: 15 32 | image_file_size_limit: 10 33 | video_file_size_limit: 100 34 | workflow_file_upload_limit: 10 35 | image: 36 | enabled: false 37 | number_limits: 3 38 | transfer_methods: 39 | - local_file 40 | - remote_url 41 | number_limits: 3 42 | opening_statement: '' 43 | retriever_resource: 44 | enabled: true 45 | sensitive_word_avoidance: 46 | enabled: false 47 | speech_to_text: 48 | enabled: false 49 | suggested_questions: [] 50 | suggested_questions_after_answer: 51 | enabled: false 52 | text_to_speech: 53 | enabled: false 54 | language: '' 55 | voice: '' 56 | graph: 57 | edges: 58 | - data: 59 | isInIteration: false 60 | sourceType: start 61 | targetType: code 62 | id: 1739954682920-source-1739954688851-target 63 | selected: false 64 | source: '1739954682920' 65 | sourceHandle: source 66 | target: '1739954688851' 67 | targetHandle: target 68 | type: custom 69 | zIndex: 0 70 | - data: 71 | isInIteration: false 72 | sourceType: code 73 | targetType: end 74 | id: 1739954688851-source-1739954691511-target 75 | source: '1739954688851' 76 | sourceHandle: source 77 | target: '1739954691511' 78 | targetHandle: target 79 | type: custom 80 | zIndex: 0 81 | nodes: 82 | - data: 83 | desc: '' 84 | selected: false 85 | title: 开始 86 | type: start 87 | variables: 88 | - allowed_file_extensions: [] 89 | allowed_file_types: 90 | - image 91 | allowed_file_upload_methods: 92 | - local_file 93 | - remote_url 94 | label: img 95 | max_length: 48 96 | options: [] 97 | required: true 98 | type: file 99 | variable: img 100 | height: 111 101 | id: '1739954682920' 102 | position: 103 | x: 80 104 | y: 282 105 | positionAbsolute: 106 | x: 80 107 | y: 282 108 | selected: false 109 | sourcePosition: right 110 | targetPosition: left 111 | type: custom 112 | width: 244 113 | - data: 114 | code: "import os\n\n\ndef main(arg1: str) -> dict:\n file_size = os.path.getsize(\n\ 115 | \ arg1.replace('/app/api/storage', '/usr/local/storage'))\n return\ 116 | \ {\n \"result\": file_size,\n }\n" 117 | code_language: python3 118 | desc: '' 119 | outputs: 120 | result: 121 | children: null 122 | type: number 123 | selected: true 124 | title: 代码执行 125 | type: code 126 | variables: 127 | - value_selector: 128 | - '1739954682920' 129 | - img 130 | - url 131 | variable: arg1 132 | height: 66 133 | id: '1739954688851' 134 | position: 135 | x: 384 136 | y: 282 137 | positionAbsolute: 138 | x: 384 139 | y: 282 140 | selected: true 141 | sourcePosition: right 142 | targetPosition: left 143 | type: custom 144 | width: 244 145 | - data: 146 | desc: '' 147 | outputs: 148 | - value_selector: 149 | - '1739954688851' 150 | - result 151 | variable: result 152 | - value_selector: 153 | - '1739954682920' 154 | - img 155 | - name 156 | variable: name 157 | - value_selector: 158 | - '1739954682920' 159 | - img 160 | - url 161 | variable: url 162 | selected: false 163 | title: 结束 164 | type: end 165 | height: 176 166 | id: '1739954691511' 167 | position: 168 | x: 688 169 | y: 282 170 | positionAbsolute: 171 | x: 688 172 | y: 282 173 | selected: false 174 | sourcePosition: right 175 | targetPosition: left 176 | type: custom 177 | width: 244 178 | viewport: 179 | x: -158 180 | y: 98 181 | zoom: 1 182 | --------------------------------------------------------------------------------