topfans/backend/scripts/migrations/migrate_ai_chat_tables.sql
2026-05-28 12:00:19 +08:00

150 lines
9.2 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- AI Chat Service 数据库迁移
-- 创建人设表、用户记忆表、配置表
-- ============================================
-- 1. ai_personas 表 - 人设表
-- 存储用户创建的 AI 聊天人设配置
-- ============================================
CREATE TABLE IF NOT EXISTS ai_personas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- 人设唯一标识符
user_id BIGINT NOT NULL, -- 所属用户 ID
name VARCHAR(64) NOT NULL, -- 人设名称
description TEXT, -- 人设描述/简介
avatar_url VARCHAR(512), -- 头像 URL
talk_style VARCHAR(256), -- 说话风格描述
system_prompt TEXT NOT NULL, -- 系统提示词(人设核心定义)
is_default BOOLEAN DEFAULT FALSE, -- 是否为默认人设
created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000, -- 创建时间(毫秒时间戳)
updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000 -- 更新时间(毫秒时间戳)
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_ai_personas_user_id ON ai_personas(user_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_ai_personas_user_default ON ai_personas(user_id) WHERE is_default = TRUE;
-- ============================================
-- 2. ai_user_memories 表 - 用户长期记忆表
-- 存储用户的长期记忆信息,用于 AI 对话时召回
-- ============================================
CREATE TABLE IF NOT EXISTS ai_user_memories (
id SERIAL PRIMARY KEY, -- 记忆唯一标识符
user_id BIGINT NOT NULL, -- 所属用户 ID
content TEXT NOT NULL, -- 记忆内容
keywords TEXT[], -- 关键词数组(用于检索)
weight INTEGER DEFAULT 50, -- 权重0-100影响召回优先级
is_core BOOLEAN DEFAULT FALSE, -- 是否为核心记忆(核心记忆优先召回)
created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000, -- 创建时间
updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000 -- 更新时间
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_ai_user_memories_user_id ON ai_user_memories(user_id);
CREATE INDEX IF NOT EXISTS idx_ai_user_memories_keywords ON ai_user_memories USING GIN(keywords);
CREATE INDEX IF NOT EXISTS idx_ai_user_memories_weight ON ai_user_memories(weight DESC);
-- ============================================
-- 3. ai_chat_configs 表 - AI Chat 配置表
-- 存储 AI Chat 服务的各类配置项
-- ============================================
CREATE TABLE IF NOT EXISTS ai_chat_configs (
id SERIAL PRIMARY KEY, -- 配置项唯一 ID
config_key VARCHAR(128) NOT NULL UNIQUE, -- 配置键
config_value TEXT NOT NULL, -- 配置值
config_type VARCHAR(32) NOT NULL DEFAULT 'string', -- 配置类型string/number/boolean/json
category VARCHAR(64) NOT NULL, -- 配置分类redis/llm/dialog/token/circuit/summary
description VARCHAR(256), -- 配置描述
is_encrypted BOOLEAN DEFAULT FALSE, -- 是否加密存储(加密字段不返回明文)
updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000, -- 更新时间
created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000 -- 创建时间
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_ai_chat_configs_category ON ai_chat_configs(category);
CREATE INDEX IF NOT EXISTS idx_ai_chat_configs_key ON ai_chat_configs(config_key);
-- 初始配置数据
INSERT INTO ai_chat_configs (config_key, config_value, config_type, category, description, is_encrypted) VALUES
-- Redis 配置
('redis.host', '127.0.0.1', 'string', 'redis', 'Redis 主机地址', FALSE),
('redis.port', '6379', 'number', 'redis', 'Redis 端口', FALSE),
('redis.password', '123456', 'string', 'redis', 'Redis 密码', TRUE),
('redis.db', '0', 'number', 'redis', 'Redis 数据库编号', FALSE),
-- MiniMax 大模型配置
('minimax.api_key', '', 'string', 'llm', 'MiniMax API Key', TRUE),
('minimax.api_url', 'https://api.minimaxi.com/v1', 'string', 'llm', 'MiniMax API 地址', FALSE),
('minimax.model', 'M2-her', 'string', 'llm', 'MiniMax 模型名称', FALSE),
-- 通义备用模型配置
('qwen.api_key', '', 'string', 'llm', '通义 API Key', TRUE),
('qwen.api_url', 'https://dashscope.aliyuncs.com/compatible-mode/v1', 'string', 'llm', '通义 API 地址', FALSE),
('qwen.model', 'qwen-plus', 'string', 'llm', '通义模型名称', FALSE),
-- 对话配置
('dialog.max_context_turns', '10', 'number', 'dialog', '最大上下文轮数', FALSE),
('dialog.context_expire_seconds', '86400', 'number', 'dialog', '上下文过期时间(秒)', FALSE),
('dialog.memory_recall_topn', '5', 'number', 'dialog', '记忆召回返回条数', FALSE),
('dialog.fallback_threshold', '3', 'number', 'dialog', '模型降级连续失败次数阈值', FALSE),
('dialog.slow_response_ms', '5000', 'number', 'dialog', '慢响应判定阈值(毫秒)', FALSE),
-- AI Token 限制配置
('token.max_total', '32000', 'number', 'token', '总 Token 上限', FALSE),
('token.max_history', '24000', 'number', 'token', '对话历史最大 Token', FALSE),
('token.max_system', '4000', 'number', 'token', 'System Prompt 最大 Token', FALSE),
('token.max_memory', '2000', 'number', 'token', '记忆召回最大 Token', FALSE),
('token.reserved', '2000', 'number', 'token', '保留空间 Token', FALSE),
-- 熔断配置
('circuit.max_fail_count', '5', 'number', 'circuit', '熔断连续失败次数', FALSE),
('circuit.breaker_timeout', '60', 'number', 'circuit', '熔断恢复超时(秒)', FALSE),
-- 摘要配置
('summary.trigger_turns', '10', 'number', 'summary', '自动摘要触发轮数', FALSE),
('summary.max_length', '100', 'number', 'summary', '摘要最大字数', FALSE)
ON CONFLICT (config_key) DO NOTHING;
-- ============================================
-- 表结构注释
-- ============================================
COMMENT ON TABLE ai_personas IS 'AI 人设表 - 存储用户创建的聊天人设配置';
COMMENT ON TABLE ai_user_memories IS '用户长期记忆表 - 存储用户记忆信息,用于对话时召回';
COMMENT ON TABLE ai_chat_configs IS 'AI Chat 配置表 - 存储服务各类配置项';
-- ============================================
-- ai_personas 列注释
-- ============================================
COMMENT ON COLUMN ai_personas.id IS '人设唯一标识符';
COMMENT ON COLUMN ai_personas.user_id IS '所属用户ID';
COMMENT ON COLUMN ai_personas.name IS '人设名称';
COMMENT ON COLUMN ai_personas.description IS '人设描述/简介';
COMMENT ON COLUMN ai_personas.avatar_url IS '人设头像URL';
COMMENT ON COLUMN ai_personas.talk_style IS 'AI说话风格描述';
COMMENT ON COLUMN ai_personas.system_prompt IS '系统提示词,定义人设核心性格和行为';
COMMENT ON COLUMN ai_personas.is_default IS '是否为用户的默认人设';
COMMENT ON COLUMN ai_personas.created_at IS '记录创建时间(毫秒时间戳)';
COMMENT ON COLUMN ai_personas.updated_at IS '记录更新时间(毫秒时间戳)';
-- ============================================
-- ai_user_memories 列注释
-- ============================================
COMMENT ON COLUMN ai_user_memories.id IS '记忆记录唯一ID';
COMMENT ON COLUMN ai_user_memories.user_id IS '所属用户ID';
COMMENT ON COLUMN ai_user_memories.content IS '记忆内容文本';
COMMENT ON COLUMN ai_user_memories.keywords IS '关键词数组,用于记忆检索';
COMMENT ON COLUMN ai_user_memories.weight IS '记忆权重(0-100),影响召回优先级';
COMMENT ON COLUMN ai_user_memories.is_core IS '是否为核心记忆,核心记忆优先召回';
COMMENT ON COLUMN ai_user_memories.created_at IS '记忆创建时间';
COMMENT ON COLUMN ai_user_memories.updated_at IS '记忆更新时间';
-- ============================================
-- ai_chat_configs 列注释
-- ============================================
COMMENT ON COLUMN ai_chat_configs.id IS '配置项唯一ID';
COMMENT ON COLUMN ai_chat_configs.config_key IS '配置键名称';
COMMENT ON COLUMN ai_chat_configs.config_value IS '配置值';
COMMENT ON COLUMN ai_chat_configs.config_type IS '配置类型string/number/boolean/json';
COMMENT ON COLUMN ai_chat_configs.category IS '配置分类redis/llm/dialog/token/circuit/summary';
COMMENT ON COLUMN ai_chat_configs.description IS '配置项的中文描述';
COMMENT ON COLUMN ai_chat_configs.is_encrypted IS '是否加密存储,加密字段不会返回明文';
COMMENT ON COLUMN ai_chat_configs.updated_at IS '配置更新时间';
COMMENT ON COLUMN ai_chat_configs.created_at IS '配置创建时间';