good version for 算法注册

This commit is contained in:
2026-02-15 21:23:28 +08:00
parent 3c03777b97
commit 62ea5d36a5
115 changed files with 9566 additions and 1576 deletions

View File

@@ -14,6 +14,7 @@ from app.schemas.user import UserResponse
from app.services.project_analyzer import ProjectAnalyzer
from app.services.service_generator import ServiceGenerator
from app.services.service_orchestrator import ServiceOrchestrator
from app.gitea.service import gitea_service
router = APIRouter(prefix="/services", tags=["services"])
@@ -23,6 +24,9 @@ class RegisterServiceRequest(BaseModel):
repository_id: str
name: str
version: str = "1.0.0"
description: Optional[str] = ""
tech_category: str = "computer_vision"
output_type: str = "image"
service_type: str = "http"
host: str = "0.0.0.0"
port: int = 8000
@@ -154,31 +158,24 @@ async def register_service(
# 记录仓库信息
print(f"仓库信息: {repo.name}, {repo.description}, {repo.repo_url}")
# 2. 分析项目
repo_path = f"/tmp/repository_{request.repository_id}"
# 注意:在实际实现中,应该从算法仓库中获取项目文件
# 这里简化处理,创建一个模拟的项目结构
os.makedirs(repo_path, exist_ok=True)
# 2. 从Gitea仓库克隆代码到本地
repo_path = f"/tmp/algorithms/{request.repository_id}"
# 创建模拟的算法文件
with open(os.path.join(repo_path, "algorithm.py"), "w") as f:
f.write("""
def predict(data):
return {"result": "Prediction result", "input": data}
def run(data):
return {"result": "Run result", "input": data}
def main(data):
return {"result": "Main result", "input": data}
""")
# 使用Gitea服务克隆仓库
clone_success = gitea_service.clone_repository(repo.repo_url, request.repository_id, repo.branch or "main")
if not clone_success:
raise HTTPException(status_code=400, detail=f"克隆仓库失败: {repo.repo_url}")
# 分析项目
print(f"仓库克隆成功: {repo_path}")
# 3. 分析项目
project_info = project_analyzer.analyze_project(repo_path)
if not project_info["success"]:
raise HTTPException(status_code=400, detail=f"项目分析失败: {project_info['error']}")
# 3. 生成服务包装器
print(f"项目分析成功: {project_info}")
# 4. 生成服务包装器
service_config = {
"name": request.name,
"version": request.version,
@@ -194,24 +191,31 @@ def main(data):
if not generate_result["success"]:
raise HTTPException(status_code=400, detail=f"服务生成失败: {generate_result['error']}")
# 4. 部署服务
print(f"服务生成成功: {generate_result}")
# 5. 部署服务
service_id = str(uuid.uuid4())
deploy_result = service_orchestrator.deploy_service(service_id, service_config, project_info)
deploy_result = service_orchestrator.deploy_service(service_id, service_config, project_info, repo_path)
if not deploy_result["success"]:
raise HTTPException(status_code=400, detail=f"服务部署失败: {deploy_result['error']}")
# 5. 保存服务信息到数据库
print(f"服务部署成功: {deploy_result}")
# 6. 保存服务信息到数据库
new_service = AlgorithmService(
id=str(uuid.uuid4()),
service_id=service_id,
name=request.name,
algorithm_name=repo.name, # 使用仓库名称作为算法名称
version=request.version,
tech_category=request.tech_category,
output_type=request.output_type,
host=request.host,
port=request.port,
api_url=deploy_result["api_url"],
status=deploy_result["status"],
config={
"repository_id": request.repository_id, # 保存仓库ID
"service_type": request.service_type,
"timeout": request.timeout,
"health_check_path": request.health_check_path,
@@ -352,8 +356,64 @@ async def start_service(
# 启动服务
start_result = service_orchestrator.start_service(service_id, container_id)
# 如果启动失败,尝试从数据库重新注册服务
if not start_result["success"]:
raise HTTPException(status_code=400, detail=f"服务启动失败: {start_result['error']}")
print(f"服务启动失败: {start_result['error']},尝试从数据库重新注册服务")
# 获取仓库信息
repository_id = service.config.get("repository_id")
if not repository_id:
raise HTTPException(status_code=400, detail="Repository ID not found in service config")
repository = db.query(AlgorithmRepository).filter(AlgorithmRepository.id == repository_id).first()
if not repository:
raise HTTPException(status_code=404, detail="Repository not found")
# 从Gitea克隆仓库
clone_success = gitea_service.clone_repository(
repository.repo_url,
service_id,
repository.branch or "main"
)
if not clone_success:
raise HTTPException(status_code=400, detail="Failed to clone repository")
# 仓库路径
repo_path = f"/tmp/algorithms/{service_id}"
# 分析项目
project_info = project_analyzer.analyze_project(repo_path)
if not project_info:
raise HTTPException(status_code=400, detail="Failed to analyze project")
# 生成服务
service_config = {
"name": service.name,
"version": service.version,
"host": service.host,
"port": service.port,
"timeout": service.config.get("timeout", 30),
"health_check_path": service.config.get("health_check_path", "/health"),
"environment": service.config.get("environment", {})
}
# 部署服务
deploy_result = service_orchestrator.deploy_service(service_id, project_info, service_config, repo_path)
if not deploy_result["success"]:
raise HTTPException(status_code=400, detail=f"服务部署失败: {deploy_result['error']}")
# 更新服务配置
service.config["container_id"] = deploy_result["container_id"]
service.api_url = deploy_result["api_url"]
db.commit()
start_result = {
"success": True,
"service_id": service_id,
"status": "running",
"error": None
}
# 更新服务状态
service.status = start_result["status"]
@@ -1065,3 +1125,108 @@ async def batch_delete_services(
)
finally:
db.close()
class ServiceCallRequest(BaseModel):
"""服务调用请求"""
service_id: str
payload: Dict[str, Any]
class ServiceCallResponse(BaseModel):
"""服务调用响应"""
success: bool
result: Dict[str, Any]
service_id: str
execution_time: float
error: Optional[str] = None
@router.post("/call")
async def call_service(
request: ServiceCallRequest,
current_user: UserResponse = Depends(get_current_active_user)
):
"""直接调用注册的服务"""
import time
import httpx
# 创建数据库会话
db = SessionLocal()
try:
# 查询服务
service = db.query(AlgorithmService).filter(
AlgorithmService.service_id == request.service_id
).first()
if not service:
raise HTTPException(status_code=404, detail="服务不存在")
# 检查服务状态
if service.status != "running":
raise HTTPException(
status_code=503,
detail=f"服务未运行,当前状态: {service.status}"
)
# 调用服务
start_time = time.time()
try:
# 构建服务URL
service_url = service.api_url
# 如果URL没有路径添加默认路径
if not service_url.endswith("/"):
service_url += "/"
# 添加调用端点
call_url = f"{service_url}predict"
# 使用httpx调用服务
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
call_url,
json=request.payload,
headers={"Content-Type": "application/json"}
)
execution_time = time.time() - start_time
if response.status_code == 200:
return ServiceCallResponse(
success=True,
result=response.json(),
service_id=request.service_id,
execution_time=execution_time
)
else:
return ServiceCallResponse(
success=False,
result={},
service_id=request.service_id,
execution_time=execution_time,
error=f"服务返回错误: HTTP {response.status_code} - {response.text}"
)
except httpx.RequestError as e:
execution_time = time.time() - start_time
return ServiceCallResponse(
success=False,
result={},
service_id=request.service_id,
execution_time=execution_time,
error=f"无法连接到服务: {str(e)}"
)
except Exception as e:
execution_time = time.time() - start_time
return ServiceCallResponse(
success=False,
result={},
service_id=request.service_id,
execution_time=execution_time,
error=f"服务调用异常: {str(e)}"
)
finally:
db.close()