119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
"""Signal feedback endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.future import select
|
|
|
|
from ...core.response import success_response
|
|
from ...core.database import get_db
|
|
from ...dependencies.auth import get_current_user
|
|
from ...dependencies.tenant import get_tenant_id
|
|
from ...models import Signal, SignalFeedback, User
|
|
from ...schemas import SignalFeedbackCreate, SignalFeedbackResponse
|
|
from ...services.feedback_center import FeedbackCenterService
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/{signal_id}/feedback")
|
|
async def submit_signal_feedback(
|
|
signal_id: int,
|
|
feedback: SignalFeedbackCreate,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
"""提交信号反馈"""
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
result = await db.execute(
|
|
select(Signal).where(
|
|
Signal.id == signal_id,
|
|
Signal.tenant_id == effective_tenant_id,
|
|
)
|
|
)
|
|
signal = result.scalar_one_or_none()
|
|
if not signal:
|
|
raise HTTPException(status_code=404, detail="Signal not found")
|
|
|
|
ai_predicted_strategic = False
|
|
ai_confidence = 0.0
|
|
if signal.strategic_analysis:
|
|
try:
|
|
analysis = json.loads(signal.strategic_analysis)
|
|
ai_predicted_strategic = analysis.get("is_strategic", signal.impact_score >= 0.9)
|
|
ai_confidence = analysis.get("confidence", 0.0)
|
|
except Exception:
|
|
ai_predicted_strategic = signal.impact_score >= 0.9
|
|
|
|
new_feedback = SignalFeedback(
|
|
tenant_id=effective_tenant_id,
|
|
signal_id=signal_id,
|
|
was_strategic=feedback.was_strategic,
|
|
reason=feedback.reason,
|
|
user_id=str(getattr(current_user, "id", feedback.user_id) or feedback.user_id or ""),
|
|
ai_predicted_strategic=ai_predicted_strategic,
|
|
ai_confidence=ai_confidence,
|
|
)
|
|
db.add(new_feedback)
|
|
await db.commit()
|
|
await db.refresh(new_feedback)
|
|
|
|
try:
|
|
await FeedbackCenterService(db).ingest_signal_feedback(
|
|
signal_feedback=new_feedback,
|
|
signal=signal,
|
|
commit=True,
|
|
)
|
|
except Exception:
|
|
await db.rollback()
|
|
|
|
is_correct = ai_predicted_strategic == feedback.was_strategic
|
|
|
|
return success_response(
|
|
SignalFeedbackResponse(
|
|
id=new_feedback.id,
|
|
signal_id=new_feedback.signal_id,
|
|
was_strategic=new_feedback.was_strategic,
|
|
ai_predicted_strategic=new_feedback.ai_predicted_strategic,
|
|
ai_confidence=new_feedback.ai_confidence or 0.0,
|
|
is_correct=is_correct,
|
|
).model_dump()
|
|
)
|
|
|
|
@router.get("/{signal_id}/feedbacks")
|
|
async def get_signal_feedbacks(
|
|
signal_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
"""获取某信号的全部反馈"""
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
result = await db.execute(
|
|
select(SignalFeedback)
|
|
.where(
|
|
SignalFeedback.signal_id == signal_id,
|
|
SignalFeedback.tenant_id == effective_tenant_id,
|
|
)
|
|
.order_by(SignalFeedback.created_at.desc())
|
|
)
|
|
feedbacks = result.scalars().all()
|
|
|
|
items = [
|
|
SignalFeedbackResponse(
|
|
id=feedback.id,
|
|
signal_id=feedback.signal_id,
|
|
was_strategic=feedback.was_strategic,
|
|
ai_predicted_strategic=feedback.ai_predicted_strategic,
|
|
ai_confidence=feedback.ai_confidence or 0.0,
|
|
is_correct=feedback.ai_predicted_strategic == feedback.was_strategic,
|
|
).model_dump()
|
|
for feedback in feedbacks
|
|
]
|
|
return success_response({"items": items})
|