Skip to content

Commit da9f927

Browse files
committed
update
1 parent 78598a8 commit da9f927

File tree

9 files changed

+156
-53
lines changed

9 files changed

+156
-53
lines changed

.env.example

Lines changed: 0 additions & 1 deletion
This file was deleted.

examples/.env.examples

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
DIFY_BASE_URL=xxx
2+
DIFY_API_KEY_AGENT=xxx
3+
DIFY_API_KEY_CHATBOT=xxx
4+
DIFY_API_KEY_CHATFLOW=xxx
5+
DIFY_API_KEY_WORKFLOW=xxx
6+
DIFY_API_KEY_TEXT_GENERATION=xxx

examples/agent_example.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,39 @@
99
import base64
1010
from pprint import pprint
1111

12+
# load_env
13+
from dotenv import load_dotenv
14+
load_dotenv()
15+
1216
# 将父目录添加到 sys.path,使示例可以直接运行
1317
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
1418

1519
from pydify import AgentClient
1620

1721
# 从环境变量或直接设置 API 密钥
18-
API_KEY = os.environ.get("DIFY_API_KEY", "app-JH2PWol59GDhOfLpB1Qwvts3")
19-
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://sandanapp.com/v1")
22+
API_KEY = os.environ.get("DIFY_API_KEY_AGENT", "app-JH2PWol59GDhOfLpB1Qwvts3")
23+
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://sandanapp.com:8080/v1")
2024
USER_ID = "user_123" # 用户唯一标识
2125

26+
# 配置API请求参数
27+
REQUEST_TIMEOUT = 30 # API请求超时时间(秒)
28+
MAX_RETRIES = 3 # 最大重试次数
29+
RETRY_DELAY = 2 # 重试延迟时间(秒)
30+
2231
# 初始化客户端
23-
client = AgentClient(api_key=API_KEY, base_url=BASE_URL)
32+
client = AgentClient(
33+
api_key=API_KEY,
34+
base_url=BASE_URL,
35+
)
36+
37+
# 自定义请求参数的函数
38+
def get_request_kwargs():
39+
"""返回一个包含请求参数的字典,可用于所有API请求"""
40+
return {
41+
"timeout": REQUEST_TIMEOUT,
42+
"max_retries": MAX_RETRIES,
43+
"retry_delay": RETRY_DELAY
44+
}
2445

2546
def example_get_app_info():
2647
"""获取应用信息示例"""

examples/chatbot_example.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313

1414
from pydify import ChatbotClient
1515

16+
# load_env
17+
from dotenv import load_dotenv
18+
load_dotenv()
19+
1620
# 从环境变量或直接设置 API 密钥
17-
API_KEY = os.environ.get("DIFY_API_KEY", "your_api_key_here")
21+
API_KEY = os.environ.get("DIFY_API_KEY_CHATBOT", "your_api_key_here")
1822
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://your-dify-instance.com/v1")
1923
USER_ID = "user_123" # 用户唯一标识
2024

examples/chatflow_example.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
import base64
1010
from pprint import pprint
1111

12+
# load_env
13+
from dotenv import load_dotenv
14+
load_dotenv()
15+
1216
# 将父目录添加到 sys.path,使示例可以直接运行
1317
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
1418

1519
from pydify import ChatflowClient
1620

1721
# 从环境变量或直接设置 API 密钥
18-
API_KEY = os.environ.get("DIFY_API_KEY", "your_api_key_here")
22+
API_KEY = os.environ.get("DIFY_API_KEY_CHATFLOW", "your_api_key_here")
1923
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://your-dify-instance.com/v1")
2024
USER_ID = "user_123" # 用户唯一标识
2125

examples/test_examples.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616

1717
# 设置API基础URL
18-
DIFY_BASE_URL = "http://sandanapp.com/v1"
18+
DIFY_BASE_URL = "http://sandanapp.com:8080/v1"
1919

2020
# 将父目录添加到 sys.path,使示例可以直接运行
2121
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

examples/text_generation_example.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import sys
99
from pprint import pprint
1010

11+
# load_env
12+
from dotenv import load_dotenv
13+
load_dotenv()
14+
1115
# 将父目录添加到 sys.path,使示例可以直接运行
1216
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
1317

@@ -18,7 +22,7 @@
1822
)
1923

2024
# 从环境变量或直接设置 API 密钥
21-
API_KEY = os.environ.get("DIFY_API_KEY", "your_api_key_here")
25+
API_KEY = os.environ.get("DIFY_API_KEY_TEXT_GENERATION", "your_api_key_here")
2226
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://your-dify-instance.com/v1")
2327
USER_ID = "user_123" # 用户唯一标识
2428

examples/workflow_example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from pydify import WorkflowClient
1515

1616
# 从环境变量或直接设置 API 密钥
17-
API_KEY = os.environ.get("DIFY_API_KEY", "your_api_key_here")
17+
API_KEY = os.environ.get("DIFY_API_KEY_WORKFLOW", "your_api_key_here")
1818
BASE_URL = os.environ.get("DIFY_BASE_URL", "http://your-dify-instance.com/v1")
1919
USER_ID = "user_123" # 用户唯一标识
2020

pydify/common.py

Lines changed: 109 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,50 @@ def _request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
6565
url = urljoin(self.base_url, endpoint)
6666
headers = kwargs.pop("headers", {})
6767
headers.update(self._get_headers())
68-
69-
response = requests.request(method, url, headers=headers, **kwargs)
7068

71-
if not response.ok:
72-
error_msg = f"API request failed: {response.status_code}"
73-
error_data = {}
74-
try:
75-
error_data = response.json()
76-
error_msg = f"{error_msg} - {error_data.get('error', {}).get('message', '')}"
77-
except RequestsJSONDecodeError:
78-
pass
79-
80-
raise DifyAPIError(error_msg, status_code=response.status_code, error_data=error_data)
69+
# 设置重试机制
70+
max_retries = kwargs.pop("max_retries", 2)
71+
retry_delay = kwargs.pop("retry_delay", 1)
72+
timeout = kwargs.pop("timeout", 30)
8173

82-
return response
74+
# 添加超时参数
75+
kwargs["timeout"] = timeout
76+
77+
for attempt in range(max_retries + 1):
78+
try:
79+
response = requests.request(method, url, headers=headers, **kwargs)
80+
81+
if not response.ok:
82+
error_msg = f"API request failed: {response.status_code}"
83+
error_data = {}
84+
try:
85+
error_data = response.json()
86+
error_msg = f"{error_msg} - {error_data.get('error', {}).get('message', '')}"
87+
except RequestsJSONDecodeError:
88+
if response.text:
89+
error_msg = f"{error_msg} - {response.text[:100]}"
90+
91+
# 如果是可重试的错误码,并且还有重试次数,则重试
92+
if response.status_code in [429, 500, 502, 503, 504] and attempt < max_retries:
93+
print(f"请求失败,状态码: {response.status_code}{attempt+1}秒后重试...")
94+
import time
95+
time.sleep(retry_delay)
96+
continue
97+
98+
# 否则抛出异常
99+
raise DifyAPIError(error_msg, status_code=response.status_code, error_data=error_data)
100+
101+
return response
102+
103+
except (requests.RequestException, ConnectionError) as e:
104+
# 如果是网络错误且还有重试次数,则重试
105+
if attempt < max_retries:
106+
print(f"网络错误: {str(e)}{attempt+1}秒后重试...")
107+
import time
108+
time.sleep(retry_delay)
109+
continue
110+
111+
raise DifyAPIError(f"网络请求异常: {str(e)}")
83112

84113
def get(self, endpoint: str, **kwargs) -> Dict[str, Any]:
85114
"""
@@ -102,10 +131,10 @@ def get(self, endpoint: str, **kwargs) -> Dict[str, Any]:
102131
return {}
103132
return response.json()
104133
except RequestsJSONDecodeError as e:
105-
# 捕获JSON解析错误,提供更有用的错误消息
106-
error_msg = f"无法解析API响应为JSON: {str(e)}"
107-
error_data = {"response_text": response.text[:100], "endpoint": endpoint}
108-
raise DifyAPIError(error_msg, response.status_code, error_data) from e
134+
# 捕获JSON解析错误,打印警告信息并返回空字典
135+
print(f"警告: 无法解析API响应为JSON ({endpoint})")
136+
print(f"响应内容: {response.text[:100]}")
137+
return {}
109138

110139
def post(self, endpoint: str, data: Dict[str, Any] = None, json_data: Dict[str, Any] = None, **kwargs) -> Dict[str, Any]:
111140
"""
@@ -130,10 +159,10 @@ def post(self, endpoint: str, data: Dict[str, Any] = None, json_data: Dict[str,
130159
return {}
131160
return response.json()
132161
except RequestsJSONDecodeError as e:
133-
# 捕获JSON解析错误,提供更有用的错误消息
134-
error_msg = f"无法解析API响应为JSON: {str(e)}"
135-
error_data = {"response_text": response.text[:100], "endpoint": endpoint}
136-
raise DifyAPIError(error_msg, response.status_code, error_data) from e
162+
# 捕获JSON解析错误,打印警告信息并返回空字典
163+
print(f"警告: 无法解析API响应为JSON ({endpoint})")
164+
print(f"响应内容: {response.text[:100]}")
165+
return {}
137166

138167
def post_stream(self, endpoint: str, json_data: Dict[str, Any], **kwargs) -> Generator[Dict[str, Any], None, None]:
139168
"""
@@ -153,30 +182,66 @@ def post_stream(self, endpoint: str, json_data: Dict[str, Any], **kwargs) -> Gen
153182
url = urljoin(self.base_url, endpoint)
154183
headers = kwargs.pop("headers", {})
155184
headers.update(self._get_headers())
156-
157-
with requests.post(url, json=json_data, headers=headers, stream=True, **kwargs) as response:
158-
if not response.ok:
159-
error_msg = f"API request failed: {response.status_code}"
160-
error_data = {}
161-
try:
162-
error_data = response.json()
163-
error_msg = f"{error_msg} - {error_data.get('error', {}).get('message', '')}"
164-
except RequestsJSONDecodeError:
165-
pass
166-
167-
raise DifyAPIError(error_msg, status_code=response.status_code, error_data=error_data)
168-
169-
# 处理SSE流式响应
170-
for line in response.iter_lines():
171-
if line:
172-
line = line.decode('utf-8')
173-
if line.startswith('data: '):
174-
data = line[6:] # 移除 'data: ' 前缀
185+
186+
# 设置重试机制
187+
max_retries = kwargs.pop("max_retries", 2)
188+
retry_delay = kwargs.pop("retry_delay", 1)
189+
timeout = kwargs.pop("timeout", 60) # 流式请求需要更长的超时时间
190+
191+
# 添加超时参数
192+
kwargs["timeout"] = timeout
193+
194+
for attempt in range(max_retries + 1):
195+
try:
196+
with requests.post(url, json=json_data, headers=headers, stream=True, **kwargs) as response:
197+
if not response.ok:
198+
error_msg = f"API request failed: {response.status_code}"
199+
error_data = {}
175200
try:
176-
yield json.loads(data)
177-
except json.JSONDecodeError:
178-
# 忽略无法解析的行
179-
pass
201+
error_data = response.json()
202+
error_msg = f"{error_msg} - {error_data.get('error', {}).get('message', '')}"
203+
except RequestsJSONDecodeError:
204+
# 如果无法解析为JSON,提供一个简单的错误消息
205+
error_msg = f"{error_msg} - 响应无法解析为JSON"
206+
if response.text:
207+
print(f"响应内容: {response.text[:100]}")
208+
209+
# 如果是可重试的错误码,并且还有重试次数,则重试
210+
if response.status_code in [429, 500, 502, 503, 504] and attempt < max_retries:
211+
print(f"请求失败,状态码: {response.status_code}{attempt+1}秒后重试...")
212+
import time
213+
time.sleep(retry_delay)
214+
continue
215+
216+
raise DifyAPIError(error_msg, status_code=response.status_code, error_data=error_data)
217+
218+
# 处理SSE流式响应
219+
for line in response.iter_lines():
220+
if line:
221+
line = line.decode('utf-8')
222+
if line.startswith('data: '):
223+
data = line[6:] # 移除 'data: ' 前缀
224+
try:
225+
yield json.loads(data)
226+
except json.JSONDecodeError as e:
227+
# 打印警告信息并继续处理
228+
print(f"警告: 无法解析流式响应行为JSON: {data[:100]}")
229+
# 返回一个带有错误信息的字典,而不是抛出异常
230+
yield {"error": "JSON解析错误", "raw_data": data[:100]}
231+
232+
# 如果成功完成了迭代,就跳出重试循环
233+
break
234+
235+
except (requests.RequestException, ConnectionError) as e:
236+
# 如果是网络错误且还有重试次数,则重试
237+
if attempt < max_retries:
238+
print(f"网络错误: {str(e)}{attempt+1}秒后重试...")
239+
import time
240+
time.sleep(retry_delay)
241+
continue
242+
243+
# 如果已经重试了所有次数仍失败,抛出异常
244+
raise DifyAPIError(f"流式请求异常: {str(e)}")
180245

181246
# 通用方法 - 这些方法在多个子类中重复出现,可以移到基类
182247

0 commit comments

Comments
 (0)