From ccdcb83b60d3faa5a12dac60554ef22e271f3edb Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 17 Jun 2026 21:14:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E7=99=BB=E8=AE=B0=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=B9=B6=E8=A7=84=E8=8C=83=E8=80=81=E5=B8=88=E5=A7=93?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/app/ai_register.py | 3 ++- app/app/config.py | 2 +- app/app/data.py | 21 +++++++++++++-------- app/docker-compose.yml | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/app/ai_register.py b/app/app/ai_register.py index e3b12a3..73b1f1a 100644 --- a/app/app/ai_register.py +++ b/app/app/ai_register.py @@ -13,6 +13,7 @@ from urllib import error, request from .config import ACCOUNTS_PATH, AI_REGISTER_MODEL, AI_REGISTER_TIMEOUT_SECONDS, CODEX_AUTH_PATH, CODEX_CONFIG_PATH from .data import ( SUBJECTS, + canonical_teacher_name, class_record_to_line, course_summary_to_class_record_line, extract_course_summary_from_text, @@ -275,7 +276,7 @@ def _extract_student(text: str) -> str: def _extract_teacher(text: str) -> str: match = TEACHER_RE.search(text) - return match.group("teacher") if match else "" + return canonical_teacher_name(match.group("teacher")) if match else "" def _extract_subject(text: str) -> str: diff --git a/app/app/config.py b/app/app/config.py index 73d47bf..5bf8928 100644 --- a/app/app/config.py +++ b/app/app/config.py @@ -18,7 +18,7 @@ OPERATION_LOGS_PATH = Path(os.getenv("OPERATION_LOGS_PATH", "/data/operation_log CODEX_CONFIG_PATH = Path(os.getenv("CODEX_CONFIG_PATH", "/run/codex/config.toml")) CODEX_AUTH_PATH = Path(os.getenv("CODEX_AUTH_PATH", "/run/codex/auth.json")) AI_REGISTER_TIMEOUT_SECONDS = float(os.getenv("AI_REGISTER_TIMEOUT_SECONDS", "8")) -AI_REGISTER_MODEL = os.getenv("AI_REGISTER_MODEL", "").strip() +AI_REGISTER_MODEL = "gpt-5.4-mini" BASIC_AUTH_PASSWORD = os.getenv("BASIC_AUTH_PASSWORD", "") ACCOUNTS_AUTH_PASSWORD = os.getenv("ACCOUNTS_AUTH_PASSWORD") or os.getenv("ACCOUNT_AUTH_PASSWORD", "") diff --git a/app/app/data.py b/app/app/data.py index b76a3e6..5c26645 100644 --- a/app/app/data.py +++ b/app/app/data.py @@ -71,6 +71,11 @@ def canonical_name(name: str) -> str: return FALLBACK_ALIASES.get(text, text) +def canonical_teacher_name(name: str) -> str: + text = canonical_name(name).strip() + return re.sub(r"(?:老师|教师)$", "", text).strip() + + def parse_hours_text(text: str) -> float: match = re.fullmatch(r"(\d+)小时(\d+)分", text.strip()) if not match: @@ -189,7 +194,7 @@ def read_classnotes(path: Path) -> list[ClassRecord]: student=canonical_name(match.group("student")), duration=duration_text_from_minutes(true_minutes), duration_hours=round(true_minutes / 60.0, 2), - teacher=match.group("teacher").strip(), + teacher=canonical_teacher_name(match.group("teacher")), subject=match.group("subject").strip(), ) ) @@ -256,7 +261,7 @@ def read_teachers(path: Path) -> list[Teacher]: validate_teacher( Teacher( teacher_id=teacher_id, - name=canonical_name(name), + name=canonical_teacher_name(name), alias=alias.strip(), subjects=parse_teacher_subjects(subjects), status=status, @@ -287,7 +292,7 @@ def parse_class_record_line(line: str) -> ClassRecord: raise ValueError(f"上课记录时长与时间段不一致: {line}") student = canonical_name(match.group("student")) - teacher = match.group("teacher").strip() + teacher = canonical_teacher_name(match.group("teacher")) subject = match.group("subject").strip() if not student or not teacher or not subject: raise ValueError(f"上课记录学生、老师、科目不能为空: {line}") @@ -1466,7 +1471,7 @@ def extract_course_summary_from_text(text: str, index: int = 0, known_students: def normalize_course_summary(raw: dict) -> dict: student = canonical_name(str(raw.get("student") or "").strip()) - teacher = canonical_name(str(raw.get("teacher") or "").strip()) + teacher = canonical_teacher_name(str(raw.get("teacher") or "").strip()) subject = parse_subject_code(str(raw.get("subject") or "").strip()) body = str(raw.get("body") or raw.get("content") or "").strip() if not student: @@ -1901,7 +1906,7 @@ def parse_course_summary_file_identity(root: Path, path: Path) -> dict: subject = "" if len(parts) >= 3: student = canonical_name(parts[0]) - teacher = canonical_name("_".join(parts[1:-1])) + teacher = canonical_teacher_name("_".join(parts[1:-1])) subject = parts[-1] return { "student": student, @@ -2037,7 +2042,7 @@ def course_summary_matched_fields(item: dict, q: str) -> list[str]: def course_summary_record_key(student: str, teacher: str, subject: str, date_iso: str, time_range: str) -> tuple[str, str, str, str, str]: return ( canonical_name(student.strip()), - canonical_name(teacher.strip()), + canonical_teacher_name(teacher.strip()), normalize_subject(subject.strip()), date_iso.strip(), normalize_time_range_text(time_range) if time_range else "", @@ -2210,7 +2215,7 @@ def query_course_summaries( item, keyword, canonical_name(student.strip()), - canonical_name(teacher.strip()), + canonical_teacher_name(teacher.strip()), subject.strip(), normalized_from, normalized_to, @@ -2536,7 +2541,7 @@ def create_incomplete_course_summary_review_task( "time_range": str(raw.get("time_range") or raw.get("raw_time") or raw.get("time") or "").strip(), "duration_minutes": raw.get("duration_minutes"), "duration": str(raw.get("duration") or "").strip(), - "teacher": canonical_name(str(raw.get("teacher") or "").strip()), + "teacher": canonical_teacher_name(str(raw.get("teacher") or "").strip()), "subject": str(raw.get("subject") or "").strip(), "group": str(raw.get("group") or "").strip(), "sender": str(raw.get("sender") or raw.get("sender_name") or "").strip(), diff --git a/app/docker-compose.yml b/app/docker-compose.yml index e8337ad..23bac95 100644 --- a/app/docker-compose.yml +++ b/app/docker-compose.yml @@ -20,7 +20,7 @@ services: CODEX_CONFIG_PATH: ${CODEX_CONFIG_PATH:-/run/codex/config.toml} CODEX_AUTH_PATH: ${CODEX_AUTH_PATH:-/run/codex/auth.json} AI_REGISTER_TIMEOUT_SECONDS: ${AI_REGISTER_TIMEOUT_SECONDS:-8} - AI_REGISTER_MODEL: ${AI_REGISTER_MODEL:-} + AI_REGISTER_MODEL: gpt-5.4-mini INGEST_AUTH_TOKEN: ${INGEST_AUTH_TOKEN:-} ports: - "${APP_PORT:-18080}:8000"