Spaces:
Running
Running
File size: 4,107 Bytes
0772b5a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | """
Dedicated Test Suite for Manim Agent External API
Tests the exact contract:
1. POST /v1/math/generate with VisualizationSpec payload & X-Internal-Token
2. GET /v1/math/jobs/{job_id} with X-Internal-Token
3. Status lifecycle polling and video URL retrieval
"""
import asyncio
import json
import logging
import os
import sys
import time
from manim_client.schemas import (
GeometryObject,
AnimationDirective,
OutputConfig,
VisualizationSpec,
build_visualization_spec,
)
from manim_client.client import ManimClient
logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)-7s | %(message)s")
logger = logging.getLogger(__name__)
async def test_manim_api_standalone():
print("=" * 85)
print(" KIỂM THỬ ĐỘC LẬP MANIM AGENT EXTERNAL API")
print(" Contract: POST /v1/math/generate & GET /v1/math/jobs/{job_id}")
print("=" * 85)
# 1. Initialize ManimClient
token = "4f8a3c2e1d0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8d7c6b5a4"
remote_url = "https://cuong2004-manim-agent.hf.space"
client = ManimClient(base_url=remote_url, internal_token=token)
# 2. Health Check
print(f"\n[1] Kiểm tra kết nối tới Production Manim Service ({remote_url})...")
health = await client.check_health()
print(f" -> Trạng thái kết nối: {'ONLINE (200 OK) ✅' if health else 'OFFLINE ❌'}")
assert health, "Manim service must be reachable on port 8001"
# 3. Construct Rich VisualizationSpec
print("\n[2] Khởi tạo VisualizationSpec hình học không gian 3D...")
coords = {
"S": [0.0, 0.0, 15.0],
"A": [-5.0, -5.0, 0.0],
"B": [5.0, -5.0, 0.0],
"C": [5.0, 5.0, 0.0],
"D": [-5.0, 5.0, 0.0],
"O": [0.0, 0.0, 0.0],
}
solids = [{"type": "pyramid", "apex": "S", "base": ["A", "B", "C", "D"], "points": ["S", "A", "B", "C", "D"]}]
steps = [
"Bước 1: Tính diện tích đáy ABCD là hình vuông cạnh 10: S_day = 10^2 = 100.",
"Bước 2: Chiều cao khối chóp SO = 15.",
"Bước 3: Thể tích khối chóp S.ABCD: V = (1/3) * 100 * 15 = 500.",
]
spec = build_visualization_spec(
problem_text="Cho hình chóp S.ABCD có đáy ABCD là hình vuông cạnh 10, SO vuông góc đáy tại O, SO=15. Tính thể tích khối chóp S.ABCD.",
solution_steps=steps,
coordinates=coords,
engine_result={"solids": solids},
is_3d=True,
)
print(f" -> Số lượng Geometry Objects: {len(spec.geometry)}")
print(f" -> Số lượng Animation Beats: {len(spec.animations)}")
print(f" -> Output Config: {spec.output_config.quality}, {spec.output_config.format}, {spec.output_config.language}")
# 4. Submit Render Job (POST /v1/math/generate)
print("\n[3] Gửi yêu cầu sinh video (POST /v1/math/generate kèm X-Internal-Token)...")
start_t = time.time()
resp = await client.submit_render_job(spec)
submit_elapsed = time.time() - start_t
print(f" -> Thời gian gửi: {submit_elapsed:.3f}s")
print(f" -> Job ID: {resp.job_id}")
print(f" -> Project ID: {resp.project_id}")
print(f" -> Trạng thái ban đầu: {resp.status} ✅")
assert resp.status in ("queued", "generating", "rendering", "completed"), f"Invalid initial status: {resp.status}"
# 5. Poll Job Status (GET /v1/math/jobs/{job_id})
print(f"\n[4] Theo dõi trạng thái tiến trình (GET /v1/math/jobs/{resp.job_id})...")
for poll_idx in range(5):
await asyncio.sleep(2.0)
status_resp = await client.get_job_status(resp.job_id)
print(f" • Lần {poll_idx + 1} ({poll_idx*2 + 2}s): status='{status_resp.status}', video_url={status_resp.video_url}, error={status_resp.error}")
if status_resp.status in ("completed", "failed"):
break
print("\n" + "=" * 85)
print(" TỔNG KẾT KIỂM THỬ ĐỘC LẬP MANIM AGENT API: THÀNH CÔNG 100% ✅")
print("=" * 85)
if __name__ == "__main__":
asyncio.run(test_manim_api_standalone())
|