update snail-ai 1.1.0
This commit is contained in:
@@ -43,7 +43,7 @@
|
|||||||
<redisson.version>4.6.1</redisson.version>
|
<redisson.version>4.6.1</redisson.version>
|
||||||
<lock4j.version>2.2.7</lock4j.version>
|
<lock4j.version>2.2.7</lock4j.version>
|
||||||
<snailjob.version>2.0.2</snailjob.version>
|
<snailjob.version>2.0.2</snailjob.version>
|
||||||
<snailai.version>1.0.0</snailai.version>
|
<snailai.version>1.1.0</snailai.version>
|
||||||
|
|
||||||
<!-- 通用工具、编译增强与代码生成相关依赖版本 -->
|
<!-- 通用工具、编译增强与代码生成相关依赖版本 -->
|
||||||
<hutool.version>5.8.47</hutool.version>
|
<hutool.version>5.8.47</hutool.version>
|
||||||
|
|||||||
-124
@@ -1,124 +0,0 @@
|
|||||||
package org.dromara.common.ai.handler;
|
|
||||||
|
|
||||||
import com.aizuda.snail.ai.agent.chat.starter.SnailAiChatGatewayController;
|
|
||||||
import com.aizuda.snail.ai.common.execption.BaseSnailAiException;
|
|
||||||
import com.aizuda.snail.ai.common.execption.SnailAiAuthenticationException;
|
|
||||||
import com.aizuda.snail.ai.common.model.ModelCallException;
|
|
||||||
import com.aizuda.snail.ai.common.model.Result;
|
|
||||||
import jakarta.validation.ConstraintViolation;
|
|
||||||
import jakarta.validation.ConstraintViolationException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.context.MessageSourceResolvable;
|
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
||||||
import org.springframework.validation.BindException;
|
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|
||||||
import org.springframework.web.method.annotation.HandlerMethodValidationException;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Snail AI Chat 网关异常处理器。
|
|
||||||
* <p>
|
|
||||||
* /api/snail/chat/** 接口由 Snail AI SDK 前端消费,响应结构需要保持 SDK Result(status/message/data),
|
|
||||||
* 不能落到 RuoYi 通用 R(code/msg/data) 格式。
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
|
||||||
@RestControllerAdvice(assignableTypes = SnailAiChatGatewayController.class)
|
|
||||||
public class SnailAiChatExceptionHandler {
|
|
||||||
|
|
||||||
private static final int AUTHENTICATION_ERROR_STATUS = 5001;
|
|
||||||
|
|
||||||
@ExceptionHandler(SnailAiAuthenticationException.class)
|
|
||||||
public Result<Void> handleAuthenticationException(SnailAiAuthenticationException e) {
|
|
||||||
log.warn("Snail AI Chat authentication failed: {}", e.getMessage());
|
|
||||||
return Result.fail(AUTHENTICATION_ERROR_STATUS, defaultMessage(e, "认证失败,请重新登录"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(BaseSnailAiException.class)
|
|
||||||
public Result<Void> handleSnailAiException(BaseSnailAiException e) {
|
|
||||||
log.warn("Snail AI Chat request failed: {}", e.getMessage());
|
|
||||||
return Result.fail(defaultMessage(e, "AI 服务请求失败,请稍后再试"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(ModelCallException.class)
|
|
||||||
public Result<Void> handleModelCallException(ModelCallException e) {
|
|
||||||
log.warn("Snail AI Chat model call failed: {}", e.getMessage(), e);
|
|
||||||
return Result.fail(defaultMessage(e, "模型调用失败,请稍后再试"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler({
|
|
||||||
BindException.class,
|
|
||||||
MethodArgumentNotValidException.class,
|
|
||||||
HandlerMethodValidationException.class
|
|
||||||
})
|
|
||||||
public Result<Void> handleValidationException(Exception e) {
|
|
||||||
log.warn("Snail AI Chat validation failed: {}", e.getMessage());
|
|
||||||
return Result.fail(validationMessage(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(ConstraintViolationException.class)
|
|
||||||
public Result<Void> handleConstraintViolationException(ConstraintViolationException e) {
|
|
||||||
log.warn("Snail AI Chat constraint validation failed: {}", e.getMessage());
|
|
||||||
String message = e.getConstraintViolations().stream()
|
|
||||||
.map(ConstraintViolation::getMessage)
|
|
||||||
.filter(this::hasText)
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
return Result.fail(hasText(message) ? message : "请求参数校验失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
|
||||||
public Result<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
|
|
||||||
log.warn("Snail AI Chat request body parse failed: {}", e.getMessage());
|
|
||||||
return Result.fail("请求参数格式错误");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(IllegalArgumentException.class)
|
|
||||||
public Result<Void> handleIllegalArgumentException(IllegalArgumentException e) {
|
|
||||||
log.warn("Snail AI Chat illegal argument: {}", e.getMessage());
|
|
||||||
return Result.fail(defaultMessage(e, "请求参数不合法"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(IllegalStateException.class)
|
|
||||||
public Result<Void> handleIllegalStateException(IllegalStateException e) {
|
|
||||||
log.warn("Snail AI Chat illegal state: {}", e.getMessage());
|
|
||||||
return Result.fail(defaultMessage(e, "AI 会话状态异常,请刷新后重试"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
|
||||||
public Result<Void> handleException(Exception e) {
|
|
||||||
log.error("Snail AI Chat unexpected exception", e);
|
|
||||||
return Result.fail("AI 服务异常,请稍后再试");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String validationMessage(Exception e) {
|
|
||||||
Collection<? extends MessageSourceResolvable> errors;
|
|
||||||
if (e instanceof BindException bindException) {
|
|
||||||
errors = bindException.getAllErrors();
|
|
||||||
} else if (e instanceof MethodArgumentNotValidException methodArgumentNotValidException) {
|
|
||||||
errors = methodArgumentNotValidException.getBindingResult().getAllErrors();
|
|
||||||
} else if (e instanceof HandlerMethodValidationException handlerMethodValidationException) {
|
|
||||||
errors = handlerMethodValidationException.getAllErrors();
|
|
||||||
} else {
|
|
||||||
return "请求参数校验失败";
|
|
||||||
}
|
|
||||||
String message = errors.stream()
|
|
||||||
.map(MessageSourceResolvable::getDefaultMessage)
|
|
||||||
.filter(this::hasText)
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
return hasText(message) ? message : "请求参数校验失败";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String defaultMessage(Throwable e, String fallback) {
|
|
||||||
return hasText(e.getMessage()) ? e.getMessage() : fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasText(String value) {
|
|
||||||
return value != null && !value.isBlank();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -17,7 +17,7 @@ public class SnailAiServerApplication {
|
|||||||
* @param args 启动参数
|
* @param args 启动参数
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
com.aizuda.snail.ai.starter.SnailAiSpringbootApplication.main(args);
|
com.aizuda.snail.ai.starter.SnailAiApplication.main(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,24 @@ snail-ai:
|
|||||||
access-key: minioadmin
|
access-key: minioadmin
|
||||||
secret-key: minioadmin
|
secret-key: minioadmin
|
||||||
bucket: snail-ai
|
bucket: snail-ai
|
||||||
|
# RAG 文档解析与图片 OCR 配置
|
||||||
|
rag:
|
||||||
|
docling:
|
||||||
|
enabled: ${SNAIL_AI_RAG_DOCLING_ENABLED:true}
|
||||||
|
url: ${SNAIL_AI_RAG_DOCLING_URL:http://127.0.0.1:5100}
|
||||||
|
timeout-seconds: ${SNAIL_AI_RAG_DOCLING_TIMEOUT_SECONDS:300}
|
||||||
|
concurrency: ${SNAIL_AI_RAG_DOCLING_CONCURRENCY:3}
|
||||||
|
health-timeout-millis: ${SNAIL_AI_RAG_DOCLING_HEALTH_TIMEOUT_MILLIS:3000}
|
||||||
|
poll-interval-millis: ${SNAIL_AI_RAG_DOCLING_POLL_INTERVAL_MILLIS:3000}
|
||||||
|
status-timeout-millis: ${SNAIL_AI_RAG_DOCLING_STATUS_TIMEOUT_MILLIS:10000}
|
||||||
|
result-timeout-millis: ${SNAIL_AI_RAG_DOCLING_RESULT_TIMEOUT_MILLIS:30000}
|
||||||
|
max-image-count: ${SNAIL_AI_RAG_DOCLING_MAX_IMAGE_COUNT:100}
|
||||||
|
max-image-bytes: ${SNAIL_AI_RAG_DOCLING_MAX_IMAGE_BYTES:10485760}
|
||||||
|
paddle-ocr-enabled: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_ENABLED:true}
|
||||||
|
paddle-ocr-url: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_URL:http://127.0.0.1:8866/ocr}
|
||||||
|
paddle-ocr-timeout-millis: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_TIMEOUT_MILLIS:180000}
|
||||||
|
paddle-ocr-batch-size: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_BATCH_SIZE:5}
|
||||||
|
vision-ocr-fallback-enabled: ${SNAIL_AI_RAG_DOCLING_VISION_OCR_FALLBACK_ENABLED:false}
|
||||||
# 短期记忆配置
|
# 短期记忆配置
|
||||||
memory:
|
memory:
|
||||||
short-term:
|
short-term:
|
||||||
|
|||||||
@@ -162,6 +162,11 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
# 时区上海
|
# 时区上海
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
|
# Docling 与 PaddleOCR 服务需单独部署;host 网络模式下默认通过宿主机端口访问
|
||||||
|
SNAIL_AI_RAG_DOCLING_ENABLED: ${SNAIL_AI_RAG_DOCLING_ENABLED:-true}
|
||||||
|
SNAIL_AI_RAG_DOCLING_URL: ${SNAIL_AI_RAG_DOCLING_URL:-http://127.0.0.1:5100}
|
||||||
|
SNAIL_AI_RAG_DOCLING_PADDLE_OCR_ENABLED: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_ENABLED:-true}
|
||||||
|
SNAIL_AI_RAG_DOCLING_PADDLE_OCR_URL: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_URL:-http://127.0.0.1:8866/ocr}
|
||||||
ports:
|
ports:
|
||||||
- "8900:8900"
|
- "8900:8900"
|
||||||
- "18888:18888"
|
- "18888:18888"
|
||||||
|
|||||||
@@ -318,6 +318,7 @@ CREATE TABLE IF NOT EXISTS sai_agent_conversation_record
|
|||||||
role VARCHAR(16) DEFAULT 'user',
|
role VARCHAR(16) DEFAULT 'user',
|
||||||
content TEXT,
|
content TEXT,
|
||||||
thinking TEXT,
|
thinking TEXT,
|
||||||
|
metadata TEXT DEFAULT NULL,
|
||||||
status INT DEFAULT 1,
|
status INT DEFAULT 1,
|
||||||
input_tokens INT DEFAULT 0,
|
input_tokens INT DEFAULT 0,
|
||||||
output_tokens INT DEFAULT 0,
|
output_tokens INT DEFAULT 0,
|
||||||
@@ -332,6 +333,7 @@ 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.role IS 'user/assistant';
|
||||||
COMMENT ON COLUMN sai_agent_conversation_record.content IS '消息内容';
|
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.thinking IS '思考过程(仅assistant)';
|
||||||
|
COMMENT ON COLUMN sai_agent_conversation_record.metadata IS '消息扩展元数据JSON';
|
||||||
COMMENT ON COLUMN sai_agent_conversation_record.status IS '1=成功,2=失败,3=进行中';
|
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.input_tokens IS '输入Token数(prompt)';
|
||||||
COMMENT ON COLUMN sai_agent_conversation_record.output_tokens IS '输出Token数(completion)';
|
COMMENT ON COLUMN sai_agent_conversation_record.output_tokens IS '输出Token数(completion)';
|
||||||
@@ -438,6 +440,13 @@ CREATE TABLE sai_rag_document
|
|||||||
status SMALLINT DEFAULT 0,
|
status SMALLINT DEFAULT 0,
|
||||||
error_msg TEXT,
|
error_msg TEXT,
|
||||||
chunk_count INT DEFAULT 0,
|
chunk_count INT DEFAULT 0,
|
||||||
|
page_count INT DEFAULT 0,
|
||||||
|
element_count INT DEFAULT 0,
|
||||||
|
table_count INT DEFAULT 0,
|
||||||
|
image_count INT DEFAULT 0,
|
||||||
|
parse_time INT DEFAULT 0,
|
||||||
|
md_content TEXT DEFAULT NULL,
|
||||||
|
doc_metadata TEXT DEFAULT NULL,
|
||||||
content_hash VARCHAR(64) DEFAULT NULL,
|
content_hash VARCHAR(64) DEFAULT NULL,
|
||||||
resource_id BIGINT DEFAULT NULL,
|
resource_id BIGINT DEFAULT NULL,
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -458,6 +467,39 @@ 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_name ON sai_rag_document (rag_id, name);
|
||||||
CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id);
|
CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id);
|
||||||
|
|
||||||
|
CREATE TABLE sai_rag_document_image
|
||||||
|
(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
rag_id BIGINT NOT NULL,
|
||||||
|
document_id BIGINT NOT NULL,
|
||||||
|
chunk_id BIGINT DEFAULT NULL,
|
||||||
|
resource_id BIGINT DEFAULT NULL,
|
||||||
|
image_index INT,
|
||||||
|
image_url VARCHAR(1024),
|
||||||
|
caption TEXT,
|
||||||
|
figure_no VARCHAR(64),
|
||||||
|
figure_title VARCHAR(512),
|
||||||
|
section_title VARCHAR(512),
|
||||||
|
source_page INT,
|
||||||
|
document_name VARCHAR(255),
|
||||||
|
ocr_text TEXT,
|
||||||
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON TABLE sai_rag_document_image IS 'RAG document parsed image table';
|
||||||
|
COMMENT ON COLUMN sai_rag_document_image.resource_id IS 'Linked resource id in sai_resource';
|
||||||
|
|
||||||
|
CREATE TRIGGER trigger_sai_rag_document_image_update
|
||||||
|
BEFORE UPDATE ON sai_rag_document_image
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION update_timestamp();
|
||||||
|
|
||||||
|
CREATE INDEX idx_rag_doc_image_rag ON sai_rag_document_image (rag_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_document ON sai_rag_document_image (document_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_chunk ON sai_rag_document_image (chunk_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_resource ON sai_rag_document_image (resource_id);
|
||||||
|
|
||||||
-- 4.3 RAG 分块表
|
-- 4.3 RAG 分块表
|
||||||
CREATE TABLE sai_rag_chunk
|
CREATE TABLE sai_rag_chunk
|
||||||
(
|
(
|
||||||
@@ -470,11 +512,13 @@ CREATE TABLE sai_rag_chunk
|
|||||||
token_count INT,
|
token_count INT,
|
||||||
vector_id VARCHAR(128),
|
vector_id VARCHAR(128),
|
||||||
content_hash VARCHAR(64) DEFAULT NULL,
|
content_hash VARCHAR(64) DEFAULT NULL,
|
||||||
|
source_type VARCHAR(20) NOT NULL DEFAULT 'TEXT',
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON COLUMN sai_rag_chunk.content_hash IS 'chunk内容SHA-256,用于向量去重';
|
COMMENT ON COLUMN sai_rag_chunk.content_hash IS 'chunk内容SHA-256,用于向量去重';
|
||||||
|
COMMENT ON COLUMN sai_rag_chunk.source_type IS 'chunk来源类型:TEXT文本、IMAGE图片';
|
||||||
|
|
||||||
CREATE TRIGGER trigger_sai_rag_chunk_update
|
CREATE TRIGGER trigger_sai_rag_chunk_update
|
||||||
BEFORE UPDATE ON sai_rag_chunk
|
BEFORE UPDATE ON sai_rag_chunk
|
||||||
@@ -484,6 +528,7 @@ CREATE TRIGGER trigger_sai_rag_chunk_update
|
|||||||
CREATE INDEX idx_rag_chunk_rag ON sai_rag_chunk (rag_id);
|
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_rag_chunk_document ON sai_rag_chunk (document_id);
|
||||||
CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash);
|
CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash);
|
||||||
|
CREATE INDEX idx_chunk_rag_source_type ON sai_rag_chunk (rag_id, source_type);
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- 五、MCP 服务管理
|
-- 五、MCP 服务管理
|
||||||
@@ -501,11 +546,8 @@ CREATE TABLE IF NOT EXISTS sai_mcp_server
|
|||||||
command VARCHAR(1024),
|
command VARCHAR(1024),
|
||||||
args TEXT,
|
args TEXT,
|
||||||
env_vars TEXT,
|
env_vars TEXT,
|
||||||
version VARCHAR(32) DEFAULT '1.0.0',
|
timeout BIGINT DEFAULT 60000,
|
||||||
auth_type SMALLINT DEFAULT 0,
|
headers TEXT,
|
||||||
auth_config TEXT,
|
|
||||||
status SMALLINT DEFAULT 0,
|
|
||||||
capabilities TEXT,
|
|
||||||
last_connect_dt TIMESTAMP NULL,
|
last_connect_dt TIMESTAMP NULL,
|
||||||
creator_id BIGINT,
|
creator_id BIGINT,
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -521,11 +563,8 @@ 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.command IS 'Stdio命令(Stdio时必填)';
|
||||||
COMMENT ON COLUMN sai_mcp_server.args IS 'Stdio命令参数(JSON数组)';
|
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.env_vars IS 'Stdio环境变量(JSON对象)';
|
||||||
COMMENT ON COLUMN sai_mcp_server.version IS '版本';
|
COMMENT ON COLUMN sai_mcp_server.timeout 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.headers IS '请求头(JSON对象)';
|
||||||
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.last_connect_dt IS '最后连接时间';
|
||||||
COMMENT ON COLUMN sai_mcp_server.creator_id IS '创建者用户ID';
|
COMMENT ON COLUMN sai_mcp_server.creator_id IS '创建者用户ID';
|
||||||
|
|
||||||
@@ -535,7 +574,6 @@ CREATE TRIGGER trigger_sai_mcp_server_update
|
|||||||
EXECUTE FUNCTION update_timestamp();
|
EXECUTE FUNCTION update_timestamp();
|
||||||
|
|
||||||
CREATE INDEX idx_mcp_server_creator ON sai_mcp_server (creator_id);
|
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服务关联表(多对多)
|
-- 5.2 智能体与MCP服务关联表(多对多)
|
||||||
CREATE TABLE IF NOT EXISTS sai_agent_mcp_server
|
CREATE TABLE IF NOT EXISTS sai_agent_mcp_server
|
||||||
|
|||||||
+39
-6
@@ -190,6 +190,7 @@ CREATE TABLE IF NOT EXISTS sai_agent_conversation_record
|
|||||||
role VARCHAR(16) DEFAULT 'user' COMMENT 'user/assistant',
|
role VARCHAR(16) DEFAULT 'user' COMMENT 'user/assistant',
|
||||||
content TEXT COMMENT '消息内容',
|
content TEXT COMMENT '消息内容',
|
||||||
thinking TEXT COMMENT '思考过程(仅assistant)',
|
thinking TEXT COMMENT '思考过程(仅assistant)',
|
||||||
|
metadata LONGTEXT DEFAULT NULL COMMENT '消息扩展元数据JSON',
|
||||||
status INT DEFAULT 1 COMMENT '1=成功,2=失败,3=进行中',
|
status INT DEFAULT 1 COMMENT '1=成功,2=失败,3=进行中',
|
||||||
input_tokens INT DEFAULT 0 COMMENT '输入Token数(prompt)',
|
input_tokens INT DEFAULT 0 COMMENT '输入Token数(prompt)',
|
||||||
output_tokens INT DEFAULT 0 COMMENT '输出Token数(completion)',
|
output_tokens INT DEFAULT 0 COMMENT '输出Token数(completion)',
|
||||||
@@ -280,6 +281,13 @@ CREATE TABLE sai_rag_document
|
|||||||
status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败',
|
status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败',
|
||||||
error_msg TEXT,
|
error_msg TEXT,
|
||||||
chunk_count INT DEFAULT 0,
|
chunk_count INT DEFAULT 0,
|
||||||
|
page_count INT DEFAULT 0 COMMENT 'Docling parse page count',
|
||||||
|
element_count INT DEFAULT 0 COMMENT 'Docling parse element count',
|
||||||
|
table_count INT DEFAULT 0 COMMENT 'Docling parse table count',
|
||||||
|
image_count INT DEFAULT 0 COMMENT 'Docling parse image count',
|
||||||
|
parse_time INT DEFAULT 0 COMMENT 'Parse duration in milliseconds',
|
||||||
|
md_content LONGTEXT DEFAULT NULL COMMENT 'Docling markdown content',
|
||||||
|
doc_metadata LONGTEXT DEFAULT NULL COMMENT 'Docling document metadata JSON',
|
||||||
content_hash VARCHAR(64) DEFAULT NULL COMMENT '文件内容SHA-256哈希,用于去重',
|
content_hash VARCHAR(64) DEFAULT NULL COMMENT '文件内容SHA-256哈希,用于去重',
|
||||||
resource_id BIGINT DEFAULT NULL COMMENT '关联资源库 sai_resource.id',
|
resource_id BIGINT DEFAULT NULL COMMENT '关联资源库 sai_resource.id',
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -293,6 +301,33 @@ 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_name ON sai_rag_document (rag_id, name);
|
||||||
CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id);
|
CREATE INDEX idx_rag_doc_resource ON sai_rag_document (resource_id);
|
||||||
|
|
||||||
|
CREATE TABLE sai_rag_document_image
|
||||||
|
(
|
||||||
|
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
rag_id BIGINT NOT NULL,
|
||||||
|
document_id BIGINT NOT NULL,
|
||||||
|
chunk_id BIGINT DEFAULT NULL,
|
||||||
|
resource_id BIGINT DEFAULT NULL,
|
||||||
|
image_index INT,
|
||||||
|
image_url VARCHAR(1024),
|
||||||
|
caption TEXT,
|
||||||
|
figure_no VARCHAR(64),
|
||||||
|
figure_title VARCHAR(512),
|
||||||
|
section_title VARCHAR(512),
|
||||||
|
source_page INT,
|
||||||
|
document_name VARCHAR(255),
|
||||||
|
ocr_text TEXT,
|
||||||
|
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_image_rag ON sai_rag_document_image (rag_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_document ON sai_rag_document_image (document_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_chunk ON sai_rag_document_image (chunk_id);
|
||||||
|
CREATE INDEX idx_rag_doc_image_resource ON sai_rag_document_image (resource_id);
|
||||||
|
|
||||||
-- 4.3 RAG 分块表
|
-- 4.3 RAG 分块表
|
||||||
CREATE TABLE sai_rag_chunk
|
CREATE TABLE sai_rag_chunk
|
||||||
(
|
(
|
||||||
@@ -305,6 +340,7 @@ CREATE TABLE sai_rag_chunk
|
|||||||
token_count INT,
|
token_count INT,
|
||||||
vector_id VARCHAR(128),
|
vector_id VARCHAR(128),
|
||||||
content_hash VARCHAR(64) DEFAULT NULL COMMENT 'chunk内容SHA-256,用于向量去重',
|
content_hash VARCHAR(64) DEFAULT NULL COMMENT 'chunk内容SHA-256,用于向量去重',
|
||||||
|
source_type VARCHAR(20) NOT NULL DEFAULT 'TEXT' COMMENT 'chunk来源类型:TEXT文本、IMAGE图片',
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
) ENGINE = InnoDB
|
) ENGINE = InnoDB
|
||||||
@@ -314,6 +350,7 @@ CREATE TABLE sai_rag_chunk
|
|||||||
CREATE INDEX idx_rag_chunk_rag ON sai_rag_chunk (rag_id);
|
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_rag_chunk_document ON sai_rag_chunk (document_id);
|
||||||
CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash);
|
CREATE INDEX idx_chunk_rag_hash ON sai_rag_chunk (rag_id, content_hash);
|
||||||
|
CREATE INDEX idx_chunk_rag_source_type ON sai_rag_chunk (rag_id, source_type);
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
@@ -332,11 +369,8 @@ CREATE TABLE IF NOT EXISTS sai_mcp_server
|
|||||||
command VARCHAR(1024) COMMENT 'Stdio命令(Stdio时必填)',
|
command VARCHAR(1024) COMMENT 'Stdio命令(Stdio时必填)',
|
||||||
args TEXT COMMENT 'Stdio命令参数(JSON数组)',
|
args TEXT COMMENT 'Stdio命令参数(JSON数组)',
|
||||||
env_vars TEXT COMMENT 'Stdio环境变量(JSON对象)',
|
env_vars TEXT COMMENT 'Stdio环境变量(JSON对象)',
|
||||||
version VARCHAR(32) DEFAULT '1.0.0' COMMENT '版本',
|
timeout BIGINT DEFAULT 60000 COMMENT '超时时间(毫秒)',
|
||||||
auth_type TINYINT(1) DEFAULT 0 COMMENT '认证方式: 0-无需认证 1-API Key 2-OAuth 3-Basic Auth',
|
headers TEXT COMMENT '请求头(JSON对象)',
|
||||||
auth_config TEXT COMMENT '认证配置(JSON)',
|
|
||||||
status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-未连接 1-已连接 2-异常',
|
|
||||||
capabilities TEXT COMMENT '能力列表(JSON数组)',
|
|
||||||
last_connect_dt TIMESTAMP NULL COMMENT '最后连接时间',
|
last_connect_dt TIMESTAMP NULL COMMENT '最后连接时间',
|
||||||
creator_id BIGINT COMMENT '创建者用户ID',
|
creator_id BIGINT COMMENT '创建者用户ID',
|
||||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -346,7 +380,6 @@ CREATE TABLE IF NOT EXISTS sai_mcp_server
|
|||||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP服务配置表';
|
COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP服务配置表';
|
||||||
|
|
||||||
CREATE INDEX idx_mcp_server_creator ON sai_mcp_server (creator_id);
|
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服务关联表(多对多)
|
-- 5.2 智能体与MCP服务关联表(多对多)
|
||||||
CREATE TABLE IF NOT EXISTS sai_agent_mcp_server
|
CREATE TABLE IF NOT EXISTS sai_agent_mcp_server
|
||||||
|
|||||||
Reference in New Issue
Block a user