Просмотр исходного кода

chore: auto bump version and changelog [skip ci]

iwt 3 месяцев назад
Родитель
Сommit
8ec45ee1ed

+ 154 - 0
cfc-langgraph/app/api/adapter.py

@@ -0,0 +1,154 @@
+from fastapi import APIRouter, HTTPException
+from pydantic import BaseModel
+from typing import Optional
+from app.graphs.chat_graph import create_chat_graph
+from app.graphs.analysis_graph import create_analysis_graph
+import uuid
+import time
+
+router = APIRouter(prefix="/api/v1", tags=["adapter"])
+
+# ---- Dify-compatible request/response models ----
+
+class DifyMessage(BaseModel):
+    role: str
+    content: str
+
+class DifyChatRequest(BaseModel):
+    query: str = ""
+    user: str = "anonymous"
+    conversation_id: str = ""
+    messages: list[DifyMessage] = []
+    inputs: dict = {}
+    response_mode: str = "blocking"  # blocking / streaming
+    user_id: str = ""
+    bot_name: str = "AI管家"
+
+class DifyAnalysisRequest(BaseModel):
+    report_id: Optional[int] = None
+    user_id: Optional[str] = None
+    focus: Optional[str] = None
+    messages: list[DifyMessage] = []
+
+class DifyChoice(BaseModel):
+    index: int
+    message: dict
+    finish_reason: str = "stop"
+
+class DifyUsage(BaseModel):
+    prompt_tokens: int = 0
+    completion_tokens: int = 0
+    total_tokens: int = 0
+
+class DifyResponse(BaseModel):
+    id: str
+    object: str = "chat.completion"
+    created: int
+    model: str = "langgraph-cfc"
+    choices: list[DifyChoice]
+    usage: DifyUsage = DifyUsage()
+    metadata: dict = {}
+
+# ---- Helpers ----
+
+def _now_ts() -> int:
+    return int(time.time())
+
+def _extract_query(req: DifyChatRequest) -> str:
+    if req.query:
+        return req.query
+    # fallback: take last user message
+    for msg in reversed(req.messages):
+        if msg.role == "user":
+            return msg.content
+    return ""
+
+def _to_langgraph_context(req: DifyChatRequest) -> dict:
+    ctx = {}
+    if isinstance(req.inputs, dict):
+        ctx["child_id"] = req.inputs.get("child_id")
+        ctx["report_id"] = req.inputs.get("report_id")
+        ctx["family_id"] = req.inputs.get("family_id")
+    return ctx
+
+# ---- Dify-compatible endpoints ----
+
+@router.post("/chat/completion", response_model=DifyResponse)
+async def chat_completion(req: DifyChatRequest):
+    query = _extract_query(req)
+    if not query:
+        raise HTTPException(status_code=400, detail="query 为空")
+
+    graph = create_chat_graph()
+    initial_state = {
+        "query": query,
+        "user_id": int(req.user_id) if str(req.user_id).isdigit() else 0,
+        "conversation_id": req.conversation_id or None,
+        "intent": None,
+        "context": _to_langgraph_context(req),
+        "messages": None,
+        "answer": None,
+        "tasks": [],
+        "sources": [],
+    }
+    config = {
+        "configurable": {"thread_id": req.conversation_id or str(req.user_id or "default")},
+    }
+    result = await graph.ainvoke(initial_state, config)
+    answer = result.get("answer") or ""
+    return DifyResponse(
+        id=f"chatcmpl-{uuid.uuid4().hex[:24]}",
+        created=_now_ts(),
+        choices=[
+            DifyChoice(
+                index=0,
+                message={"role": "assistant", "content": answer},
+                finish_reason="stop",
+            )
+        ],
+        usage=DifyUsage(
+            prompt_tokens=len(query.split()),
+            completion_tokens=len(answer.split()),
+            total_tokens=len(query.split()) + len(answer.split()),
+        ),
+    )
+
+
+@router.post("/analysis/run", response_model=DifyResponse)
+async def analysis_run(req: DifyAnalysisRequest):
+    graph = create_analysis_graph()
+    report_id = req.report_id
+    if report_id is None and isinstance(req.inputs, dict):
+        report_id = req.inputs.get("report_id")
+    initial_state = {
+        "report_id": report_id,
+        "user_id": int(req.user_id) if str(req.user_id).isdigit() else 0,
+        "focus": req.focus,
+        "report_data": None,
+        "survey_data": None,
+        "dimension_scores": None,
+        "analysis": None,
+        "recommendations": [],
+    }
+    result = await graph.ainvoke(initial_state, {})
+    analysis = result.get("analysis") or ""
+    recommendations = result.get("recommendations") or []
+    content = analysis
+    if recommendations:
+        content += "\n\n建议:\n" + "\n".join(f"- {r}" for r in recommendations)
+    return DifyResponse(
+        id=f"analysis-{uuid.uuid4().hex[:24]}",
+        created=_now_ts(),
+        choices=[
+            DifyChoice(
+                index=0,
+                message={"role": "assistant", "content": content},
+                finish_reason="stop",
+            )
+        ],
+        usage=DifyUsage(
+            prompt_tokens=len((req.focus or "").split()),
+            completion_tokens=len(content.split()),
+            total_tokens=len((req.focus or "").split()) + len(content.split()),
+        ),
+    )

+ 2 - 1
cfc-langgraph/app/main.py

@@ -3,7 +3,7 @@ import time
 import asyncio
 import logging
 from fastapi import FastAPI, Request
-from app.api import health, recommend, chat, analyze, tongue
+from app.api import health, recommend, chat, analyze, tongue, adapter
 from app import monitoring
 
 logger = logging.getLogger(__name__)
@@ -15,6 +15,7 @@ app.include_router(recommend.router)
 app.include_router(chat.router)
 app.include_router(analyze.router)
 app.include_router(tongue.router)
+app.include_router(adapter.router)
 app.include_router(monitoring.router)
 
 

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-6a40b52b12e5835d73c32eeafe095585c902928a
+a435e5dac6ee4aba0673f73f592dbf93d3a7f938

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.491",
+  "version": "1.0.492",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 26 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,32 @@
 
 ---
 
+## v1.0.492 (2026-07-22)
+
+### Bug 修复
+- @keyframes 从 scoped 移到非 scoped 样式块,修复 vue-cli-plugin-uni 编译错误
+
+### 其他
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web: 更新knowledge.html和sitemap.xml适配articles/目录结构
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles: 移动疾病科普六篇到articles/子目录
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles: 移动geo-faq三篇及尿酸文章到articles/子目录
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles/tap-water-pollution.html: 自来水中的隐形威胁
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+
+
 ## v1.0.491 (2026-07-22)
 
 ### 文档

+ 27 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.491
+> 当前版本: v1.0.492
 
 ## 历史版本
 
@@ -8,6 +8,32 @@
 
 ---
 
+## v1.0.492 (2026-07-22)
+
+### Bug 修复
+- @keyframes 从 scoped 移到非 scoped 样式块,修复 vue-cli-plugin-uni 编译错误
+
+### 其他
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web: 更新knowledge.html和sitemap.xml适配articles/目录结构
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles: 移动疾病科普六篇到articles/子目录
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles: 移动geo-faq三篇及尿酸文章到articles/子目录
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+- web/articles/tap-water-pollution.html: 自来水中的隐形威胁
+- Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
+- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
+- 
+
+
 ## v1.0.491 (2026-07-22)
 
 ### 文档