search.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. """
  2. 搜索功能数据ORM定义
  3. 定义搜索功能相关的数据库表结构,包含用户搜索偏好和使用记录
  4. """
  5. from datetime import datetime
  6. from sqlalchemy import (
  7. Column, Integer, String, Boolean, DateTime, Numeric, ForeignKey,
  8. Index, CheckConstraint, BigInteger, JSON
  9. )
  10. from sqlalchemy.sql import func
  11. from sqlalchemy.orm import relationship
  12. from app.database import Base
  13. class UserSearchPreferences(Base):
  14. """
  15. 用户搜索偏好ORM类
  16. 存储用户的默认搜索配置,包括搜索策略、时效性等偏好设置
  17. """
  18. __tablename__ = "user_search_preferences"
  19. # 主键
  20. id = Column(Integer, primary_key=True, autoincrement=True, comment="主键ID")
  21. # 用户ID(外键关联users表,级联删除)
  22. user_id = Column(
  23. String(50),
  24. ForeignKey("aigcspace.users.id", ondelete="CASCADE"),
  25. nullable=False,
  26. unique=True,
  27. comment="用户ID"
  28. )
  29. # 默认搜索策略
  30. default_search_strategy = Column(
  31. String(10),
  32. nullable=False,
  33. default='turbo',
  34. comment="默认搜索策略:turbo/max/agent"
  35. )
  36. # 是否启用垂域搜索
  37. enable_search_extension = Column(
  38. Boolean,
  39. nullable=False,
  40. default=False,
  41. comment="是否启用垂域搜索"
  42. )
  43. # 默认搜索时效性(天)
  44. default_freshness = Column(
  45. Integer,
  46. nullable=True,
  47. comment="默认搜索时效性(天):7/30/180/365"
  48. )
  49. # 是否启用引用标注
  50. enable_citation = Column(
  51. Boolean,
  52. nullable=False,
  53. default=False,
  54. comment="是否启用引用标注"
  55. )
  56. # 引用格式
  57. citation_format = Column(
  58. String(20),
  59. nullable=False,
  60. default='[<number>]',
  61. comment="引用格式:[<number>] 或 [ref_<number>]"
  62. )
  63. # 创建时间
  64. created_at = Column(
  65. DateTime,
  66. nullable=False,
  67. server_default=func.now(),
  68. comment="创建时间"
  69. )
  70. # 更新时间
  71. updated_at = Column(
  72. DateTime,
  73. nullable=False,
  74. server_default=func.now(),
  75. onupdate=func.now(),
  76. comment="更新时间"
  77. )
  78. # 表级配置
  79. __table_args__ = (
  80. Index('idx_user_search_preferences_user_id', 'user_id'),
  81. CheckConstraint(
  82. "default_search_strategy IN ('turbo', 'max', 'agent')",
  83. name='chk_search_strategy'
  84. ),
  85. CheckConstraint(
  86. "default_freshness IS NULL OR default_freshness IN (7, 30, 180, 365)",
  87. name='chk_freshness'
  88. ),
  89. CheckConstraint(
  90. "citation_format IN ('[<number>]', '[ref_<number>]')",
  91. name='chk_citation_format'
  92. ),
  93. {'schema': 'aigcspace', 'comment': '用户搜索偏好表,存储用户的默认搜索配置'}
  94. )
  95. def __repr__(self):
  96. return f"<UserSearchPreferences(id={self.id}, user_id='{self.user_id}', strategy='{self.default_search_strategy}')>"
  97. class SearchUsageLog(Base):
  98. """
  99. 搜索使用记录ORM类
  100. 记录用户的搜索使用情况,用于统计分析和计费管理
  101. """
  102. __tablename__ = "search_usage_log"
  103. # 主键
  104. id = Column(BigInteger, primary_key=True, autoincrement=True, comment="主键ID")
  105. # 用户ID(外键关联users表,级联删除)
  106. user_id = Column(
  107. String(50),
  108. ForeignKey("aigcspace.users.id", ondelete="CASCADE"),
  109. nullable=False,
  110. comment="用户ID"
  111. )
  112. # 会话ID(外键关联ai_conversation表,允许为空)
  113. conversation_id = Column(
  114. Integer,
  115. ForeignKey("aigcspace.ai_conversation.id", ondelete="SET NULL"),
  116. nullable=True,
  117. comment="会话ID"
  118. )
  119. # 使用的模型名称
  120. model_name = Column(
  121. String(255),
  122. nullable=False,
  123. comment="使用的模型名称"
  124. )
  125. # 搜索策略
  126. search_strategy = Column(
  127. String(10),
  128. nullable=False,
  129. comment="搜索策略:turbo/max/agent"
  130. )
  131. # 搜索次数
  132. search_count = Column(
  133. Integer,
  134. nullable=False,
  135. default=1,
  136. comment="搜索次数"
  137. )
  138. # 搜索成本
  139. search_cost = Column(
  140. Numeric(10, 4),
  141. nullable=False,
  142. default=0.0000,
  143. comment="搜索成本"
  144. )
  145. # 创建时间
  146. created_at = Column(
  147. DateTime,
  148. nullable=False,
  149. server_default=func.now(),
  150. comment="创建时间"
  151. )
  152. # 表级配置
  153. __table_args__ = (
  154. Index('idx_search_usage_log_user_id', 'user_id'),
  155. Index('idx_search_usage_log_conversation_id', 'conversation_id'),
  156. Index('idx_search_usage_log_user_created', 'user_id', 'created_at'),
  157. Index('idx_search_usage_log_created_at', 'created_at'),
  158. Index('idx_search_usage_log_model_name', 'model_name'),
  159. CheckConstraint(
  160. "search_strategy IN ('turbo', 'max', 'agent')",
  161. name='chk_search_usage_strategy'
  162. ),
  163. CheckConstraint(
  164. "search_count > 0",
  165. name='chk_search_count'
  166. ),
  167. CheckConstraint(
  168. "search_cost >= 0",
  169. name='chk_search_cost'
  170. ),
  171. {'schema': 'aigcspace', 'comment': '搜索使用记录表,用于统计和计费'}
  172. )
  173. def __repr__(self):
  174. return f"<SearchUsageLog(id={self.id}, user_id='{self.user_id}', strategy='{self.search_strategy}', cost={self.search_cost})>"