# database/ai_models.py # ⚠️ 這四個 class 的原始定義已移至 autoheal_models.py(ADR-013 統一管理)。 # 此檔僅作向後相容 re-export shim,不再重複定義 SQLAlchemy Table, # 以避免 "Table already defined for this MetaData instance" 衝突。 from .autoheal_models import ( # noqa: F401 AgentContext, ActionPlan, ActionOutcome, AgentStrategyWeights, ) # AI history and template models from sqlalchemy import Column, Integer, String, DateTime, Text, Boolean, Float from database.models import Base from datetime import datetime class AIGenerationHistory(Base): """ AI generation history tracking """ __tablename__ = 'ai_generation_history' id = Column(Integer, primary_key=True, autoincrement=True) generation_type = Column(String(50), nullable=False) # product_desc, marketing_copy, etc. product_name = Column(String(200)) input_keywords = Column(Text) # JSON string input_trend_topic = Column(String(500)) output_content = Column(Text) generation_duration = Column(Float) # seconds is_favorite = Column(Boolean, default=False) is_used = Column(Boolean, default=False) created_by = Column(String(100)) created_at = Column(DateTime, default=datetime.now) def to_dict(self): return { 'id': self.id, 'generation_type': self.generation_type, 'product_name': self.product_name, 'input_keywords': self.input_keywords, 'input_trend_topic': self.input_trend_topic, 'output_content': self.output_content, 'generation_duration': self.generation_duration, 'is_favorite': self.is_favorite, 'is_used': self.is_used, 'created_by': self.created_by, 'created_at': self.created_at.isoformat() if self.created_at else None } class AIPromptTemplate(Base): """ AI prompt templates """ __tablename__ = 'ai_prompt_templates' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(200), nullable=False) description = Column(Text) template_type = Column(String(50), nullable=False) # product_desc, marketing_copy, etc. prompt_content = Column(Text, nullable=False) variables = Column(Text) # JSON string of variable definitions is_active = Column(Boolean, default=True) is_system = Column(Boolean, default=False) created_by = Column(String(100)) created_at = Column(DateTime, default=datetime.now) updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now) def to_dict(self): return { 'id': self.id, 'name': self.name, 'description': self.description, 'template_type': self.template_type, 'prompt_content': self.prompt_content, 'variables': self.variables, 'is_active': self.is_active, 'is_system': self.is_system, 'created_by': self.created_by, 'created_at': self.created_at.isoformat() if self.created_at else None, 'updated_at': self.updated_at.isoformat() if self.updated_at else None } class AIUsageTracking(Base): """ AI usage tracking for analytics and billing """ __tablename__ = 'ai_usage_tracking' id = Column(Integer, primary_key=True, autoincrement=True) user_id = Column(String(100)) session_id = Column(String(100)) service_type = Column(String(50), nullable=False) # openai, ollama, etc. model_name = Column(String(100)) prompt_tokens = Column(Integer, default=0) completion_tokens = Column(Integer, default=0) total_tokens = Column(Integer, default=0) cost_usd = Column(Float, default=0.0) request_type = Column(String(50)) # generation, analysis, etc. status = Column(String(20), default='success') # success, failed error_message = Column(Text) duration_ms = Column(Float) created_at = Column(DateTime, default=datetime.now) def to_dict(self): return { 'id': self.id, 'user_id': self.user_id, 'session_id': self.session_id, 'service_type': self.service_type, 'model_name': self.model_name, 'prompt_tokens': self.prompt_tokens, 'completion_tokens': self.completion_tokens, 'total_tokens': self.total_tokens, 'cost_usd': self.cost_usd, 'request_type': self.request_type, 'status': self.status, 'error_message': self.error_message, 'duration_ms': self.duration_ms, 'created_at': self.created_at.isoformat() if self.created_at else None } class AIInsight(Base): """ AI 洞察知識庫(ai_insights 表)— KM 沉澱核心,支援 RAG 向量化。 對應 openclaw_learning_service / scheduler 各任務寫入。 """ __tablename__ = 'ai_insights' id = Column(Integer, primary_key=True, autoincrement=True) insight_type = Column(String(50), nullable=False) # backup_status / human_review / auto_heal_playbook 等 period = Column(String(50)) # 分析週期,e.g. "2026-04-20" product_sku = Column(String(50)) content = Column(Text, nullable=False) metadata_json = Column(Text) # JSON extra payload avg_quality = Column(Float, default=0.0) status = Column(String(20), default='active') # active / archived decay_exempt = Column(Boolean, default=False) ai_model = Column(String(50)) feedback_up = Column(Integer, default=0) feedback_down = Column(Integer, default=0) confidence = Column(Float, default=1.0) created_by = Column(String(50)) created_at = Column(DateTime, default=datetime.now) updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now) # embedding 欄位為 pgvector 型別,透過 raw SQL 寫入,此處不聲明以避免型別衝突 def to_dict(self): return { 'id': self.id, 'insight_type': self.insight_type, 'period': self.period, 'product_sku': self.product_sku, 'content': self.content, 'avg_quality': self.avg_quality, 'status': self.status, 'ai_model': self.ai_model, 'feedback_up': self.feedback_up, 'feedback_down': self.feedback_down, 'confidence': self.confidence, 'created_by': self.created_by, 'created_at': self.created_at.isoformat() if self.created_at else None, } __all__ = [ "AgentContext", "ActionPlan", "ActionOutcome", "AgentStrategyWeights", "AIGenerationHistory", "AIPromptTemplate", "AIUsageTracking", "AIInsight", ]