finalize medical consultation agent backend
This commit is contained in:
@@ -6,8 +6,8 @@ from app.models.knowledge import KnowledgeChunk, KnowledgeDocument, KnowledgeSou
|
||||
from app.models.prompt import PromptTemplate
|
||||
from app.models.source_case import CaseBase, CaseExamItem, ScoringRule, TeachingCase, TraditionalCase
|
||||
from app.models.training import SessionOrder, SessionSubmission, TrainingSession
|
||||
from app.models.training_record import TrainingRecord
|
||||
from app.models.user import User, UserLearningProfile
|
||||
from app.models.training_record import TrainingRecord, TrainingScoreDetail
|
||||
from app.models.user import User
|
||||
|
||||
__all__ = [
|
||||
"AuditLog",
|
||||
@@ -25,6 +25,6 @@ __all__ = [
|
||||
"SessionSubmission",
|
||||
"TrainingSession",
|
||||
"TrainingRecord",
|
||||
"TrainingScoreDetail",
|
||||
"User",
|
||||
"UserLearningProfile",
|
||||
]
|
||||
|
||||
@@ -12,7 +12,7 @@ class AuditLog(Base):
|
||||
__tablename__ = "audit_logs"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[str | None] = mapped_column(String(128), index=True)
|
||||
user_id: Mapped[str | None] = mapped_column(String(128), index=True, comment="Django用户中心ID")
|
||||
tenant_id: Mapped[str | None] = mapped_column(String(128))
|
||||
session_id: Mapped[int | None] = mapped_column(Integer, index=True)
|
||||
action: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import Boolean, ForeignKey, Integer, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy import BigInteger, Integer, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db.base import Base
|
||||
from app.models.mixins import TimestampMixin
|
||||
|
||||
BIGINT_PK = BigInteger().with_variant(Integer, "sqlite")
|
||||
|
||||
|
||||
class Department(TimestampMixin, Base):
|
||||
"""科室模型:维护病例、知识库和评分规则的科室分类。"""
|
||||
"""科室模型:使用用户端确定的 department 表字段。"""
|
||||
|
||||
__tablename__ = "departments"
|
||||
__tablename__ = "department"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
||||
code: Mapped[str] = mapped_column(String(50), nullable=False, unique=True, index=True)
|
||||
parent_id: Mapped[int | None] = mapped_column(ForeignKey("departments.id"), nullable=True)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="科室ID")
|
||||
name: Mapped[str] = mapped_column(String(100), nullable=False, comment="科室名称")
|
||||
category: Mapped[str] = mapped_column(String(50), nullable=False, comment="科室分类")
|
||||
institution_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True, comment="所属机构ID")
|
||||
|
||||
parent: Mapped["Department | None"] = relationship(remote_side=[id])
|
||||
__table_args__ = {"comment": "科室表"}
|
||||
|
||||
@@ -29,7 +29,7 @@ class KnowledgeDocument(TimestampMixin, Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
source_id: Mapped[int] = mapped_column(ForeignKey("knowledge_sources.id"), nullable=False, index=True)
|
||||
department_id: Mapped[int | None] = mapped_column(ForeignKey("departments.id"), nullable=True, index=True)
|
||||
department_id: Mapped[int | None] = mapped_column(ForeignKey("department.id"), nullable=True, index=True)
|
||||
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
task_type: Mapped[str | None] = mapped_column(String(64), index=True)
|
||||
summary: Mapped[str | None] = mapped_column(Text)
|
||||
@@ -46,7 +46,7 @@ class KnowledgeChunk(Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
document_id: Mapped[int] = mapped_column(ForeignKey("knowledge_documents.id"), nullable=False, index=True)
|
||||
department_id: Mapped[int | None] = mapped_column(ForeignKey("departments.id"), nullable=True, index=True)
|
||||
department_id: Mapped[int | None] = mapped_column(ForeignKey("department.id"), nullable=True, index=True)
|
||||
task_type: Mapped[str | None] = mapped_column(String(64), index=True)
|
||||
chunk_text: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
keywords: Mapped[list | None] = mapped_column(JSON)
|
||||
|
||||
@@ -10,13 +10,13 @@ BIGINT_PK = BigInteger().with_variant(Integer, "sqlite")
|
||||
|
||||
|
||||
class TrainingSession(TimestampMixin, Base):
|
||||
"""训练会话表:保存一次训练的运行状态、用户隔离信息和短期 memory key。"""
|
||||
"""训练会话表:保存一次训练的运行状态、Django 用户隔离信息和短期 memory key。"""
|
||||
|
||||
__tablename__ = "training_session"
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="训练会话ID")
|
||||
session_code: Mapped[str] = mapped_column(String(64), nullable=False, unique=True, index=True, comment="会话编码")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="宿主系统用户ID")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
|
||||
tenant_id: Mapped[str | None] = mapped_column(String(128), comment="租户或项目ID")
|
||||
class_id: Mapped[str | None] = mapped_column(String(128), comment="班级或课程ID")
|
||||
entry_scene: Mapped[str | None] = mapped_column(String(64), comment="入口场景")
|
||||
@@ -45,7 +45,7 @@ class SessionOrder(Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="检查申请ID")
|
||||
session_id: Mapped[int] = mapped_column(ForeignKey("training_session.id"), nullable=False, index=True, comment="训练会话ID")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="宿主系统用户ID")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
|
||||
case_id: Mapped[int] = mapped_column(ForeignKey("case_base.id"), nullable=False, index=True, comment="病例ID")
|
||||
case_exam_item_id: Mapped[int] = mapped_column("exam_item_id", ForeignKey("case_exam_item.id"), nullable=False, comment="检查项目ID")
|
||||
item_code: Mapped[str] = mapped_column(String(64), nullable=False, comment="项目编码")
|
||||
@@ -74,7 +74,7 @@ class SessionSubmission(TimestampMixin, Base):
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="提交记录ID")
|
||||
session_id: Mapped[int] = mapped_column(ForeignKey("training_session.id"), nullable=False, unique=True, comment="训练会话ID")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="宿主系统用户ID")
|
||||
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
|
||||
primary_diagnosis: Mapped[str | None] = mapped_column(Text, comment="主要诊断")
|
||||
differential_diagnoses: Mapped[list | None] = mapped_column(JSON, comment="鉴别诊断")
|
||||
diagnosis_basis: Mapped[str | None] = mapped_column(Text, comment="诊断依据")
|
||||
|
||||
@@ -3,8 +3,8 @@ from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import BigInteger, DateTime, Integer, JSON, Numeric, String, Text, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, JSON, Numeric, String, Text, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.db.base import Base
|
||||
from app.models.mixins import TimestampMixin
|
||||
@@ -42,8 +42,8 @@ class TrainingRecord(TimestampMixin, Base):
|
||||
rag_context_version: Mapped[str] = mapped_column(String(50), nullable=False, default="none", comment="RAG上下文版本")
|
||||
case_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True, comment="病例ID")
|
||||
teacher_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="教师ID")
|
||||
user_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="数字用户ID")
|
||||
external_user_id: Mapped[str] = mapped_column(String(128), nullable=False, index=True, comment="宿主系统用户ID")
|
||||
user_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="Django用户中心数字ID")
|
||||
external_user_id: Mapped[str] = mapped_column(String(128), nullable=False, index=True, comment="Django用户中心ID")
|
||||
session_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="训练会话ID")
|
||||
evaluation_record_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="兼容旧评价记录ID")
|
||||
score_type: Mapped[str] = mapped_column(String(20), nullable=False, default="percentage", comment="分数类型")
|
||||
@@ -53,3 +53,25 @@ class TrainingRecord(TimestampMixin, Base):
|
||||
UniqueConstraint("session_id", name="uk_training_record_session"),
|
||||
{"comment": "训练记录表"},
|
||||
)
|
||||
|
||||
score_details = relationship("TrainingScoreDetail", back_populates="record", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class TrainingScoreDetail(TimestampMixin, Base):
|
||||
"""评分明细表:保存每条 scoring_rule 对应的 AI 评分、扣分原因、证据和置信度。"""
|
||||
|
||||
__tablename__ = "training_score_detail"
|
||||
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="评分明细ID")
|
||||
record_id: Mapped[int] = mapped_column(ForeignKey("training_record.id"), nullable=False, index=True, comment="训练记录ID")
|
||||
rule_id: Mapped[int | None] = mapped_column(ForeignKey("scoring_rule.id"), nullable=True, index=True, comment="评分规则ID")
|
||||
dimension: Mapped[str] = mapped_column(String(50), nullable=False, index=True, comment="评分维度")
|
||||
score: Mapped[Decimal] = mapped_column(Numeric(5, 2), nullable=False, default=0, comment="分数")
|
||||
deducted_reason: Mapped[str | None] = mapped_column(Text, comment="扣分原因")
|
||||
evidence_message_ids: Mapped[list] = mapped_column(JSON, nullable=False, default=list, comment="对应对话证据")
|
||||
ai_confidence: Mapped[Decimal | None] = mapped_column(Numeric(5, 2), comment="AI评分置信度")
|
||||
comment: Mapped[str | None] = mapped_column(Text, comment="评语")
|
||||
|
||||
record = relationship("TrainingRecord", back_populates="score_details")
|
||||
|
||||
__table_args__ = {"comment": "评分明细表"}
|
||||
|
||||
+34
-21
@@ -1,33 +1,46 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, Integer, JSON, Numeric, String
|
||||
from sqlalchemy import BigInteger, Boolean, DateTime, Integer, JSON, SmallInteger, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db.base import Base
|
||||
from app.models.mixins import TimestampMixin
|
||||
|
||||
BIGINT_PK = BigInteger().with_variant(Integer, "sqlite")
|
||||
|
||||
|
||||
class User(TimestampMixin, Base):
|
||||
"""宿主用户引用:保存外部 user_id,不承担登录注册职责。"""
|
||||
"""用户端用户表:按 Django 用户中心确定字段建模,只读取不承担登录注册职责。"""
|
||||
|
||||
__tablename__ = "users"
|
||||
__tablename__ = "user"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
external_user_id: Mapped[str] = mapped_column(String(128), nullable=False, unique=True, index=True)
|
||||
display_name: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
||||
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="用户ID")
|
||||
username: Mapped[str] = mapped_column(String(50), nullable=False, unique=True, index=True, comment="用户名")
|
||||
password: Mapped[str] = mapped_column(String(255), nullable=False, comment="密码哈希")
|
||||
real_name: Mapped[str] = mapped_column(String(50), nullable=False, comment="真实姓名")
|
||||
phone: Mapped[str] = mapped_column(String(20), nullable=False, unique=True, index=True, comment="手机号")
|
||||
avatar: Mapped[str] = mapped_column(String(255), nullable=False, default="", comment="头像")
|
||||
gender: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=0, comment="性别")
|
||||
role_type: Mapped[str] = mapped_column(String(30), nullable=False, comment="角色类型")
|
||||
title_name: Mapped[str] = mapped_column(String(50), nullable=False, default="", comment="职称")
|
||||
major: Mapped[str] = mapped_column(String(100), nullable=False, default="", comment="专业")
|
||||
training_stage: Mapped[str] = mapped_column(String(50), nullable=False, default="", comment="培训阶段")
|
||||
learning_target: Mapped[str] = mapped_column(String(255), nullable=False, default="", comment="学习目标")
|
||||
competency_profile: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict, comment="能力画像")
|
||||
weak_dimensions: Mapped[list] = mapped_column(JSON, nullable=False, default=list, comment="薄弱维度")
|
||||
strong_dimensions: Mapped[list] = mapped_column(JSON, nullable=False, default=list, comment="优势维度")
|
||||
ai_preference: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict, comment="AI偏好")
|
||||
total_training_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="训练次数")
|
||||
total_case_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="病例数")
|
||||
current_level: Mapped[str] = mapped_column(String(30), nullable=False, default="", comment="当前等级")
|
||||
status: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=1, comment="状态")
|
||||
last_login: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="最后登录")
|
||||
last_login_time: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="最后登录时间")
|
||||
is_superuser: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, comment="是否超级用户")
|
||||
is_staff: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, comment="是否员工")
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, comment="是否激活")
|
||||
date_joined: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="加入时间")
|
||||
department_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="科室ID")
|
||||
institution_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True, comment="机构ID")
|
||||
|
||||
|
||||
class UserLearningProfile(TimestampMixin, Base):
|
||||
"""学习档案模型:聚合完整评价记录形成用户能力画像。"""
|
||||
|
||||
__tablename__ = "user_learning_profiles"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[str] = mapped_column(String(128), nullable=False, index=True)
|
||||
tenant_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
|
||||
total_evaluations: Mapped[int] = mapped_column(Integer, default=0)
|
||||
avg_score_percentage: Mapped[float | None] = mapped_column(Numeric(6, 2))
|
||||
avg_score_five_point: Mapped[float | None] = mapped_column(Numeric(4, 2))
|
||||
weak_dimensions: Mapped[list | None] = mapped_column(JSON)
|
||||
last_evaluation_id: Mapped[int | None] = mapped_column(Integer)
|
||||
last_trained_at: Mapped[datetime | None] = mapped_column(DateTime, index=True)
|
||||
__table_args__ = {"comment": "用户表"}
|
||||
|
||||
Reference in New Issue
Block a user