Skip to content

Commit c6cad29

Browse files
committed
v0.1.0
1 parent 4acfa10 commit c6cad29

File tree

7 files changed

+189
-36
lines changed

7 files changed

+189
-36
lines changed

.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

pydify/agent.py

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,60 @@ def message_feedback(
127127

128128
return self.post(endpoint, json_data=payload)
129129

130-
def get_suggested_questions(self, message_id: str, user: str) -> Dict[str, Any]:
130+
def get_suggested_questions(self, message_id: str, user: str, **kwargs) -> Dict[str, Any]:
131131
"""
132132
获取下一轮建议问题列表。
133133
134134
Args:
135135
message_id (str): 消息ID
136136
user (str): 用户标识
137+
**kwargs: 额外的请求参数,如timeout、max_retries等
137138
138139
Returns:
139140
Dict[str, Any]: 建议问题列表
140141
141142
Raises:
142-
requests.HTTPError: 当API请求失败时
143+
DifyAPIError: 当API请求失败时
143144
"""
144-
endpoint = f"messages/{message_id}/suggested"
145-
params = {"user": user}
146-
return self.get(endpoint, params=params)
145+
# 尝试多种可能的端点路径格式
146+
possible_endpoints = [
147+
f"messages/{message_id}/suggested", # 原始格式
148+
f"messages/{message_id}/suggested-questions", # 新格式1
149+
f"chat-messages/{message_id}/suggested-questions", # 新格式2
150+
"suggested-questions", # 当前格式
151+
]
152+
153+
params = {
154+
"user": user,
155+
}
156+
157+
# 添加详细日志
158+
# print(f"请求推荐问题: 消息ID={message_id}, 用户={user}")
159+
160+
# 尝试所有可能的端点,直到找到一个有效的
161+
last_error = None
162+
for endpoint in possible_endpoints:
163+
try:
164+
params_to_use = params.copy()
165+
# 如果端点是standalone的suggested-questions,需要添加message_id参数
166+
if endpoint == "suggested-questions":
167+
params_to_use["message_id"] = message_id
168+
else:
169+
# 否则可能不需要在参数中包含message_id
170+
params_to_use.pop("message_id", None)
171+
172+
print(f"尝试端点: {endpoint}, 参数: {params_to_use}")
173+
result = self.get(endpoint, params=params_to_use, **kwargs)
174+
print(f"端点 {endpoint} 请求成功!")
175+
return result
176+
except Exception as e:
177+
last_error = e
178+
print(f"端点 {endpoint} 请求失败: {str(e)}")
179+
continue
180+
181+
# 如果所有端点都失败,记录最后一个错误并返回空结果
182+
print(f"所有推荐问题端点请求都失败。最后错误: {str(last_error)}")
183+
return {"data": []}
147184

148185
def get_messages(
149186
self,

pydify/chatbot.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77

88
import os
9+
import json
910
from typing import Dict, Any, List, Optional, Union, Generator
1011

1112
from .common import DifyBaseClient
@@ -27,6 +28,7 @@ def send_message(
2728
conversation_id: str = None,
2829
files: List[Dict[str, Any]] = None,
2930
auto_generate_name: bool = True,
31+
**kwargs
3032
) -> Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
3133
"""
3234
发送对话消息,创建会话消息。
@@ -39,6 +41,7 @@ def send_message(
3941
conversation_id (str, optional): 会话ID,基于之前的聊天记录继续对话时需提供。默认为None
4042
files (List[Dict[str, Any]], optional): 要包含在消息中的文件列表,每个文件为一个字典。默认为None
4143
auto_generate_name (bool, optional): 是否自动生成会话标题。默认为True
44+
**kwargs: 额外的请求参数,如timeout、max_retries等
4245
4346
Returns:
4447
Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
@@ -59,8 +62,8 @@ def send_message(
5962
"auto_generate_name": auto_generate_name,
6063
}
6164

62-
if inputs:
63-
payload["inputs"] = inputs
65+
# 确保inputs始终存在,即使是空字典
66+
payload["inputs"] = inputs or {}
6467

6568
if conversation_id:
6669
payload["conversation_id"] = conversation_id
@@ -70,10 +73,14 @@ def send_message(
7073

7174
endpoint = "chat-messages"
7275

76+
# 打印请求信息,便于调试
77+
print(f"请求URL: {self.base_url}{endpoint}")
78+
print(f"请求参数: {json.dumps(payload)}")
79+
7380
if response_mode == "streaming":
74-
return self.post_stream(endpoint, json_data=payload)
81+
return self.post_stream(endpoint, json_data=payload, **kwargs)
7582
else:
76-
return self.post(endpoint, json_data=payload)
83+
return self.post(endpoint, json_data=payload, **kwargs)
7784

7885
def stop_response(self, task_id: str, user: str) -> Dict[str, Any]:
7986
"""

pydify/chatflow.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def send_message(
2929
conversation_id: str = None,
3030
files: List[Dict[str, Any]] = None,
3131
auto_generate_name: bool = True,
32+
**kwargs
3233
) -> Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
3334
"""
3435
发送对话消息,创建会话消息。
@@ -41,6 +42,7 @@ def send_message(
4142
conversation_id (str, optional): 会话ID,基于之前的聊天记录继续对话时需提供。默认为None
4243
files (List[Dict[str, Any]], optional): 要包含在消息中的文件列表,每个文件为一个字典。默认为None
4344
auto_generate_name (bool, optional): 是否自动生成会话标题。默认为True
45+
**kwargs: 额外的请求参数,如timeout、max_retries等
4446
4547
Returns:
4648
Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
@@ -49,7 +51,7 @@ def send_message(
4951
5052
Raises:
5153
ValueError: 当提供了无效的参数时
52-
requests.HTTPError: 当API请求失败时
54+
DifyAPIError: 当API请求失败时
5355
"""
5456
if response_mode not in ["streaming", "blocking"]:
5557
raise ValueError("response_mode must be 'streaming' or 'blocking'")
@@ -61,8 +63,8 @@ def send_message(
6163
"auto_generate_name": auto_generate_name,
6264
}
6365

64-
if inputs:
65-
payload["inputs"] = inputs
66+
# 确保inputs字段始终存在,即使是空字典
67+
payload["inputs"] = inputs or {}
6668

6769
if conversation_id:
6870
payload["conversation_id"] = conversation_id
@@ -73,9 +75,9 @@ def send_message(
7375
endpoint = "chat-messages"
7476

7577
if response_mode == "streaming":
76-
return self.post_stream(endpoint, json_data=payload)
78+
return self.post_stream(endpoint, json_data=payload, **kwargs)
7779
else:
78-
return self.post(endpoint, json_data=payload)
80+
return self.post(endpoint, json_data=payload, **kwargs)
7981

8082
def stop_response(self, task_id: str, user: str) -> Dict[str, Any]:
8183
"""

pydify/common.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,43 @@ def _request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
103103
except (requests.RequestException, ConnectionError) as e:
104104
# 如果是网络错误且还有重试次数,则重试
105105
if attempt < max_retries:
106-
print(f"网络错误: {str(e)}{attempt+1}秒后重试...")
106+
# 提供更详细的错误信息
107+
error_type = type(e).__name__
108+
109+
# 检测具体的连接问题类型
110+
if isinstance(e, requests.exceptions.SSLError):
111+
error_msg = f"SSL连接错误: {str(e)}"
112+
elif isinstance(e, requests.exceptions.ConnectTimeout):
113+
error_msg = f"连接超时: {str(e)}"
114+
elif isinstance(e, requests.exceptions.ReadTimeout):
115+
error_msg = f"读取超时: {str(e)}"
116+
elif isinstance(e, requests.exceptions.ConnectionError):
117+
error_msg = f"网络连接错误: {str(e)}"
118+
else:
119+
error_msg = f"网络错误({error_type}): {str(e)}"
120+
121+
print(f"{error_msg}{attempt+1}秒后重试...")
107122
import time
108123
time.sleep(retry_delay)
109124
continue
110125

111-
raise DifyAPIError(f"网络请求异常: {str(e)}")
126+
# 提供更友好的错误信息
127+
error_type = type(e).__name__
128+
if isinstance(e, requests.exceptions.SSLError):
129+
error_msg = f"SSL连接错误: {str(e)}"
130+
elif isinstance(e, requests.exceptions.ConnectTimeout):
131+
error_msg = f"连接超时: {str(e)}"
132+
elif isinstance(e, requests.exceptions.ReadTimeout):
133+
error_msg = f"读取超时: {str(e)}"
134+
elif isinstance(e, requests.exceptions.ConnectionError):
135+
error_msg = f"网络连接错误: {str(e)}"
136+
else:
137+
error_msg = f"网络错误({error_type}): {str(e)}"
138+
139+
# 提供连接问题的建议
140+
suggestions = "\n请检查:\n1. 网络连接是否正常\n2. API地址是否正确\n3. 服务器是否可用\n4. SSL证书是否有效"
141+
142+
raise DifyAPIError(f"{error_msg}{suggestions}")
112143

113144
def get(self, endpoint: str, **kwargs) -> Dict[str, Any]:
114145
"""
@@ -252,13 +283,43 @@ def post_stream(self, endpoint: str, json_data: Dict[str, Any], **kwargs) -> Gen
252283
except (requests.RequestException, ConnectionError) as e:
253284
# 如果是网络错误且还有重试次数,则重试
254285
if attempt < max_retries:
255-
print(f"网络错误: {str(e)}{attempt+1}秒后重试...")
286+
# 提供更详细的错误信息
287+
error_type = type(e).__name__
288+
289+
# 检测具体的连接问题类型
290+
if isinstance(e, requests.exceptions.SSLError):
291+
error_msg = f"SSL连接错误: {str(e)}"
292+
elif isinstance(e, requests.exceptions.ConnectTimeout):
293+
error_msg = f"连接超时: {str(e)}"
294+
elif isinstance(e, requests.exceptions.ReadTimeout):
295+
error_msg = f"读取超时: {str(e)}"
296+
elif isinstance(e, requests.exceptions.ConnectionError):
297+
error_msg = f"网络连接错误: {str(e)}"
298+
else:
299+
error_msg = f"网络错误({error_type}): {str(e)}"
300+
301+
print(f"{error_msg}{attempt+1}秒后重试...")
256302
import time
257303
time.sleep(retry_delay)
258304
continue
259305

260-
# 如果已经重试了所有次数仍失败,抛出异常
261-
raise DifyAPIError(f"流式请求异常: {str(e)}")
306+
# 提供更友好的错误信息
307+
error_type = type(e).__name__
308+
if isinstance(e, requests.exceptions.SSLError):
309+
error_msg = f"SSL连接错误: {str(e)}"
310+
elif isinstance(e, requests.exceptions.ConnectTimeout):
311+
error_msg = f"连接超时: {str(e)}"
312+
elif isinstance(e, requests.exceptions.ReadTimeout):
313+
error_msg = f"读取超时: {str(e)}"
314+
elif isinstance(e, requests.exceptions.ConnectionError):
315+
error_msg = f"网络连接错误: {str(e)}"
316+
else:
317+
error_msg = f"网络错误({error_type}): {str(e)}"
318+
319+
# 提供连接问题的建议
320+
suggestions = "\n请检查:\n1. 网络连接是否正常\n2. API地址是否正确\n3. 服务器是否可用\n4. SSL证书是否有效"
321+
322+
raise DifyAPIError(f"{error_msg}{suggestions}")
262323

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

@@ -348,6 +409,7 @@ def message_feedback(
348409
user: str,
349410
rating: str = None,
350411
content: str = None,
412+
**kwargs # 添加kwargs参数支持
351413
) -> Dict[str, Any]:
352414
"""
353415
对消息进行反馈(点赞/点踩)。
@@ -357,6 +419,7 @@ def message_feedback(
357419
user (str): 用户标识
358420
rating (str, optional): 评价,可选值:'like'(点赞), 'dislike'(点踩), None(撤销)。默认为None
359421
content (str, optional): 反馈的具体信息。默认为None
422+
**kwargs: 额外的请求参数,如timeout、max_retries等
360423
361424
Returns:
362425
Dict[str, Any]: 反馈结果
@@ -376,7 +439,7 @@ def message_feedback(
376439
if content:
377440
payload["content"] = content
378441

379-
return self.post(f"messages/{message_id}/feedbacks", json_data=payload)
442+
return self.post(f"messages/{message_id}/feedbacks", json_data=payload, **kwargs)
380443

381444
def get_app_info(self) -> Dict[str, Any]:
382445
"""

pydify/text_generation.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def completion(
2525
response_mode: str = "streaming",
2626
inputs: Dict[str, Any] = None,
2727
files: List[Dict[str, Any]] = None,
28+
**kwargs # 添加kwargs参数支持
2829
) -> Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
2930
"""
3031
发送消息给文本生成应用。
@@ -35,6 +36,7 @@ def completion(
3536
response_mode (str, optional): 响应模式,'streaming'(流式)或'blocking'(阻塞)。默认为'streaming'
3637
inputs (Dict[str, Any], optional): 额外的输入参数。默认为None,若提供,会与query合并
3738
files (List[Dict[str, Any]], optional): 要包含在消息中的文件列表,每个文件为一个字典。默认为None
39+
**kwargs: 额外的请求参数,如timeout、max_retries等
3840
3941
Returns:
4042
Union[Dict[str, Any], Generator[Dict[str, Any], None, None]]:
@@ -68,9 +70,9 @@ def completion(
6870
endpoint = "completion-messages"
6971

7072
if response_mode == "streaming":
71-
return self.post_stream(endpoint, json_data=payload)
73+
return self.post_stream(endpoint, json_data=payload, **kwargs) # 传递kwargs
7274
else:
73-
return self.post(endpoint, json_data=payload)
75+
return self.post(endpoint, json_data=payload, **kwargs) # 传递kwargs
7476

7577
def stop_completion(self, task_id: str, user: str) -> Dict[str, Any]:
7678
"""

0 commit comments

Comments
 (0)