在Dify中访问Gemini等模型代理设置指南
问题背景
Google Gemini模型可纯免费使用,且性能也相当不错,一般个人使用或研究足够。但在在国内访问,需设置代理。在Docker部署Dify时,虽然按官方文档介绍设置代理环境变量,但实测发现并不生效。我们通过研究试验解决了这个问题,并探索了可配置化的按需走代理的方法。
说明:本文主要内容不是介绍dify本地部署的内容,可参见Dify官方部署指南。如看官有兴趣,小子可以写一个专门文章。
根因分析
先说结论
Dify中访问Gemini模型使用了Google的generativeai Python SDK,底层通过gRPC进行通信,它要求代理相关的环境变量必须使用小写形式,大写形式不生效。
详细分析过程
-
Dify官方文档说明
Dify的官方文档中提到可以通过设置环境变量(在.env.example和.env文件中)来配置代理,但没有特别说明大小写问题。文档中通常使用的是大写形式的环境变量,如HTTP_PROXY和HTTPS_PROXY。HTTP_PROXYHTTP 代理地址,用于解决国内无法访问 OpenAI、HuggingFace 的问题。注意,若代理部署在宿主机 (例如 http://127.0.0.1:7890),此处代理地址应当和接入本地模型时一样,使用 Docker 容器内部的宿主机地址(例如 http://192.168.1.100:7890 或 http://172.17.0.1:7890)。HTTPS_PROXYHTTPS 代理地址,用于解决国内无法访问 OpenAI、HuggingFace 的问题。同上。 -
Gemini模型插件实现
Dify的Gemini模型插件使用了Google的generativeai Python SDK。 -
底层通信机制
Google的generativeai SDK底层使用gRPC进行通信。根据gRPC官方文档,它支持以下几个代理相关的环境变量:grpc_proxy, https_proxy, http_proxy The URI of the proxy to use for HTTP CONNECT support. These variables are checked in order, and the first one that has a value is used. no_grpc_proxy, no_proxy A comma separated list of hostnames to connect to without using a proxy even if a proxy is set. These variables are checked in order, and the first one that has a value is used. -
问题确认
对比Dify文档中说明的变量是大写形式(如HTTP_PROXY),而gRPC文档中是小写形式(如http_proxy)。通过实验确认,只有小写形式的环境变量对Gemini模型生效。 -
版本差异
对于Dify 0.15.x版本(尚未引入插件概念的版本),Gemini模型的源代码位于主仓库中,但代理环境变量的要求相同。
解决方案
同时设置大小写环境变量
最直接的解决方法是同时设置大小写两套环境变量,确保各种组件都能正确识别代理设置。
如果在Docker容器中设置了全局代理环境变量,所有HTTP请求都会走代理,这可能会导致不必要的性能开销。
虽然可能通过no_proxy(NO_PROXY)配置,但黑名单域名多起来就比较麻烦。
也可以让http proxy server那边配置,也不是所有的proxy server都能进行配置。我们看到,dify本身是有一个ssrf_proxy的容器服务,是使用squid支持的。至于为何dify添加了这个组件,一句话:为了安全,参见官方介绍。
我们借用这个服务,更优雅地实现按需代理。因为squid是一个非常经典的代理服务器,它支持代理链(proxy chain)和域名白名单配置。
实现步骤
确保已有可用的HTTP代理服务器(相信看官都会有,如果没有小子也提供不了)
-
在dify/docker/.env中配置环境变量
变量名没有使用官方指定,因为原来处理逻辑比较绕,可以简化,另外域名变量是为了使用白名单,而不是黑名单。为何分开主机和端口配置?这个是为了适配squid(ssrf_proxy),后续说明。# public http proxy server used in ssrf_proxy service(squid), change for your ip/port HTTP_PROXY_SERVER_HOST = 192.168.0.1 HTTP_PROXY_SERVER_PORT = 3128 # domains through public http proxy, space separate(if include subdomains, domain wildcard must be begin with comma) DOMAINS_BY_PROXY = ".googleapis.com .google.com google.dev .openai.com .anthropic.com .github.com .githubusercontent.com .githubassets.com .youtube.com .duckduckgo.com .huggingface.co .dify.ai" -
修改dify/docker/ssrf_proxy/squid.conf.template
找到以下行(40多行的位置):# cache_dir ufs /var/spool/squid 100 16 256 # upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks # cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default替换为(必须要替换在原来的这个位置,因为squid有一序列的规则,有兴趣可参见官方文档):
# 使用squid的机制实现对指定域名及其子域名走上游代理, cache_peer ${HTTP_PROXY_SERVER_HOST} parent ${HTTP_PROXY_SERVER_PORT} 0 no-query no-digest no-netdb-exchange default acl external_domains dstdomain ${DOMAINS_BY_PROXY} never_direct allow external_domains cache_peer_access ${HTTP_PROXY_SERVER_HOST} allow external_domains cache_peer_access ${HTTP_PROXY_SERVER_HOST} deny all -
修改dify/docker/docker-compose-template.yaml
尽量不直接修改docker-compose.yaml,但也是可行的,看官自己选择。在api、plugin_daemon、sandbox几个服务的"environment:" 节中增加如下配置environment:...# setting http proxy using ssrf_proxy serviceHTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}# lowercase set again for google grpc and othershttp_proxy: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}https_proxy: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128} -
使用工具重新生成docker-compose.yaml
cd dify/docker ./generate_docker_compose -
重建container并重启
cd dify/docker docker compose down docker compose up -d -
验证配置
在Dify控制台中添加Gemini模型,测试连接是否成功。如果配置正确,应该能够成功连接到Google的Gemini API服务。可以docker logs docker-ssrf_proxy-1查看日志,出现以下日志(FIRSTUP_PARENT/)说明已经走了上游代理。1741518209.044 260965 172.19.0.8 TCP_TUNNEL/200 13177 CONNECT generativelanguage.googleapis.com:443 - FIRSTUP_PARENT/192.168.0.1 -
Dify的Docker网络架构简要说明
这个图表主要展示了Dify系统中的网络连接情况(可能不完全准确供参考),重点突出了以下几个方面:
-
用户访问流程:用户通过nginx访问系统,nginx将请求分发给api和web服务
-
核心服务组件:
- api:核心API服务
- web:前端Web应用
- worker:后台工作进程
- plugin_daemon:插件管理服务
- sandbox:安全的代码执行环境
-
代理服务:
- ssrf_proxy:基于Squid的代理服务器,
注意事项
- 本方案已在Dify 1.0.0版本上验证通过,对0.15.x系列版本也适用
- 如果使用SSRF代理方式,确保
ssrf_proxy容器能够正常访问您的代理服务器 - 对于不同的模型提供商,可能需要不同的代理配置,请根据实际情况调整(国内的供应供应商一般不用配置)
- 另外发现dify官方域名dify.ai主机也是在国外,有时访问不畅,尤其是添加工具或插件,查看插件市场时,访问缓慢,所以可以让它也走代理,配置方案参见第3点。
总结
通过正确配置代理环境变量,特别是注意使用小写形式的环境变量,可以解决在国内环境下Dify使用Gemini模型的网络连接问题。利用Dify内置的SSRF代理组件,可以实现更灵活的按需代理配置,提高系统整体性能。
参考资料
- Dify官方文档
- gRPC环境变量文档
- Google Generative AI Python SDK
相关文章:
在Dify中访问Gemini等模型代理设置指南
问题背景 Google Gemini模型可纯免费使用,且性能也相当不错,一般个人使用或研究足够。但在在国内访问,需设置代理。在Docker部署Dify时,虽然按官方文档介绍设置代理环境变量,但实测发现并不生效。我们通过研究试验解决…...
MySQL的安装以及数据库的基本配置
MySQL的安装及配置 MySQL的下载 选择想要安装的版本,点击Download下载 Mysql官网下载地址: https://downloads.mysql.com/archives/installer/ MySQL的安装 选择是自定义安装,所以直接选择“Custom”,点击“Next” …...
设备树的组成
根节点下含有 compatile 属性的子节点 含有特定 compatile 属性的节点的子节点 如果一个节点的 compatile 属性,它的值是这 4 者之一:"simple-bus","simple-mfd","isa","arm,amba-bus", 那 么 它 的 子结点 (…...
C++入门——输入输出、缺省参数
C入门——输入输出、缺省参数 一、C标准库——命名空间 std C标准库std是一个命名空间,全称为"standard",其中包括标准模板库(STL),输入输出系统,文件系统库,智能指针与内存管理&am…...
deepseek 本地部署
deepseek 本地部署 纯新手教学,手把手5分钟带你在本地部署一个私有的deepseek,再也不用受网络影响。流畅使用deepseek!!! 如果不想看文章,指路:Deep seek R1本地部署 小白超详细教程 ࿰…...
[网络爬虫] 动态网页抓取 — Selenium 入门操作
🌟想系统化学习爬虫技术?看看这个:[数据抓取] Python 网络爬虫 - 学习手册-CSDN博客 0x01:WebDriver 类基础属性 & 方法 为模仿用户真实操作浏览器的基本过程,Selenium 的 WebDriver 模块提供了一个 WebDriver 类…...
HTML 超链接(简单易懂较详细)
在 HTML 中,超链接是通过 <a> 标签(anchor tag)创建的。超链接允许用户通过点击文本、图像或其他元素跳转到另一个网页、文件或页面的特定部分。本文将详细介绍 HTML 超链接的语法、属性和应用场景。 一、基本语法 <a href"U…...
rpc和proto
rpc全称远程过程控制,说白了是一种对信息发送和接收的规则编写方法,来自google,这些规则会以protobuf代码存到proto文件里。我以autoGen中agent_worker.proto为例,大概长这样 syntax "proto3";package agents;option …...
OPENGLPG第九版学习 -颜色、像素和片元 PART1
文章目录 4.1 基本颜色理论4.2 缓存及其用途颜色缓存深度缓存 / z缓存 / z-buffer模板缓存 4.2.1 缓存的清除4.2.2 缓存的掩码 4.3 颜色与OpenGL4.3.1 颜色的表达与OpenGL4.3.2 平滑数据插值 4.4 片元的测试与操作4.4.1 剪切测试4.4.2 多重采样的片元操作4.4.3 模板测试模板查询…...
【js逆向】某精灵网
地址:aHR0cHM6Ly93d3cuamluZ2xpbmdzaHVqdS5jb20vYXJ0aWNsZXM f12查看数据包,下面这个不是,你得到的是你的用户信息,需要点击第2页才会显示数据接口 查看载荷 查看预览数据,发现是加密的 查看启动器,看到 Pr…...
自然语言处理:高斯混合模型
介绍 大家好,博主又来给大家分享知识了,今天给大家分享的内容是自然语言处理中的高斯混合模型。 在自然语言处理这个充满挑战与机遇的领域,我们常常面临海量且复杂的文本数据。如何从这些数据中挖掘出有价值的信息,对文本进行有…...
RISC-V汇编学习(三)—— RV指令集
有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识,本节开始介绍RISC-V指令集和伪指令。 前面说了RISC-V的模块化特点,是以RV32I为作为ISA的核心模块,其他都是要基于此为基础,可以这样认为:RISC-V ISA 基本整数指…...
OpenCV连续数字识别—可运行验证
前言 文章开始,瞎说一点其他的东西,真的是很离谱,找了至少两三个小时,就一个简单的需求: 1、利用OpenCV 在Windows进行抓图 2、利用OpenCV 进行连续数字的检测。 3、使用C,Qt 3、将检测的结果显示出来 …...
Python中与字符串操作相关的30个常用函数及其示例
以下是Python中与字符串操作相关的30个常用函数及其示例: 1. str.capitalize() 将字符串的第一个字符大写,其余字符小写。 s "hello world" print(s.capitalize()) # 输出: Hello world2. str.lower() 将字符串中的所有字符转换为小写。…...
007-Property在C++中的实现与应用
Property在C中的实现与应用 以下是在C中实现属性(Property)的完整实现方案,结合模板技术和运算符重载实现类型安全的属性访问,支持独立模块化封装: #include <iostream> #include <functional>template<typename HostType, t…...
【实战篇】【DeepSeek 全攻略:从入门到进阶,再到高级应用】
凌晨三点,某程序员在Stack Overflow上发出灵魂拷问:“为什么我的DeepSeek会把财务报表生成成修仙小说?” 这个魔性的AI工具,今天我们就来场从开机键到改造人类文明的硬核教学。(文末含高危操作集锦,未成年人请在师父陪同下观看) 一、萌新村任务:把你的电脑变成炼丹炉 …...
clickhouse属于国产吗
《ClickHouse:探索其背景与国内的应用实例》 当我们谈论数据库技术时,ClickHouse是一个绕不开的话题。很多人可能会好奇,ClickHouse是否属于国产软件呢?答案是,虽然ClickHouse最初并非在中国开发,但这款列…...
ESP32 UART select解析json数据,上位机控制LED灯实验
前言: 本实验的目的主要是通过上位机通过UART来控制ESP32端的LED的点亮以及熄灭,整个项目逻辑比较简单,整体架构如下: 上位机(PC)主要是跑在PC端的一个软件,主要作用包含: 1)串口相关配置&…...
K8S 集群搭建——cri-dockerd版
目录 一、工作准备 1.配置主机名 2.配置hosts解析 3.配置免密登录(只需要在master上操作) 4.时间同步(每台节点都要做,必做,否则可能会因为时间不同步导致集群初始化失败) 5.关闭系统防火墙 6.配置…...
基于Python的电商销售数据分析与可视化系统实
一、系统架构设计 1.1系统流程图 #mermaid-svg-Pdo9oZWrVHNuOoTT {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Pdo9oZWrVHNuOoTT .error-icon{fill:#552222;}#mermaid-svg-Pdo9oZWrVHNuOoTT .error-text{fill:#5…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
