Initial MVP for QA asset backend
This commit is contained in:
43
hy_qa_asset_backend/backend/app/utils/json_validator.py
Normal file
43
hy_qa_asset_backend/backend/app/utils/json_validator.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
REQUIRED_QA_FIELDS = {
|
||||
"session_id",
|
||||
"qa_id",
|
||||
"raw_question",
|
||||
"normalized_question",
|
||||
"raw_answer",
|
||||
"normalized_answer",
|
||||
"suggested_standard_question",
|
||||
"suggested_standard_answer",
|
||||
"answer_person",
|
||||
"primary_topic",
|
||||
"problem_tags",
|
||||
"course_stage",
|
||||
"audience_tags",
|
||||
"emotion_intensity",
|
||||
"risk_level",
|
||||
"risk_types",
|
||||
"risk_notes",
|
||||
"need_desensitization",
|
||||
"desensitization_status",
|
||||
"suggested_review_status",
|
||||
"suggested_to_standard_qa",
|
||||
"source_timestamp",
|
||||
"review_notes",
|
||||
}
|
||||
|
||||
|
||||
def validate_ai_qa_items(payload: Any) -> list[dict[str, Any]]:
|
||||
if not isinstance(payload, list):
|
||||
raise ValueError("AI 返回必须是 JSON 数组")
|
||||
valid_items: list[dict[str, Any]] = []
|
||||
for index, item in enumerate(payload, start=1):
|
||||
if not isinstance(item, dict):
|
||||
raise ValueError(f"第 {index} 条 AI 结果不是对象")
|
||||
missing = REQUIRED_QA_FIELDS.difference(item)
|
||||
if missing:
|
||||
raise ValueError(f"第 {index} 条 AI 结果缺少字段: {', '.join(sorted(missing))}")
|
||||
valid_items.append(item)
|
||||
return valid_items
|
||||
|
||||
6
hy_qa_asset_backend/backend/app/utils/text_reader.py
Normal file
6
hy_qa_asset_backend/backend/app/utils/text_reader.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def read_text_file(path: str | Path) -> str:
|
||||
return Path(path).read_text(encoding="utf-8")
|
||||
|
||||
20
hy_qa_asset_backend/backend/app/utils/time_utils.py
Normal file
20
hy_qa_asset_backend/backend/app/utils/time_utils.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def utc_now() -> datetime:
|
||||
return datetime.now(timezone.utc)
|
||||
|
||||
|
||||
def split_cron(cron: str) -> dict[str, str]:
|
||||
parts = cron.split()
|
||||
if len(parts) != 5:
|
||||
raise ValueError("SCHEDULE_CRON 需要使用 5 段 cron 表达式,例如 0 1 * * *")
|
||||
minute, hour, day, month, day_of_week = parts
|
||||
return {
|
||||
"minute": minute,
|
||||
"hour": hour,
|
||||
"day": day,
|
||||
"month": month,
|
||||
"day_of_week": day_of_week,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user