|
|
@@ -1,21 +1,13 @@
|
|
|
-import httpx
|
|
|
from typing import Optional
|
|
|
-from app.config import settings
|
|
|
import logging
|
|
|
|
|
|
+from src.graphs.tongue import get_tongue_graph
|
|
|
+
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
class TongueDiagnosisAgent:
|
|
|
- """舌诊分析 Agent
|
|
|
-
|
|
|
- 当前实现: 代理到 Dify Workflow (多模态最成熟)
|
|
|
- 后续可替换: 直接调用多模态 LLM API
|
|
|
- """
|
|
|
-
|
|
|
- def __init__(self):
|
|
|
- self.dify_base = settings.dify_base_url or ""
|
|
|
- self.dify_api_key = settings.dify_tongue_api_key or ""
|
|
|
+ """舌诊分析 Agent — 调用 LangGraph 舌诊 graph(glm-5 视觉模型)"""
|
|
|
|
|
|
async def diagnose(
|
|
|
self,
|
|
|
@@ -23,46 +15,29 @@ class TongueDiagnosisAgent:
|
|
|
user_id: int,
|
|
|
additional_context: Optional[dict] = None,
|
|
|
) -> dict:
|
|
|
- """舌诊分析: 调用 Dify Workflow 或直接 LLM"""
|
|
|
- if self.dify_base and self.dify_api_key:
|
|
|
- return await self._via_dify(image_url, user_id, additional_context)
|
|
|
- else:
|
|
|
- return await self._via_llm(image_url)
|
|
|
-
|
|
|
- async def _via_dify(
|
|
|
- self, image_url: str, user_id: int, context: Optional[dict]
|
|
|
- ) -> dict:
|
|
|
- """通过 Dify Workflow 执行舌诊"""
|
|
|
- url = f"{self.dify_base}/workflows/run"
|
|
|
- headers = {
|
|
|
- "Authorization": f"Bearer {self.dify_api_key}",
|
|
|
- "Content-Type": "application/json",
|
|
|
- }
|
|
|
- inputs = {"tongue_image": {"type": "image", "url": image_url}}
|
|
|
- if context:
|
|
|
- inputs.update(context)
|
|
|
-
|
|
|
- body = {
|
|
|
- "inputs": inputs,
|
|
|
- "user": str(user_id),
|
|
|
- "response_mode": "blocking",
|
|
|
- }
|
|
|
+ return await self._via_llm(image_url)
|
|
|
|
|
|
+ async def _via_llm(self, image_url: str) -> dict:
|
|
|
try:
|
|
|
- async with httpx.AsyncClient(timeout=30) as client:
|
|
|
- resp = await client.post(url, json=body, headers=headers)
|
|
|
- data = resp.json()
|
|
|
- if "data" in data and "outputs" in data["data"]:
|
|
|
- return data["data"]["outputs"]
|
|
|
+ graph = get_tongue_graph()
|
|
|
+ result = graph.invoke({
|
|
|
+ "request": {"image_url": image_url},
|
|
|
+ "image_base64": None,
|
|
|
+ "raw_response": "",
|
|
|
+ "overall_assessment": "",
|
|
|
+ "indicators": [],
|
|
|
+ "error": None,
|
|
|
+ })
|
|
|
+ if result.get("error"):
|
|
|
+ logger.warning("舌诊 graph 失败: %s", result["error"])
|
|
|
+ return self._mock_result()
|
|
|
+ return {
|
|
|
+ "overall_assessment": result["overall_assessment"],
|
|
|
+ "indicators": result["indicators"],
|
|
|
+ }
|
|
|
except Exception as e:
|
|
|
- logger.warning("Dify 舌诊失败: %s", e)
|
|
|
-
|
|
|
- return self._mock_result()
|
|
|
-
|
|
|
- async def _via_llm(self, image_url: str) -> dict:
|
|
|
- """直接调用多模态 LLM (预留)"""
|
|
|
- logger.warning("多模态 LLM 未配置, 返回模拟数据")
|
|
|
- return self._mock_result()
|
|
|
+ logger.warning("舌诊 graph 执行异常: %s", e)
|
|
|
+ return self._mock_result()
|
|
|
|
|
|
def _mock_result(self) -> dict:
|
|
|
return {
|