53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
"""ORM model for user feedback on assistant answers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
from sqlalchemy import Index, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from deerflow.persistence.base import Base
|
|
from deerflow.persistence.types import BeijingDateTime, PortableJSON
|
|
|
|
|
|
class FeedbackRow(Base):
|
|
__tablename__ = "feedback"
|
|
|
|
# ``target_key`` is a SHA-256 digest of user/thread/message/agent. A
|
|
# digest keeps the idempotency index well below MySQL's legacy utf8mb4
|
|
# key-size limit; indexing all four source strings would exceed it.
|
|
__table_args__ = (
|
|
Index("uq_feedback_target_key", "target_key", unique=True),
|
|
Index("ix_feedback_agent_created", "agent_id", "created_at"),
|
|
)
|
|
|
|
feedback_id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
run_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
|
thread_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
|
user_id: Mapped[str | None] = mapped_column(String(64), index=True)
|
|
message_id: Mapped[str | None] = mapped_column(String(64))
|
|
# ``message_id`` is the LangChain/checkpoint message id serialized inside
|
|
# a RunEventStore ``llm.ai.response`` event. It stays nullable solely for
|
|
# legacy run-level feedback rows created before answer-level feedback.
|
|
|
|
agent_id: Mapped[str] = mapped_column(String(128), nullable=False, default="lead_agent")
|
|
target_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
|
|
rating: Mapped[int] = mapped_column(nullable=False)
|
|
# +1 (thumbs-up) or -1 (thumbs-down)
|
|
|
|
comment: Mapped[str | None] = mapped_column(Text)
|
|
# Optional user detail. The API exposes this as ``detail`` and retains
|
|
# ``comment`` as a compatibility alias for older clients.
|
|
|
|
reasons: Mapped[list[str]] = mapped_column(PortableJSON(), default=list)
|
|
# Stable machine-readable reason codes for negative feedback.
|
|
|
|
created_at: Mapped[datetime] = mapped_column(BeijingDateTime(), default=lambda: datetime.now(UTC))
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
BeijingDateTime(),
|
|
default=lambda: datetime.now(UTC),
|
|
onupdate=lambda: datetime.now(UTC),
|
|
)
|