back
This commit is contained in:
93
services/dify_client.py
Normal file
93
services/dify_client.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# services/dify_client.py
|
||||
import os, json, re, requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
DIFY_BASE = os.getenv("DIFY_API_BASE_URL", "https://api.dify.ai/v1")
|
||||
TIMEOUT = 60
|
||||
|
||||
def _post_request(endpoint: str, api_key: str, payload: dict):
|
||||
"""Generic function to post a request to a Dify endpoint."""
|
||||
if not api_key:
|
||||
raise RuntimeError("Dify API key is not set")
|
||||
|
||||
url = f"{DIFY_BASE}{endpoint}"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
# For debugging the exact payload sent to the API
|
||||
print(f"Sending Dify request to {url}: {json.dumps(payload, indent=2, ensure_ascii=False)}")
|
||||
|
||||
resp = requests.post(url, headers=headers, json=payload, timeout=TIMEOUT)
|
||||
|
||||
if resp.status_code != 200:
|
||||
print(f"Dify API Error Response: {resp.text}")
|
||||
resp.raise_for_status()
|
||||
|
||||
data = resp.json()
|
||||
return data.get("answer") or data
|
||||
|
||||
def translate_text(text: str, target_lang: str, user_id: str = "system") -> str:
|
||||
"""
|
||||
Calls the Dify CHAT API for translation, mimicking a user query.
|
||||
"""
|
||||
api_key = os.getenv("DIFY_TRANSLATOR_API_KEY")
|
||||
# Combine all information into a single query string, as expected by the prompt
|
||||
query = f"目標語言:{target_lang}\n需翻譯內容:\n{text}"
|
||||
|
||||
payload = {
|
||||
"inputs": {}, # Chatbot apps generally don't use inputs here
|
||||
"response_mode": "blocking",
|
||||
"user": user_id,
|
||||
"query": query,
|
||||
# conversation_id is optional for single-turn interactions
|
||||
}
|
||||
return _post_request("/chat-messages", api_key, payload)
|
||||
|
||||
def summarize_text(text: str, user_id: str = "system") -> str:
|
||||
api_key = os.getenv("DIFY_SUMMARIZER_API_KEY")
|
||||
payload = {
|
||||
"inputs": {},
|
||||
"response_mode": "blocking",
|
||||
"user": user_id,
|
||||
"query": text,
|
||||
}
|
||||
return _post_request("/chat-messages", api_key, payload)
|
||||
|
||||
def extract_action_items(text: str, user_id: str = "system") -> list[dict]:
|
||||
api_key = os.getenv("DIFY_ACTION_EXTRACTOR_API_KEY")
|
||||
payload = {
|
||||
"inputs": {},
|
||||
"response_mode": "blocking",
|
||||
"user": user_id,
|
||||
"query": text,
|
||||
}
|
||||
raw = _post_request("/chat-messages", api_key, payload)
|
||||
|
||||
# Fault tolerance for JSON parsing
|
||||
s = str(raw).strip()
|
||||
s = re.sub(r"^```(?:json)?|```$", "", s, flags=re.IGNORECASE|re.MULTILINE).strip()
|
||||
if not (s.startswith("[") and s.endswith("]")):
|
||||
m = re.search(r"[\s\S]*\[[\s\S]*\][\s\S]*", s)
|
||||
if m: s = m.group(0)
|
||||
|
||||
items = json.loads(s)
|
||||
if not isinstance(items, list):
|
||||
raise ValueError("Extractor did not return a list")
|
||||
|
||||
# Normalize keys for database storage
|
||||
normalized = []
|
||||
for i in items:
|
||||
for k in ("item", "action", "owner", "duedate"):
|
||||
if k not in i:
|
||||
raise ValueError(f"Extractor item is missing required key: {k}")
|
||||
normalized.append({
|
||||
"item": i["item"],
|
||||
"action": i["action"],
|
||||
"owner": i["owner"],
|
||||
"due_date": i["duedate"],
|
||||
})
|
||||
return normalized
|
Reference in New Issue
Block a user