91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
|
|
"""moldinsight 域模型:老师傅经验反馈表。
|
|||
|
|
|
|||
|
|
Human-in-Loop 闭环(D17,2026-09):老师傅对系统推荐方案给出"采纳 / 调整 / 拒绝"
|
|||
|
|
反馈,按"产品指纹 + 工艺参数"为索引跨任务匹配;下次同指纹产品分析自动消费
|
|||
|
|
(OCC worker payload 透传 → MultiSchemeMoldPlanner → PartingSchemeScorer 加成)。
|
|||
|
|
|
|||
|
|
跨模块桥接只保留裸 FK,不建 ORM relationship(base.py 约定):
|
|||
|
|
- processing_task_id -> processing_tasks.id
|
|||
|
|
- stp_file_id -> stp_files.id
|
|||
|
|
- user_id -> users.id
|
|||
|
|
|
|||
|
|
写入 feedback 时由 service 层填充 fingerprint JSON(bbox_aspect / volume_bucket /
|
|||
|
|
face_bucket / undercut_class / material_family / is_foam)。fingerprint 是跨任务
|
|||
|
|
匹配的索引列(PG 下有 GIN 索引支持 jsonb_path_query 类查询)。
|
|||
|
|
"""
|
|||
|
|
from sqlalchemy import Column, Integer, String, Text, DateTime, JSON, Float, ForeignKey, Index
|
|||
|
|
from sqlalchemy.sql import func
|
|||
|
|
|
|||
|
|
from shared.models.base import Base
|
|||
|
|
|
|||
|
|
|
|||
|
|
class ExperienceFeedback(Base):
|
|||
|
|
"""老师傅经验反馈:方案级整体反馈 + 跨任务指纹匹配。
|
|||
|
|
|
|||
|
|
关键字段:
|
|||
|
|
- feedback_status: 'adopted' / 'adjust' / 'rejected'
|
|||
|
|
- fingerprint: 跨任务匹配键,结构见 moldinsight.services.experience_feedback_service
|
|||
|
|
- expires_at: 90 天 TTL;写新反馈时同 stp_file_id 整体续期(D17 衰减机制)
|
|||
|
|
"""
|
|||
|
|
__tablename__ = "experience_feedback"
|
|||
|
|
|
|||
|
|
id = Column(Integer, primary_key=True, index=True)
|
|||
|
|
|
|||
|
|
# ── 任务归属(跨模块裸 FK,CASCADE 随任务 / 文件清理)──
|
|||
|
|
processing_task_id = Column(
|
|||
|
|
Integer,
|
|||
|
|
ForeignKey("processing_tasks.id", ondelete="CASCADE"),
|
|||
|
|
nullable=False,
|
|||
|
|
index=True,
|
|||
|
|
)
|
|||
|
|
stp_file_id = Column(
|
|||
|
|
Integer,
|
|||
|
|
ForeignKey("stp_files.id", ondelete="CASCADE"),
|
|||
|
|
nullable=False,
|
|||
|
|
index=True,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ── 方案标识 ──
|
|||
|
|
scheme_id = Column(String(64), nullable=False, index=True)
|
|||
|
|
scheme_axis = Column(String(1), nullable=False)
|
|||
|
|
scheme_method = Column(String(50), nullable=True)
|
|||
|
|
|
|||
|
|
# ── 反馈主体 ──
|
|||
|
|
feedback_status = Column(String(20), nullable=False, index=True)
|
|||
|
|
feedback_reason = Column(Text, nullable=True)
|
|||
|
|
adjust_suggestion = Column(Text, nullable=True)
|
|||
|
|
|
|||
|
|
# ── 上下文快照(用于回放)──
|
|||
|
|
process_params_snapshot = Column(JSON, nullable=True)
|
|||
|
|
fingerprint = Column(JSON, nullable=False)
|
|||
|
|
confidence_at_submit = Column(Float, nullable=True)
|
|||
|
|
score_at_submit = Column(Float, nullable=True)
|
|||
|
|
|
|||
|
|
# ── 审计(user_id RESTRICT:禁止级联删,保留审计归因)──
|
|||
|
|
user_id = Column(
|
|||
|
|
Integer,
|
|||
|
|
ForeignKey("users.id", ondelete="RESTRICT"),
|
|||
|
|
nullable=False,
|
|||
|
|
index=True,
|
|||
|
|
)
|
|||
|
|
role_code = Column(String(50), nullable=False)
|
|||
|
|
|
|||
|
|
# ── 时间戳与衰减 ──
|
|||
|
|
created_at = Column(DateTime, default=func.now(), index=True)
|
|||
|
|
expires_at = Column(DateTime, nullable=True, index=True)
|
|||
|
|
|
|||
|
|
__table_args__ = (
|
|||
|
|
Index(
|
|||
|
|
"ix_experience_feedback_stp_axis_status",
|
|||
|
|
"stp_file_id",
|
|||
|
|
"scheme_axis",
|
|||
|
|
"feedback_status",
|
|||
|
|
),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def __repr__(self) -> str:
|
|||
|
|
return (
|
|||
|
|
f"<ExperienceFeedback(id={self.id}, stp_file_id={self.stp_file_id}, "
|
|||
|
|
f"scheme_id='{self.scheme_id}', axis='{self.scheme_axis}', "
|
|||
|
|
f"status='{self.feedback_status}')>"
|
|||
|
|
)
|