""" 重启 Celery Worker(Windows),并对「知你客服7号」做两轮 API 测试: 1)我的名字叫小七 2)我叫什么名字? 需:本机 API 已监听(默认 8037)、Redis、LLM 配置可用。 """ from __future__ import annotations import json import os import subprocess import sys import time import uuid from pathlib import Path BACKEND_DIR = Path(__file__).resolve().parents[1] VENV_PY = BACKEND_DIR / "venv" / "Scripts" / "python.exe" API_BASE = os.environ.get("API_BASE", "http://127.0.0.1:8037") def _restart_celery() -> None: ps = ( "Get-CimInstance Win32_Process | " "Where-Object { $_.CommandLine -match 'celery_app' } | " "ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }" ) subprocess.run( ["powershell", "-NoProfile", "-Command", ps], cwd=str(BACKEND_DIR), capture_output=True, text=True, ) time.sleep(2) if not VENV_PY.is_file(): print("未找到 venv Python,跳过启动 Celery", file=sys.stderr) return popen_kw: dict = { "cwd": str(BACKEND_DIR), "stdout": subprocess.DEVNULL, "stderr": subprocess.STDOUT, } if sys.platform == "win32": popen_kw["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore[attr-defined] subprocess.Popen( [ str(VENV_PY), "-m", "celery", "-A", "app.core.celery_app", "worker", "--loglevel=info", "--pool=threads", "--concurrency=8", ], **popen_kw, ) print("已启动新 Celery Worker(线程池),等待就绪…") time.sleep(4) def _touch_api_reload() -> None: """若 uvicorn 带 --reload,触发重载。""" main_py = BACKEND_DIR / "app" / "main.py" if main_py.is_file(): main_py.touch() print("已 touch app/main.py 以触发 API 热重载(若启用 --reload)") def main() -> int: os.chdir(BACKEND_DIR) sys.path.insert(0, str(BACKEND_DIR)) _restart_celery() _touch_api_reload() import httpx from app.core.database import SessionLocal from app.core.security import create_access_token from app.models.agent import Agent from app.models.user import User db = SessionLocal() try: agent = db.query(Agent).filter(Agent.name == "知你客服7号").first() if not agent: print("数据库中未找到名为「知你客服7号」的 Agent", file=sys.stderr) return 1 owner = db.query(User).filter(User.id == agent.user_id).first() user = owner or db.query(User).first() if not user: print("无可用用户,无法签发 JWT", file=sys.stderr) return 1 token = create_access_token(data={"sub": user.id, "username": user.username}) headers = {"Authorization": f"Bearer {token}"} uid = f"e2e_xiaoqi_{uuid.uuid4().hex[:10]}" print(f"agent_id={agent.id} owner={user.username} user_id={uid}") print(f"请确认工作流 Cache 键为 user_memory_{{{{user_id}}}},请求中已带 user_id={uid}\n") def poll(client: httpx.Client, execution_id: str, timeout: float = 300.0) -> dict: t0 = time.time() while time.time() - t0 < timeout: r = client.get(f"/api/v1/executions/{execution_id}", headers=headers) r.raise_for_status() data = r.json() st = data.get("status") if st == "completed": return data if st == "failed": print("error:", data.get("error_message"), file=sys.stderr) raise RuntimeError("执行失败") time.sleep(1) raise TimeoutError("等待执行完成超时") with httpx.Client(base_url=API_BASE, timeout=300.0) as client: r = client.post( "/api/v1/executions", json={ "agent_id": str(agent.id), "input_data": {"query": "我的名字叫小七", "user_id": uid}, }, headers=headers, ) if r.status_code >= 400: print(r.text, file=sys.stderr) r.raise_for_status() eid1 = r.json()["id"] print("第一轮 execution_id:", eid1) out1 = poll(client, eid1) print("第一轮 output_data:", json.dumps(out1.get("output_data"), ensure_ascii=False)[:1200]) r = client.post( "/api/v1/executions", json={ "agent_id": str(agent.id), "input_data": {"query": "我叫什么名字?", "user_id": uid}, }, headers=headers, ) r.raise_for_status() eid2 = r.json()["id"] print("\n第二轮 execution_id:", eid2) out2 = poll(client, eid2) print("第二轮 output_data:", json.dumps(out2.get("output_data"), ensure_ascii=False)[:1200]) # Redis 键检查 try: from app.core.config import settings import redis as redis_lib url = getattr(settings, "REDIS_URL", None) or "redis://localhost:6379/0" rc = redis_lib.from_url(url, decode_responses=True) key = f"user_memory_{uid}" raw = rc.get(key) print(f"\nRedis 键 {key}:", "存在" if raw else "不存在") if raw: try: mem = json.loads(raw) print("memory.user_profile:", mem.get("user_profile")) except Exception as ex: print("解析 Redis 值失败:", ex) except Exception as ex: print("Redis 检查跳过:", ex) finally: db.close() return 0 if __name__ == "__main__": raise SystemExit(main())