精简后端功能模块并补充教学互动
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.response import ApiResponse, ok
|
||||
from app.core.user_context import UserContext, get_user_context
|
||||
from app.db.session import get_db
|
||||
from app.schemas.knowledge import KnowledgeSearchResponse
|
||||
from app.services.knowledge_service import KnowledgeService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/search", response_model=ApiResponse[KnowledgeSearchResponse])
|
||||
def search_knowledge(
|
||||
_: UserContext = Depends(get_user_context),
|
||||
db: Session = Depends(get_db),
|
||||
department_id: int = Query(...),
|
||||
training_type: str = Query(...),
|
||||
q: str = Query(default=""),
|
||||
):
|
||||
"""知识检索:按科室、训练类别和关键词检索评分参考指南。"""
|
||||
keywords = [item.strip() for item in q.split(",") if item.strip()]
|
||||
result = KnowledgeService(db).search_guidelines(department_id, training_type, keywords)
|
||||
return ok(KnowledgeSearchResponse(**result))
|
||||
@@ -1,108 +0,0 @@
|
||||
import time
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from app.agents.llm_adapter import OpenAICompatibleLLMClient
|
||||
from app.core.config import settings
|
||||
from app.core.exceptions import AppError
|
||||
from app.core.response import ApiResponse, ok
|
||||
from app.core.user_context import UserContext, get_user_context
|
||||
from app.schemas.llm import LLMTestRequest, LLMTestResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/deepseek-fast", response_model=ApiResponse[LLMTestResponse])
|
||||
async def test_deepseek_fast(
|
||||
payload: LLMTestRequest,
|
||||
_: UserContext = Depends(get_user_context),
|
||||
):
|
||||
"""Fast 模型测试:验证快速模型的非流式响应耗时。"""
|
||||
client = OpenAICompatibleLLMClient()
|
||||
response = await client.chat(
|
||||
[{"role": "user", "content": payload.message}],
|
||||
settings.llm_fast_model,
|
||||
thinking_enabled=settings.llm_fast_thinking_enabled,
|
||||
max_tokens=min(settings.llm_fast_max_tokens, 256),
|
||||
)
|
||||
return ok(
|
||||
LLMTestResponse(
|
||||
model=response.model,
|
||||
total_latency_ms=response.latency_ms,
|
||||
stream=False,
|
||||
mock_mode=client.is_mock_mode,
|
||||
fallback_used=response.model.startswith("mock-fallback"),
|
||||
thinking_enabled=settings.llm_fast_thinking_enabled,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.post("/deepseek-reason", response_model=ApiResponse[LLMTestResponse])
|
||||
async def test_deepseek_reason(
|
||||
payload: LLMTestRequest,
|
||||
_: UserContext = Depends(get_user_context),
|
||||
):
|
||||
"""Reason 模型测试:优先验证流式耗时,流式不兼容时降级为真实非流式测试。"""
|
||||
client = OpenAICompatibleLLMClient()
|
||||
messages = [{"role": "user", "content": payload.message}]
|
||||
first_token_ms = None
|
||||
start = time.perf_counter()
|
||||
|
||||
try:
|
||||
async for chunk in client.stream_chat(
|
||||
messages,
|
||||
settings.llm_reason_model,
|
||||
thinking_enabled=settings.llm_reason_thinking_enabled,
|
||||
reasoning_effort=settings.llm_reasoning_effort if settings.llm_reason_thinking_enabled else None,
|
||||
max_tokens=min(settings.llm_fast_max_tokens, 256),
|
||||
):
|
||||
if first_token_ms is None and chunk.first_token_ms is not None:
|
||||
first_token_ms = chunk.first_token_ms
|
||||
if chunk.done:
|
||||
return ok(
|
||||
LLMTestResponse(
|
||||
model=chunk.model or (settings.llm_reason_model if not client.is_mock_mode else f"mock-{settings.llm_reason_model}"),
|
||||
first_token_ms=first_token_ms,
|
||||
total_latency_ms=chunk.total_latency_ms or int((time.perf_counter() - start) * 1000),
|
||||
stream=True,
|
||||
mock_mode=client.is_mock_mode,
|
||||
fallback_used=chunk.fallback_used,
|
||||
thinking_enabled=settings.llm_reason_thinking_enabled,
|
||||
reasoning_effort=settings.llm_reasoning_effort if settings.llm_reason_thinking_enabled else None,
|
||||
)
|
||||
)
|
||||
except AppError as exc:
|
||||
if exc.code != "LLM_STREAM_FAILED":
|
||||
raise
|
||||
response = await client.chat(
|
||||
messages,
|
||||
settings.llm_reason_model,
|
||||
thinking_enabled=settings.llm_reason_thinking_enabled,
|
||||
reasoning_effort=settings.llm_reasoning_effort if settings.llm_reason_thinking_enabled else None,
|
||||
max_tokens=min(settings.llm_fast_max_tokens, 256),
|
||||
)
|
||||
return ok(
|
||||
LLMTestResponse(
|
||||
model=response.model,
|
||||
first_token_ms=None,
|
||||
total_latency_ms=response.latency_ms,
|
||||
stream=False,
|
||||
mock_mode=client.is_mock_mode,
|
||||
fallback_used=response.model.startswith("mock-fallback"),
|
||||
thinking_enabled=settings.llm_reason_thinking_enabled,
|
||||
reasoning_effort=settings.llm_reasoning_effort if settings.llm_reason_thinking_enabled else None,
|
||||
)
|
||||
)
|
||||
|
||||
return ok(
|
||||
LLMTestResponse(
|
||||
model=settings.llm_reason_model,
|
||||
first_token_ms=first_token_ms,
|
||||
total_latency_ms=int((time.perf_counter() - start) * 1000),
|
||||
stream=True,
|
||||
mock_mode=client.is_mock_mode,
|
||||
fallback_used=False,
|
||||
thinking_enabled=settings.llm_reason_thinking_enabled,
|
||||
reasoning_effort=settings.llm_reasoning_effort if settings.llm_reason_thinking_enabled else None,
|
||||
)
|
||||
)
|
||||
+2
-3
@@ -1,6 +1,6 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.api import agent, auth, cases, evaluations, knowledge, llm_test, sessions, training_config
|
||||
from app.api import agent, auth, cases, evaluations, sessions, teaching, training_config
|
||||
|
||||
api_router = APIRouter()
|
||||
api_router.include_router(agent.router, tags=["agent"])
|
||||
@@ -8,6 +8,5 @@ api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||
api_router.include_router(cases.router, prefix="/cases", tags=["cases"])
|
||||
api_router.include_router(training_config.router, prefix="/training-config", tags=["training-config"])
|
||||
api_router.include_router(sessions.router, prefix="/sessions", tags=["sessions"])
|
||||
api_router.include_router(teaching.router, prefix="/teaching", tags=["teaching"])
|
||||
api_router.include_router(evaluations.router, prefix="/evaluations", tags=["evaluations"])
|
||||
api_router.include_router(knowledge.router, prefix="/knowledge", tags=["knowledge"])
|
||||
api_router.include_router(llm_test.router, prefix="/llm/test", tags=["llm-test"])
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.response import ApiResponse, ok
|
||||
from app.core.user_context import UserContext, get_user_context
|
||||
from app.db.session import get_db
|
||||
from app.schemas.teaching import CreateTeachingEvaluationRequest, TeachingEvaluationResponse, TeachingItemsResponse
|
||||
from app.services.teaching_service import TeachingService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/cases/{case_id}/items", response_model=ApiResponse[TeachingItemsResponse])
|
||||
def get_teaching_items(
|
||||
case_id: int,
|
||||
ctx: UserContext = Depends(get_user_context),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""教学列表:返回病例、题目、选项、答案、解析文本和教学视频。"""
|
||||
return ok(TeachingService(db).list_items(ctx, case_id))
|
||||
|
||||
|
||||
@router.post("/evaluation", response_model=ApiResponse[TeachingEvaluationResponse])
|
||||
async def create_teaching_evaluation(
|
||||
payload: CreateTeachingEvaluationRequest,
|
||||
ctx: UserContext = Depends(get_user_context),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""教学评价:根据教学互动作答生成 AI 评价并写入训练记录。"""
|
||||
result = await TeachingService(db).create_evaluation(ctx, payload)
|
||||
db.commit()
|
||||
return ok(result)
|
||||
Reference in New Issue
Block a user