Files
worldquant-alpha-system/backend/app/research/routes.py
T

152 lines
5.3 KiB
Python
Raw Normal View History

"""Authenticated research workspace; previewing never starts a platform simulation."""
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from ..security import require_auth
from .assets import Assets
from .comparisons import compare
from .experiments import Experiments
from .model import request_model
from .workspace_contracts import (
AssetWrite,
CompareInput,
Expansion,
ExperimentPreview,
Generation,
ImportCommit,
ImportPreview,
SettingVariants,
)
router = APIRouter(prefix="/api/v1/research", tags=["research"], dependencies=[Depends(require_auth)])
@router.get("/inputs")
async def inputs(request: Request, limit: int = Query(100, ge=1, le=100)):
async with request.app.state.sessions() as db:
return await Experiments(db).available_inputs(limit)
@router.get("/assets")
async def assets(
request: Request,
kind: str = "template",
q: str = "",
limit: int = Query(25, ge=1, le=100),
offset: int = Query(0, ge=0),
):
if kind != "template":
raise HTTPException(422, "当前素材类型尚未开放")
async with request.app.state.sessions() as db:
return await Assets(db).list(kind, q, limit, offset)
@router.post("/assets", status_code=201)
async def save_asset(body: AssetWrite, request: Request):
if body.kind != "template":
raise HTTPException(422, "当前素材类型尚未开放")
async with request.app.state.sessions.begin() as db:
return await Assets(db).save(body)
@router.get("/assets/{asset_id}")
async def asset(asset_id: str, request: Request, version: int | None = Query(None, ge=1)):
async with request.app.state.sessions() as db:
return await Assets(db).get(asset_id, version)
@router.put("/assets/{asset_id}")
async def update_asset(asset_id: str, body: AssetWrite, request: Request):
if body.kind != "template":
raise HTTPException(422, "当前素材类型尚未开放")
async with request.app.state.sessions.begin() as db:
return await Assets(db).save(body, asset_id)
@router.delete("/assets/{asset_id}")
async def archive_asset(asset_id: str, request: Request, version: int = Query(ge=1)):
async with request.app.state.sessions.begin() as db:
return await Assets(db).archive(asset_id, version)
@router.get("/assets/{asset_id}/versions")
async def versions(asset_id: str, request: Request):
async with request.app.state.sessions() as db:
return await Assets(db).versions(asset_id)
@router.post("/templates/import-preview")
async def import_preview(body: ImportPreview, request: Request):
async with request.app.state.sessions() as db:
return await Assets(db).import_preview(body.templates)
@router.post("/templates/import", status_code=201)
async def import_commit(body: ImportCommit, request: Request):
async with request.app.state.sessions.begin() as db:
return await Assets(db).import_commit(body)
@router.post("/generate", status_code=201)
async def generate(body: Generation, request: Request):
if body.method == "feature":
raise HTTPException(422, "特征方案生成将在特征工程阶段开放")
async with request.app.state.sessions() as db:
context = await Experiments(db).generation_context(body)
result, evidence = await request_model(request.app.state.ai, context)
async with request.app.state.sessions.begin() as db:
asset = await Assets(db).save(
AssetWrite(kind="template", content=result.model_dump(mode="json")),
provenance={"generation": evidence, "context": context},
)
return {
**asset,
"generation": evidence,
"parent_alpha_ids": body.parent_alpha_ids,
"parent_experiment_ids": body.parent_experiment_ids,
}
@router.post("/experiments", status_code=201)
async def expand(body: Expansion, request: Request):
async with request.app.state.sessions.begin() as db:
kind = "variant" if body.parent_alpha_ids or body.parent_experiment_ids else "template"
return await Experiments(db).create(
body, kind, {"method": "structure" if kind == "variant" else "template"}
)
@router.get("/experiments")
async def experiments(
request: Request,
kind: str | None = None,
limit: int = Query(25, ge=1, le=100),
offset: int = Query(0, ge=0),
):
async with request.app.state.sessions() as db:
return await Experiments(db).list(kind, limit, offset)
@router.get("/experiments/{experiment_id}")
async def experiment(experiment_id: str, request: Request):
async with request.app.state.sessions() as db:
return await Experiments(db).get(experiment_id)
@router.post("/experiments/{experiment_id}/preview", status_code=201)
async def preview(experiment_id: str, body: ExperimentPreview, request: Request):
async with request.app.state.sessions.begin() as db:
return await Experiments(db).preview(experiment_id, body.candidate_ids)
@router.post("/variants/settings", status_code=201)
async def settings_variants(body: SettingVariants, request: Request):
async with request.app.state.sessions.begin() as db:
return await Experiments(db).setting_variants(body)
@router.post("/compare")
async def comparison(body: CompareInput, request: Request):
async with request.app.state.sessions() as db:
return await compare(db, body.alpha_ids)