Parcourir la source

docs(langgraph): sync phase1-4 plan checkpoints; add langgraph start.sh; ignore .venv

Xiaogang Liao il y a 2 mois
Parent
commit
58a248a38b

+ 4 - 0
.gitignore

@@ -58,3 +58,7 @@ __pycache__/
 .opencode/
 dev-browser/
 .omo/
+
+# Python venv
+.venv/
+venv/

+ 14 - 0
cfc-langgraph/start.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+# LangGraph 服务启动脚本
+# 用法: ./start.sh
+
+cd "$(dirname "$0")"
+rm -rf data/chroma_db data/chroma_db_memory
+nohup .venv/bin/uvicorn app.main:app \
+  --host 0.0.0.0 --port 9000 \
+  --workers 1 --log-level info \
+  > /tmp/langgraph.log 2>&1 &
+
+echo "PID: $!"
+sleep 3
+curl -s http://localhost:9000/api/v1/health

+ 54 - 54
docs/superpowers/plans/2026-07-20-langgraph-phase1.md

@@ -32,7 +32,7 @@
 **Interfaces:**
 - Produces: FastAPI app 入口 `app.main:app`,`/health` 返回 200
 
-- [ ] **Step 1: 创建 `pyproject.toml`**
+- [x] **Step 1: 创建 `pyproject.toml`**
 
 ```toml
 [project]
@@ -70,7 +70,7 @@ select = ["E", "F", "I", "N", "W"]
 ignore = ["E501"]
 ```
 
-- [ ] **Step 2: 创建 `.env.example`**
+- [x] **Step 2: 创建 `.env.example`**
 
 ```bash
 # LLM
@@ -101,7 +101,7 @@ LOG_LEVEL=info
 CHROMA_DB_PATH=./data/chroma_db
 ```
 
-- [ ] **Step 3: 创建 `.gitignore`**
+- [x] **Step 3: 创建 `.gitignore`**
 
 ```
 __pycache__/
@@ -114,7 +114,7 @@ dist/
 .pytest_cache/
 ```
 
-- [ ] **Step 4: 创建 `Dockerfile`**
+- [x] **Step 4: 创建 `Dockerfile`**
 
 ```dockerfile
 FROM python:3.11-slim
@@ -132,9 +132,9 @@ EXPOSE 9000
 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "9000"]
 ```
 
-- [ ] **Step 5: 创建 `app/__init__.py`**(空文件)
+- [x] **Step 5: 创建 `app/__init__.py`**(空文件)
 
-- [ ] **Step 6: 创建 `app/main.py`**
+- [x] **Step 6: 创建 `app/main.py`**
 
 ```python
 from fastapi import FastAPI
@@ -153,7 +153,7 @@ async def shutdown():
     pass  # 后续 Phase 在此清理资源
 ```
 
-- [ ] **Step 7: 验证服务可启动**
+- [x] **Step 7: 验证服务可启动**
 
 ```bash
 cd cfc-langgraph
@@ -164,9 +164,9 @@ curl http://localhost:9000/health
 kill %1
 ```
 
-- [ ] **Step 8: 创建 `app/api/__init__.py`**(空文件)
+- [x] **Step 8: 创建 `app/api/__init__.py`**(空文件)
 
-- [ ] **Step 9: 创建 `app/api/health.py`**
+- [x] **Step 9: 创建 `app/api/health.py`**
 
 ```python
 from fastapi import APIRouter
@@ -178,7 +178,7 @@ async def health():
     return {"status": "ok"}
 ```
 
-- [ ] **Step 10: Commit**
+- [x] **Step 10: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -195,7 +195,7 @@ git commit -m "feat(langgraph): scaffold Python sidecar project"
 **Interfaces:**
 - Produces: `app.config.settings` — Pydantic Settings 单例,所有模块通过 `from app.config import settings` 读取
 
-- [ ] **Step 1: 创建 `app/config.py`**
+- [x] **Step 1: 创建 `app/config.py`**
 
 ```python
 from pydantic_settings import BaseSettings
@@ -246,14 +246,14 @@ class Settings(BaseSettings):
 settings = Settings()
 ```
 
-- [ ] **Step 2: 创建 `.env` 文件(从 `.env.example` 复制,填入真实 Key)**
+- [x] **Step 2: 创建 `.env` 文件(从 `.env.example` 复制,填入真实 Key)**
 
 ```bash
 cp cfc-langgraph/.env.example cfc-langgraph/.env
 # 手动编辑填入 LLM_API_KEY
 ```
 
-- [ ] **Step 3: 验证配置可加载**
+- [x] **Step 3: 验证配置可加载**
 
 ```bash
 cd cfc-langgraph
@@ -261,7 +261,7 @@ python -c "from app.config import settings; print(settings.llm_model)"
 # 预期输出: deepseek-chat
 ```
 
-- [ ] **Step 4: Commit**
+- [x] **Step 4: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -281,7 +281,7 @@ git commit -m "feat(langgraph): config management with pydantic-settings"
 **Interfaces:**
 - Produces: Phase 1 所需的请求/响应模型
 
-- [ ] **Step 1: 创建 `app/models/__init__.py`**
+- [x] **Step 1: 创建 `app/models/__init__.py`**
 
 ```python
 from .common import UserContext, SourceInfo
@@ -289,7 +289,7 @@ from .chat import ChatRequest, ChatResponse
 from .recommend import RecommendRequest, RecommendResponse, RecommendItem
 ```
 
-- [ ] **Step 2: 创建 `app/models/common.py`**
+- [x] **Step 2: 创建 `app/models/common.py`**
 
 ```python
 from pydantic import BaseModel
@@ -310,7 +310,7 @@ class SourceInfo(BaseModel):
     score: Optional[float] = None
 ```
 
-- [ ] **Step 3: 创建 `app/models/chat.py`**
+- [x] **Step 3: 创建 `app/models/chat.py`**
 
 ```python
 from pydantic import BaseModel
@@ -331,7 +331,7 @@ class ChatResponse(BaseModel):
     trace_id: str = ""
 ```
 
-- [ ] **Step 4: 创建 `app/models/recommend.py`**
+- [x] **Step 4: 创建 `app/models/recommend.py`**
 
 ```python
 from pydantic import BaseModel
@@ -362,7 +362,7 @@ class RecommendResponse(BaseModel):
     trace_id: str = ""
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -382,14 +382,14 @@ git commit -m "feat(langgraph): pydantic models for API"
 - Produces: `embeddings.get_embeddings()` → Embeddings 实例
 - Produces: `retriever.RagRetriever` 类,提供 `retrieve(query, filters, k)` 方法
 
-- [ ] **Step 1: 创建 `app/rag/__init__.py`**
+- [x] **Step 1: 创建 `app/rag/__init__.py`**
 
 ```python
 from .embeddings import get_embeddings
 from .retriever import RagRetriever
 ```
 
-- [ ] **Step 2: 创建 `app/rag/embeddings.py`**
+- [x] **Step 2: 创建 `app/rag/embeddings.py`**
 
 ```python
 from langchain_openai import OpenAIEmbeddings
@@ -408,7 +408,7 @@ def get_embeddings():
     return _embeddings
 ```
 
-- [ ] **Step 3: 创建 `app/rag/retriever.py`**
+- [x] **Step 3: 创建 `app/rag/retriever.py`**
 
 ```python
 from langchain_chroma import Chroma
@@ -507,7 +507,7 @@ class RagRetriever:
         return results[:k]
 ```
 
-- [ ] **Step 4: Commit**
+- [x] **Step 4: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -526,13 +526,13 @@ git commit -m "feat(langgraph): ChromaDB + RAG retriever infrastructure"
 - Produces: `JavaClient` 类, 封装对所有 Java 接口的 HTTP 调用
 - Produces: `get_published_articles()`, `search_products()`, `search_activities()`, `search_articles()`
 
-- [ ] **Step 1: 创建 `app/tools/__init__.py`**
+- [x] **Step 1: 创建 `app/tools/__init__.py`**
 
 ```python
 from .java_client import JavaClient
 ```
 
-- [ ] **Step 2: 创建 `app/tools/java_client.py`**
+- [x] **Step 2: 创建 `app/tools/java_client.py`**
 
 ```python
 import httpx
@@ -617,7 +617,7 @@ class JavaClient:
         return {}
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -641,7 +641,7 @@ git commit -m "feat(langgraph): Java HTTP client for tool calls"
 - Consumes: `JavaClient`, `RagRetriever`, `ChatOpenAI`
 - Produces: `POST /api/v1/recommend` 接口
 
-- [ ] **Step 1: 创建 `app/tools/product_tools.py`**
+- [x] **Step 1: 创建 `app/tools/product_tools.py`**
 
 ```python
 from langchain_core.tools import tool
@@ -701,11 +701,11 @@ async def search_article_by_keyword(keyword: str, limit: int = 5) -> str:
         return "[]"
 ```
 
-- [ ] **Step 2: 创建 `app/agents/__init__.py`**(空)
+- [x] **Step 2: 创建 `app/agents/__init__.py`**(空)
 
-- [ ] **Step 3: 创建 `app/graphs/__init__.py`**(空)
+- [x] **Step 3: 创建 `app/graphs/__init__.py`**(空)
 
-- [ ] **Step 4: 创建 `app/graphs/recommend_graph.py`**
+- [x] **Step 4: 创建 `app/graphs/recommend_graph.py`**
 
 Phase 1 用**最简单的单步 Agent**(不涉及 StateGraph 复杂特性),后续 Phase 再升级为图编排:
 
@@ -788,7 +788,7 @@ class RecommendAgent:
             return {"items": [], "text": content}
 ```
 
-- [ ] **Step 5: 创建 `app/api/recommend.py`**
+- [x] **Step 5: 创建 `app/api/recommend.py`**
 
 ```python
 from fastapi import APIRouter
@@ -839,7 +839,7 @@ async def recommend(req: RecommendRequest):
         return RecommendResponse(items=[], source="error")
 ```
 
-- [ ] **Step 6: 修改 `app/main.py` 注册路由**
+- [x] **Step 6: 修改 `app/main.py` 注册路由**
 
 ```python
 from fastapi import FastAPI
@@ -863,7 +863,7 @@ async def shutdown():
     await client.close()
 ```
 
-- [ ] **Step 7: 验证 Recommend API**
+- [x] **Step 7: 验证 Recommend API**
 
 ```bash
 cd cfc-langgraph
@@ -876,7 +876,7 @@ curl -X POST http://localhost:9000/api/v1/recommend \
 kill %1
 ```
 
-- [ ] **Step 8: Commit**
+- [x] **Step 8: Commit**
 
 ```bash
 git add cfc-langgraph/
@@ -895,7 +895,7 @@ git commit -m "feat(langgraph): RecommendAgent with tool calling"
 - Produces: `AiGateway.recommend()` — Java 端统一的 Python 调用入口,超时/异常自动 fallback
 - Consumes: Python `POST /api/v1/recommend`
 
-- [ ] **Step 1: 在 `application.yml` 中新增配置**
+- [x] **Step 1: 在 `application.yml` 中新增配置**
 
 ```yaml
 # application.yml 底部追加
@@ -908,7 +908,7 @@ python:
     reset-timeout-ms: 30000
 ```
 
-- [ ] **Step 2: 创建 `AiGateway.java`**
+- [x] **Step 2: 创建 `AiGateway.java`**
 
 ```java
 package com.etotem.cfc.service;
@@ -1058,7 +1058,7 @@ public class AiGateway {
 }
 ```
 
-- [ ] **Step 3: 编译验证**
+- [x] **Step 3: 编译验证**
 
 ```bash
 cd cfc-backend
@@ -1066,7 +1066,7 @@ mvn clean compile -q
 # 预期: BUILD SUCCESS
 ```
 
-- [ ] **Step 4: Commit**
+- [x] **Step 4: Commit**
 
 ```bash
 git add cfc-backend/src/main/java/com/etotem/cfc/service/AiGateway.java
@@ -1086,7 +1086,7 @@ git commit -m "feat(backend): AiGateway with circuit breaker for LangGraph"
 - Consumes: `AiGateway.recommend()`
 - 灰度策略: 5% 流量走 Python, 异常自动 fallback 现有逻辑
 
-- [ ] **Step 1: 修改 `RecommendationController.java`**
+- [x] **Step 1: 修改 `RecommendationController.java`**
 
 ```java
 // 注入 AiGateway
@@ -1132,7 +1132,7 @@ public Result<List<RecommendationResult>> search(
 }
 ```
 
-- [ ] **Step 2: 编译验证**
+- [x] **Step 2: 编译验证**
 
 ```bash
 cd cfc-backend
@@ -1140,7 +1140,7 @@ mvn clean compile -q
 # 预期: BUILD SUCCESS
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-backend/src/main/java/com/etotem/cfc/controller/ai/RecommendationController.java
@@ -1154,7 +1154,7 @@ git commit -m "feat(backend): 5% recommend traffic routed to LangGraph"
 **Files:**
 - Create: `cfc-langgraph/docker-compose.yml`
 
-- [ ] **Step 1: 创建 `docker-compose.yml`**
+- [x] **Step 1: 创建 `docker-compose.yml`**
 
 ```yaml
 version: "3.8"
@@ -1181,7 +1181,7 @@ volumes:
   langgraph-data:
 ```
 
-- [ ] **Step 2: Commit**
+- [x] **Step 2: Commit**
 
 ```bash
 git add cfc-langgraph/docker-compose.yml
@@ -1197,9 +1197,9 @@ git commit -m "chore(langgraph): Docker Compose for local dev"
 - Create: `cfc-langgraph/tests/conftest.py`
 - Create: `cfc-langgraph/tests/test_recommend.py`
 
-- [ ] **Step 1: 创建 `tests/__init__.py`**(空文件)
+- [x] **Step 1: 创建 `tests/__init__.py`**(空文件)
 
-- [ ] **Step 2: 创建 `tests/conftest.py`**
+- [x] **Step 2: 创建 `tests/conftest.py`**
 
 ```python
 import pytest
@@ -1218,7 +1218,7 @@ async def health_response(client):
     return resp
 ```
 
-- [ ] **Step 3: 创建 `tests/test_recommend.py`**
+- [x] **Step 3: 创建 `tests/test_recommend.py`**
 
 ```python
 import pytest
@@ -1264,7 +1264,7 @@ async def test_recommend_with_tags():
         assert "source" in data
 ```
 
-- [ ] **Step 4: 运行测试**
+- [x] **Step 4: 运行测试**
 
 ```bash
 cd cfc-langgraph
@@ -1274,7 +1274,7 @@ pytest tests/ -v
 # test_recommend_with_tags 可能因 Java 后端未运行而返回空列表, 但不应该报错
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/tests/
@@ -1285,9 +1285,9 @@ git commit -m "test(langgraph): Phase 1 integration tests"
 
 ## 自审清单
 
-- [ ] 每个 Task 的产出物独立可测试
-- [ ] 没有 "TBD" / "TODO" 占位符
-- [ ] Python 侧没有直连 MySQL
-- [ ] Java 侧灰度开关 + 熔断器 + Fallback 三层保护
-- [ ] Docker Compose 可一键启动开发环境
-- [ ] Phase 1 产出物: 运行中的 Recommend API + 知识库基础设施
+- [x] 每个 Task 的产出物独立可测试
+- [x] 没有 "TBD" / "TODO" 占位符
+- [x] Python 侧没有直连 MySQL
+- [x] Java 侧灰度开关 + 熔断器 + Fallback 三层保护
+- [x] Docker Compose 可一键启动开发环境
+- [x] Phase 1 产出物: 运行中的 Recommend API + 知识库基础设施

+ 32 - 32
docs/superpowers/plans/2026-07-20-langgraph-phase2.md

@@ -28,13 +28,13 @@
 **Interfaces:**
 - Produces: `MemoryManager` 类,提供 `load(user_id, conv_id)` / `save(user_id, conv_id, messages)` / `recall(user_id, query)`
 
-- [ ] **Step 1: 创建 `app/memory/__init__.py`**
+- [x] **Step 1: 创建 `app/memory/__init__.py`**
 
 ```python
 from .store import MemoryManager
 ```
 
-- [ ] **Step 2: 创建 `app/memory/store.py`**
+- [x] **Step 2: 创建 `app/memory/store.py`**
 
 ```python
 from langchain.memory import ConversationSummaryBufferMemory, VectorStoreRetrieverMemory
@@ -129,7 +129,7 @@ class MemoryManager:
         return [doc.page_content for doc in results]
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/app/memory/
@@ -146,7 +146,7 @@ git commit -m "feat(langgraph): 3-layer memory manager"
 **Interfaces:**
 - Produces: `IntentClassifier.classify(query, context)` → `Intent` 枚举
 
-- [ ] **Step 1: 创建 `app/agents/intent_classifier.py`**
+- [x] **Step 1: 创建 `app/agents/intent_classifier.py`**
 
 ```python
 from enum import Enum
@@ -208,7 +208,7 @@ class IntentClassifier:
             return Intent.CHAT
 ```
 
-- [ ] **Step 2: Commit**
+- [x] **Step 2: Commit**
 
 ```bash
 git add cfc-langgraph/app/agents/intent_classifier.py
@@ -227,7 +227,7 @@ git commit -m "feat(langgraph): intent classifier for chat routing"
 - Consumes: `MemoryManager`, `IntentClassifier`, `JavaClient`
 - Produces: `ChatAgent.run()` → `{"answer", "conversation_id", "tasks", "sources"}`
 
-- [ ] **Step 1: 创建 `app/agents/chat_agent.py`**
+- [x] **Step 1: 创建 `app/agents/chat_agent.py`**
 
 ```python
 from typing import Optional
@@ -267,7 +267,7 @@ class ChatAgent:
         return tasks
 ```
 
-- [ ] **Step 2: 创建 `app/graphs/chat_graph.py`**
+- [x] **Step 2: 创建 `app/graphs/chat_graph.py`**
 
 ```python
 from typing import TypedDict, Literal
@@ -441,7 +441,7 @@ def create_chat_graph():
     return graph
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/app/agents/chat_agent.py cfc-langgraph/app/graphs/chat_graph.py
@@ -456,7 +456,7 @@ git commit -m "feat(langgraph): ChatAgent StateGraph with intent routing and mem
 - Create: `cfc-langgraph/app/api/chat.py`
 - Modify: `cfc-langgraph/app/main.py` (注册路由)
 
-- [ ] **Step 1: 创建 `app/api/chat.py`**
+- [x] **Step 1: 创建 `app/api/chat.py`**
 
 ```python
 from fastapi import APIRouter
@@ -517,7 +517,7 @@ async def chat(req: ChatRequest):
     )
 ```
 
-- [ ] **Step 2: 修改 `app/main.py` 注册路由**
+- [x] **Step 2: 修改 `app/main.py` 注册路由**
 
 ```python
 from app.api import health, recommend, chat  # 新增 chat
@@ -525,7 +525,7 @@ from app.api import health, recommend, chat  # 新增 chat
 app.include_router(chat.router)  # 新增
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/app/api/chat.py cfc-langgraph/app/main.py
@@ -539,7 +539,7 @@ git commit -m "feat(langgraph): chat API endpoint with LangGraph graph"
 **Files:**
 - Modify: `cfc-langgraph/app/rag/retriever.py` (升级为 ensemble + compression)
 
-- [ ] **Step 1: 重写 `app/rag/retriever.py`**
+- [x] **Step 1: 重写 `app/rag/retriever.py`**
 
 ```python
 from langchain_chroma import Chroma
@@ -652,7 +652,7 @@ class RagRetriever:
         return results[:k]
 ```
 
-- [ ] **Step 2: Commit**
+- [x] **Step 2: Commit**
 
 ```bash
 git add cfc-langgraph/app/rag/retriever.py
@@ -670,7 +670,7 @@ git commit -m "feat(langgraph): RAG pipeline upgraded to ensemble + compression"
 **Interfaces:**
 - Produces: `POST /api/ai/context` (Python 可调用的 HTTP 数据接口, 接收 `user_id` + `intent_type` + `params`)
 
-- [ ] **Step 1: 创建 `ContextApiController.java`**
+- [x] **Step 1: 创建 `ContextApiController.java`**
 
 ```java
 package com.etotem.cfc.controller.ai;
@@ -716,14 +716,14 @@ public class ContextApiController {
 }
 ```
 
-- [ ] **Step 2: 编译验证**
+- [x] **Step 2: 编译验证**
 
 ```bash
 cd cfc-backend
 mvn clean compile -q
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-backend/src/main/java/com/etotem/cfc/controller/ai/ContextApiController.java
@@ -738,7 +738,7 @@ git commit -m "feat(backend): context API for LangGraph Python service"
 - Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java`
 - Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/AiGateway.java` (新增 chat 方法)
 
-- [ ] **Step 1: AiGateway 新增 `chat()` 方法**
+- [x] **Step 1: AiGateway 新增 `chat()` 方法**
 
 ```java
 // 在 AiGateway.java 中追加
@@ -802,7 +802,7 @@ private List<Map<String, Object>> parseTasks(JsonNode tasksNode) {
 }
 ```
 
-- [ ] **Step 2: 修改 `AIService.sendMessage()`, 增加 Python 优先路由**
+- [x] **Step 2: 修改 `AIService.sendMessage()`, 增加 Python 优先路由**
 
 ```java
 // 在 AIService 中注入 AiGateway
@@ -863,14 +863,14 @@ private Map<String, Object> sendMessageToDify(String query, String userId,
 }
 ```
 
-- [ ] **Step 3: 编译验证**
+- [x] **Step 3: 编译验证**
 
 ```bash
 cd cfc-backend
 mvn clean compile -q
 ```
 
-- [ ] **Step 4: Commit**
+- [x] **Step 4: Commit**
 
 ```bash
 git add cfc-backend/src/main/java/com/etotem/cfc/service/AiGateway.java
@@ -887,7 +887,7 @@ git commit -m "feat(backend): AIService routes to LangGraph with Dify fallback"
 - Create: `cfc-langgraph/tests/test_memory.py`
 - Create: `cfc-langgraph/tests/test_intent.py`
 
-- [ ] **Step 1: 创建 `tests/test_intent.py`**
+- [x] **Step 1: 创建 `tests/test_intent.py`**
 
 ```python
 import pytest
@@ -918,7 +918,7 @@ async def test_classify_mind():
     assert intent == Intent.MIND
 ```
 
-- [ ] **Step 2: 创建 `tests/test_memory.py`**
+- [x] **Step 2: 创建 `tests/test_memory.py`**
 
 ```python
 import pytest
@@ -938,7 +938,7 @@ async def test_working_memory():
     assert mem.memory_key == "history"
 ```
 
-- [ ] **Step 3: 创建 `tests/test_chat.py`**
+- [x] **Step 3: 创建 `tests/test_chat.py`**
 
 ```python
 import pytest
@@ -960,7 +960,7 @@ async def test_chat_endpoint():
         assert isinstance(data.get("tasks"), list)
 ```
 
-- [ ] **Step 4: 运行测试**
+- [x] **Step 4: 运行测试**
 
 ```bash
 cd cfc-langgraph
@@ -970,7 +970,7 @@ pytest tests/ -v
 # test_chat 通过 (需要 Java 后端 + LLM API Key)
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/tests/
@@ -981,10 +981,10 @@ git commit -m "test(langgraph): Phase 2 tests for chat, memory, intent"
 
 ### Phase 2 自审清单
 
-- [ ] 三层记忆模块: 工作记忆/长期事实/语义向量召回
-- [ ] 意图分类器: 6 类意图, 失败默认 chat
-- [ ] ChatAgent StateGraph: 分类→上下文→LLM→任务提取→保存记忆
-- [ ] Chat API: `POST /api/v1/chat` 完整链路
-- [ ] RAG: 混合检索 + LLM 压缩重排序
-- [ ] Java ContextApiController: Python 可调用
-- [ ] Java AIService: Python 优先 + Dify 回退
+- [x] 三层记忆模块: 工作记忆/长期事实/语义向量召回
+- [x] 意图分类器: 6 类意图, 失败默认 chat
+- [x] ChatAgent StateGraph: 分类→上下文→LLM→任务提取→保存记忆
+- [x] Chat API: `POST /api/v1/chat` 完整链路
+- [x] RAG: 混合检索 + LLM 压缩重排序
+- [x] Java ContextApiController: Python 可调用
+- [x] Java AIService: Python 优先 + Dify 回退

+ 32 - 32
docs/superpowers/plans/2026-07-20-langgraph-phase3.md

@@ -27,7 +27,7 @@
 **Interfaces:**
 - Produces: 3 个 Tool:`get_report_detail`, `get_survey_data`, `get_dimension_scores`
 
-- [ ] **Step 1: 创建 `app/tools/report_tools.py`**
+- [x] **Step 1: 创建 `app/tools/report_tools.py`**
 
 ```python
 from langchain_core.tools import tool
@@ -95,7 +95,7 @@ async def get_dimension_scores(family_id: int) -> str:
         return "{}"
 ```
 
-- [ ] **Step 2: Commit**
+- [x] **Step 2: Commit**
 
 ```bash
 git add cfc-langgraph/app/tools/report_tools.py
@@ -116,7 +116,7 @@ git commit -m "feat(langgraph): report analysis tools"
 - Consumes: `report_tools`, `JavaClient`
 - Produces: `POST /api/v1/analyze` 报告解读接口
 
-- [ ] **Step 1: 创建 `app/agents/analysis_agent.py`**
+- [x] **Step 1: 创建 `app/agents/analysis_agent.py`**
 
 ```python
 from app.tools.java_client import JavaClient
@@ -146,7 +146,7 @@ class AnalysisAgent:
         return {}
 ```
 
-- [ ] **Step 2: 创建 `app/graphs/analysis_graph.py`**
+- [x] **Step 2: 创建 `app/graphs/analysis_graph.py`**
 
 ```python
 from typing import TypedDict, Optional
@@ -247,7 +247,7 @@ def create_analysis_graph():
     return builder.compile(checkpointer=checkpointer)
 ```
 
-- [ ] **Step 3: 创建 `app/api/analyze.py`**
+- [x] **Step 3: 创建 `app/api/analyze.py`**
 
 ```python
 from fastapi import APIRouter
@@ -293,7 +293,7 @@ async def analyze(req: AnalyzeRequest):
     return AnalyzeResponse(analysis=result.get("analysis", ""))
 ```
 
-- [ ] **Step 4: 修改 `app/main.py`**
+- [x] **Step 4: 修改 `app/main.py`**
 
 ```python
 from app.api import health, recommend, chat, analyze  # 新增 analyze
@@ -301,7 +301,7 @@ from app.api import health, recommend, chat, analyze  # 新增 analyze
 app.include_router(analyze.router)  # 新增
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/app/agents/analysis_agent.py \
@@ -322,7 +322,7 @@ git commit -m "feat(langgraph): AnalysisAgent for health report interpretation"
 
 **Design Decision:** 舌诊涉及图片上传+多模态识别,Dify Workflow 在这块最成熟。Python 侧做薄代理层:HTTP 透传图片到 Dify Workflow,返回结果。后续若需替换多模态模型,改 Python 侧即可。
 
-- [ ] **Step 1: 创建 `app/agents/multimodal_agent.py`**
+- [x] **Step 1: 创建 `app/agents/multimodal_agent.py`**
 
 ```python
 import httpx
@@ -406,7 +406,7 @@ class TongueDiagnosisAgent:
         }
 ```
 
-- [ ] **Step 2: 创建 `app/api/tongue.py`**
+- [x] **Step 2: 创建 `app/api/tongue.py`**
 
 ```python
 from fastapi import APIRouter, UploadFile, File, Form
@@ -458,7 +458,7 @@ async def tongue_diagnose(
         os.unlink(tmp.name)
 ```
 
-- [ ] **Step 3: 修改 `app/main.py`**
+- [x] **Step 3: 修改 `app/main.py`**
 
 ```python
 from app.api import health, recommend, chat, analyze, tongue  # 新增 tongue
@@ -466,7 +466,7 @@ from app.api import health, recommend, chat, analyze, tongue  # 新增 tongue
 app.include_router(tongue.router)  # 新增
 ```
 
-- [ ] **Step 4: 添加 Dify 配置到 `app/config.py`**
+- [x] **Step 4: 添加 Dify 配置到 `app/config.py`**
 
 ```python
 # 在 Settings 类中追加
@@ -474,7 +474,7 @@ dify_base_url: Optional[str] = None
 dify_tongue_api_key: Optional[str] = None
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/app/agents/multimodal_agent.py \
@@ -498,7 +498,7 @@ git commit -m "feat(langgraph): multimodal agent for tongue diagnosis"
 - Produces: 定时任务, 从 Java 拉取文章→分块→向量化→更新 ChromaDB
 - Produces: 增量更新策略 (只处理有变动的文档)
 
-- [ ] **Step 1: 创建 `app/rag/loader.py`**
+- [x] **Step 1: 创建 `app/rag/loader.py`**
 
 ```python
 from app.tools.java_client import JavaClient
@@ -552,7 +552,7 @@ class KnowledgeLoader:
         return docs
 ```
 
-- [ ] **Step 2: 创建 `app/rag/splitter.py`**
+- [x] **Step 2: 创建 `app/rag/splitter.py`**
 
 ```python
 from langchain.text_splitter import RecursiveCharacterTextSplitter
@@ -578,9 +578,9 @@ def get_summary_splitter() -> RecursiveCharacterTextSplitter:
     )
 ```
 
-- [ ] **Step 3: 创建 `app/tasks/__init__.py`**(空文件)
+- [x] **Step 3: 创建 `app/tasks/__init__.py`**(空文件)
 
-- [ ] **Step 4: 创建 `app/tasks/knowledge_sync.py`**
+- [x] **Step 4: 创建 `app/tasks/knowledge_sync.py`**
 
 ```python
 """知识库同步定时任务: 定期从 Java 拉取文章, 更新 ChromaDB"""
@@ -664,7 +664,7 @@ async def sync_knowledge_base():
     logger.info("知识库同步完成: 新增 %d 篇文章, %d 个块", len(articles), len(chunks))
 ```
 
-- [ ] **Step 5: 在 FastAPI 启动时注册定时任务**
+- [x] **Step 5: 在 FastAPI 启动时注册定时任务**
 
 ```python
 # 修改 app/main.py 中的 startup 事件
@@ -687,7 +687,7 @@ async def startup():
     asyncio.create_task(schedule_kb_sync())
 ```
 
-- [ ] **Step 6: Commit**
+- [x] **Step 6: Commit**
 
 ```bash
 git add cfc-langgraph/app/rag/loader.py \
@@ -707,7 +707,7 @@ git commit -m "feat(langgraph): knowledge base auto-sync pipeline"
 
 **Note:** LangChain 通过环境变量 `LANGCHAIN_TRACING_V2=true` + `LANGCHAIN_API_KEY` + `LANGCHAIN_PROJECT` 自动接入 LangSmith,零代码侵入。
 
-- [ ] **Step 1: 验证 LangSmith 配置**
+- [x] **Step 1: 验证 LangSmith 配置**
 
 ```python
 # 在 app/main.py startup 中添加:
@@ -724,7 +724,7 @@ async def startup():
     # ... 其余初始化
 ```
 
-- [ ] **Step 2: 在 API handler 中注入 trace_id**
+- [x] **Step 2: 在 API handler 中注入 trace_id**
 
 ```python
 # 修改 app/api/chat.py 和 app/api/recommend.py 等
@@ -759,7 +759,7 @@ return ChatResponse(
 
 同理修改 `recommend.py` 和 `analyze.py`。
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/app/main.py \
@@ -777,7 +777,7 @@ git commit -m "feat(langgraph): LangSmith tracing enabled"
 - Create: `cfc-langgraph/tests/test_analyze.py`
 - Create: `cfc-langgraph/tests/test_tongue.py`
 
-- [ ] **Step 1: 创建 `tests/test_analyze.py`**
+- [x] **Step 1: 创建 `tests/test_analyze.py`**
 
 ```python
 import pytest
@@ -812,7 +812,7 @@ async def test_analyze_missing_report():
         assert isinstance(data.get("analysis"), str)
 ```
 
-- [ ] **Step 2: 运行测试**
+- [x] **Step 2: 运行测试**
 
 ```bash
 cd cfc-langgraph
@@ -820,7 +820,7 @@ pytest tests/ -v
 # 预期: 全部通过 (需要 Java 后端 + LLM API Key)
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/tests/
@@ -831,11 +831,11 @@ git commit -m "test(langgraph): Phase 3 tests for analyze and tongue APIs"
 
 ### Phase 3 自审清单
 
-- [ ] 报告解读 Tool: 获取报告详情/问卷/维度分数
-- [ ] AnalysisAgent StateGraph: 数据收集→LLM 分析
-- [ ] `POST /api/v1/analyze` 端点
-- [ ] MultiModalAgent: 舌诊图片上传→Dify Workflow/LLM
-- [ ] `POST /api/v1/tongue/diagnose` 端点
-- [ ] 知识库定时同步: 增量拉取→分块→向量化→入库
-- [ ] LangSmith Trace: 环境变量驱动, 零侵入
-- [ ] 所有 API 响应含 trace_id
+- [x] 报告解读 Tool: 获取报告详情/问卷/维度分数
+- [x] AnalysisAgent StateGraph: 数据收集→LLM 分析
+- [x] `POST /api/v1/analyze` 端点
+- [x] MultiModalAgent: 舌诊图片上传→Dify Workflow/LLM
+- [x] `POST /api/v1/tongue/diagnose` 端点
+- [x] 知识库定时同步: 增量拉取→分块→向量化→入库
+- [x] LangSmith Trace: 环境变量驱动, 零侵入
+- [x] 所有 API 响应含 trace_id

+ 40 - 40
docs/superpowers/plans/2026-07-20-langgraph-phase4.md

@@ -24,7 +24,7 @@
 - Modify: `cfc-langgraph/app/tools/java_client.py` (连接池复用)
 - Modify: `cfc-langgraph/app/rag/embeddings.py` (缓存)
 
-- [ ] **Step 1: 优化 `JavaClient` 连接池**
+- [x] **Step 1: 优化 `JavaClient` 连接池**
 
 ```python
 # app/tools/java_client.py — 确保 httpx.AsyncClient 复用连接池
@@ -72,14 +72,14 @@ class JavaClient:
     # ... 其余方法保持与 Phase 1/2/3 一致
 ```
 
-- [ ] **Step 2: Embedding 实例缓存 (单例模式)**
+- [x] **Step 2: Embedding 实例缓存 (单例模式)**
 
 ```python
 # app/rag/embeddings.py — 已实现单例, 验证即可
 # 确保 _embeddings 不会被重复创建
 ```
 
-- [ ] **Step 3: 添加请求耗时中间件**
+- [x] **Step 3: 添加请求耗时中间件**
 
 ```python
 # 在 app/main.py 中追加
@@ -108,7 +108,7 @@ async def timing_middleware(request: Request, call_next):
     return response
 ```
 
-- [ ] **Step 4: ChromaDB 批量写入优化**
+- [x] **Step 4: ChromaDB 批量写入优化**
 
 知识库同步时使用批量写入替代逐条写入:
 
@@ -131,7 +131,7 @@ async def sync_knowledge_base():
     # ... 后续逻辑不变 ...
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/app/tools/java_client.py \
@@ -148,7 +148,7 @@ git commit -m "perf(langgraph): connection pool, timing middleware, batch write"
 - Create: `cfc-langgraph/app/monitoring.py`
 - Modify: `cfc-langgraph/app/main.py` (注册 metrics 路由)
 
-- [ ] **Step 1: 创建 `app/monitoring.py`**
+- [x] **Step 1: 创建 `app/monitoring.py`**
 
 ```python
 """Prometheus 监控指标"""
@@ -301,7 +301,7 @@ async def detailed_health():
     return status
 ```
 
-- [ ] **Step 2: 注册 metrics 路由到 `app/main.py`**
+- [x] **Step 2: 注册 metrics 路由到 `app/main.py`**
 
 ```python
 from app import monitoring  # 新增
@@ -309,7 +309,7 @@ from app import monitoring  # 新增
 app.include_router(monitoring.router)  # 新增
 ```
 
-- [ ] **Step 3: 在 Agent 调用处插入监控装饰器**
+- [x] **Step 3: 在 Agent 调用处插入监控装饰器**
 
 ```python
 # app/graphs/recommend_graph.py — RecommendAgent.run()
@@ -324,7 +324,7 @@ class RecommendAgent:
 
 同理在 `chat_graph.py` 的 `llm_call` 节点和 `analysis_graph.py` 的 `analyze` 节点也加上。
 
-- [ ] **Step 4: 添加 `prometheus-client` 依赖到 `pyproject.toml`**
+- [x] **Step 4: 添加 `prometheus-client` 依赖到 `pyproject.toml`**
 
 ```toml
 dependencies = [
@@ -333,7 +333,7 @@ dependencies = [
 ]
 ```
 
-- [ ] **Step 5: 验证 metrics 端点**
+- [x] **Step 5: 验证 metrics 端点**
 
 ```bash
 cd cfc-langgraph
@@ -344,7 +344,7 @@ curl http://localhost:9000/metrics
 kill %1
 ```
 
-- [ ] **Step 6: Commit**
+- [x] **Step 6: Commit**
 
 ```bash
 git add cfc-langgraph/app/monitoring.py \
@@ -364,7 +364,7 @@ git commit -m "feat(langgraph): Prometheus metrics and detailed health check"
 - Create: `cfc-langgraph/app/log_config.py`
 - Modify: `cfc-langgraph/app/main.py`
 
-- [ ] **Step 1: 创建 `app/log_config.py`**
+- [x] **Step 1: 创建 `app/log_config.py`**
 
 ```python
 """结构化日志配置"""
@@ -422,7 +422,7 @@ def setup_logging(level: str = "INFO", json_format: bool = False):
     logging.getLogger("langchain").setLevel(logging.WARNING)
 ```
 
-- [ ] **Step 2: 在 `app/main.py` 启动时配置**
+- [x] **Step 2: 在 `app/main.py` 启动时配置**
 
 ```python
 @app.on_event("startup")
@@ -433,7 +433,7 @@ async def startup():
     # ... 其余初始化代码 ...
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/app/log_config.py cfc-langgraph/app/main.py
@@ -448,7 +448,7 @@ git commit -m "feat(langgraph): structured JSON logging"
 - Create: `cfc-langgraph/docker-compose.yml` (覆盖 Phase 1 的开发版)
 - Create: `cfc-langgraph/Dockerfile` (多阶段构建)
 
-- [ ] **Step 1: 优化 `Dockerfile` (多阶段构建)**
+- [x] **Step 1: 优化 `Dockerfile` (多阶段构建)**
 
 ```dockerfile
 # ── 构建阶段 ──
@@ -489,7 +489,7 @@ CMD ["gunicorn", "app.main:app", \
      "--error-logfile", "-"]
 ```
 
-- [ ] **Step 2: 创建生产 `docker-compose.yml`**
+- [x] **Step 2: 创建生产 `docker-compose.yml`**
 
 ```yaml
 version: "3.8"
@@ -560,7 +560,7 @@ volumes:
   prometheus-data:
 ```
 
-- [ ] **Step 3: 创建 Prometheus 配置**
+- [x] **Step 3: 创建 Prometheus 配置**
 
 ```yaml
 # cfc-langgraph/prometheus.yml
@@ -575,7 +575,7 @@ scrape_configs:
     metrics_path: /metrics
 ```
 
-- [ ] **Step 4: 创建生产环境 `.env.production` 模板**
+- [x] **Step 4: 创建生产环境 `.env.production` 模板**
 
 ```bash
 # cfc-langgraph/.env.production (不上传 git, 手动部署时创建)
@@ -595,7 +595,7 @@ LOG_LEVEL=info
 JSON_LOGS=true
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-langgraph/Dockerfile \
@@ -614,7 +614,7 @@ git commit -m "ops(langgraph): production Docker Compose with monitoring"
 - Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java` (简化, 移除 Dify 直接调用)
 - Delete: `cfc-backend/src/main/resources/application.yml` 中 dify.* 配置 (可选保留 Dify fallback)
 
-- [ ] **Step 1: 标记 `DifySyncService` 废弃**
+- [x] **Step 1: 标记 `DifySyncService` 废弃**
 
 ```java
 // DifySyncService.java 头部加 @Deprecated 注解
@@ -631,7 +631,7 @@ public class DifySyncService {
 }
 ```
 
-- [ ] **Step 2: 简化 `AIService.java`**
+- [x] **Step 2: 简化 `AIService.java`**
 
 Dify 相关的方法合并为单一的 fallback 块:
 
@@ -652,7 +652,7 @@ public Map<String, Object> sendMessage(String query, String userId,
 }
 ```
 
-- [ ] **Step 3: 清理 `application.yml` 中的 Dify 配置 (保留 fallback 选项)**
+- [x] **Step 3: 清理 `application.yml` 中的 Dify 配置 (保留 fallback 选项)**
 
 ```yaml
 # application.yml — 保留 dify.* 配置但标记为降级通道
@@ -666,7 +666,7 @@ dify:
   # 正常情况下应通过 python.enabled=true 启用 LangGraph
 ```
 
-- [ ] **Step 4: 编译验证**
+- [x] **Step 4: 编译验证**
 
 ```bash
 cd cfc-backend
@@ -674,7 +674,7 @@ mvn clean compile -q
 # 预期: BUILD SUCCESS (可能有 @Deprecated 警告, 不影响编译)
 ```
 
-- [ ] **Step 5: Commit**
+- [x] **Step 5: Commit**
 
 ```bash
 git add cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java \
@@ -691,7 +691,7 @@ git commit -m "chore(backend): mark DifySyncService as deprecated, clean up AISe
 - Create: `cfc-langgraph/docs/deployment.md`
 - Create: `cfc-langgraph/docs/operations.md`
 
-- [ ] **Step 1: 创建 `docs/deployment.md`**
+- [x] **Step 1: 创建 `docs/deployment.md`**
 
 ```markdown
 # LangGraph Sidecar 部署文档
@@ -793,7 +793,7 @@ Response:
 ```
 ```
 
-- [ ] **Step 2: 创建 `docs/operations.md`**
+- [x] **Step 2: 创建 `docs/operations.md`**
 
 ```markdown
 # LangGraph Sidecar 运维手册
@@ -919,7 +919,7 @@ tar czf chroma_backup_$(date +%Y%m%d).tar.gz data/chroma_db/
 ```
 ```
 
-- [ ] **Step 3: Commit**
+- [x] **Step 3: Commit**
 
 ```bash
 git add cfc-langgraph/docs/
@@ -930,16 +930,16 @@ git commit -m "docs(langgraph): deployment and operations manual"
 
 ### Phase 4 自审清单
 
-- [ ] Python 连接池复用 (单例 + httpx limits)
-- [ ] 请求耗时中间件 + 慢查询告警
-- [ ] ChromaDB 批量写入 (每批 100 条)
-- [ ] Prometheus 指标: LLM/RAG/Agent/Java/知识库
-- [ ] 详细健康检查: ChromaDB/LLM/Java 组件状态
-- [ ] Agent 监控装饰器
-- [ ] 结构化 JSON 日志
-- [ ] 生产 Dockerfile (多阶段构建)
-- [ ] Docker Compose 编排 (Java + Python + Prometheus)
-- [ ] DifySyncService @Deprecated 标记
-- [ ] AIService 简化
-- [ ] 部署手册 (deployment.md)
-- [ ] 运维手册 (operations.md)
+- [x] Python 连接池复用 (单例 + httpx limits)
+- [x] 请求耗时中间件 + 慢查询告警
+- [x] ChromaDB 批量写入 (每批 100 条)
+- [x] Prometheus 指标: LLM/RAG/Agent/Java/知识库
+- [x] 详细健康检查: ChromaDB/LLM/Java 组件状态
+- [x] Agent 监控装饰器
+- [x] 结构化 JSON 日志
+- [x] 生产 Dockerfile (多阶段构建)
+- [x] Docker Compose 编排 (Java + Python + Prometheus)
+- [x] DifySyncService @Deprecated 标记
+- [x] AIService 简化
+- [x] 部署手册 (deployment.md)
+- [x] 运维手册 (operations.md)