feat: persist feature research and versioned alpha assessments
This commit is contained in:
@@ -5,13 +5,17 @@ from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from ..security import require_auth
|
||||
from .assets import Assets
|
||||
from .comparisons import compare
|
||||
from .evaluations import Evaluations
|
||||
from .experiments import Experiments
|
||||
from .model import request_model
|
||||
from .features import Features
|
||||
from .model import OUTPUTS, Advice, request_model
|
||||
from .workspace_contracts import (
|
||||
AssetWrite,
|
||||
CompareInput,
|
||||
EvaluateInput,
|
||||
Expansion,
|
||||
ExperimentPreview,
|
||||
FeatureConversion,
|
||||
Generation,
|
||||
ImportCommit,
|
||||
ImportPreview,
|
||||
@@ -35,7 +39,7 @@ async def assets(
|
||||
limit: int = Query(25, ge=1, le=100),
|
||||
offset: int = Query(0, ge=0),
|
||||
):
|
||||
if kind != "template":
|
||||
if kind not in ("template", "feature", "view"):
|
||||
raise HTTPException(422, "当前素材类型尚未开放")
|
||||
async with request.app.state.sessions() as db:
|
||||
return await Assets(db).list(kind, q, limit, offset)
|
||||
@@ -43,7 +47,7 @@ async def assets(
|
||||
|
||||
@router.post("/assets", status_code=201)
|
||||
async def save_asset(body: AssetWrite, request: Request):
|
||||
if body.kind != "template":
|
||||
if body.kind not in ("template", "feature", "view"):
|
||||
raise HTTPException(422, "当前素材类型尚未开放")
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Assets(db).save(body)
|
||||
@@ -57,7 +61,7 @@ async def asset(asset_id: str, request: Request, version: int | None = Query(Non
|
||||
|
||||
@router.put("/assets/{asset_id}")
|
||||
async def update_asset(asset_id: str, body: AssetWrite, request: Request):
|
||||
if body.kind != "template":
|
||||
if body.kind not in ("template", "feature", "view"):
|
||||
raise HTTPException(422, "当前素材类型尚未开放")
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Assets(db).save(body, asset_id)
|
||||
@@ -89,14 +93,17 @@ async def import_commit(body: ImportCommit, request: Request):
|
||||
|
||||
@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)
|
||||
result, evidence = await request_model(request.app.state.ai, context, OUTPUTS[body.method])
|
||||
if body.method == "feature" and set(result.input_ids) != set(body.input_ids):
|
||||
raise HTTPException(422, "模型不能改变已固定的输入范围")
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
asset = await Assets(db).save(
|
||||
AssetWrite(kind="template", content=result.model_dump(mode="json")),
|
||||
AssetWrite(
|
||||
kind="feature" if body.method == "feature" else "template",
|
||||
content=result.model_dump(mode="json"),
|
||||
),
|
||||
provenance={"generation": evidence, "context": context},
|
||||
)
|
||||
return {
|
||||
@@ -149,3 +156,72 @@ async def settings_variants(body: SettingVariants, request: Request):
|
||||
async def comparison(body: CompareInput, request: Request):
|
||||
async with request.app.state.sessions() as db:
|
||||
return await compare(db, body.alpha_ids)
|
||||
|
||||
|
||||
@router.post("/features/{asset_id}/template", status_code=201)
|
||||
async def feature_template(asset_id: str, body: FeatureConversion, request: Request):
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Features(db).to_template(asset_id, body.version)
|
||||
|
||||
|
||||
@router.post("/evaluations", status_code=201)
|
||||
async def evaluate(body: EvaluateInput, request: Request):
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Evaluations(db).create(body)
|
||||
|
||||
|
||||
@router.get("/evaluations")
|
||||
async def evaluations(
|
||||
request: Request,
|
||||
alpha_id: str | None = None,
|
||||
experiment_id: 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 Evaluations(db).list(alpha_id, experiment_id, limit, offset)
|
||||
|
||||
|
||||
@router.get("/evaluations/{evaluation_id}")
|
||||
async def evaluation(evaluation_id: str, request: Request):
|
||||
async with request.app.state.sessions() as db:
|
||||
return await Evaluations(db).get(evaluation_id)
|
||||
|
||||
|
||||
@router.post("/evaluations/{evaluation_id}/advice", status_code=201)
|
||||
async def evaluation_advice(evaluation_id: str, request: Request):
|
||||
async with request.app.state.sessions() as db:
|
||||
original = await Evaluations(db).get(evaluation_id)
|
||||
report = original["report"]
|
||||
context = {
|
||||
"evaluation_id": evaluation_id,
|
||||
"rules": report["rules"],
|
||||
"verdict": report["verdict"],
|
||||
"total_records": len(report["records"]),
|
||||
"records": [
|
||||
{
|
||||
key: row.get(key)
|
||||
for key in ("alpha_id", "client_item_id", "evidence", "missing", "failed", "verdict")
|
||||
}
|
||||
for row in report["records"][:20]
|
||||
],
|
||||
"record_limit": 20,
|
||||
}
|
||||
result, evidence = await request_model(request.app.state.ai, context, Advice)
|
||||
evidence["context"] = context
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Evaluations(db).add_advice(evaluation_id, result.model_dump(mode="json"), evidence)
|
||||
|
||||
|
||||
@router.get("/lineage")
|
||||
async def research_lineage(
|
||||
request: Request,
|
||||
alpha_id: str | None = None,
|
||||
experiment_id: str | None = None,
|
||||
limit: int = Query(25, ge=1, le=100),
|
||||
offset: int = Query(0, ge=0),
|
||||
):
|
||||
from .lineage import lineage
|
||||
|
||||
async with request.app.state.sessions() as db:
|
||||
return await lineage(db, alpha_id, experiment_id, limit, offset)
|
||||
|
||||
Reference in New Issue
Block a user