baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
97
backend/app/models/flywheel.py
Normal file
97
backend/app/models/flywheel.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
app/models/flywheel.py — preference_events / ai_call_logs
|
||||
Alembic 003(ai_call_logs)+ Alembic 004(preference_events)
|
||||
preference_profile 二期预留,一期不建。
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import (
|
||||
BigInteger, DateTime, Enum, ForeignKey,
|
||||
Index, Integer, String, Text, func,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.constants.enums import DataOwnership, SignalType
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class PreferenceEvent(Base):
|
||||
"""
|
||||
飞轮信号日志。
|
||||
workspace_id + product_id 都必须有(跨公司隔离 + 按产品分开学)。
|
||||
angle_label 跟着产品的文案角度走,不写死(基石A)。
|
||||
"""
|
||||
__tablename__ = "preference_events"
|
||||
|
||||
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
||||
workspace_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
product_id: Mapped[int] = mapped_column(
|
||||
BigInteger, ForeignKey("products.id"), nullable=False
|
||||
)
|
||||
task_id: Mapped[int] = mapped_column(
|
||||
BigInteger, ForeignKey("generation_tasks.id"), nullable=False
|
||||
)
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
BigInteger, ForeignKey("users.id"), nullable=False
|
||||
)
|
||||
signal_type: Mapped[str] = mapped_column(
|
||||
Enum(SignalType, values_callable=lambda x: [e.value for e in x]),
|
||||
nullable=False,
|
||||
)
|
||||
signal_weight: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
candidate_id: Mapped[int | None] = mapped_column(BigInteger)
|
||||
angle_label: Mapped[str | None] = mapped_column(String(64))
|
||||
reason: Mapped[str | None] = mapped_column(Text) # 打回原因原文
|
||||
signal_meta: Mapped[str | None] = mapped_column(Text) # JSON,扩展用
|
||||
data_ownership: Mapped[str] = mapped_column(
|
||||
Enum(DataOwnership, values_callable=lambda x: [e.value for e in x]),
|
||||
default=DataOwnership.CLIENT_DATA, nullable=False,
|
||||
)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime, server_default=func.now(), nullable=False
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
Index(
|
||||
"idx_preference_events_ws_product_created",
|
||||
"workspace_id", "product_id", "created_at",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class AiCallLog(Base):
|
||||
"""
|
||||
AI 调用记录(usage + 排障基础)。
|
||||
调用失败归因到个人 key(错误码50002)。
|
||||
绝不记录明文 key,只记录 key_id。
|
||||
"""
|
||||
__tablename__ = "ai_call_logs"
|
||||
|
||||
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
||||
workspace_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
BigInteger, ForeignKey("users.id"), nullable=False
|
||||
)
|
||||
key_id: Mapped[int | None] = mapped_column(
|
||||
BigInteger, ForeignKey("user_api_keys.id")
|
||||
)
|
||||
task_id: Mapped[int | None] = mapped_column(
|
||||
BigInteger, ForeignKey("generation_tasks.id")
|
||||
)
|
||||
provider: Mapped[str | None] = mapped_column(String(32))
|
||||
model: Mapped[str | None] = mapped_column(String(64))
|
||||
call_type: Mapped[str | None] = mapped_column(String(32)) # text/image/analyze
|
||||
prompt_tokens: Mapped[int | None] = mapped_column(Integer)
|
||||
completion_tokens: Mapped[int | None] = mapped_column(Integer)
|
||||
success: Mapped[bool] = mapped_column(default=True, nullable=False)
|
||||
error_code: Mapped[str | None] = mapped_column(String(32))
|
||||
latency_ms: Mapped[int | None] = mapped_column(Integer)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime, server_default=func.now(), nullable=False
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
Index("idx_ai_call_logs_workspace_user", "workspace_id", "user_id"),
|
||||
Index("idx_ai_call_logs_task_id", "task_id"),
|
||||
)
|
||||
Reference in New Issue
Block a user