59 lines
2.0 KiB
Python
59 lines
2.0 KiB
Python
"""STEP 05 — Entity Aligner (实体归一) endpoints."""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
from app.auth import CurrentUser
|
|
from app.config import settings
|
|
from app.contracts import AlignSuggestRequest, MergeEntities
|
|
from app.db import get_candidate_entity
|
|
from app.agents.aligner import align_candidates
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/aligner/suggest")
|
|
async def _suggest(body: AlignSuggestRequest, _user: CurrentUser = None):
|
|
"""Given candidate IDs, run the aligner agent to suggest merges."""
|
|
candidates = []
|
|
for cid in body.candidate_ids:
|
|
c = await get_candidate_entity(cid)
|
|
if c:
|
|
candidates.append(c)
|
|
|
|
if not candidates:
|
|
raise HTTPException(404, "No candidates found")
|
|
|
|
results = await align_candidates(candidates)
|
|
return {"suggestions": results}
|
|
|
|
|
|
@router.post("/aligner/auto-merge")
|
|
async def _auto_merge(body: AlignSuggestRequest, user: CurrentUser):
|
|
"""Run aligner and auto-merge high-confidence matches."""
|
|
from app.db import update_candidate_entity, create_review_action
|
|
|
|
candidates = []
|
|
for cid in body.candidate_ids:
|
|
c = await get_candidate_entity(cid)
|
|
if c:
|
|
candidates.append(c)
|
|
|
|
results = await align_candidates(candidates)
|
|
|
|
merged = 0
|
|
for r in results:
|
|
if r.get("action") == "merge" and r.get("confidence", 0) >= 0.95:
|
|
cid = r["candidate_id"]
|
|
target = r.get("target_entity_id")
|
|
if target:
|
|
await update_candidate_entity(cid, {"status": "merged"})
|
|
await create_review_action({
|
|
"candidate_id": cid,
|
|
"candidate_type": "entity",
|
|
"action": "merged",
|
|
"actor": user["username"],
|
|
"note": f"Auto-merged into {target} by aligner (confidence={r['confidence']:.2f})",
|
|
})
|
|
merged += 1
|
|
|
|
return {"total": len(results), "auto_merged": merged, "suggestions": results}
|