refactor: unify data preparations and research input snapshots
Deploy production / deploy (push) Successful in 53s
Deploy production / deploy (push) Successful in 53s
This commit is contained in:
@@ -5,12 +5,9 @@ not FASTEXPR operator semantics or the account's current platform permissions.
|
||||
"""
|
||||
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import select
|
||||
|
||||
from ..backtests.contracts import Candidate, DraftInput, PreviewInput, Source
|
||||
from ..catalog.contracts import EntryOutput, InputPreparation
|
||||
from ..catalog.service import Catalog
|
||||
from ..models import CatalogEntry
|
||||
from .expressions import analyze, expand
|
||||
|
||||
|
||||
@@ -21,55 +18,18 @@ class ResearchBuilder:
|
||||
self.backtests = backtests
|
||||
|
||||
async def select_input(self, body):
|
||||
"""Fix explicit fields in one published version; reject missing or stale members."""
|
||||
collection = await self.catalog.collection(body.scope, body.dataset_id)
|
||||
chosen = set(body.field_ids)
|
||||
if len(chosen) != len(body.field_ids) or not chosen.issubset(collection["field_ids"]):
|
||||
raise HTTPException(422, "字段选择含重复、未知或其他数据集字段")
|
||||
saved = await self.catalog.prepare(
|
||||
InputPreparation(
|
||||
scope=body.scope,
|
||||
dataset_id=body.dataset_id,
|
||||
collection_version=body.collection_version,
|
||||
selection="explicit",
|
||||
excluded_ids=[field for field in collection["field_ids"] if field not in chosen],
|
||||
)
|
||||
)
|
||||
from ..preparations.service import Preparations
|
||||
saved = (await Preparations(self.db).freeze(body.items))[0]
|
||||
return await self.input_page(saved["id"])
|
||||
|
||||
async def input_page(self, input_id, limit=25, offset=0, q="", field_type=None):
|
||||
"""Read the saved version, including field descriptions, with explicit pagination."""
|
||||
saved = await self.catalog.input(input_id)
|
||||
ids = [
|
||||
field
|
||||
for field in saved["field_ids"]
|
||||
if q.lower() in field.lower()
|
||||
and (field_type is None or saved["field_types"].get(field) == field_type)
|
||||
]
|
||||
page = ids[offset : offset + limit]
|
||||
entries = {
|
||||
row.id: row
|
||||
for row in await self.db.scalars(
|
||||
select(CatalogEntry).where(
|
||||
CatalogEntry.batch_id == saved["collection_version"], CatalogEntry.id.in_(page)
|
||||
)
|
||||
)
|
||||
}
|
||||
return {
|
||||
**{
|
||||
k: saved[k]
|
||||
for k in ("id", "scope", "dataset_id", "collection_version", "selection", "created_at")
|
||||
},
|
||||
"field_count": len(saved["field_ids"]),
|
||||
"items": [
|
||||
EntryOutput.model_validate(entries[field], from_attributes=True).model_dump()
|
||||
for field in page
|
||||
],
|
||||
"total": len(ids),
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
"has_more": offset + limit < len(ids),
|
||||
}
|
||||
fields = [f for f in saved["fields"] if (not q or q.lower() in
|
||||
" ".join(str(f.get(k) or "") for k in ("id", "name", "description", "dataset_id")).lower())
|
||||
and (not field_type or f["field_type"] == field_type)]
|
||||
return {**{k: v for k, v in saved.items() if k not in ("fields", "field_ids", "field_types")},
|
||||
"field_count": len(saved["fields"]), "items": fields[offset:offset + limit],
|
||||
"total": len(fields), "limit": limit, "offset": offset, "has_more": offset + limit < len(fields)}
|
||||
|
||||
async def prepare(self, body):
|
||||
"""Bind templates against an immutable input, then reuse the fixed-preview interface.
|
||||
@@ -77,7 +37,7 @@ class ResearchBuilder:
|
||||
Raises HTTPException(422) for wrong scope, membership or declared type.
|
||||
No expression execution or implicit cleaning/aggregation takes place here.
|
||||
"""
|
||||
saved = await self.catalog.input(body.template_input_id)
|
||||
saved = await self.catalog.input(body.input_snapshot_id)
|
||||
scope = saved["scope"]
|
||||
candidates = []
|
||||
for item in body.candidates:
|
||||
@@ -114,7 +74,7 @@ class ResearchBuilder:
|
||||
source = Source.model_validate(
|
||||
{
|
||||
**body.source.model_dump(),
|
||||
"template_input_id": saved["id"],
|
||||
"input_snapshot_id": saved["id"],
|
||||
"hypothesis": body.hypothesis,
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user