bounded_capacity_acceptance.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import asyncio
  2. import json
  3. import os
  4. import platform
  5. from pathlib import Path
  6. import httpx
  7. from capacity_acceptance import accounts, measure
  8. from retrieval_evaluation import publish_dataset
  9. from sqlalchemy import func, select
  10. from test_after_sales import scenario # noqa: F401
  11. from test_knowledge_memory import cleanup_vectors
  12. from zhifu.modules.agent_runtime.models import ModelAttempt
  13. async def test_bounded_current_api_and_retrieval_capacity(scenario): # noqa: F811
  14. report = {
  15. "environment": platform.platform(), "python": platform.python_version(),
  16. "logical_cpus": os.cpu_count(), "api_workers": 1, "database_pool": "5+5",
  17. "inference_device": "cpu", "documents": 12, "account_count": 16,
  18. "maximum_load_requests": 3200, "maximum_seconds": 120, "stages": [],
  19. "production_acceptance": "NOT_RUN",
  20. "production_targets": {"api_rps": 1000, "api_p95_ms": 300,
  21. "error_rate_below": 0.001, "sse_connections": 3000,
  22. "agent_turns_per_second": 50, "first_response_p95_ms": 3000},
  23. }
  24. try:
  25. async with asyncio.timeout(120):
  26. await publish_dataset(scenario)
  27. identities = await accounts(scenario)
  28. async with httpx.AsyncClient(
  29. base_url="http://127.0.0.1:18000", timeout=15, trust_env=False,
  30. limits=httpx.Limits(max_connections=32),
  31. ) as client:
  32. for workload, method, path, body in (
  33. ("orders", "GET", f"/openapi/v1/orders?store_id={scenario['store']}", None),
  34. ("knowledge", "POST",
  35. f"/openapi/v1/stores/{scenario['store']}/knowledge/search",
  36. {"query": "键盘脏了能放水里洗吗"}),
  37. ):
  38. for concurrency in (1, 16):
  39. result = await measure(client, method, path, body, concurrency,
  40. identities, seconds=5, maximum_requests=800)
  41. report["stages"].append({"workload": workload, **result})
  42. assert set(result["statuses"]) <= {"200", "429"}, result
  43. assert result["statuses"].get("200", 0) > 0
  44. assert result["requests"] <= 800
  45. async with scenario["app"].state.sessions() as session:
  46. report["generation_attempts"] = await session.scalar(
  47. select(func.count()).select_from(ModelAttempt).where(
  48. ModelAttempt.tenant_id == scenario["tenant"].bytes))
  49. assert report["generation_attempts"] == 0
  50. finally:
  51. await asyncio.to_thread(Path(".work/long-capacity.json").write_text,
  52. json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
  53. await cleanup_vectors(scenario["tenant"])