| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- """五维自检题目生成 API
- 提供基于用户画路径的智能题目生成服务,包含:
- - AI生成 20 道情境化问卷题目
- - 支持自定义维度分配
- - 支持历史记题目去重
- - 与现有 15 题固定题库并存"""
- import logging
- from fastapi import APIRouter
- from pydantic import BaseModel
- from typing import Any, Dict, List, Optional
- from app.graphs.question_generation_graph import run_question_gen
- logger = logging.getLogger(__name__)
- router = APIRouter(prefix="/api/v1", tags=["question-generate"])
- class QuestionGenRequest(BaseModel):
- """题目生成请求"""
- user_id: int
- count: int = 20 # 题目总数,默认20(满足系统≥10题门槛)
- difficulty: str = "balanced" # balanced/easy/hard/contextual
- dimensions: Optional[List[str]] = None # 可选指定维度,如 ["body", "wisdom"]
- exclude_ids: Optional[List[int]] = None # 历史题目ID列表,用于避免重复
- class QuestionGenResponse(BaseModel):
- """题目生成响应"""
- questions: List[Dict[str, Any]]
- total_generated: int
- generation_time: float
- rationale: str
- dimension_distribution: Dict[str, int]
- fallback_used: bool
- @router.post("/question-generate", response_model=QuestionGenResponse)
- async def question_generate(req: QuestionGenRequest):
- """AI生成五维自检题目
-
- 根据用户画像生成 20 道情境化问卷题目,满足系统最低门槛:
- - 总题数≥10
- - 每个维度至少 1 题
-
- 请求体:
- - user_id: 必填,用户 ID
- - count: 可选,题目总数,默认 20
- - difficulty: 可选,难度提示,默认 "balanced"
- - dimensions: 可选,指定维度列表,如 ["body", "wisdom"]
- - exclude_ids: 可选,历史题目 ID 列表,用于避免重复提问
-
- 响应体:
- - questions: 生成的题目列表,每题包含 id, dimension, text, options
- - total_generated: 实际生成数量
- - generation_time: 生成耗时(秒)
- - rationale: 生成 rationale,解释维度选择逻辑
- - dimension_distribution: 各维度题目数量分布
- - fallback_used: 是否使用了降级方案(LLM失败回退到本地题库)
- """
- try:
- result = await run_question_gen(
- user_id=user_id,
- count=req.count,
- difficulty=req.difficulty,
- dimensions=req.dimensions,
- exclude_ids=req.exclude_ids,
- )
-
- return QuestionGenResponse(
- questions=result.get("questions", []),
- total_generated=result.get("total_generated", 0),
- generation_time=result.get("generation_time", 0.0),
- rationale=result.get("rationale", ""),
- dimension_distribution=result.get("dimension_distribution", {}),
- fallback_used=result.get("fallback_used", False),
- )
-
- except Exception as e:
- logger.error(f"AI 生成题目失败: {e}", exc_info=True)
- # 降级:返回空结果,前端可据此提示用户或使用固定题库
- return QuestionGenResponse(
- questions=[],
- total_generated=0,
- generation_time=0.0,
- rationale=f"生成失败: {str(e)},将使用固定题库",
- dimension_distribution={},
- fallback_used=True,
- )
|