add explain module

This commit is contained in:
2026-09-06 07:38:56 +08:00
parent 7d843e8ff1
commit 701148e00e
20 changed files with 775 additions and 8 deletions

View File

@@ -27,6 +27,7 @@ from fastapi.responses import FileResponse, RedirectResponse, Response
from fastapi.staticfiles import StaticFiles
from starlette.concurrency import run_in_threadpool
from starlette.requests import ClientDisconnect
from .ai_tutor import AITutor, AITutorError
from .assessment import AssessmentService
from .auth import AuthenticatedUser
@@ -40,6 +41,8 @@ from .models import (
SentenceBoundaryAdjust,
SentenceBoundary,
SentenceBoundaryDocument,
SentenceExplanationRequest,
SentenceExplanationResponse,
SentenceTextUpdate,
UserDubShareSummary,
SsoExchangeRequest,
@@ -93,6 +96,12 @@ def create_app(
timeout_seconds=service_settings.moss_timeout_seconds,
max_new_tokens=service_settings.moss_max_new_tokens,
)
ai_tutor = AITutor(
endpoint=service_settings.ai_api_url,
api_key=service_settings.ai_api_key,
model=service_settings.ai_model,
timeout_seconds=service_settings.ai_timeout_seconds,
)
oss = oss_uploader or VolcanoOSSUploader(service_settings)
processor = VideoProcessor(service_settings, video_repository, moss, oss)
assessment_service = AssessmentService(
@@ -110,6 +119,7 @@ def create_app(
application.state.boundary_store = legacy_store
application.state.video_repository = video_repository
application.state.transcriber = moss
application.state.ai_tutor = ai_tutor
application.state.oss_uploader = oss
application.state.video_processor = processor
application.state.assessment_service = assessment_service
@@ -161,6 +171,7 @@ def create_app(
"video_count": len(videos) + legacy_store.count(),
"managed_video_count": len(videos),
"moss_configured": moss.available,
"ai_explanation_configured": application.state.ai_tutor.available,
"volcano_oss_configured": oss.enabled,
"scoring_version": "asr-fluency-v1",
}
@@ -298,6 +309,26 @@ def create_app(
raise HTTPException(status_code=404, detail="Course is not available.")
return Response(status_code=204)
@application.post(
"/api/v1/sentences/explain",
response_model=SentenceExplanationResponse,
)
def explain_sentence(
payload: SentenceExplanationRequest,
user: AuthenticatedUser = Depends(current_user),
) -> SentenceExplanationResponse:
del user
try:
explanation = application.state.ai_tutor.explain(
payload.sentence_text,
course_title=payload.course_title,
sentence_index=payload.sentence_index,
language=payload.language or "",
)
except AITutorError as exc:
raise HTTPException(status_code=503, detail=str(exc)) from exc
return SentenceExplanationResponse(explanation=explanation)
@application.delete("/api/v1/courses/{video_hash}/enroll", status_code=204)
def unenroll_course(
video_hash: str = SHA256_PATH,