# LangGraph Sidecar — Phase 4 实施计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 性能调优、监控接入、部署标准化、清理 Dify 遗留代码, 使 LangGraph sidecar 达到可长期维护的生产状态。 **Architecture:** Prometheus 指标暴露 + 结构化日志 + Docker Compose 生产编排 + Java 端废弃代码清理。 **Tech Stack:** Python 3.11, FastAPI, Prometheus (client), Docker Compose, SLF4J ## Global Constraints - Python 3.11+,性能调优不改变外部接口签名 - 监控指标通过 HTTP `/metrics` 暴露 (Prometheus 拉取模式) - Docker Compose 同时编排 Java + Python 服务 - Java 端只清理 Dify 相关代码, 不动业务逻辑 - 所有项目文件路径相对于 `D:\workspace\cfc\` --- ### Task 1: 性能调优 **Files:** - Modify: `cfc-langgraph/app/tools/java_client.py` (连接池复用) - Modify: `cfc-langgraph/app/rag/embeddings.py` (缓存) - [x] **Step 1: 优化 `JavaClient` 连接池** ```python # app/tools/java_client.py — 确保 httpx.AsyncClient 复用连接池 import httpx from typing import Optional from app.config import settings import logging logger = logging.getLogger(__name__) class JavaClient: """Java 后端 HTTP 客户端 (单例, 复用连接池)""" _instance: Optional["JavaClient"] = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._client = None cls._instance._base_url = settings.java_base_url return cls._instance async def _get_client(self) -> httpx.AsyncClient: if self._client is None: limits = httpx.Limits( max_connections=10, max_keepalive_connections=5, keepalive_expiry=30, ) self._client = httpx.AsyncClient( base_url=self._base_url, timeout=httpx.Timeout(10.0, connect=3.0), limits=limits, ) return self._client async def close(self): if self._client: await self._client.aclose() self._client = None JavaClient._instance = None # ... 其余方法保持与 Phase 1/2/3 一致 ``` - [x] **Step 2: Embedding 实例缓存 (单例模式)** ```python # app/rag/embeddings.py — 已实现单例, 验证即可 # 确保 _embeddings 不会被重复创建 ``` - [x] **Step 3: 添加请求耗时中间件** ```python # 在 app/main.py 中追加 import time from fastapi import Request import logging logger = logging.getLogger(__name__) @app.middleware("http") async def timing_middleware(request: Request, call_next): start = time.perf_counter() response = await call_next(request) elapsed = time.perf_counter() - start # 慢查询日志: > 5s 的记录 if elapsed > 5: logger.warning("SLOW_REQUEST: %s %s took %.2fs", request.method, request.url.path, elapsed) else: logger.debug("REQUEST: %s %s took %.2fs", request.method, request.url.path, elapsed) response.headers["X-Response-Time"] = f"{elapsed:.3f}s" return response ``` - [x] **Step 4: ChromaDB 批量写入优化** 知识库同步时使用批量写入替代逐条写入: ```python # app/tasks/knowledge_sync.py — 确认已使用 aadd_documents 批量 API # 分块数 < 100 时一次提交, > 100 时分批 BATCH_SIZE = 100 async def sync_knowledge_base(): # ... 前置逻辑不变 ... # 分批写入 for i in range(0, len(chunks), BATCH_SIZE): batch = chunks[i:i + BATCH_SIZE] await vectorstore.aadd_documents(batch) vectorstore.persist() logger.debug("知识库同步进度: %d/%d", i + len(batch), len(chunks)) # ... 后续逻辑不变 ... ``` - [x] **Step 5: Commit** ```bash git add cfc-langgraph/app/tools/java_client.py \ cfc-langgraph/app/main.py \ cfc-langgraph/app/tasks/knowledge_sync.py git commit -m "perf(langgraph): connection pool, timing middleware, batch write" ``` --- ### Task 2: 监控指标暴露 **Files:** - Create: `cfc-langgraph/app/monitoring.py` - Modify: `cfc-langgraph/app/main.py` (注册 metrics 路由) - [x] **Step 1: 创建 `app/monitoring.py`** ```python """Prometheus 监控指标""" from prometheus_client import Counter, Histogram, Gauge, generate_latest from fastapi import APIRouter, Response import time import functools # ── 指标定义 ── # LLM 调用 llm_calls_total = Counter( "llm_calls_total", "Total LLM API calls", ["model", "status"], ) llm_duration_seconds = Histogram( "llm_duration_seconds", "LLM call duration", ["model"], buckets=(0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0), ) llm_tokens_total = Counter( "llm_tokens_total", "Total tokens used", ["model", "type"], # type = input / output ) # RAG 检索 rag_retrievals_total = Counter( "rag_retrievals_total", "Total RAG retrievals", ["method"], # method = vector / bm25 / ensemble ) rag_duration_seconds = Histogram( "rag_duration_seconds", "RAG retrieval duration", ["method"], buckets=(0.01, 0.05, 0.1, 0.5, 1.0), ) # Agent 调用 agent_calls_total = Counter( "agent_calls_total", "Total Agent invocations", ["agent_type"], # agent_type = chat / recommend / analysis ) agent_duration_seconds = Histogram( "agent_duration_seconds", "Agent execution duration", ["agent_type"], buckets=(0.5, 1.0, 2.0, 5.0, 10.0, 30.0, 60.0), ) # Java 后端调用 java_calls_total = Counter( "java_calls_total", "Total calls to Java backend", ["endpoint", "status"], ) java_duration_seconds = Histogram( "java_duration_seconds", "Java backend call duration", ["endpoint"], buckets=(0.01, 0.05, 0.1, 0.5, 1.0, 2.0), ) # 知识库同步 kb_sync_duration = Gauge( "kb_sync_duration_seconds", "Last knowledge base sync duration" ) kb_sync_documents = Gauge( "kb_sync_documents_total", "Documents processed in last sync" ) # ── 装饰器 ── def monitor_agent(agent_type: str): """Agent 性能监控装饰器""" def decorator(func): @functools.wraps(func) async def wrapper(*args, **kwargs): agent_calls_total.labels(agent_type=agent_type).inc() start = time.perf_counter() try: result = await func(*args, **kwargs) agent_duration_seconds.labels(agent_type=agent_type).observe( time.perf_counter() - start) return result except Exception as e: agent_duration_seconds.labels(agent_type=agent_type).observe( time.perf_counter() - start) raise return wrapper return decorator # ── Metrics 路由 ── router = APIRouter(tags=["monitoring"]) @router.get("/metrics") async def metrics(): return Response( content=generate_latest(), media_type="text/plain; charset=utf-8", ) @router.get("/api/v1/health") async def detailed_health(): """详细健康检查 (含组件状态)""" status = {"status": "ok", "components": {}} # 检查 ChromaDB try: from app.config import settings import os chroma_path = settings.chroma_db_path status["components"]["chromadb"] = { "status": "ok", "path": chroma_path, "exists": os.path.exists(chroma_path), } except Exception as e: status["components"]["chromadb"] = {"status": "error", "message": str(e)} status["status"] = "degraded" # 检查 LLM API try: from langchain_openai import ChatOpenAI llm = ChatOpenAI( model=settings.llm_model, api_key=settings.llm_api_key, base_url=settings.llm_base_url, max_tokens=5, ) await llm.ainvoke("ping") status["components"]["llm"] = {"status": "ok"} except Exception as e: status["components"]["llm"] = {"status": "error", "message": str(e)} status["status"] = "degraded" # 检查 Java 后端 try: from app.tools.java_client import JavaClient client = JavaClient() jc = await client._get_client() resp = await jc.get("/health") if resp.status_code == 200: status["components"]["java_backend"] = {"status": "ok"} else: status["components"]["java_backend"] = {"status": "error", "code": resp.status_code} status["status"] = "degraded" except Exception as e: status["components"]["java_backend"] = {"status": "error", "message": str(e)} status["status"] = "degraded" return status ``` - [x] **Step 2: 注册 metrics 路由到 `app/main.py`** ```python from app import monitoring # 新增 app.include_router(monitoring.router) # 新增 ``` - [x] **Step 3: 在 Agent 调用处插入监控装饰器** ```python # app/graphs/recommend_graph.py — RecommendAgent.run() from app.monitoring import monitor_agent class RecommendAgent: @monitor_agent("recommend") async def run(self, query: str, tags: list[str], limit: int = 5) -> dict: # ... 原有代码不变 ... ``` 同理在 `chat_graph.py` 的 `llm_call` 节点和 `analysis_graph.py` 的 `analyze` 节点也加上。 - [x] **Step 4: 添加 `prometheus-client` 依赖到 `pyproject.toml`** ```toml dependencies = [ # ... 现有依赖保持不变 ... "prometheus-client>=0.21", ] ``` - [x] **Step 5: 验证 metrics 端点** ```bash cd cfc-langgraph pip install -e . uvicorn app.main:app --port 9000 & curl http://localhost:9000/metrics # 预期: 以 # HELP / # TYPE 开头的 Prometheus 格式文本 kill %1 ``` - [x] **Step 6: Commit** ```bash git add cfc-langgraph/app/monitoring.py \ cfc-langgraph/app/main.py \ cfc-langgraph/app/graphs/recommend_graph.py \ cfc-langgraph/app/graphs/chat_graph.py \ cfc-langgraph/app/graphs/analysis_graph.py \ cfc-langgraph/pyproject.toml git commit -m "feat(langgraph): Prometheus metrics and detailed health check" ``` --- ### Task 3: 结构化日志 **Files:** - Create: `cfc-langgraph/app/log_config.py` - Modify: `cfc-langgraph/app/main.py` - [x] **Step 1: 创建 `app/log_config.py`** ```python """结构化日志配置""" import logging import json import sys from datetime import datetime, timezone class JsonFormatter(logging.Formatter): """JSON 日志格式化器 (适合生产环境日志聚合)""" def format(self, record: logging.LogRecord) -> str: log_entry = { "timestamp": datetime.now(timezone.utc).isoformat(), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if hasattr(record, "trace_id"): log_entry["trace_id"] = record.trace_id if record.exc_info and record.exc_info[0]: log_entry["exception"] = self.formatException(record.exc_info) return json.dumps(log_entry, ensure_ascii=False) def setup_logging(level: str = "INFO", json_format: bool = False): """配置日志 Args: level: 日志级别 json_format: True=JSON 格式, False=开发友好格式 """ root = logging.getLogger() root.setLevel(getattr(logging, level.upper(), logging.INFO)) # 清除已有 handler root.handlers.clear() handler = logging.StreamHandler(sys.stdout) if json_format: handler.setFormatter(JsonFormatter()) else: handler.setFormatter(logging.Formatter( "%(asctime)s [%(levelname)s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", )) root.addHandler(handler) # 第三方库日志级别 logging.getLogger("httpx").setLevel(logging.WARNING) logging.getLogger("chromadb").setLevel(logging.WARNING) logging.getLogger("langchain").setLevel(logging.WARNING) ``` - [x] **Step 2: 在 `app/main.py` 启动时配置** ```python @app.on_event("startup") async def startup(): import os json_logs = os.getenv("JSON_LOGS", "false").lower() == "true" setup_logging(level=settings.log_level, json_format=json_logs) # ... 其余初始化代码 ... ``` - [x] **Step 3: Commit** ```bash git add cfc-langgraph/app/log_config.py cfc-langgraph/app/main.py git commit -m "feat(langgraph): structured JSON logging" ``` --- ### Task 4: 生产级 Docker Compose 编排 **Files:** - Create: `cfc-langgraph/docker-compose.yml` (覆盖 Phase 1 的开发版) - Create: `cfc-langgraph/Dockerfile` (多阶段构建) - [x] **Step 1: 优化 `Dockerfile` (多阶段构建)** ```dockerfile # ── 构建阶段 ── FROM python:3.11-slim AS builder WORKDIR /build COPY pyproject.toml . RUN pip install --no-cache-dir -e . && \ pip install --no-cache-dir gunicorn # ── 运行阶段 ── FROM python:3.11-slim # 时区 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone WORKDIR /app COPY --from=builder /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.11/site-packages/ COPY --from=builder /usr/local/bin/ /usr/local/bin/ COPY app/ app/ COPY data/ data/ 2>/dev/null || true RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app USER appuser EXPOSE 9000 CMD ["gunicorn", "app.main:app", \ "--worker-class", "uvicorn.workers.UvicornWorker", \ "--bind", "0.0.0.0:9000", \ "--workers", "2", \ "--timeout", "60", \ "--keep-alive", "10", \ "--access-logfile", "-", \ "--error-logfile", "-"] ``` - [x] **Step 2: 创建生产 `docker-compose.yml`** ```yaml version: "3.8" services: cfc-backend: build: context: ../cfc-backend dockerfile: Dockerfile ports: - "9082:9082" environment: - SPRING_PROFILES_ACTIVE=prod - python.enabled=true - python.base-url=http://langgraph-svc:9000 networks: - cfc-net restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9082/actuator/health"] interval: 30s timeout: 5s retries: 3 langgraph-svc: build: context: . dockerfile: Dockerfile ports: - "9000:9000" env_file: - .env.production environment: - JAVA_BASE_URL=http://cfc-backend:9082 - CHROMA_DB_PATH=/data/chroma_db - JSON_LOGS=true - LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2:-false} volumes: - langgraph-data:/data networks: - cfc-net restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/api/v1/health"] interval: 30s timeout: 5s retries: 3 depends_on: - cfc-backend # Prometheus (可选: 指标采集) prometheus: image: prom/prometheus:latest volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus networks: - cfc-net restart: unless-stopped profiles: - monitoring networks: cfc-net: volumes: langgraph-data: prometheus-data: ``` - [x] **Step 3: 创建 Prometheus 配置** ```yaml # cfc-langgraph/prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: "langgraph-svc" static_configs: - targets: ["langgraph-svc:9000"] metrics_path: /metrics ``` - [x] **Step 4: 创建生产环境 `.env.production` 模板** ```bash # cfc-langgraph/.env.production (不上传 git, 手动部署时创建) LLM_API_KEY=sk-your-production-key LLM_BASE_URL=https://api.deepseek.com/v1 LLM_MODEL=deepseek-chat EMBEDDING_API_KEY=${LLM_API_KEY} EMBEDDING_BASE_URL=${LLM_BASE_URL} EMBEDDING_MODEL=text-embedding-v3 LANGCHAIN_TRACING_V2=false LANGCHAIN_API_KEY= LANGCHAIN_PROJECT=cfc-langgraph-prod LOG_LEVEL=info JSON_LOGS=true ``` - [x] **Step 5: Commit** ```bash git add cfc-langgraph/Dockerfile \ cfc-langgraph/docker-compose.yml \ cfc-langgraph/prometheus.yml \ cfc-langgraph/.env.production git commit -m "ops(langgraph): production Docker Compose with monitoring" ``` --- ### Task 5: Java 端废弃代码清理 **Files:** - Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java` (标记废弃) - Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java` (简化, 移除 Dify 直接调用) - Delete: `cfc-backend/src/main/resources/application.yml` 中 dify.* 配置 (可选保留 Dify fallback) - [x] **Step 1: 标记 `DifySyncService` 废弃** ```java // DifySyncService.java 头部加 @Deprecated 注解 /** * 知识库同步服务 * @deprecated 知识库同步已迁移到 LangGraph Python 服务 (cfc-langgraph/app/tasks/knowledge_sync.py) * 计划在下一个大版本移除 */ @Deprecated @Service public class DifySyncService { // ... 代码保持不变 ... } ``` - [x] **Step 2: 简化 `AIService.java`** Dify 相关的方法合并为单一的 fallback 块: ```java // AIService.java // sendMessageToDify() 保留为私有 fallback 方法 // 公开的 sendMessage() 优先 Python, 仅当 Python 不可用时调用 sendMessageToDify() /** * 发送聊天消息 (自动选择后端) * 优先 LangGraph Python 服务, 失败时回退 Dify */ public Map sendMessage(String query, String userId, String conversationId, Map inputs) { // Phase 2 已实现的逻辑: aiGateway.chat() → fallback sendMessageToDify() // 如果 aiGateway 长期稳定, 可在此处移除 Dify fallback } ``` - [x] **Step 3: 清理 `application.yml` 中的 Dify 配置 (保留 fallback 选项)** ```yaml # application.yml — 保留 dify.* 配置但标记为降级通道 dify: base-url: http://dify.bianwoyou.cn/v1 api-key: ${DIFY_API_KEY:} nutrition-api-key: ${DIFY_NUTRITION_API_KEY:} tongue-api-key: ${DIFY_TONGUE_API_KEY:} callback-secret: ${DIFY_CALLBACK_SECRET:} # 注意: 以上配置仅作为 LangGraph 不可用时的降级通道 # 正常情况下应通过 python.enabled=true 启用 LangGraph ``` - [x] **Step 4: 编译验证** ```bash cd cfc-backend mvn clean compile -q # 预期: BUILD SUCCESS (可能有 @Deprecated 警告, 不影响编译) ``` - [x] **Step 5: Commit** ```bash git add cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java \ cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java \ cfc-backend/src/main/resources/application.yml git commit -m "chore(backend): mark DifySyncService as deprecated, clean up AIService" ``` --- ### Task 6: 运维文档 **Files:** - Create: `cfc-langgraph/docs/deployment.md` - Create: `cfc-langgraph/docs/operations.md` - [x] **Step 1: 创建 `docs/deployment.md`** ```markdown # LangGraph Sidecar 部署文档 ## 前置依赖 - Docker + Docker Compose (推荐) - 或 Python 3.11+ + pip (直接部署) - LLM API Key (DeepSeek / OpenAI 兼容) ## 目录结构 ``` cfc-langgraph/ ├── Dockerfile ├── docker-compose.yml ├── prometheus.yml ├── .env.production # 生产配置 (手动创建, 不上传 git) ├── app/ # 服务代码 │ ├── main.py # FastAPI 入口 │ ├── config.py # 配置管理 │ ├── api/ # HTTP 接口 │ ├── agents/ # Agent 定义 │ ├── graphs/ # LangGraph StateGraph │ ├── tools/ # Agent Tool │ ├── rag/ # RAG Pipeline │ ├── memory/ # 三层记忆 │ └── tasks/ # 定时任务 ├── data/ │ └── chroma_db/ # ChromaDB 持久化 (自动创建) └── docs/ ├── deployment.md # 本文件 └── operations.md # 运维手册 ``` ## Docker Compose 部署 ```bash # 1. 创建生产配置 cp .env.example .env.production # 编辑 .env.production 填入 LLM_API_KEY # 2. 构建并启动 docker-compose up -d # 3. 验证 curl http://localhost:9000/api/v1/health # 4. 查看日志 docker-compose logs -f langgraph-svc ``` ## 直接部署 (无 Docker) ```bash # 1. 安装依赖 pip install -e . # 2. 配置环境变量 export LLM_API_KEY=sk-xxx export JAVA_BASE_URL=http://localhost:9082 # 3. 启动 gunicorn app.main:app \ --worker-class uvicorn.workers.UvicornWorker \ --bind 0.0.0.0:9000 \ --workers 2 \ --timeout 60 \ --access-logfile - \ --error-logfile - ``` ## 环境变量说明 | 变量 | 必填 | 说明 | |------|------|------| | LLM_API_KEY | 是 | LLM API Key | | LLM_BASE_URL | 否 | 默认 https://api.deepseek.com/v1 | | LLM_MODEL | 否 | 默认 deepseek-chat | | JAVA_BASE_URL | 是 | Java 后端地址 | | CHROMA_DB_PATH | 否 | ChromaDB 持久化路径, 默认 ./data/chroma_db | | LOG_LEVEL | 否 | 日志级别, 默认 info | | JSON_LOGS | 否 | 启用 JSON 日志格式, 默认 false | ## 健康检查 ``` GET /api/v1/health Response: { "status": "ok", "components": { "chromadb": {"status": "ok", "path": "...", "exists": true}, "llm": {"status": "ok"}, "java_backend": {"status": "ok"} } } ``` ``` - [x] **Step 2: 创建 `docs/operations.md`** ```markdown # LangGraph Sidecar 运维手册 ## 日常监控 ### 1. 健康检查 生产环境建议配置 30 秒定时健康检查: ```bash curl -f http://localhost:9000/api/v1/health ``` 预期返回 `{"status":"ok"}`。组件降级时返回 `{"status":"degraded"}`。 ### 2. Prometheus 指标 ``` GET /metrics 关键指标: - agent_calls_total{agent_type="chat|recommend|analysis"} - agent_duration_seconds{agent_type="..."} - llm_calls_total{model="deepseek-chat",status="ok|error"} - llm_duration_seconds{model="..."} - kb_sync_duration_seconds # 知识库同步耗时 ``` ### 3. 日志 JSON 格式日志可直接接入 ELK / Loki: ```json {"timestamp":"2026-07-20T10:00:00","level":"WARN","logger":"app.main","message":"SLOW_REQUEST: POST /api/v1/chat took 8.23s"} ``` ## 常见问题 ### Python 服务无法启动 ```bash # 检查依赖 pip list | grep -E "fastapi|langchain|langgraph" # 检查配置 python -c "from app.config import settings; print(settings.llm_model)" # 检查端口占用 netstat -ano | grep 9000 ``` ### LLM 调用失败 1. 检查 `.env.production` 中的 `LLM_API_KEY` 是否有效 2. 检查 `LLM_BASE_URL` 是否可访问 3. 查看日志: `docker-compose logs langgraph-svc | grep llm_call` ### ChromaDB 损坏 ```bash # 删除后重建 (知识库会自动同步) rm -rf data/chroma_db/ docker-compose restart langgraph-svc # 或触发手动同步 curl -X POST http://localhost:9000/api/v1/admin/kb-sync ``` ### 知识库同步失败 ```bash # 检查 Java 后端是否可访问 curl http://localhost:9082/health # 检查文章接口 curl -X POST http://localhost:9082/api/article/updated-since \ -H "Content-Type: application/json" \ -d '{"since":"2026-01-01T00:00:00","status":"published"}' # 手动触发同步 docker-compose exec langgraph-svc python -c " import asyncio from app.tasks.knowledge_sync import sync_knowledge_base asyncio.run(sync_knowledge_base()) " ``` ### Java 端回退 Dify 如果 Python 服务异常, Java 会自动回退 Dify: ```yaml # application.yml 检查配置 python: enabled: true circuit-breaker: failure-threshold: 3 reset-timeout-ms: 30000 ``` 熔断器打开时, Java 侧日志会输出 `AiGateway 熔断器已打开`, 等待 `reset-timeout-ms` 后自动半开重试。 ## 扩缩容 LangGraph 服务是无状态的 (ChromaDB 在共享存储上): ```yaml # docker-compose 增加副本数 services: langgraph-svc: deploy: replicas: 2 ``` 注意: ChromaDB 文件模式不支持并发写入, 多副本时知识库同步需加锁或切 PGVector。 ## 备份 ```bash # ChromaDB 数据 tar czf chroma_backup_$(date +%Y%m%d).tar.gz data/chroma_db/ ``` ``` - [x] **Step 3: Commit** ```bash git add cfc-langgraph/docs/ git commit -m "docs(langgraph): deployment and operations manual" ``` --- ### Phase 4 自审清单 - [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)