ChoTensai_V3 / src /models /gemini_schemas.py
TOMOCHIN4
refactor: correct_answer を 0-indexed に統一・temperature=1.0
27a3ba5
"""
Gemini Structured Output Schemas
Pydanticモデルを使用してGeminiのJSON出力スキーマを定義。
response_json_schemaパラメータで使用することで、構造化出力を保証する。
"""
from typing import List, Optional, Literal, Dict, Any
from pydantic import BaseModel, Field
# =============================================================================
# Helper Functions (スキーマ生成ヘルパー)
# =============================================================================
def get_list_schema(item_schema: type) -> Dict[str, Any]:
"""
Pydanticモデルのリストスキーマを生成
Args:
item_schema: リスト要素のPydanticモデルクラス
Returns:
JSON Schema (配列型)
"""
item_json_schema = item_schema.model_json_schema()
# $defsを展開してフラット化
defs = item_json_schema.pop("$defs", {})
return {
"type": "array",
"items": item_json_schema,
"$defs": defs
}
# =============================================================================
# Summary Schema (サマリー生成用)
# =============================================================================
class SummarySchema(BaseModel):
"""問題群のサマリー生成スキーマ"""
keywords: List[str] = Field(
description="問題の具体的なキーワード(答え、題材)のリスト"
)
topics: List[str] = Field(
description="問題タイプ + 具体的な題材を組み合わせたトピックのリスト"
)
summary: str = Field(
description="問題群の概要(50文字以内)"
)
# =============================================================================
# Question Schema (問題生成用)
# =============================================================================
class QuestionSchema(BaseModel):
"""生成される問題のスキーマ"""
subject: str = Field(
description="教科コード (jp, math, sci, soc)"
)
category: str = Field(
description="カテゴリコード (例: JP01, MA05)"
)
difficulty: Literal["easy", "medium", "hard"] = Field(
description="難易度"
)
question: str = Field(
description="問題文"
)
choices: List[str] = Field(
description="選択肢のリスト(4つ)",
min_length=4,
max_length=4
)
correct_answer: int = Field(
description="正解の選択肢インデックス(0-3)",
ge=0,
le=3
)
explanation: str = Field(
description="解説文"
)
# QuestionsListSchemaはget_list_schema(QuestionSchema)で代替
# =============================================================================
# Evaluation Schema (評価生成用)
# =============================================================================
class SubjectEvaluationSchema(BaseModel):
"""教科別評価スキーマ"""
advice: str = Field(
description="教科別アドバイス(2-3文)"
)
strengths: List[str] = Field(
description="強み・得意分野のリスト",
min_length=1,
max_length=5
)
weaknesses: List[str] = Field(
description="改善点・苦手分野のリスト",
min_length=1,
max_length=5
)
recommended_topics: List[str] = Field(
description="おすすめの学習トピックのリスト",
min_length=1,
max_length=5
)
class OverallEvaluationSchema(BaseModel):
"""全体評価スキーマ"""
overall_advice: str = Field(
description="全体的なアドバイス(2-3文)"
)
strengths: List[str] = Field(
description="教科横断的な強みのリスト"
)
weaknesses: List[str] = Field(
description="教科横断的な改善点のリスト"
)
next_steps: List[str] = Field(
description="次のステップのリスト"
)
balance_comment: str = Field(
description="教科バランスと全体的な傾向についてのコメント"
)
class BatchEvaluationSchema(BaseModel):
"""複数教科一括評価スキーマ"""
subject_evaluations: Dict[str, SubjectEvaluationSchema] = Field(
description="教科別評価 {subject_code: SubjectEvaluationSchema}"
)
overall_evaluation: OverallEvaluationSchema = Field(
description="全体評価"
)
# =============================================================================
# Validation Schema (検証用)
# =============================================================================
class ValidationResultSchema(BaseModel):
"""問題検証結果スキーマ"""
subject: str = Field(
description="教科コード"
)
index: int = Field(
description="問題のインデックス"
)
modified: bool = Field(
description="修正されたかどうか"
)
modification_reason: Optional[str] = Field(
default=None,
description="修正理由(修正された場合のみ)"
)
question: QuestionSchema = Field(
description="検証後の問題(修正された場合は修正後)"
)
# ValidationResultsListSchemaはget_list_schema(ValidationResultSchema)で代替