Просмотр исходного кода

feat(ai-q): 数据层 — ai_q_scene/session/profile 表 + 迁移 + 实体/Mapper

Xiaogang Liao 1 месяц назад
Родитель
Сommit
074fab50a5

+ 56 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -2940,6 +2940,62 @@ log.info("已添加template_id列到tasks表");
         runLateMigrations();
         migration102();
         seedFullRegionData();
+
+        // 迁移229: 创建 ai_q_scene / ai_q_session / ai_q_profile 表(AI 动态问卷引擎)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_q_scene (" +
+                    "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "scene_key VARCHAR(50) NOT NULL, " +
+                    "scene_name VARCHAR(100) NOT NULL, " +
+                    "description VARCHAR(500), " +
+                    "opening_prompt TEXT, " +
+                    "dimensions_json JSON, " +
+                    "kb_scope VARCHAR(200) DEFAULT 'microbiome', " +
+                    "max_questions INT DEFAULT 12, " +
+                    "system_prompt TEXT, " +
+                    "enabled TINYINT DEFAULT 1, " +
+                    "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+                    "UNIQUE KEY uk_scene_key (scene_key)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-场景配置'");
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_q_session (" +
+                    "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "scene_id BIGINT NOT NULL, " +
+                    "user_id BIGINT NOT NULL, " +
+                    "member_id BIGINT NOT NULL, " +
+                    "family_id BIGINT, " +
+                    "status VARCHAR(16) DEFAULT 'running', " +
+                    "history_json JSON, " +
+                    "current_question_json JSON, " +
+                    "question_count INT DEFAULT 0, " +
+                    "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "finished_at DATETIME, " +
+                    "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+                    "INDEX idx_member_status (member_id, status), " +
+                    "INDEX idx_scene (scene_id)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-会话'");
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_q_profile (" +
+                    "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "session_id BIGINT NOT NULL, " +
+                    "scene_id BIGINT NOT NULL, " +
+                    "member_id BIGINT NOT NULL, " +
+                    "user_profile_json JSON, " +
+                    "need_profile_json JSON, " +
+                    "raw_result TEXT, " +
+                    "kb_used TINYINT DEFAULT 0, " +
+                    "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "UNIQUE KEY uk_session (session_id), " +
+                    "INDEX idx_member (member_id)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-画像结果'");
+            jdbcTemplate.execute("INSERT IGNORE INTO ai_q_scene (scene_key, scene_name, description, opening_prompt, dimensions_json, kb_scope, max_questions, enabled) " +
+                    "VALUES ('microbiome', '菌群健康评估', '通过动态问答评估肠道菌群健康状况并生成营养需求画像', " +
+                    "'我将通过几个问题了解您的肠道健康状况,请如实回答。', " +
+                    "'{\"user\": [\"肠道菌群状态\", \"饮食习惯\", \"生活方式\"], \"need\": [\"营养需求\", \"菌群调理建议\"]}', " +
+                    "'microbiome,dan_knowledge', 12, 1)");
+            log.info("已创建 ai_q_scene/ai_q_session/ai_q_profile 表并初始化 microbiome 场景");
+        } catch (Exception e) {
+            // 表已存在,忽略错误
+        }
     }
 
     private void migrateHealthDimensionsTable() {

+ 22 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/AiQProfile.java

@@ -0,0 +1,22 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+@Data
+@TableName("ai_q_profile")
+public class AiQProfile {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long sessionId;
+    private Long sceneId;
+    private Long memberId;
+    private String userProfileJson;
+    private String needProfileJson;
+    private String rawResult;
+    private Integer kbUsed;
+    private Date createdAt;
+}

+ 25 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/AiQScene.java

@@ -0,0 +1,25 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+@Data
+@TableName("ai_q_scene")
+public class AiQScene {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String sceneKey;
+    private String sceneName;
+    private String description;
+    private String openingPrompt;
+    private String dimensionsJson;
+    private String kbScope;
+    private Integer maxQuestions;
+    private String systemPrompt;
+    private Integer enabled;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 25 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/AiQSession.java

@@ -0,0 +1,25 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.util.Date;
+
+@Data
+@TableName("ai_q_session")
+public class AiQSession {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long sceneId;
+    private Long userId;
+    private Long memberId;
+    private Long familyId;
+    private String status;
+    private String historyJson;
+    private String currentQuestionJson;
+    private Integer questionCount;
+    private Date createdAt;
+    private Date finishedAt;
+    private Date updatedAt;
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/AiQProfileMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.AiQProfile;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AiQProfileMapper extends BaseMapper<AiQProfile> {
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/AiQSceneMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.AiQScene;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AiQSceneMapper extends BaseMapper<AiQScene> {
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/AiQSessionMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.AiQSession;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AiQSessionMapper extends BaseMapper<AiQSession> {
+}

+ 51 - 0
cfc-backend/src/main/resources/schema.sql

@@ -4717,3 +4717,54 @@ CREATE TABLE IF NOT EXISTS microbiome_article (
     INDEX idx_status (status),
     FULLTEXT INDEX ft_content (title, content)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菌群知识库文章';
+
+-- =============================================
+-- AI 动态问卷引擎(逐题对话式 + 画像)
+-- =============================================
+
+CREATE TABLE IF NOT EXISTS ai_q_scene (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  scene_key VARCHAR(50) NOT NULL COMMENT '场景唯一标识(如 microbiome)',
+  scene_name VARCHAR(100) NOT NULL COMMENT '场景名称',
+  description VARCHAR(500) DEFAULT NULL COMMENT '场景描述',
+  opening_prompt TEXT COMMENT '开场引导',
+  dimensions_json JSON COMMENT '画像维度定义 {user:[...], need:[...]}',
+  kb_scope VARCHAR(200) DEFAULT 'microbiome' COMMENT '知识库范围(逗号分隔 source 前缀)',
+  max_questions INT DEFAULT 12 COMMENT '题数上限',
+  system_prompt TEXT COMMENT '可选:场景自定义 system prompt',
+  enabled TINYINT DEFAULT 1 COMMENT '1=启用 0=禁用',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  UNIQUE KEY uk_scene_key (scene_key)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-场景配置';
+
+CREATE TABLE IF NOT EXISTS ai_q_session (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  scene_id BIGINT NOT NULL COMMENT '场景ID',
+  user_id BIGINT NOT NULL COMMENT '填写者用户ID',
+  member_id BIGINT NOT NULL COMMENT '画像关联成员ID',
+  family_id BIGINT DEFAULT NULL COMMENT '家庭ID',
+  status VARCHAR(16) DEFAULT 'running' COMMENT 'running/finished/aborted',
+  history_json JSON COMMENT '已回答历史 [{question:{...}, answer:"..."}]',
+  current_question_json JSON COMMENT '当前待答题',
+  question_count INT DEFAULT 0 COMMENT '已答题数',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  finished_at DATETIME DEFAULT NULL COMMENT '完成时间',
+  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  INDEX idx_member_status (member_id, status),
+  INDEX idx_scene (scene_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-会话';
+
+CREATE TABLE IF NOT EXISTS ai_q_profile (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  session_id BIGINT NOT NULL COMMENT '会话ID',
+  scene_id BIGINT NOT NULL COMMENT '场景ID',
+  member_id BIGINT NOT NULL COMMENT '成员ID',
+  user_profile_json JSON COMMENT '用户画像 [{dimension,score,description,evidence}]',
+  need_profile_json JSON COMMENT '需求画像 [{dimension,description,evidence,suggestion}]',
+  raw_result TEXT COMMENT 'LLM 原始输出(审计)',
+  kb_used TINYINT DEFAULT 0 COMMENT '是否使用了知识库',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  UNIQUE KEY uk_session (session_id),
+  INDEX idx_member (member_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI 动态问卷-画像结果';