-
Notifications
You must be signed in to change notification settings - Fork 346
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #938 from bright141/master
新增difyapi 的Chat 请求运行器
- Loading branch information
Showing
17 changed files
with
1,137 additions
and
23 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# LangBot/libs | ||
|
||
LangBot 项目下的 libs 目录下的所有代码均遵循本目录下的许可证约束。 | ||
您在使用、修改、分发本目录下的代码时,需要遵守其中包含的条款。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Dify Service API Python SDK | ||
|
||
这个 SDK 尚不完全支持 Dify Service API 的所有功能。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .v1 import client | ||
from .v1 import errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from v1 import client | ||
|
||
import asyncio | ||
|
||
import os | ||
import json | ||
|
||
|
||
class TestDifyClient: | ||
async def test_chat_messages(self): | ||
cln = client.AsyncDifyServiceClient(api_key=os.getenv("DIFY_API_KEY"), base_url=os.getenv("DIFY_BASE_URL")) | ||
|
||
resp = await cln.chat_messages(inputs={}, query="Who are you?", user="test") | ||
print(json.dumps(resp, ensure_ascii=False, indent=4)) | ||
|
||
async def test_upload_file(self): | ||
cln = client.AsyncDifyServiceClient(api_key=os.getenv("DIFY_API_KEY"), base_url=os.getenv("DIFY_BASE_URL")) | ||
|
||
file_bytes = open("img.png", "rb").read() | ||
|
||
print(type(file_bytes)) | ||
|
||
file = ("img2.png", file_bytes, "image/png") | ||
|
||
resp = await cln.upload_file(file=file, user="test") | ||
print(json.dumps(resp, ensure_ascii=False, indent=4)) | ||
|
||
async def test_workflow_run(self): | ||
cln = client.AsyncDifyServiceClient(api_key=os.getenv("DIFY_API_KEY"), base_url=os.getenv("DIFY_BASE_URL")) | ||
|
||
# resp = await cln.workflow_run(inputs={}, user="test") | ||
# # print(json.dumps(resp, ensure_ascii=False, indent=4)) | ||
# print(resp) | ||
chunks = [] | ||
|
||
ignored_events = ['text_chunk'] | ||
async for chunk in cln.workflow_run(inputs={}, user="test"): | ||
if chunk['event'] in ignored_events: | ||
continue | ||
chunks.append(chunk) | ||
print(json.dumps(chunks, ensure_ascii=False, indent=4)) | ||
|
||
if __name__ == "__main__": | ||
asyncio.run(TestDifyClient().test_workflow_run()) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
from __future__ import annotations | ||
|
||
import httpx | ||
import typing | ||
import json | ||
|
||
from .errors import DifyAPIError | ||
|
||
|
||
class AsyncDifyServiceClient: | ||
"""Dify Service API 客户端""" | ||
|
||
api_key: str | ||
base_url: str | ||
|
||
def __init__( | ||
self, | ||
api_key: str, | ||
base_url: str = "https://api.dify.ai/v1", | ||
) -> None: | ||
self.api_key = api_key | ||
self.base_url = base_url | ||
|
||
async def chat_messages( | ||
self, | ||
inputs: dict[str, typing.Any], | ||
query: str, | ||
user: str, | ||
response_mode: str = "blocking", # 当前不支持 streaming | ||
conversation_id: str = "", | ||
files: list[dict[str, typing.Any]] = [], | ||
timeout: float = 30.0, | ||
) -> dict[str, typing.Any]: | ||
"""发送消息""" | ||
if response_mode != "blocking": | ||
raise DifyAPIError("当前仅支持 blocking 模式") | ||
|
||
async with httpx.AsyncClient( | ||
base_url=self.base_url, | ||
trust_env=True, | ||
timeout=timeout, | ||
) as client: | ||
response = await client.post( | ||
"/chat-messages", | ||
headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}, | ||
json={ | ||
"inputs": inputs, | ||
"query": query, | ||
"user": user, | ||
"response_mode": response_mode, | ||
"conversation_id": conversation_id, | ||
"files": files, | ||
}, | ||
) | ||
|
||
if response.status_code != 200: | ||
raise DifyAPIError(f"{response.status_code} {response.text}") | ||
|
||
return response.json() | ||
|
||
async def workflow_run( | ||
self, | ||
inputs: dict[str, typing.Any], | ||
user: str, | ||
response_mode: str = "streaming", # 当前不支持 blocking | ||
files: list[dict[str, typing.Any]] = [], | ||
timeout: float = 30.0, | ||
) -> typing.AsyncGenerator[dict[str, typing.Any], None]: | ||
"""运行工作流""" | ||
if response_mode != "streaming": | ||
raise DifyAPIError("当前仅支持 streaming 模式") | ||
|
||
async with httpx.AsyncClient( | ||
base_url=self.base_url, | ||
trust_env=True, | ||
timeout=timeout, | ||
) as client: | ||
|
||
async with client.stream( | ||
"POST", | ||
"/workflows/run", | ||
headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}, | ||
json={ | ||
"inputs": inputs, | ||
"user": user, | ||
"response_mode": response_mode, | ||
"files": files, | ||
}, | ||
) as r: | ||
async for chunk in r.aiter_lines(): | ||
if chunk.strip() == "": | ||
continue | ||
if chunk.startswith("data:"): | ||
yield json.loads(chunk[5:]) | ||
|
||
async def upload_file( | ||
self, | ||
file: httpx._types.FileTypes, | ||
user: str, | ||
timeout: float = 30.0, | ||
) -> str: | ||
"""上传文件""" | ||
# curl -X POST 'http://dify.rockchin.top/v1/files/upload' \ | ||
# --header 'Authorization: Bearer {api_key}' \ | ||
# --form 'file=@localfile;type=image/[png|jpeg|jpg|webp|gif] \ | ||
# --form 'user=abc-123' | ||
async with httpx.AsyncClient( | ||
base_url=self.base_url, | ||
trust_env=True, | ||
timeout=timeout, | ||
) as client: | ||
# multipart/form-data | ||
response = await client.post( | ||
"/files/upload", | ||
headers={"Authorization": f"Bearer {self.api_key}"}, | ||
files={ | ||
"file": file, | ||
"user": (None, user), | ||
}, | ||
) | ||
|
||
if response.status_code != 201: | ||
raise DifyAPIError(f"{response.status_code} {response.text}") | ||
|
||
return response.json() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from . import client | ||
|
||
import asyncio | ||
|
||
import os | ||
|
||
|
||
class TestDifyClient: | ||
async def test_chat_messages(self): | ||
cln = client.DifyClient(api_key=os.getenv("DIFY_API_KEY")) | ||
|
||
resp = await cln.chat_messages(inputs={}, query="Who are you?", user_id="test") | ||
print(resp) | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(TestDifyClient().test_chat_messages()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class DifyAPIError(Exception): | ||
"""Dify API 请求失败""" | ||
|
||
def __init__(self, message: str): | ||
self.message = message | ||
super().__init__(self.message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from __future__ import annotations | ||
|
||
from .. import migration | ||
|
||
|
||
@migration.migration_class("dify-service-api-config", 16) | ||
class DifyServiceAPICfgMigration(migration.Migration): | ||
"""迁移""" | ||
|
||
async def need_migrate(self) -> bool: | ||
"""判断当前环境是否需要运行此迁移""" | ||
return 'dify-service-api' not in self.ap.provider_cfg.data | ||
|
||
async def run(self): | ||
"""执行迁移""" | ||
self.ap.provider_cfg.data['dify-service-api'] = { | ||
"base-url": "https://api.dify.ai/v1", | ||
"app-type": "chat", | ||
"chat": { | ||
"api-key": "sk-1234567890" | ||
}, | ||
"workflow": { | ||
"api-key": "sk-1234567890", | ||
"output-key": "summary" | ||
} | ||
} | ||
|
||
await self.ap.provider_cfg.dump_config() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.