312 lines
12 KiB
Python
312 lines
12 KiB
Python
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, Form, Header
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.response import success_response
|
|
from app.db import get_db_session
|
|
from app.services.audit_log_service import AuditLogService
|
|
from app.services.auth_service import AuthService
|
|
from app.services.prompt_asset_service import PromptAssetService
|
|
|
|
router = APIRouter(prefix="/prompt-assets", tags=["prompt-assets"])
|
|
ROUTE_PERMISSION_SCOPE = "prompt_asset_management"
|
|
ROUTE_PERMISSION_ACTIONS = {
|
|
"list": "prompt_assets:list",
|
|
"detail": "prompt_assets:detail",
|
|
"create": "prompt_assets:create",
|
|
"create_version": "prompt_assets:versions:create",
|
|
"evaluate": "prompt_assets:evaluations:run",
|
|
"publish": "prompt_assets:publish",
|
|
"unpublish": "prompt_assets:unpublish",
|
|
"rollback": "prompt_assets:rollback",
|
|
"record_run_link": "prompt_assets:run_links:create",
|
|
}
|
|
|
|
|
|
def get_prompt_asset_service(db: Session = Depends(get_db_session)) -> PromptAssetService:
|
|
return PromptAssetService(db)
|
|
|
|
|
|
def get_audit_log_service(db: Session = Depends(get_db_session)) -> AuditLogService:
|
|
return AuditLogService(db)
|
|
|
|
|
|
def require_current_user(
|
|
authorization: Optional[str] = Header(default=None),
|
|
db: Session = Depends(get_db_session),
|
|
):
|
|
return AuthService(db).require_current_user(authorization)
|
|
|
|
|
|
@router.get("")
|
|
def list_prompt_assets(
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
prompt_type: Optional[str] = None,
|
|
status_filter: Optional[str] = None,
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
return success_response(prompt_asset_service.list_prompt_assets(current_user, page, page_size, prompt_type, status_filter))
|
|
|
|
|
|
@router.get("/{asset_id}")
|
|
def get_prompt_asset_detail(
|
|
asset_id: str,
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
return success_response(prompt_asset_service.get_prompt_asset_detail(current_user, asset_id))
|
|
|
|
|
|
@router.post("")
|
|
def create_prompt_asset(
|
|
prompt_key: str = Form(...),
|
|
prompt_type: str = Form(...),
|
|
name: str = Form(...),
|
|
prompt_content: str = Form(...),
|
|
description: Optional[str] = Form(default=None),
|
|
target_scene: Optional[str] = Form(default=None),
|
|
system_prompt: Optional[str] = Form(default=None),
|
|
variables_json: Optional[str] = Form(default=None),
|
|
output_schema_json: Optional[str] = Form(default=None),
|
|
model_config_json: Optional[str] = Form(default=None),
|
|
evaluation_report_json: Optional[str] = Form(default=None),
|
|
evaluation_status: Optional[str] = Form(default=None),
|
|
evaluation_score: Optional[float] = Form(default=None),
|
|
change_summary: Optional[str] = Form(default=None),
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.create_prompt_asset(
|
|
current_user,
|
|
prompt_key,
|
|
prompt_type,
|
|
name,
|
|
prompt_content,
|
|
description=description,
|
|
target_scene=target_scene,
|
|
system_prompt=system_prompt,
|
|
variables_json=variables_json,
|
|
output_schema_json=output_schema_json,
|
|
model_config_json=model_config_json,
|
|
evaluation_report_json=evaluation_report_json,
|
|
evaluation_status=evaluation_status,
|
|
evaluation_score=evaluation_score,
|
|
change_summary=change_summary,
|
|
)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="create_prompt_asset",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_key": result["prompt_key"],
|
|
"prompt_type": result["prompt_type"],
|
|
"current_version_label": result["current_version_label"],
|
|
"evaluation_status": result.get("latest_evaluation_status"),
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/versions")
|
|
def create_prompt_asset_version(
|
|
asset_id: str,
|
|
prompt_content: str = Form(...),
|
|
system_prompt: Optional[str] = Form(default=None),
|
|
variables_json: Optional[str] = Form(default=None),
|
|
output_schema_json: Optional[str] = Form(default=None),
|
|
model_config_json: Optional[str] = Form(default=None),
|
|
evaluation_report_json: Optional[str] = Form(default=None),
|
|
evaluation_status: Optional[str] = Form(default=None),
|
|
evaluation_score: Optional[float] = Form(default=None),
|
|
change_summary: Optional[str] = Form(default=None),
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.create_prompt_asset_version(
|
|
current_user,
|
|
asset_id,
|
|
prompt_content,
|
|
system_prompt=system_prompt,
|
|
variables_json=variables_json,
|
|
output_schema_json=output_schema_json,
|
|
model_config_json=model_config_json,
|
|
evaluation_report_json=evaluation_report_json,
|
|
evaluation_status=evaluation_status,
|
|
evaluation_score=evaluation_score,
|
|
change_summary=change_summary,
|
|
)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="create_prompt_asset_version",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_key": result["prompt_key"],
|
|
"current_version_label": result["current_version_label"],
|
|
"evaluation_status": result.get("latest_evaluation_status"),
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/evaluations/run")
|
|
def run_prompt_asset_evaluation(
|
|
asset_id: str,
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.evaluate_current_prompt_asset(current_user, asset_id)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="run_prompt_asset_evaluation",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["asset"]["id"],
|
|
detail_json={
|
|
"prompt_key": result["asset"]["prompt_key"],
|
|
"prompt_type": result["asset"]["prompt_type"],
|
|
"version_label": result["version"]["version_label"],
|
|
"evaluation_status": result["version"]["evaluation_status"],
|
|
"evaluation_score": result["version"]["evaluation_score"],
|
|
"suite_key": result["evaluation_report"].get("suite_key"),
|
|
"evaluation_mode": result["evaluation_report"].get("evaluation_mode"),
|
|
"sample_count": result["evaluation_report"].get("sample_count"),
|
|
"passed_samples": result["evaluation_report"].get("passed_samples"),
|
|
"failed_samples": result["evaluation_report"].get("failed_samples"),
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/publish")
|
|
def publish_prompt_asset(
|
|
asset_id: str,
|
|
evaluation_report_json: Optional[str] = Form(default=None),
|
|
evaluation_status: Optional[str] = Form(default=None),
|
|
evaluation_score: Optional[float] = Form(default=None),
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.publish_prompt_asset(
|
|
current_user,
|
|
asset_id,
|
|
evaluation_report_json=evaluation_report_json,
|
|
evaluation_status=evaluation_status,
|
|
evaluation_score=evaluation_score,
|
|
)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="publish_prompt_asset",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_key": result["prompt_key"],
|
|
"published_version_id": result["published_version_id"],
|
|
"published_at": result["published_at"],
|
|
"evaluation_status": result.get("latest_evaluation_status"),
|
|
"evaluation_score": result.get("latest_evaluation_score"),
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/unpublish")
|
|
def unpublish_prompt_asset(
|
|
asset_id: str,
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.unpublish_prompt_asset(current_user, asset_id)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="unpublish_prompt_asset",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_key": result["prompt_key"],
|
|
"status": result["status"],
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/rollback")
|
|
def rollback_prompt_asset(
|
|
asset_id: str,
|
|
target_version_label: str = Form(...),
|
|
change_summary: Optional[str] = Form(default=None),
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.rollback_prompt_asset(current_user, asset_id, target_version_label, change_summary)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="rollback_prompt_asset",
|
|
resource_type="prompt_asset",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_key": result["prompt_key"],
|
|
"target_version_label": target_version_label,
|
|
"current_version_label": result["current_version_label"],
|
|
"status": result["status"],
|
|
},
|
|
)
|
|
return success_response(result)
|
|
|
|
|
|
@router.post("/{asset_id}/run-links")
|
|
def record_prompt_run_link(
|
|
asset_id: str,
|
|
run_type: str = Form(default="ai_run"),
|
|
run_id: Optional[str] = Form(default=None),
|
|
resource_type: Optional[str] = Form(default=None),
|
|
resource_id: Optional[str] = Form(default=None),
|
|
workflow_run_id: Optional[str] = Form(default=None),
|
|
task_run_id: Optional[str] = Form(default=None),
|
|
trace_json: Optional[str] = Form(default=None),
|
|
prompt_asset_service: PromptAssetService = Depends(get_prompt_asset_service),
|
|
audit_log_service: AuditLogService = Depends(get_audit_log_service),
|
|
current_user: dict = Depends(require_current_user),
|
|
):
|
|
result = prompt_asset_service.record_prompt_run_link(
|
|
current_user,
|
|
asset_id,
|
|
run_type,
|
|
run_id=run_id,
|
|
resource_type=resource_type,
|
|
resource_id=resource_id,
|
|
workflow_run_id=workflow_run_id,
|
|
task_run_id=task_run_id,
|
|
trace_json=trace_json,
|
|
)
|
|
audit_log_service.record_event(
|
|
tenant_id=current_user.get("tenant_id"),
|
|
user_id=current_user.get("id"),
|
|
action="record_prompt_asset_run_link",
|
|
resource_type="prompt_asset_run_link",
|
|
resource_id=result["id"],
|
|
detail_json={
|
|
"prompt_asset_id": result["prompt_asset_id"],
|
|
"prompt_asset_version_id": result["prompt_asset_version_id"],
|
|
"run_id": result["run_id"],
|
|
"resource_type": result["resource_type"],
|
|
"resource_id": result["resource_id"],
|
|
},
|
|
)
|
|
return success_response(result)
|