Skip to content

Commit bb5560c

Browse files
committed
update
1 parent 21196c2 commit bb5560c

File tree

7 files changed

+28
-363
lines changed

7 files changed

+28
-363
lines changed

pydify/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
包括对话、文本生成、工作流、文件上传等。
66
"""
77

8-
from .agent import AgentClient, DifyBaseClient
8+
from .agent import AgentClient
99
from .chatbot import ChatbotClient
1010
from .chatflow import ChatflowClient
1111
from .text_generation import TextGenerationClient
1212
from .workflow import WorkflowClient
13-
13+
from .common import DifyType, DifyBaseClient
1414

1515
def create_client(type: str, base_url: str, api_key: str) -> DifyBaseClient:
1616
if type == "workflow":

pydify/agent.py

Lines changed: 3 additions & 354 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
import os
1111
from typing import Any, BinaryIO, Dict, Generator, List, Optional, Tuple, Union
1212

13-
from .common import DifyBaseClient
13+
from .common import DifyBaseClient, DifyType
1414

1515

1616
class AgentClient(DifyBaseClient):
1717
"""Dify Agent应用客户端类。
1818
1919
提供与Dify Agent应用API交互的方法,包括发送消息、获取历史消息、管理会话、
2020
上传文件、语音转文字、文字转语音等功能。Agent应用支持迭代式规划推理和自主工具调用。
21-
"""
21+
"""
22+
type = DifyType.Agent
2223

2324
def send_message(
2425
self,
@@ -185,358 +186,6 @@ def get_suggested_questions(
185186
print(f"所有推荐问题端点请求都失败。最后错误: {str(last_error)}")
186187
return {"data": []}
187188

188-
def get_messages(
189-
self,
190-
conversation_id: str,
191-
user: str,
192-
first_id: str = None,
193-
limit: int = 20,
194-
) -> Dict[str, Any]:
195-
"""
196-
获取会话历史消息,滚动加载形式返回历史聊天记录,第一页返回最新limit条(倒序返回)。
197-
198-
Args:
199-
conversation_id (str): 会话ID
200-
user (str): 用户标识
201-
first_id (str, optional): 当前页第一条聊天记录的ID。默认为None
202-
limit (int, optional): 一次请求返回多少条聊天记录。默认为20
203-
204-
Returns:
205-
Dict[str, Any]: 消息列表及分页信息,包含agent_thoughts(Agent的思考过程)
206-
207-
Raises:
208-
requests.HTTPError: 当API请求失败时
209-
"""
210-
endpoint = "messages"
211-
212-
params = {
213-
"conversation_id": conversation_id,
214-
"user": user,
215-
"limit": limit,
216-
}
217-
218-
if first_id:
219-
params["first_id"] = first_id
220-
221-
return self.get(endpoint, params=params)
222-
223-
def get_conversations(
224-
self,
225-
user: str,
226-
last_id: str = None,
227-
limit: int = 20,
228-
sort_by: str = "-updated_at",
229-
) -> Dict[str, Any]:
230-
"""
231-
获取会话列表,默认返回最近的20条。
232-
233-
Args:
234-
user (str): 用户标识
235-
last_id (str, optional): 当前页最后面一条记录的ID。默认为None
236-
limit (int, optional): 一次请求返回多少条记录,默认20条,最大100条,最小1条。默认为20
237-
sort_by (str, optional): 排序字段,可选值:created_at, -created_at, updated_at, -updated_at。默认为"-updated_at"
238-
239-
Returns:
240-
Dict[str, Any]: 会话列表及分页信息
241-
242-
Raises:
243-
ValueError: 当提供了无效的参数时
244-
requests.HTTPError: 当API请求失败时
245-
"""
246-
valid_sort_values = ["created_at", "-created_at", "updated_at", "-updated_at"]
247-
if sort_by not in valid_sort_values:
248-
raise ValueError(f"sort_by must be one of {valid_sort_values}")
249-
250-
if limit < 1 or limit > 100:
251-
raise ValueError("limit must be between 1 and 100")
252-
253-
endpoint = "conversations"
254-
255-
params = {
256-
"user": user,
257-
"limit": limit,
258-
"sort_by": sort_by,
259-
}
260-
261-
if last_id:
262-
params["last_id"] = last_id
263-
264-
return self.get(endpoint, params=params)
265-
266-
def delete_conversation(self, conversation_id: str, user: str) -> Dict[str, Any]:
267-
"""
268-
删除会话。
269-
270-
Args:
271-
conversation_id (str): 会话ID
272-
user (str): 用户标识
273-
274-
Returns:
275-
Dict[str, Any]: 删除结果
276-
277-
Raises:
278-
requests.HTTPError: 当API请求失败时
279-
"""
280-
endpoint = f"conversations/{conversation_id}"
281-
payload = {"user": user}
282-
return self._request("DELETE", endpoint, json=payload).json()
283-
284-
def rename_conversation(
285-
self,
286-
conversation_id: str,
287-
user: str,
288-
name: str = None,
289-
auto_generate: bool = False,
290-
) -> Dict[str, Any]:
291-
"""
292-
会话重命名,对会话进行重命名,会话名称用于显示在支持多会话的客户端上。
293-
294-
Args:
295-
conversation_id (str): 会话ID
296-
user (str): 用户标识
297-
name (str, optional): 名称,若auto_generate为True时,该参数可不传。默认为None
298-
auto_generate (bool, optional): 自动生成标题。默认为False
299-
300-
Returns:
301-
Dict[str, Any]: 重命名后的会话信息
302-
303-
Raises:
304-
ValueError: 当提供了无效的参数时
305-
requests.HTTPError: 当API请求失败时
306-
"""
307-
if not auto_generate and not name:
308-
raise ValueError("name is required when auto_generate is False")
309-
310-
endpoint = f"conversations/{conversation_id}/name"
311-
312-
payload = {"user": user, "auto_generate": auto_generate}
313-
314-
if name:
315-
payload["name"] = name
316-
317-
return self.post(endpoint, json_data=payload)
318-
319-
def audio_to_text(self, file_path: str, user: str) -> Dict[str, Any]:
320-
"""
321-
语音转文字。
322-
323-
Args:
324-
file_path (str): 语音文件路径,支持格式:['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm']
325-
user (str): 用户标识
326-
327-
Returns:
328-
Dict[str, Any]: 转换结果,包含文字内容
329-
330-
Raises:
331-
FileNotFoundError: 当文件不存在时
332-
ValueError: 当文件格式不支持时
333-
requests.HTTPError: 当API请求失败时
334-
"""
335-
if not os.path.exists(file_path):
336-
raise FileNotFoundError(f"File not found: {file_path}")
337-
338-
# 检查文件类型
339-
supported_extensions = ["mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm"]
340-
file_extension = os.path.splitext(file_path)[1].lower().replace(".", "")
341-
342-
if file_extension not in supported_extensions:
343-
raise ValueError(
344-
f"Unsupported file type. Supported types: {supported_extensions}"
345-
)
346-
347-
with open(file_path, "rb") as file:
348-
files = {"file": file}
349-
data = {"user": user}
350-
351-
url = os.path.join(self.base_url, "audio-to-text")
352-
353-
headers = self._get_headers()
354-
# 移除Content-Type,让requests自动设置multipart/form-data
355-
headers.pop("Content-Type", None)
356-
357-
response = self._request(
358-
"POST", "audio-to-text", headers=headers, files=files, data=data
359-
)
360-
return response.json()
361-
362-
def audio_to_text_obj(
363-
self, file_obj: BinaryIO, filename: str, user: str
364-
) -> Dict[str, Any]:
365-
"""
366-
使用文件对象进行语音转文字。
367-
368-
Args:
369-
file_obj (BinaryIO): 语音文件对象
370-
filename (str): 文件名,用于确定文件类型
371-
user (str): 用户标识
372-
373-
Returns:
374-
Dict[str, Any]: 转换结果,包含文字内容
375-
376-
Raises:
377-
ValueError: 当文件格式不支持时
378-
requests.HTTPError: 当API请求失败时
379-
"""
380-
# 检查文件类型
381-
supported_extensions = ["mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm"]
382-
file_extension = os.path.splitext(filename)[1].lower().replace(".", "")
383-
384-
if file_extension not in supported_extensions:
385-
raise ValueError(
386-
f"Unsupported file type. Supported types: {supported_extensions}"
387-
)
388-
389-
files = {"file": (filename, file_obj)}
390-
data = {"user": user}
391-
392-
headers = self._get_headers()
393-
# 移除Content-Type,让requests自动设置multipart/form-data
394-
headers.pop("Content-Type", None)
395-
396-
response = self._request(
397-
"POST", "audio-to-text", headers=headers, files=files, data=data
398-
)
399-
return response.json()
400-
401-
def text_to_audio(
402-
self,
403-
user: str,
404-
message_id: str = None,
405-
text: str = None,
406-
) -> Dict[str, Any]:
407-
"""
408-
文字转语音。
409-
410-
Args:
411-
user (str): 用户标识
412-
message_id (str, optional): Dify生成的文本消息ID,如果提供,系统会自动查找相应的内容直接合成语音。默认为None
413-
text (str, optional): 语音生成内容,如果没有传message_id,则使用此字段内容。默认为None
414-
415-
Returns:
416-
Dict[str, Any]: 转换结果,包含音频数据
417-
418-
Raises:
419-
ValueError: 当必要参数缺失时
420-
requests.HTTPError: 当API请求失败时
421-
"""
422-
if not message_id and not text:
423-
raise ValueError("Either message_id or text must be provided")
424-
425-
endpoint = "text-to-audio"
426-
427-
payload = {"user": user}
428-
429-
if message_id:
430-
payload["message_id"] = message_id
431-
432-
if text:
433-
payload["text"] = text
434-
435-
return self.post(endpoint, json_data=payload)
436-
437-
def upload_file(self, file_path: str, user: str) -> Dict[str, Any]:
438-
"""
439-
上传文件(目前仅支持图片)到Dify API,可用于图文多模态理解。
440-
441-
Args:
442-
file_path (str): 要上传的文件路径,支持png, jpg, jpeg, webp, gif格式
443-
user (str): 用户标识
444-
445-
Returns:
446-
Dict[str, Any]: 上传文件的响应数据
447-
448-
Raises:
449-
FileNotFoundError: 当文件不存在时
450-
ValueError: 当文件格式不支持时
451-
requests.HTTPError: 当API请求失败时
452-
"""
453-
if not os.path.exists(file_path):
454-
raise FileNotFoundError(f"File not found: {file_path}")
455-
456-
# 检查文件类型
457-
supported_extensions = ["png", "jpg", "jpeg", "webp", "gif"]
458-
file_extension = os.path.splitext(file_path)[1].lower().replace(".", "")
459-
460-
if file_extension not in supported_extensions:
461-
raise ValueError(
462-
f"Unsupported file type. Supported types: {supported_extensions}"
463-
)
464-
465-
with open(file_path, "rb") as file:
466-
files = {"file": file}
467-
data = {"user": user}
468-
469-
headers = self._get_headers()
470-
# 移除Content-Type,让requests自动设置multipart/form-data
471-
headers.pop("Content-Type", None)
472-
473-
response = self._request(
474-
"POST", "files/upload", headers=headers, files=files, data=data
475-
)
476-
return response.json()
477-
478-
def upload_file_obj(
479-
self, file_obj: BinaryIO, filename: str, user: str
480-
) -> Dict[str, Any]:
481-
"""
482-
使用文件对象上传文件(目前仅支持图片)到Dify API。
483-
484-
Args:
485-
file_obj (BinaryIO): 文件对象
486-
filename (str): 文件名,用于确定文件类型
487-
user (str): 用户标识
488-
489-
Returns:
490-
Dict[str, Any]: 上传文件的响应数据
491-
492-
Raises:
493-
ValueError: 当文件格式不支持时
494-
requests.HTTPError: 当API请求失败时
495-
"""
496-
# 检查文件类型
497-
supported_extensions = ["png", "jpg", "jpeg", "webp", "gif"]
498-
file_extension = os.path.splitext(filename)[1].lower().replace(".", "")
499-
500-
if file_extension not in supported_extensions:
501-
raise ValueError(
502-
f"Unsupported file type. Supported types: {supported_extensions}"
503-
)
504-
505-
files = {"file": (filename, file_obj)}
506-
data = {"user": user}
507-
508-
headers = self._get_headers()
509-
# 移除Content-Type,让requests自动设置multipart/form-data
510-
headers.pop("Content-Type", None)
511-
512-
response = self._request(
513-
"POST", "files/upload", headers=headers, files=files, data=data
514-
)
515-
return response.json()
516-
517-
def get_app_info(self) -> Dict[str, Any]:
518-
"""
519-
获取应用基本信息。
520-
521-
Returns:
522-
Dict[str, Any]: 应用信息,包含名称、描述和标签
523-
524-
Raises:
525-
requests.HTTPError: 当API请求失败时
526-
"""
527-
return self.get("info")
528-
529-
def get_parameters(self) -> Dict[str, Any]:
530-
"""
531-
获取应用参数,包括功能开关、输入参数名称、类型及默认值等。
532-
533-
Returns:
534-
Dict[str, Any]: 应用参数配置
535-
536-
Raises:
537-
requests.HTTPError: 当API请求失败时
538-
"""
539-
return self.get("parameters")
540189

541190
def get_meta(self) -> Dict[str, Any]:
542191
"""

0 commit comments

Comments
 (0)