diff --git a/pom.xml b/pom.xml index bad6bb0ec..09350be28 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 4.6.1 2.2.7 2.0.0 - 0.0.5 + 0.0.6 5.8.46 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 90173874c..d2ebcb476 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -46,6 +46,20 @@ snail-ai: port: 18889 # Skill 文件临时目录 skill-temp-dir: /tmp/snail-ai-agent/skills + # ==================== Chat 嵌入模式配置 ==================== + chat.ui.embed: + # 启用嵌入模式 + enabled: true + # 嵌入模式下隐藏顶部栏 + show-header: false + # 嵌入模式下隐藏侧边栏用户信息 + show-sidebar-user: false + # 嵌入模式下隐藏智能体市场入口 + show-agent-market: false + # 嵌入模式下使用紧凑输入框 + compact-input: true + # 是否锁定当前智能体 + lock-agent: false # ==================== OpenAPI Client 配置 ==================== open-api: # 启用 OpenAPI Client diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 5c95799cb..129cb92e2 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -49,6 +49,20 @@ snail-ai: port: 18889 # Skill 文件临时目录 skill-temp-dir: /tmp/snail-ai-agent/skills + # ==================== Chat 嵌入模式配置 ==================== + chat.ui.embed: + # 启用嵌入模式 + enabled: true + # 嵌入模式下隐藏顶部栏 + show-header: false + # 嵌入模式下隐藏侧边栏用户信息 + show-sidebar-user: false + # 嵌入模式下隐藏智能体市场入口 + show-agent-market: false + # 嵌入模式下使用紧凑输入框 + compact-input: true + # 是否锁定当前智能体 + lock-agent: false # ==================== OpenAPI Client 配置 ==================== open-api: # 启用 OpenAPI Client diff --git a/ruoyi-extend/ruoyi-snailai-server/src/main/resources/application.yml b/ruoyi-extend/ruoyi-snailai-server/src/main/resources/application.yml index 6f270d82c..ca502ab3b 100644 --- a/ruoyi-extend/ruoyi-snailai-server/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-snailai-server/src/main/resources/application.yml @@ -44,8 +44,7 @@ snail-ai: store-type: db mybatis-plus: - mapper-locations: classpath:/mapper/*.xml - typeAliasesPackage: com.example.snail.job.po + typeAliasesPackage: com.aizuda.snail.ai.persistence global-config: db-config: capital-mode: false diff --git a/script/sql/postgres/postgres_ry_ai.sql b/script/sql/postgres/postgres_ry_ai.sql new file mode 100644 index 000000000..69551deed --- /dev/null +++ b/script/sql/postgres/postgres_ry_ai.sql @@ -0,0 +1,823 @@ +-- ============================================================ +-- Snail AI PostgreSQL 全量建表脚本(仅 CREATE,无 ALTER) +-- 使用:psql -U user -d snail_ai -f postgres_ry_ai.sql +-- 结构来源:snail_ai_schema.sql +-- ============================================================ + +-- ============================================================ +-- 公共触发器函数:模拟 MySQL ON UPDATE CURRENT_TIMESTAMP +-- ============================================================ +CREATE OR REPLACE FUNCTION update_timestamp() +RETURNS TRIGGER AS $$ +BEGIN + NEW.update_dt = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION update_timestamp_updated() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_dt = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION update_timestamp_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- ============================================================ +-- 一、用户与权限 +-- ============================================================ + +-- 1.1 用户表 +CREATE TABLE sai_user +( + id BIGSERIAL PRIMARY KEY, + role INT, + totals INT, + username VARCHAR(255), + nickname VARCHAR(128) DEFAULT NULL, + email VARCHAR(64), + password VARCHAR(255) NOT NULL, + resource_id BIGINT DEFAULT NULL, + create_dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_username UNIQUE (username) +); + +COMMENT ON COLUMN sai_user.nickname IS '用户昵称'; +COMMENT ON COLUMN sai_user.resource_id IS '头像资源ID,关联 sai_resource.id'; + +CREATE TRIGGER trigger_sai_user_update + BEFORE UPDATE ON sai_user + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +-- 1.2 OpenAPI 外部用户映射表 +CREATE TABLE sai_openapi_user +( + id BIGSERIAL PRIMARY KEY, + app_id VARCHAR(128) NOT NULL, + open_id VARCHAR(64) NOT NULL, + platform_user_id BIGINT NOT NULL, + external_id VARCHAR(256) DEFAULT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_app_open UNIQUE (app_id, open_id), + CONSTRAINT uk_app_external UNIQUE (app_id, external_id) +); + +COMMENT ON TABLE sai_openapi_user IS 'OpenAPI 外部用户映射表'; +COMMENT ON COLUMN sai_openapi_user.app_id IS '关联 sai_app.app_id'; +COMMENT ON COLUMN sai_openapi_user.open_id IS '平台分配的唯一标识(UUID)'; +COMMENT ON COLUMN sai_openapi_user.platform_user_id IS '关联 sai_user.id,注册时自动创建'; +COMMENT ON COLUMN sai_openapi_user.external_id IS '外部系统的用户标识(可选,幂等用)'; + +CREATE TRIGGER trigger_sai_openapi_user_update + BEFORE UPDATE ON sai_openapi_user + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_open_id ON sai_openapi_user (open_id); +CREATE INDEX idx_platform_user ON sai_openapi_user (platform_user_id); + +-- ============================================================ +-- 二、AI 模型管理 +-- ============================================================ + +-- 2.1 AI 模型提供商表 +CREATE TABLE IF NOT EXISTS sai_model_provider +( + id BIGSERIAL PRIMARY KEY, + provider_name VARCHAR(255) NOT NULL, + provider_key VARCHAR(50) NOT NULL, + description TEXT, + icon_url VARCHAR(500), + is_enabled BOOLEAN DEFAULT TRUE, + created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_provider_name UNIQUE (provider_name), + CONSTRAINT uk_provider_key UNIQUE (provider_key) +); + +COMMENT ON TABLE sai_model_provider IS 'AI模型提供商表'; +COMMENT ON COLUMN sai_model_provider.provider_name IS '提供商名称'; +COMMENT ON COLUMN sai_model_provider.provider_key IS '提供商标识符'; +COMMENT ON COLUMN sai_model_provider.description IS '提供商描述'; +COMMENT ON COLUMN sai_model_provider.icon_url IS 'LOGO图标URL'; +COMMENT ON COLUMN sai_model_provider.is_enabled IS '是否启用'; +COMMENT ON COLUMN sai_model_provider.created_dt IS '创建时间'; +COMMENT ON COLUMN sai_model_provider.updated_dt IS '更新时间'; + +CREATE TRIGGER trigger_sai_model_provider_update + BEFORE UPDATE ON sai_model_provider + FOR EACH ROW + EXECUTE FUNCTION update_timestamp_updated(); + +CREATE INDEX idx_provider_key ON sai_model_provider (provider_key); +CREATE INDEX idx_is_enabled ON sai_model_provider (is_enabled); + +-- 2.2 AI模型配置表 +CREATE TABLE IF NOT EXISTS sai_model_config +( + id BIGSERIAL PRIMARY KEY, + provider_id BIGINT NOT NULL, + model_name VARCHAR(255) NOT NULL, + model_key VARCHAR(100) NOT NULL, + model_type VARCHAR(50) NOT NULL, + adapter_key VARCHAR(100), + description VARCHAR(1000), + api_key VARCHAR(1000), + api_endpoint VARCHAR(500), + config_json TEXT, + owner_id BIGINT, + scope VARCHAR(20) NOT NULL DEFAULT 'GLOBAL', + is_default BOOLEAN DEFAULT FALSE, + is_enabled BOOLEAN DEFAULT TRUE, + created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_model_config IS 'AI模型配置表'; +COMMENT ON COLUMN sai_model_config.provider_id IS '提供商ID'; +COMMENT ON COLUMN sai_model_config.model_name IS '模型名称'; +COMMENT ON COLUMN sai_model_config.model_key IS '模型标识符'; +COMMENT ON COLUMN sai_model_config.model_type IS '模型类型(CHAT/EMBEDDING/RERANKER/IMAGE/SPEECH)'; +COMMENT ON COLUMN sai_model_config.adapter_key IS '底层协议适配器标识(openai-compatible/http等)'; +COMMENT ON COLUMN sai_model_config.description IS '模型描述'; +COMMENT ON COLUMN sai_model_config.api_key IS 'API密钥(加密存储)'; +COMMENT ON COLUMN sai_model_config.api_endpoint IS 'API端点URL'; +COMMENT ON COLUMN sai_model_config.config_json IS '模型参数配置(JSON格式)'; +COMMENT ON COLUMN sai_model_config.owner_id IS '所有者ID(NULL=全局,具体值=用户ID)'; +COMMENT ON COLUMN sai_model_config.scope IS '作用域(GLOBAL/PERSONAL)'; +COMMENT ON COLUMN sai_model_config.is_default IS '是否为默认模型'; +COMMENT ON COLUMN sai_model_config.is_enabled IS '是否启用'; +COMMENT ON COLUMN sai_model_config.created_dt IS '创建时间'; +COMMENT ON COLUMN sai_model_config.updated_dt IS '更新时间'; + +CREATE TRIGGER trigger_sai_model_config_update + BEFORE UPDATE ON sai_model_config + FOR EACH ROW + EXECUTE FUNCTION update_timestamp_updated(); + +CREATE INDEX fk_provider_id ON sai_model_config (provider_id); + +CREATE INDEX idx_provider_model_type ON sai_model_config (provider_id, model_type); +CREATE INDEX idx_model_type_enabled ON sai_model_config (model_type, is_enabled); +CREATE INDEX idx_owner_id ON sai_model_config (owner_id); +CREATE INDEX idx_is_default ON sai_model_config (is_default); +CREATE INDEX idx_scope ON sai_model_config (scope); +CREATE INDEX idx_model_key ON sai_model_config (model_key); + +-- 2.3 模型使用统计表 +CREATE TABLE IF NOT EXISTS sai_model_usage_stat +( + id BIGSERIAL PRIMARY KEY, + model_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + total_calls BIGINT DEFAULT 0, + success_calls BIGINT DEFAULT 0, + failed_calls BIGINT DEFAULT 0, + total_tokens_used BIGINT DEFAULT 0, + total_cost DECIMAL(18, 8) DEFAULT 0, + avg_response_time BIGINT DEFAULT 0, + last_used_dt TIMESTAMP NULL DEFAULT NULL, + created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT unique_model_user UNIQUE (model_id, user_id) +); + +COMMENT ON TABLE sai_model_usage_stat IS '模型使用统计表'; +COMMENT ON COLUMN sai_model_usage_stat.model_id IS '模型ID'; +COMMENT ON COLUMN sai_model_usage_stat.user_id IS '用户ID'; +COMMENT ON COLUMN sai_model_usage_stat.total_calls IS '总调用次数'; +COMMENT ON COLUMN sai_model_usage_stat.success_calls IS '成功调用次数'; +COMMENT ON COLUMN sai_model_usage_stat.failed_calls IS '失败调用次数'; +COMMENT ON COLUMN sai_model_usage_stat.total_tokens_used IS '总Token使用量'; +COMMENT ON COLUMN sai_model_usage_stat.total_cost IS '总费用'; +COMMENT ON COLUMN sai_model_usage_stat.avg_response_time IS '平均响应时间(毫秒)'; +COMMENT ON COLUMN sai_model_usage_stat.last_used_dt IS '最后使用时间'; +COMMENT ON COLUMN sai_model_usage_stat.created_dt IS '创建时间'; +COMMENT ON COLUMN sai_model_usage_stat.updated_dt IS '更新时间'; + +CREATE TRIGGER trigger_sai_model_usage_stat_update + BEFORE UPDATE ON sai_model_usage_stat + FOR EACH ROW + EXECUTE FUNCTION update_timestamp_updated(); + +CREATE INDEX fk_stat_model_id ON sai_model_usage_stat (model_id); + +CREATE INDEX idx_model_id ON sai_model_usage_stat (model_id); +CREATE INDEX idx_user_id ON sai_model_usage_stat (user_id); +CREATE INDEX idx_last_used_dt ON sai_model_usage_stat (last_used_dt); + +-- ============================================================ +-- 三、智能体(Agent) +-- ============================================================ + +-- 3.1 智能体主表 +CREATE TABLE IF NOT EXISTS sai_agent +( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + avatar VARCHAR(512), + instruction TEXT, + greeting TEXT, + preset_questions TEXT, + chat_model_id BIGINT, + memory_enabled BOOLEAN DEFAULT FALSE, + mcp_enabled BOOLEAN DEFAULT FALSE, + skill_enabled BOOLEAN DEFAULT FALSE, + web_search_enabled BOOLEAN DEFAULT FALSE, + rag_enabled BOOLEAN DEFAULT FALSE, + rag_ids VARCHAR(64) NULL, + rag_call_mode SMALLINT DEFAULT 1, + short_term_memory_size INT DEFAULT 20, + creator_id BIGINT, + is_featured BOOLEAN DEFAULT FALSE, + view_count INT DEFAULT 0, + status SMALLINT DEFAULT 1, + config TEXT, + app_id VARCHAR(128) NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_agent IS '智能体表'; +COMMENT ON COLUMN sai_agent.name IS '智能体名称'; +COMMENT ON COLUMN sai_agent.description IS '智能体描述'; +COMMENT ON COLUMN sai_agent.avatar IS '头像URL'; +COMMENT ON COLUMN sai_agent.instruction IS '系统指令(System Prompt)'; +COMMENT ON COLUMN sai_agent.greeting IS '欢迎语'; +COMMENT ON COLUMN sai_agent.preset_questions IS '预设问题列表(JSON数组字符串)'; +COMMENT ON COLUMN sai_agent.chat_model_id IS '关联的对话模型ID'; +COMMENT ON COLUMN sai_agent.memory_enabled IS '是否启用记忆库'; +COMMENT ON COLUMN sai_agent.mcp_enabled IS '是否启用MCP'; +COMMENT ON COLUMN sai_agent.skill_enabled IS '是否启用Skill'; +COMMENT ON COLUMN sai_agent.web_search_enabled IS '是否启用联网搜索'; +COMMENT ON COLUMN sai_agent.rag_enabled IS '是否启用RAG'; +COMMENT ON COLUMN sai_agent.rag_ids IS '绑定的RAG ID列表,逗号分隔,最多5个'; +COMMENT ON COLUMN sai_agent.rag_call_mode IS 'RAG调用方式: 1=智能调用 2=强制调用'; +COMMENT ON COLUMN sai_agent.short_term_memory_size IS '短期记忆滑动窗口保留条数'; +COMMENT ON COLUMN sai_agent.creator_id IS '创建者用户ID'; +COMMENT ON COLUMN sai_agent.is_featured IS '是否精选'; +COMMENT ON COLUMN sai_agent.view_count IS '浏览次数'; +COMMENT ON COLUMN sai_agent.status IS '状态: 1-活跃 2-非活跃 3-已废弃 4-已禁用'; +COMMENT ON COLUMN sai_agent.config IS '扩展配置(预留)'; +COMMENT ON COLUMN sai_agent.app_id IS '关联应用ID(NULL=本地执行)'; + +CREATE TRIGGER trigger_sai_agent_update + BEFORE UPDATE ON sai_agent + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_agent_creator ON sai_agent (creator_id); +CREATE INDEX idx_agent_featured ON sai_agent (is_featured); + +-- 3.2 智能体对话表 +CREATE TABLE IF NOT EXISTS sai_agent_conversation +( + id BIGSERIAL PRIMARY KEY, + agent_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + conversation_id VARCHAR(64) NOT NULL, + title VARCHAR(255), + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_conv_id UNIQUE (conversation_id) +); + +COMMENT ON TABLE sai_agent_conversation IS '智能体对话表'; +COMMENT ON COLUMN sai_agent_conversation.agent_id IS '智能体ID'; +COMMENT ON COLUMN sai_agent_conversation.user_id IS '用户ID'; +COMMENT ON COLUMN sai_agent_conversation.conversation_id IS '对话ID(UUID)'; +COMMENT ON COLUMN sai_agent_conversation.title IS '对话标题'; + +CREATE TRIGGER trigger_sai_agent_conversation_update + BEFORE UPDATE ON sai_agent_conversation + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_agent_conv_agent ON sai_agent_conversation (agent_id); +CREATE INDEX idx_agent_conv_user ON sai_agent_conversation (user_id); + +-- 3.3 智能体对话消息记录表 +CREATE TABLE IF NOT EXISTS sai_agent_conversation_record +( + id BIGSERIAL PRIMARY KEY, + agent_id BIGINT NOT NULL, + conversation_id VARCHAR(64) NOT NULL, + user_id BIGINT NOT NULL, + role VARCHAR(16) DEFAULT 'user', + content TEXT, + thinking TEXT, + status INT DEFAULT 1, + input_tokens INT DEFAULT 0, + output_tokens INT DEFAULT 0, + cache_tokens INT DEFAULT 0, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_agent_conversation_record IS '智能体对话消息记录'; +COMMENT ON COLUMN sai_agent_conversation_record.agent_id IS '智能体ID'; +COMMENT ON COLUMN sai_agent_conversation_record.conversation_id IS '对话ID'; +COMMENT ON COLUMN sai_agent_conversation_record.user_id IS '用户ID'; +COMMENT ON COLUMN sai_agent_conversation_record.role IS 'user/assistant'; +COMMENT ON COLUMN sai_agent_conversation_record.content IS '消息内容'; +COMMENT ON COLUMN sai_agent_conversation_record.thinking IS '思考过程(仅assistant)'; +COMMENT ON COLUMN sai_agent_conversation_record.status IS '1=成功,2=失败,3=进行中'; +COMMENT ON COLUMN sai_agent_conversation_record.input_tokens IS '输入Token数(prompt)'; +COMMENT ON COLUMN sai_agent_conversation_record.output_tokens IS '输出Token数(completion)'; +COMMENT ON COLUMN sai_agent_conversation_record.cache_tokens IS '缓存命中Token数'; + +CREATE INDEX idx_agent_rec_conv ON sai_agent_conversation_record (conversation_id); + +-- 3.4 智能体使用统计表 +CREATE TABLE IF NOT EXISTS sai_agent_usage_stat +( + id BIGSERIAL PRIMARY KEY, + agent_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + message_count INT DEFAULT 0, + conversation_count INT DEFAULT 0, + stat_date DATE NOT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_agent_user_date UNIQUE (agent_id, user_id, stat_date) +); + +COMMENT ON TABLE sai_agent_usage_stat IS '智能体使用统计'; +COMMENT ON COLUMN sai_agent_usage_stat.agent_id IS '智能体ID'; +COMMENT ON COLUMN sai_agent_usage_stat.user_id IS '用户ID'; +COMMENT ON COLUMN sai_agent_usage_stat.message_count IS '消息条数'; +COMMENT ON COLUMN sai_agent_usage_stat.conversation_count IS '对话轮次'; +COMMENT ON COLUMN sai_agent_usage_stat.stat_date IS '统计日期'; + +CREATE TRIGGER trigger_sai_agent_usage_stat_update + BEFORE UPDATE ON sai_agent_usage_stat + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_usage_agent ON sai_agent_usage_stat (agent_id); +CREATE INDEX idx_usage_date ON sai_agent_usage_stat (stat_date); + +-- 3.5 用户订阅的智能体(多对多) +CREATE TABLE IF NOT EXISTS sai_user_agent +( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + agent_id BIGINT NOT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_user_agent UNIQUE (user_id, agent_id) +); + +COMMENT ON TABLE sai_user_agent IS '用户订阅的智能体'; +COMMENT ON COLUMN sai_user_agent.user_id IS '用户ID'; +COMMENT ON COLUMN sai_user_agent.agent_id IS '智能体ID'; + +CREATE INDEX idx_user_agent_user ON sai_user_agent (user_id); + +-- ============================================================ +-- 四、RAG 知识库 +-- ============================================================ + +-- 4.1 知识库主表 +CREATE TABLE sai_rag +( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + icon VARCHAR(512), + embedding_model_id BIGINT NOT NULL, + dimension_of_vector_model INT NOT NULL, + rerank_model_id BIGINT, + search_engine_instance_id BIGINT, + vector_store_instance_id BIGINT, + search_engine_enable BOOLEAN DEFAULT FALSE, + delimiter VARCHAR(32) DEFAULT E'\n\n', + rag_enhancement TEXT, + config TEXT DEFAULT NULL, + dedup_strategy SMALLINT NOT NULL DEFAULT 2, + dedup_action SMALLINT NOT NULL DEFAULT 0, + upload_confirm BOOLEAN NOT NULL DEFAULT TRUE, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON COLUMN sai_rag.dimension_of_vector_model IS '向量维度'; +COMMENT ON COLUMN sai_rag.config IS 'RAG检索和问答的页面配置参数'; +COMMENT ON COLUMN sai_rag.dedup_strategy IS '去重策略: 0=NONE 1=BY_NAME 2=BY_CONTENT 3=BY_NAME_OR_CONTENT'; +COMMENT ON COLUMN sai_rag.dedup_action IS '冲突动作: 0=REJECT 1=SKIP 2=OVERWRITE'; +COMMENT ON COLUMN sai_rag.upload_confirm IS '上传前二次确认: 0-关 1-开'; + +CREATE TRIGGER trigger_sai_rag_update + BEFORE UPDATE ON sai_rag + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +-- 4.2 RAG 文档表 +CREATE TABLE sai_rag_document +( + id BIGSERIAL PRIMARY KEY, + rag_id BIGINT NOT NULL, + name VARCHAR(255), + file_type VARCHAR(32), + source_type VARCHAR(32), + source_path VARCHAR(1024), + storage_path VARCHAR(1024), + storage_type VARCHAR(32) DEFAULT 'LOCAL', + file_size BIGINT DEFAULT 0, + content TEXT, + status SMALLINT DEFAULT 0, + error_msg TEXT, + chunk_count INT DEFAULT 0, + content_hash VARCHAR(64) DEFAULT NULL, + resource_id BIGINT DEFAULT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON COLUMN sai_rag_document.status IS '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败'; +COMMENT ON COLUMN sai_rag_document.content_hash IS '文件内容SHA-256哈希,用于去重'; +COMMENT ON COLUMN sai_rag_document.resource_id IS '关联资源库 sai_resource.id'; + +CREATE TRIGGER trigger_sai_rag_document_update + BEFORE UPDATE ON sai_rag_document + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_rag_doc_rag ON sai_rag_document (rag_id); +CREATE INDEX idx_rag_content_hash ON sai_rag_document (rag_id, content_hash); +CREATE INDEX idx_rag_name ON sai_rag_document (rag_id, name); +CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id); + +-- 4.3 RAG 分块表 +CREATE TABLE sai_rag_chunk +( + id BIGSERIAL PRIMARY KEY, + rag_id BIGINT NOT NULL, + document_id BIGINT NOT NULL, + paragraph_index INT, + chunk_index INT, + content TEXT, + token_count INT, + vector_id VARCHAR(128), + content_hash VARCHAR(64) DEFAULT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON COLUMN sai_rag_chunk.content_hash IS 'chunk内容SHA-256,用于向量去重'; + +CREATE TRIGGER trigger_sai_rag_chunk_update + BEFORE UPDATE ON sai_rag_chunk + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_rag_chunk_rag ON sai_rag_chunk (rag_id); +CREATE INDEX idx_rag_chunk_document ON sai_rag_chunk (document_id); +CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash); + +-- ============================================================ +-- 五、MCP 服务管理 +-- ============================================================ + +-- 5.1 MCP 服务配置表 +CREATE TABLE IF NOT EXISTS sai_mcp_server +( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + transport_type SMALLINT DEFAULT 1, + base_uri VARCHAR(1024), + endpoint VARCHAR(1024), + command VARCHAR(1024), + args TEXT, + env_vars TEXT, + version VARCHAR(32) DEFAULT '1.0.0', + auth_type SMALLINT DEFAULT 0, + auth_config TEXT, + status SMALLINT DEFAULT 0, + capabilities TEXT, + last_connect_dt TIMESTAMP NULL, + creator_id BIGINT, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_mcp_server IS 'MCP服务配置表'; +COMMENT ON COLUMN sai_mcp_server.name IS 'MCP服务名称'; +COMMENT ON COLUMN sai_mcp_server.description IS 'MCP服务描述'; +COMMENT ON COLUMN sai_mcp_server.transport_type IS '传输类型: 1-SSE 2-Streamable HTTP 3-Stdio'; +COMMENT ON COLUMN sai_mcp_server.base_uri IS '服务基础地址(SSE/Streamable HTTP时使用)'; +COMMENT ON COLUMN sai_mcp_server.endpoint IS '端点路径(SSE/Streamable HTTP时可选)'; +COMMENT ON COLUMN sai_mcp_server.command IS 'Stdio命令(Stdio时必填)'; +COMMENT ON COLUMN sai_mcp_server.args IS 'Stdio命令参数(JSON数组)'; +COMMENT ON COLUMN sai_mcp_server.env_vars IS 'Stdio环境变量(JSON对象)'; +COMMENT ON COLUMN sai_mcp_server.version IS '版本'; +COMMENT ON COLUMN sai_mcp_server.auth_type IS '认证方式: 0-无需认证 1-API Key 2-OAuth 3-Basic Auth'; +COMMENT ON COLUMN sai_mcp_server.auth_config IS '认证配置(JSON)'; +COMMENT ON COLUMN sai_mcp_server.status IS '状态: 0-未连接 1-已连接 2-异常'; +COMMENT ON COLUMN sai_mcp_server.capabilities IS '能力列表(JSON数组)'; +COMMENT ON COLUMN sai_mcp_server.last_connect_dt IS '最后连接时间'; +COMMENT ON COLUMN sai_mcp_server.creator_id IS '创建者用户ID'; + +CREATE TRIGGER trigger_sai_mcp_server_update + BEFORE UPDATE ON sai_mcp_server + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_mcp_server_creator ON sai_mcp_server (creator_id); +CREATE INDEX idx_mcp_server_status ON sai_mcp_server (status); + +-- 5.2 智能体与MCP服务关联表(多对多) +CREATE TABLE IF NOT EXISTS sai_agent_mcp_server +( + id BIGSERIAL PRIMARY KEY, + agent_id BIGINT NOT NULL, + mcp_server_id BIGINT NOT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_agent_mcp UNIQUE (agent_id, mcp_server_id) +); + +COMMENT ON TABLE sai_agent_mcp_server IS '智能体MCP服务关联表'; +COMMENT ON COLUMN sai_agent_mcp_server.agent_id IS '智能体ID'; +COMMENT ON COLUMN sai_agent_mcp_server.mcp_server_id IS 'MCP服务ID'; + +CREATE INDEX idx_agent_mcp_agent ON sai_agent_mcp_server (agent_id); +CREATE INDEX idx_agent_mcp_server ON sai_agent_mcp_server (mcp_server_id); + +-- ============================================================ +-- 六、Skill 技能包管理 +-- ============================================================ + +-- 6.1 Skill 技能包表 +CREATE TABLE IF NOT EXISTS sai_skill +( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + file_name VARCHAR(255), + file_path VARCHAR(1024), + file_size BIGINT DEFAULT 0, + skill_content TEXT, + storage_path VARCHAR(500) DEFAULT NULL, + version BIGINT DEFAULT 0, + has_files BOOLEAN DEFAULT FALSE, + creator_id BIGINT, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_skill IS 'Skill技能包表'; +COMMENT ON COLUMN sai_skill.name IS 'Skill名称(从SKILL.md解析)'; +COMMENT ON COLUMN sai_skill.description IS 'Skill描述(从SKILL.md解析)'; +COMMENT ON COLUMN sai_skill.file_name IS '上传的zip文件名'; +COMMENT ON COLUMN sai_skill.file_path IS '解压后存储路径'; +COMMENT ON COLUMN sai_skill.file_size IS '文件大小(字节)'; +COMMENT ON COLUMN sai_skill.skill_content IS 'SKILL.md正文内容(去除frontmatter)'; +COMMENT ON COLUMN sai_skill.storage_path IS '对象存储相对路径前缀(如 skills/123/)'; +COMMENT ON COLUMN sai_skill.version IS '版本号,文件变更时自增,用于缓存一致性校验'; +COMMENT ON COLUMN sai_skill.has_files IS '是否包含支撑文件(0=仅SKILL.md,1=有scripts/references等)'; +COMMENT ON COLUMN sai_skill.creator_id IS '创建者用户ID'; + +CREATE TRIGGER trigger_sai_skill_update + BEFORE UPDATE ON sai_skill + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_skill_creator ON sai_skill (creator_id); + +-- 6.2 Skill 支撑文件内容表 +CREATE TABLE IF NOT EXISTS sai_skill_file +( + id BIGSERIAL PRIMARY KEY, + skill_id BIGINT NOT NULL, + file_path VARCHAR(255) NOT NULL, + content TEXT NOT NULL, + file_size INT NOT NULL, + encoding VARCHAR(50) DEFAULT 'utf-8', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_skill_path UNIQUE (skill_id, file_path) +); + +COMMENT ON TABLE sai_skill_file IS 'Skill支撑文件内容表'; +COMMENT ON COLUMN sai_skill_file.skill_id IS 'Skill ID'; +COMMENT ON COLUMN sai_skill_file.file_path IS '文件相对路径'; +COMMENT ON COLUMN sai_skill_file.content IS '文件内容'; +COMMENT ON COLUMN sai_skill_file.file_size IS '文件大小(字节)'; +COMMENT ON COLUMN sai_skill_file.encoding IS '编码方式'; +COMMENT ON COLUMN sai_skill_file.created_at IS '创建时间'; +COMMENT ON COLUMN sai_skill_file.updated_at IS '更新时间'; + +CREATE TRIGGER trigger_sai_skill_file_update + BEFORE UPDATE ON sai_skill_file + FOR EACH ROW + EXECUTE FUNCTION update_timestamp_updated_at(); + +CREATE INDEX idx_skill_id ON sai_skill_file (skill_id); + +-- 6.3 智能体与Skill关联表(多对多) +CREATE TABLE IF NOT EXISTS sai_agent_skill +( + id BIGSERIAL PRIMARY KEY, + agent_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_agent_skill UNIQUE (agent_id, skill_id) +); + +COMMENT ON TABLE sai_agent_skill IS '智能体Skill关联表'; +COMMENT ON COLUMN sai_agent_skill.agent_id IS '智能体ID'; +COMMENT ON COLUMN sai_agent_skill.skill_id IS 'Skill ID'; + +CREATE INDEX idx_agent_skill_agent ON sai_agent_skill (agent_id); +CREATE INDEX idx_agent_skill_skill ON sai_agent_skill (skill_id); + +-- ============================================================ +-- 七、客户端应用与节点 +-- ============================================================ + +-- 7.1 客户端应用 +CREATE TABLE IF NOT EXISTS sai_app +( + id BIGSERIAL PRIMARY KEY, + app_id VARCHAR(128) NOT NULL, + app_name VARCHAR(255) NOT NULL, + description VARCHAR(512), + token VARCHAR(128) NOT NULL, + route_strategy VARCHAR(32) DEFAULT 'LEAST_LOAD', + status SMALLINT DEFAULT 1, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_app_id UNIQUE (app_id) +); + +COMMENT ON TABLE sai_app IS '客户端应用'; +COMMENT ON COLUMN sai_app.app_id IS '应用唯一标识'; +COMMENT ON COLUMN sai_app.app_name IS '应用名称'; +COMMENT ON COLUMN sai_app.description IS '应用描述'; +COMMENT ON COLUMN sai_app.token IS '通信认证令牌'; +COMMENT ON COLUMN sai_app.route_strategy IS '路由策略'; +COMMENT ON COLUMN sai_app.status IS '1=启用, 0=停用'; + +CREATE TRIGGER trigger_sai_app_update + BEFORE UPDATE ON sai_app + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +-- 7.2 AI客户端实例节点 +CREATE TABLE IF NOT EXISTS sai_client_node +( + id BIGSERIAL PRIMARY KEY, + app_id VARCHAR(128) NOT NULL, + host_id VARCHAR(128) NOT NULL, + host_ip VARCHAR(64) NOT NULL, + grpc_port INT NOT NULL, + max_concurrent INT DEFAULT 10, + active_chats INT DEFAULT 0, + supported_providers TEXT, + labels TEXT, + expire_dt TIMESTAMP NOT NULL, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_client_node UNIQUE (app_id, host_id) +); + +COMMENT ON TABLE sai_client_node IS 'AI客户端实例节点'; +COMMENT ON COLUMN sai_client_node.app_id IS '所属应用ID'; +COMMENT ON COLUMN sai_client_node.host_id IS '客户端实例唯一标识'; +COMMENT ON COLUMN sai_client_node.host_ip IS '客户端IP'; +COMMENT ON COLUMN sai_client_node.grpc_port IS '客户端gRPC端口'; +COMMENT ON COLUMN sai_client_node.max_concurrent IS '最大并发对话数'; +COMMENT ON COLUMN sai_client_node.active_chats IS '当前活跃对话数'; +COMMENT ON COLUMN sai_client_node.supported_providers IS '支持的模型提供商(JSON数组)'; +COMMENT ON COLUMN sai_client_node.labels IS '路由标签'; +COMMENT ON COLUMN sai_client_node.expire_dt IS '过期时间(心跳更新)'; + +CREATE TRIGGER trigger_sai_client_node_update + BEFORE UPDATE ON sai_client_node + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_app_expire ON sai_client_node (app_id, expire_dt); + +-- ============================================================ +-- 八、存储与资源 +-- ============================================================ + +-- 8.1 存储实例 +CREATE TABLE IF NOT EXISTS sai_store_instance +( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(128) NOT NULL, + category SMALLINT NOT NULL, + type SMALLINT NOT NULL, + config TEXT DEFAULT NULL, + status SMALLINT DEFAULT 1, + is_default BOOLEAN DEFAULT FALSE, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +COMMENT ON TABLE sai_store_instance IS '存储实例'; +COMMENT ON COLUMN sai_store_instance.name IS '实例名称'; +COMMENT ON COLUMN sai_store_instance.category IS '分类: 1-向量库 2-搜索引擎'; +COMMENT ON COLUMN sai_store_instance.type IS '类型: 1-PG_VECTOR 2-MILVUS 3-ELASTICSEARCH 4-PG_FULLTEXT'; +COMMENT ON COLUMN sai_store_instance.config IS '连接参数 JSON'; +COMMENT ON COLUMN sai_store_instance.status IS '状态: 0-停用 1-启用'; +COMMENT ON COLUMN sai_store_instance.is_default IS '是否为该 category 下默认实例'; + +CREATE TRIGGER trigger_sai_store_instance_update + BEFORE UPDATE ON sai_store_instance + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_store_instance_category ON sai_store_instance (category); +CREATE INDEX idx_store_instance_type ON sai_store_instance (type); + +-- 8.2 通用资源存储 +CREATE TABLE IF NOT EXISTS sai_resource +( + id BIGSERIAL PRIMARY KEY, + storage_key VARCHAR(512) NOT NULL, + original_name VARCHAR(255) NOT NULL, + file_size BIGINT DEFAULT 0, + mime_type VARCHAR(128), + storage_type VARCHAR(32) NOT NULL DEFAULT 'LOCAL', + access_url VARCHAR(1024), + biz_type VARCHAR(64) NOT NULL DEFAULT 'GENERAL', + biz_id BIGINT, + creator_id BIGINT, + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT uk_storage_key UNIQUE (storage_key) +); + +COMMENT ON TABLE sai_resource IS '通用资源存储'; +COMMENT ON COLUMN sai_resource.storage_key IS '存储键(相对路径或对象Key)'; +COMMENT ON COLUMN sai_resource.original_name IS '原始文件名'; +COMMENT ON COLUMN sai_resource.file_size IS '文件大小(bytes)'; +COMMENT ON COLUMN sai_resource.mime_type IS 'MIME类型'; +COMMENT ON COLUMN sai_resource.storage_type IS '存储类型: LOCAL/MINIO'; +COMMENT ON COLUMN sai_resource.access_url IS '访问URL'; +COMMENT ON COLUMN sai_resource.biz_type IS '业务类型: AVATAR/ATTACHMENT/DOCUMENT/GENERAL'; +COMMENT ON COLUMN sai_resource.biz_id IS '关联业务ID'; +COMMENT ON COLUMN sai_resource.creator_id IS '上传者ID'; + +CREATE TRIGGER trigger_sai_resource_update + BEFORE UPDATE ON sai_resource + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +CREATE INDEX idx_biz ON sai_resource (biz_type, biz_id); +CREATE INDEX idx_creator ON sai_resource (creator_id); + +-- ============================================================ +-- 九、初始化数据 +-- ============================================================ + +-- 默认管理员:admin / admin123 +INSERT INTO sai_user VALUES (1, 2, NULL, 'admin', 'admin', '', 'pbkdf2$120000$c25haWwtYWktYWRtaW4tMQ==$kakglT/wYKOgv/77Ah1stie58d/JbY2nGgq5DwgUBw4=', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +SELECT setval(pg_get_serial_sequence('sai_user', 'id'), COALESCE((SELECT MAX(id) FROM sai_user), 1), TRUE); + +-- 插入常见的AI提供商 +INSERT INTO sai_model_provider (provider_name, provider_key, description, is_enabled) +VALUES ('OpenAI', 'openai', 'OpenAI官方模型 (GPT-4, GPT-3.5等)', TRUE), + ('Claude', 'claude', 'Anthropic Claude模型', TRUE), + ('Ollama', 'ollama', '本地开源模型 (Llama, Mistral等)', TRUE), + ('Google Gemini', 'gemini', 'Google Gemini模型', TRUE), + ('阿里云百炼', 'qwen', '阿里云百炼 OpenAI 兼容模型 (Qwen等)', TRUE), + ('DeepSeek', 'deepseek', 'DeepSeek OpenAI 兼容模型', TRUE), + ('智谱AI', 'zhipu', '智谱AI OpenAI 兼容模型 (GLM等)', TRUE) +ON CONFLICT (provider_key) DO NOTHING; + +INSERT INTO sai_model_config VALUES (1, 5, 'glm-5.1', 'glm-5.1', 'CHAT', 'openai-compatible', '', 'xxx', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{"frequencyPenalty":0.0,"maxTokens":20000,"presencePenalty":0.0,"stopSequences":[],"stream":true,"temperature":0.7,"timeoutMs":300000,"topK":1,"topP":1.0}', NULL, 'GLOBAL', TRUE, TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +SELECT setval(pg_get_serial_sequence('sai_model_config', 'id'), COALESCE((SELECT MAX(id) FROM sai_model_config), 1), TRUE); + +INSERT INTO sai_agent VALUES (1, '智测先锋专家', '智测先锋专家是一款专注于软件测试与质量保障领域的智能助手。它能够高效生成覆盖全面的测试用例,深度分析Bug根因并提供修复建议,支持编写自动化测试脚本,以及解读复杂的测试报告。适用于软件开发周期的各个QA阶段,包括单元测试、接口测试、UI自动化及回归测试规划。其核心特点是逻辑严密、注重边界与异常场景,帮助团队大幅提升测试效率与软件质量。', NULL, '你是一位资深的软件测试与质量保障(QA)专家,名为“智测先锋专家”。\n\n【角色定位】你是开发团队的最后一道防线,致力于保障软件产品的卓越质量。\n\n【专业领域】精通黑盒与白盒测试、自动化测试框架(如Selenium、Pytest)、接口与性能测试、安全测试及CI/CD持续集成流程。\n\n【回答风格】逻辑严密、条理清晰、客观专业。善于使用结构化排版(如Markdown列表、代码块、表格)呈现测试用例和步骤,语言精炼,直击痛点。\n\n【行为指南】\n1. 生成测试用例:必须覆盖正常流、异常流、边界值和兼容性等方面,确保测试的全面性与无遗漏。\n2. 分析Bug根因:从代码逻辑、数据状态、环境配置等多维度推导,不仅给出修复建议,更要提供预防性的测试策略。\n3. 编写自动化脚本:确保代码规范、包含必要注释与断言(Assert),并明确说明运行依赖与环境配置。\n4. 需求澄清:若用户提问模糊,主动追问业务背景、技术栈等关键细节,拒绝给出宽泛且无实操价值的答案。\n5. 风险预警:始终秉持质量第一理念,在解答中适时提示潜在的测试盲区与质量风险。', '你好!我是智测先锋专家,你的专属软件测试与质量保障顾问。无论是编写用例还是排查Bug,我都能为你提供专业支持!', '["如何为一个用户登录接口设计全面的测试用例?","帮我分析这个空指针异常Bug的可能根因及修复建议。","请提供一段Python的Pytest接口自动化测试脚本示例。","怎样制定一个高效的回归测试策略?"]', 2, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, 1, 20, 1, FALSE, 1, 1, NULL, '1', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +SELECT setval(pg_get_serial_sequence('sai_agent', 'id'), COALESCE((SELECT MAX(id) FROM sai_agent), 1), TRUE); + +INSERT INTO sai_app VALUES (1, '1', '测试', '', 'SAI_566a6bfbc26e4998b4841cc927d50c5d', 'LEAST_LOAD', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +SELECT setval(pg_get_serial_sequence('sai_app', 'id'), COALESCE((SELECT MAX(id) FROM sai_app), 1), TRUE); + +INSERT INTO sai_openapi_user VALUES (1, '1', '46ed53c6a20044c7bbd870848e80f92f', 1, '1', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +SELECT setval(pg_get_serial_sequence('sai_openapi_user', 'id'), COALESCE((SELECT MAX(id) FROM sai_openapi_user), 1), TRUE); diff --git a/script/sql/ry_ai.sql b/script/sql/ry_ai.sql index 4a1e8b3d4..29ac0669f 100644 --- a/script/sql/ry_ai.sql +++ b/script/sql/ry_ai.sql @@ -1,105 +1,53 @@ -- ============================================================ -- Snail AI MySQL 全量建表脚本(仅 CREATE,无 ALTER) --- 使用:mysql -u user -p database < snail_ai_schema.sql +-- 使用:mysql -u user -p database < ry_ai.sql -- ============================================================ + -- ============================================================ --- Enterprise RAG Schema for MySQL +-- 一、用户与权限 -- ============================================================ --- Knowledge Base -CREATE TABLE sai_rag -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(255) NOT NULL, - description TEXT, - icon VARCHAR(512), - embedding_model_id BIGINT(128) NOT NULL, - dimension_of_vector_model INT NOT NULL COMMENT '向量维度', - rerank_model_id BIGINT(128), - search_engine_instance_id BIGINT(128), - vector_store_instance_id BIGINT(128), - search_engine_enable TINYINT(1) DEFAULT 0, - delimiter VARCHAR(32) DEFAULT '\n\n', - rag_enhancement TEXT, - config TEXT DEFAULT NULL COMMENT 'RAG检索和问答的页面配置参数', - dedup_strategy TINYINT(1) NOT NULL DEFAULT 2 COMMENT '去重策略: 0=NONE 1=BY_NAME 2=BY_CONTENT 3=BY_NAME_OR_CONTENT', - dedup_action TINYINT(1) NOT NULL DEFAULT 0 COMMENT '冲突动作: 0=REJECT 1=SKIP 2=OVERWRITE', - upload_confirm TINYINT(1) NOT NULL DEFAULT 1 COMMENT '上传前二次确认: 0-关 1-开', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci; - --- RAG Documents -CREATE TABLE sai_rag_document -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - rag_id BIGINT NOT NULL, - name VARCHAR(255), - file_type VARCHAR(32), - source_type VARCHAR(32), - source_path VARCHAR(1024), - storage_path VARCHAR(1024), - storage_type VARCHAR(32) DEFAULT 'LOCAL', - file_size BIGINT DEFAULT 0, - content TEXT, - status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败', - error_msg TEXT, - chunk_count INT DEFAULT 0, - content_hash VARCHAR(64) DEFAULT NULL COMMENT '文件内容SHA-256哈希,用于去重', - resource_id BIGINT DEFAULT NULL COMMENT '关联资源库 sai_resource.id', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci; - -CREATE INDEX idx_rag_doc_rag ON sai_rag_document (rag_id); -CREATE INDEX idx_rag_content_hash ON sai_rag_document (rag_id, content_hash); -CREATE INDEX idx_rag_name ON sai_rag_document (rag_id, name); -CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id); - --- RAG Chunks -CREATE TABLE sai_rag_chunk -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - rag_id BIGINT NOT NULL, - document_id BIGINT NOT NULL, - paragraph_index INT, - chunk_index INT, - content TEXT, - token_count INT, - vector_id VARCHAR(128), - content_hash VARCHAR(64) DEFAULT NULL COMMENT 'chunk内容SHA-256,用于向量去重', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci; - -CREATE INDEX idx_rag_chunk_rag ON sai_rag_chunk (rag_id); -CREATE INDEX idx_rag_chunk_document ON sai_rag_chunk (document_id); -CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash); - +-- 1.1 用户表 CREATE TABLE sai_user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, role INT, totals INT, username VARCHAR(255), + nickname VARCHAR(128) DEFAULT NULL COMMENT '用户昵称', email VARCHAR(64), password VARCHAR(255) NOT NULL, + resource_id BIGINT DEFAULT NULL COMMENT '头像资源ID,关联 sai_resource.id', create_dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_username (username) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; --- ============================================ --- 1. AI 模型提供商表 --- ============================================ +-- 1.2 OpenAPI 外部用户映射表 +CREATE TABLE sai_openapi_user +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + app_id VARCHAR(128) NOT NULL COMMENT '关联 sai_app.app_id', + open_id VARCHAR(64) NOT NULL COMMENT '平台分配的唯一标识(UUID)', + platform_user_id BIGINT NOT NULL COMMENT '关联 sai_user.id,注册时自动创建', + external_id VARCHAR(256) DEFAULT NULL COMMENT '外部系统的用户标识(可选,幂等用)', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_app_open (app_id, open_id), + UNIQUE KEY uk_app_external (app_id, external_id), + INDEX idx_open_id (open_id), + INDEX idx_platform_user (platform_user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + COMMENT='OpenAPI 外部用户映射表'; + + +-- ============================================================ +-- 二、AI 模型管理 +-- ============================================================ + +-- 2.1 AI 模型提供商表 CREATE TABLE IF NOT EXISTS sai_model_provider ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -119,9 +67,7 @@ CREATE TABLE IF NOT EXISTS sai_model_provider CREATE INDEX idx_provider_key ON sai_model_provider (provider_key); CREATE INDEX idx_is_enabled ON sai_model_provider (is_enabled); --- ============================================ --- 2. AI模型配置表 --- ============================================ +-- 2.2 AI模型配置表 CREATE TABLE IF NOT EXISTS sai_model_config ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -152,9 +98,7 @@ CREATE INDEX idx_is_default ON sai_model_config (is_default); CREATE INDEX idx_scope ON sai_model_config (scope); CREATE INDEX idx_model_key ON sai_model_config (model_key); --- ============================================ --- 3. 模型使用统计表 --- ============================================ +-- 2.3 模型使用统计表 CREATE TABLE IF NOT EXISTS sai_model_usage_stat ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -179,11 +123,12 @@ CREATE INDEX idx_model_id ON sai_model_usage_stat (model_id); CREATE INDEX idx_user_id ON sai_model_usage_stat (user_id); CREATE INDEX idx_last_used_dt ON sai_model_usage_stat (last_used_dt); --- ============================================ --- 智能体相关表 --- ============================================ --- 智能体主表 +-- ============================================================ +-- 三、智能体(Agent) +-- ============================================================ + +-- 3.1 智能体主表 CREATE TABLE IF NOT EXISTS sai_agent ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -217,7 +162,7 @@ CREATE TABLE IF NOT EXISTS sai_agent CREATE INDEX idx_agent_creator ON sai_agent (creator_id); CREATE INDEX idx_agent_featured ON sai_agent (is_featured); --- 智能体对话表 +-- 3.2 智能体对话表 CREATE TABLE IF NOT EXISTS sai_agent_conversation ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -235,7 +180,7 @@ CREATE TABLE IF NOT EXISTS sai_agent_conversation CREATE INDEX idx_agent_conv_agent ON sai_agent_conversation (agent_id); CREATE INDEX idx_agent_conv_user ON sai_agent_conversation (user_id); --- 智能体对话消息记录表 +-- 3.3 智能体对话消息记录表 CREATE TABLE IF NOT EXISTS sai_agent_conversation_record ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -246,7 +191,9 @@ CREATE TABLE IF NOT EXISTS sai_agent_conversation_record content TEXT COMMENT '消息内容', thinking TEXT COMMENT '思考过程(仅assistant)', status INT DEFAULT 1 COMMENT '1=成功,2=失败,3=进行中', - token_count INT DEFAULT 0 COMMENT 'Token数', + input_tokens INT DEFAULT 0 COMMENT '输入Token数(prompt)', + output_tokens INT DEFAULT 0 COMMENT '输出Token数(completion)', + cache_tokens INT DEFAULT 0 COMMENT '缓存命中Token数', create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -254,14 +201,12 @@ CREATE TABLE IF NOT EXISTS sai_agent_conversation_record CREATE INDEX idx_agent_rec_conv ON sai_agent_conversation_record (conversation_id); --- 智能体使用统计表 +-- 3.4 智能体使用统计表 CREATE TABLE IF NOT EXISTS sai_agent_usage_stat ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, agent_id BIGINT NOT NULL COMMENT '智能体ID', user_id BIGINT NOT NULL COMMENT '用户ID', - user_name VARCHAR(255) COMMENT '用户名', - department VARCHAR(255) DEFAULT '' COMMENT '部门', message_count INT DEFAULT 0 COMMENT '消息条数', conversation_count INT DEFAULT 0 COMMENT '对话轮次', stat_date DATE NOT NULL COMMENT '统计日期', @@ -275,11 +220,107 @@ CREATE TABLE IF NOT EXISTS sai_agent_usage_stat CREATE INDEX idx_usage_agent ON sai_agent_usage_stat (agent_id); CREATE INDEX idx_usage_date ON sai_agent_usage_stat (stat_date); --- ============================================ --- MCP 服务管理 --- ============================================ +-- 3.5 用户订阅的智能体(多对多) +CREATE TABLE IF NOT EXISTS sai_user_agent +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + user_id BIGINT NOT NULL COMMENT '用户ID', + agent_id BIGINT NOT NULL COMMENT '智能体ID', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY uk_user_agent (user_id, agent_id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = '用户订阅的智能体'; --- MCP 服务配置表 +CREATE INDEX idx_user_agent_user ON sai_user_agent (user_id); + + +-- ============================================================ +-- 四、RAG 知识库 +-- ============================================================ + +-- 4.1 知识库主表 +CREATE TABLE sai_rag +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + icon VARCHAR(512), + embedding_model_id BIGINT(128) NOT NULL, + dimension_of_vector_model INT NOT NULL COMMENT '向量维度', + rerank_model_id BIGINT(128), + search_engine_instance_id BIGINT(128), + vector_store_instance_id BIGINT(128), + search_engine_enable TINYINT(1) DEFAULT 0, + delimiter VARCHAR(32) DEFAULT '\n\n', + rag_enhancement TEXT, + config TEXT DEFAULT NULL COMMENT 'RAG检索和问答的页面配置参数', + dedup_strategy TINYINT(1) NOT NULL DEFAULT 2 COMMENT '去重策略: 0=NONE 1=BY_NAME 2=BY_CONTENT 3=BY_NAME_OR_CONTENT', + dedup_action TINYINT(1) NOT NULL DEFAULT 0 COMMENT '冲突动作: 0=REJECT 1=SKIP 2=OVERWRITE', + upload_confirm TINYINT(1) NOT NULL DEFAULT 1 COMMENT '上传前二次确认: 0-关 1-开', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + +-- 4.2 RAG 文档表 +CREATE TABLE sai_rag_document +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + rag_id BIGINT NOT NULL, + name VARCHAR(255), + file_type VARCHAR(32), + source_type VARCHAR(32), + source_path VARCHAR(1024), + storage_path VARCHAR(1024), + storage_type VARCHAR(32) DEFAULT 'LOCAL', + file_size BIGINT DEFAULT 0, + content TEXT, + status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败', + error_msg TEXT, + chunk_count INT DEFAULT 0, + content_hash VARCHAR(64) DEFAULT NULL COMMENT '文件内容SHA-256哈希,用于去重', + resource_id BIGINT DEFAULT NULL COMMENT '关联资源库 sai_resource.id', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + +CREATE INDEX idx_rag_doc_rag ON sai_rag_document (rag_id); +CREATE INDEX idx_rag_content_hash ON sai_rag_document (rag_id, content_hash); +CREATE INDEX idx_rag_name ON sai_rag_document (rag_id, name); +CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id); + +-- 4.3 RAG 分块表 +CREATE TABLE sai_rag_chunk +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + rag_id BIGINT NOT NULL, + document_id BIGINT NOT NULL, + paragraph_index INT, + chunk_index INT, + content TEXT, + token_count INT, + vector_id VARCHAR(128), + content_hash VARCHAR(64) DEFAULT NULL COMMENT 'chunk内容SHA-256,用于向量去重', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + +CREATE INDEX idx_rag_chunk_rag ON sai_rag_chunk (rag_id); +CREATE INDEX idx_rag_chunk_document ON sai_rag_chunk (document_id); +CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash); + + +-- ============================================================ +-- 五、MCP 服务管理 +-- ============================================================ + +-- 5.1 MCP 服务配置表 CREATE TABLE IF NOT EXISTS sai_mcp_server ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -307,7 +348,7 @@ CREATE TABLE IF NOT EXISTS sai_mcp_server CREATE INDEX idx_mcp_server_creator ON sai_mcp_server (creator_id); CREATE INDEX idx_mcp_server_status ON sai_mcp_server (status); --- 智能体与MCP服务关联表(多对多) +-- 5.2 智能体与MCP服务关联表(多对多) CREATE TABLE IF NOT EXISTS sai_agent_mcp_server ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -322,25 +363,12 @@ CREATE TABLE IF NOT EXISTS sai_agent_mcp_server CREATE INDEX idx_agent_mcp_agent ON sai_agent_mcp_server (agent_id); CREATE INDEX idx_agent_mcp_server ON sai_agent_mcp_server (mcp_server_id); --- 用户订阅的智能体(多对多) -CREATE TABLE IF NOT EXISTS sai_user_agent -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - user_id BIGINT NOT NULL COMMENT '用户ID', - agent_id BIGINT NOT NULL COMMENT '智能体ID', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY uk_user_agent (user_id, agent_id) - ) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci COMMENT = '用户订阅的智能体'; -CREATE INDEX idx_user_agent_user ON sai_user_agent (user_id); +-- ============================================================ +-- 六、Skill 技能包管理 +-- ============================================================ --- ============================================ --- Skill 技能包管理 --- ============================================ - --- Skill 技能包表 +-- 6.1 Skill 技能包表 CREATE TABLE IF NOT EXISTS sai_skill ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -362,7 +390,7 @@ CREATE TABLE IF NOT EXISTS sai_skill CREATE INDEX idx_skill_creator ON sai_skill (creator_id); --- Skill 支撑文件内容表 +-- 6.2 Skill 支撑文件内容表 CREATE TABLE IF NOT EXISTS sai_skill_file ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -379,7 +407,7 @@ CREATE TABLE IF NOT EXISTS sai_skill_file DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Skill支撑文件内容表'; --- 智能体与Skill关联表(多对多) +-- 6.3 智能体与Skill关联表(多对多) CREATE TABLE IF NOT EXISTS sai_agent_skill ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -394,7 +422,55 @@ CREATE TABLE IF NOT EXISTS sai_agent_skill CREATE INDEX idx_agent_skill_agent ON sai_agent_skill (agent_id); CREATE INDEX idx_agent_skill_skill ON sai_agent_skill (skill_id); + -- ============================================================ +-- 七、客户端应用与节点 +-- ============================================================ + +-- 7.1 客户端应用 +CREATE TABLE IF NOT EXISTS sai_app +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + app_id VARCHAR(128) NOT NULL COMMENT '应用唯一标识', + app_name VARCHAR(255) NOT NULL COMMENT '应用名称', + description VARCHAR(512) COMMENT '应用描述', + token VARCHAR(128) NOT NULL COMMENT '通信认证令牌', + route_strategy VARCHAR(32) DEFAULT 'LEAST_LOAD' COMMENT '路由策略', + status TINYINT(1) DEFAULT 1 COMMENT '1=启用, 0=停用', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_app_id (app_id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = '客户端应用'; + +-- 7.2 AI客户端实例节点 +CREATE TABLE IF NOT EXISTS sai_client_node +( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + app_id VARCHAR(128) NOT NULL COMMENT '所属应用ID', + host_id VARCHAR(128) NOT NULL COMMENT '客户端实例唯一标识', + host_ip VARCHAR(64) NOT NULL COMMENT '客户端IP', + grpc_port INT NOT NULL COMMENT '客户端gRPC端口', + max_concurrent INT DEFAULT 10 COMMENT '最大并发对话数', + active_chats INT DEFAULT 0 COMMENT '当前活跃对话数', + supported_providers TEXT COMMENT '支持的模型提供商(JSON数组)', + labels TEXT COMMENT '路由标签', + expire_dt DATETIME NOT NULL COMMENT '过期时间(心跳更新)', + create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_client_node (app_id, host_id), + INDEX idx_app_expire (app_id, expire_dt) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci COMMENT = 'AI客户端实例节点'; + + +-- ============================================================ +-- 八、存储与资源 +-- ============================================================ + +-- 8.1 存储实例 CREATE TABLE IF NOT EXISTS sai_store_instance ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -413,69 +489,7 @@ CREATE TABLE IF NOT EXISTS sai_store_instance CREATE INDEX idx_store_instance_category ON sai_store_instance (category); CREATE INDEX idx_store_instance_type ON sai_store_instance (type); --- 客户端应用 --- ---------------------------- -CREATE TABLE IF NOT EXISTS sai_app -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - app_id VARCHAR(128) NOT NULL COMMENT '应用唯一标识', - app_name VARCHAR(255) NOT NULL COMMENT '应用名称', - description VARCHAR(512) COMMENT '应用描述', - token VARCHAR(128) NOT NULL COMMENT '通信认证令牌', - route_strategy VARCHAR(32) DEFAULT 'LEAST_LOAD' COMMENT '路由策略', - status TINYINT(1) DEFAULT 1 COMMENT '1=启用, 0=停用', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_app_id (app_id) - ) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci COMMENT = '客户端应用'; - --- ---------------------------- --- AI客户端实例节点 --- ---------------------------- -CREATE TABLE IF NOT EXISTS sai_client_node -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - app_id VARCHAR(128) NOT NULL COMMENT '所属应用ID', - host_id VARCHAR(128) NOT NULL COMMENT '客户端实例唯一标识', - host_ip VARCHAR(64) NOT NULL COMMENT '客户端IP', - grpc_port INT NOT NULL COMMENT '客户端gRPC端口', - max_concurrent INT DEFAULT 10 COMMENT '最大并发对话数', - active_chats INT DEFAULT 0 COMMENT '当前活跃对话数', - supported_providers TEXT COMMENT '支持的模型提供商(JSON数组)', - labels TEXT COMMENT '路由标签', - expire_dt DATETIME NOT NULL COMMENT '过期时间(心跳更新)', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_client_node (app_id, host_id), - INDEX idx_app_expire (app_id, expire_dt) - ) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_unicode_ci COMMENT = 'AI客户端实例节点'; - --- OpenAPI 外部用户映射表 -CREATE TABLE sai_openapi_user -( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - app_id VARCHAR(128) NOT NULL COMMENT '关联 sai_app.app_id', - open_id VARCHAR(64) NOT NULL COMMENT '平台分配的唯一标识(UUID)', - platform_user_id BIGINT NOT NULL COMMENT '关联 sai_user.id,注册时自动创建', - external_id VARCHAR(256) DEFAULT NULL COMMENT '外部系统的用户标识(可选,幂等用)', - nickname VARCHAR(128) DEFAULT NULL COMMENT '外部用户昵称', - create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_app_open (app_id, open_id), - UNIQUE KEY uk_app_external (app_id, external_id), - INDEX idx_open_id (open_id), - INDEX idx_platform_user (platform_user_id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci - COMMENT='OpenAPI 外部用户映射表'; - - --- ---------------------------- --- 通用资源存储 --- ---------------------------- +-- 8.2 通用资源存储 CREATE TABLE IF NOT EXISTS sai_resource ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -497,14 +511,13 @@ CREATE TABLE IF NOT EXISTS sai_resource DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '通用资源存储'; --- ============================================ --- 初始化数据 --- ============================================ + +-- ============================================================ +-- 九、初始化数据 +-- ============================================================ -- 默认管理员:admin / admin123 -INSERT INTO sai_user (id, role, username, email, password, create_dt, update_dt) -VALUES (1, 2, 'admin', '', 'pbkdf2$120000$c25haWwtYWktYWRtaW4tMQ==$kakglT/wYKOgv/77Ah1stie58d/JbY2nGgq5DwgUBw4=', - '2026-02-11 13:56:48.210429', '2026-02-11 13:56:48.210429'); +INSERT INTO sai_user VALUES (1, 2, NULL, 'admin', 'admin', '', 'pbkdf2$120000$c25haWwtYWktYWRtaW4tMQ==$kakglT/wYKOgv/77Ah1stie58d/JbY2nGgq5DwgUBw4=', NULL, NOW(), NOW()); -- 插入常见的AI提供商 INSERT INTO sai_model_provider (provider_name, provider_key, description, is_enabled) @@ -516,10 +529,10 @@ VALUES ('OpenAI', 'openai', 'OpenAI官方模型 (GPT-4, GPT-3.5等)', 1), ('DeepSeek', 'deepseek', 'DeepSeek OpenAI 兼容模型', 1), ('智谱AI', 'zhipu', '智谱AI OpenAI 兼容模型 (GLM等)', 1); -INSERT INTO sai_model_config VALUES (1, 5, 'glm-5.1', 'glm-5.1', 'CHAT', 'openai-compatible', '', 'xxx', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{\"frequencyPenalty\":0.0,\"maxTokens\":20000,\"presencePenalty\":0.0,\"stopSequences\":[],\"stream\":true,\"temperature\":0.7,\"timeoutMs\":300000,\"topK\":1,\"topP\":1.0}', NULL, 'GLOBAL', 1, 1, '2026-06-05 09:34:01', '2026-06-05 09:34:02'); +INSERT INTO sai_model_config VALUES (1, 5, 'glm-5.1', 'glm-5.1', 'CHAT', 'openai-compatible', '', 'xxx', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{\"frequencyPenalty\":0.0,\"maxTokens\":20000,\"presencePenalty\":0.0,\"stopSequences\":[],\"stream\":true,\"temperature\":0.7,\"timeoutMs\":300000,\"topK\":1,\"topP\":1.0}', NULL, 'GLOBAL', 1, 1, NOW(), NOW()); -INSERT INTO sai_agent VALUES (1, '智测先锋专家', '智测先锋专家是一款专注于软件测试与质量保障领域的智能助手。它能够高效生成覆盖全面的测试用例,深度分析Bug根因并提供修复建议,支持编写自动化测试脚本,以及解读复杂的测试报告。适用于软件开发周期的各个QA阶段,包括单元测试、接口测试、UI自动化及回归测试规划。其核心特点是逻辑严密、注重边界与异常场景,帮助团队大幅提升测试效率与软件质量。', NULL, '你是一位资深的软件测试与质量保障(QA)专家,名为“智测先锋专家”。\\n\\n【角色定位】你是开发团队的最后一道防线,致力于保障软件产品的卓越质量。\\n\\n【专业领域】精通黑盒与白盒测试、自动化测试框架(如Selenium、Pytest)、接口与性能测试、安全测试及CI/CD持续集成流程。\\n\\n【回答风格】逻辑严密、条理清晰、客观专业。善于使用结构化排版(如Markdown列表、代码块、表格)呈现测试用例和步骤,语言精炼,直击痛点。\\n\\n【行为指南】\\n1. 生成测试用例:必须覆盖正常流、异常流、边界值和兼容性等方面,确保测试的全面性与无遗漏。\\n2. 分析Bug根因:从代码逻辑、数据状态、环境配置等多维度推导,不仅给出修复建议,更要提供预防性的测试策略。\\n3. 编写自动化脚本:确保代码规范、包含必要注释与断言(Assert),并明确说明运行依赖与环境配置。\\n4. 需求澄清:若用户提问模糊,主动追问业务背景、技术栈等关键细节,拒绝给出宽泛且无实操价值的答案。\\n5. 风险预警:始终秉持质量第一理念,在解答中适时提示潜在的测试盲区与质量风险。', '你好!我是智测先锋专家,你的专属软件测试与质量保障顾问。无论是编写用例还是排查Bug,我都能为你提供专业支持!', '[\"如何为一个用户登录接口设计全面的测试用例?\",\"帮我分析这个空指针异常Bug的可能根因及修复建议。\",\"请提供一段Python的Pytest接口自动化测试脚本示例。\",\"怎样制定一个高效的回归测试策略?\"]', 2, 0, 0, 0, 0, 0, NULL, 1, 20, 1, 0, 1, 1, NULL, '1', '2026-06-05 09:34:50', '2026-06-05 09:34:51'); +INSERT INTO sai_agent VALUES (1, '智测先锋专家', '智测先锋专家是一款专注于软件测试与质量保障领域的智能助手。它能够高效生成覆盖全面的测试用例,深度分析Bug根因并提供修复建议,支持编写自动化测试脚本,以及解读复杂的测试报告。适用于软件开发周期的各个QA阶段,包括单元测试、接口测试、UI自动化及回归测试规划。其核心特点是逻辑严密、注重边界与异常场景,帮助团队大幅提升测试效率与软件质量。', NULL, '你是一位资深的软件测试与质量保障(QA)专家,名为“智测先锋专家”。\\n\\n【角色定位】你是开发团队的最后一道防线,致力于保障软件产品的卓越质量。\\n\\n【专业领域】精通黑盒与白盒测试、自动化测试框架(如Selenium、Pytest)、接口与性能测试、安全测试及CI/CD持续集成流程。\\n\\n【回答风格】逻辑严密、条理清晰、客观专业。善于使用结构化排版(如Markdown列表、代码块、表格)呈现测试用例和步骤,语言精炼,直击痛点。\\n\\n【行为指南】\\n1. 生成测试用例:必须覆盖正常流、异常流、边界值和兼容性等方面,确保测试的全面性与无遗漏。\\n2. 分析Bug根因:从代码逻辑、数据状态、环境配置等多维度推导,不仅给出修复建议,更要提供预防性的测试策略。\\n3. 编写自动化脚本:确保代码规范、包含必要注释与断言(Assert),并明确说明运行依赖与环境配置。\\n4. 需求澄清:若用户提问模糊,主动追问业务背景、技术栈等关键细节,拒绝给出宽泛且无实操价值的答案。\\n5. 风险预警:始终秉持质量第一理念,在解答中适时提示潜在的测试盲区与质量风险。', '你好!我是智测先锋专家,你的专属软件测试与质量保障顾问。无论是编写用例还是排查Bug,我都能为你提供专业支持!', '[\"如何为一个用户登录接口设计全面的测试用例?\",\"帮我分析这个空指针异常Bug的可能根因及修复建议。\",\"请提供一段Python的Pytest接口自动化测试脚本示例。\",\"怎样制定一个高效的回归测试策略?\"]', 2, 0, 0, 0, 0, 0, NULL, 1, 20, 1, 0, 1, 1, NULL, '1', NOW(), NOW()); -INSERT INTO sai_app VALUES (1, '1', '测试', '', 'SAI_566a6bfbc26e4998b4841cc927d50c5d', 'LEAST_LOAD', 1, '2026-06-05 09:32:50', '2026-06-05 09:32:50'); +INSERT INTO sai_app VALUES (1, '1', '测试', '', 'SAI_566a6bfbc26e4998b4841cc927d50c5d', 'LEAST_LOAD', 1, NOW(), NOW()); -INSERT INTO sai_openapi_user VALUES (1, '1', '46ed53c6a20044c7bbd870848e80f92f', 1, '1', 'test', NOW(), NOW()); +INSERT INTO sai_openapi_user VALUES (1, '1', '46ed53c6a20044c7bbd870848e80f92f', 1, '1', NOW(), NOW());