-- model-asynch 核心表(pgsql) -- 1) asynch_models:模型配置 -- 2) asynch_task:异步任务 -- 3) logs_model_op:操作日志(统计用) -- 4) logs_model_stat:按天模型请求统计(限流/监控用) -- ========================= -- 1) asynch_models -- ========================= CREATE TABLE IF NOT EXISTS asynch_models ( -- 基础字段 id BIGINT PRIMARY KEY, -- 主键ID(非自增) tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID creator VARCHAR(64) NOT NULL, -- 创建人 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间 updater VARCHAR(64) NOT NULL, -- 更新人 updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间 deleted_at TIMESTAMP(6), -- 删除时间(软删) -- 业务字段 model_name VARCHAR(128) NOT NULL, -- 模型名称 model_type SMALLINT NOT NULL DEFAULT 0, -- 模型类型 base_url VARCHAR(256) NOT NULL, -- 模型地址 http_method VARCHAR(8) NOT NULL DEFAULT 'POST', -- 请求方式 GET/POST head_msg VARCHAR(1024) DEFAULT '', -- 请求头绑定(支持多个,逗号分隔)示例 X-API:xxx,operation:true is_private SMALLINT NOT NULL DEFAULT 0, -- 是否私有化 0-私有 1-公共 enabled SMALLINT NOT NULL DEFAULT 1, -- 是否启用 0停用 1-启用 is_chat_model SMALLINT NOT NULL DEFAULT 0, -- 是否为对话模型 0-否 1-是 is_owner SMALLINT NOT NULL DEFAULT 99, -- 1=当前用户创建的,0=超级管理员的 api_key VARCHAR(256) NOT NULL DEFAULT '', -- 调用凭证,密钥 prompt TEXT NOT NULL DEFAULT '', -- 提示词内容(文本) form_json JSONB NOT NULL DEFAULT '{}'::jsonb, -- 表单结构(用于前端渲染) request_mapping JSONB NOT NULL DEFAULT '{}'::jsonb -- 请求映射 response_mapping JSONB NOT NULL DEFAULT '{}'::jsonb, -- 返回映射 response_body JSONB NOT NULL DEFAULT '{}'::jsonb, -- 返回主体 max_concurrency INT NOT NULL DEFAULT 10, -- 单模型最大并发 queue_limit INT NOT NULL DEFAULT 1000, -- 排队上限(近似控制) timeout_seconds INT NOT NULL DEFAULT 600, -- 调用模型服务超时(秒) expected_seconds INT NOT NULL DEFAULT 600, -- 模型预计执行时间(秒) retry_times SMALLINT NOT NULL DEFAULT 3, -- 失败重试次数 retry_queue_max_seconds INT NOT NULL DEFAULT 600, -- 失败重试最大排队时间(秒 0=插队到队首;>0=排队超过该时间后插队,否则仍到队尾) auto_clean_seconds INT NOT NULL DEFAULT 86400, -- 已下载(state=4 后的保留时间(秒),到期清理) remark TEXT DEFAULT '' -- 备注 response_token_field VARCHAR(128) NOT NULL DEFAULT ''; -- 响应中消耗token的字段映射 operator_name VARCHAR(64) NOT NULL DEFAULT '', -- 运营商名称 stream_config JSONB NOT NULL DEFAULT '{}'::jsonb, -- 流式配置 token_config JSONB NOT NULL DEFAULT '{}'::jsonb -- Token配置 extend_mapping JSONB NOT NULL DEFAULT '{}'::jsonb, query_config JSONB NOT NULL DEFAULT '{}'::jsonb; ); CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_models_tenant_creator_chat ON asynch_models(tenant_id, creator) WHERE is_chat_model = 1 AND deleted_at IS NULL; CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_models_tenant_model_name ON asynch_models(tenant_id, creator, model_name); CREATE INDEX IF NOT EXISTS idx_asynch_models_tenant_id ON asynch_models(tenant_id); CREATE INDEX IF NOT EXISTS idx_asynch_models_model_name ON asynch_models(model_name); CREATE INDEX IF NOT EXISTS idx_asynch_models_model_type ON asynch_models(model_type); CREATE INDEX IF NOT EXISTS idx_asynch_models_enabled ON asynch_models(enabled); CREATE INDEX IF NOT EXISTS idx_asynch_models_deleted_at ON asynch_models(deleted_at); COMMENT ON TABLE asynch_models IS '模型配置表'; COMMENT ON COLUMN asynch_models.id IS '主键ID(非自增)'; COMMENT ON COLUMN asynch_models.tenant_id IS '租户ID'; COMMENT ON COLUMN asynch_models.creator IS '创建人'; COMMENT ON COLUMN asynch_models.created_at IS '创建时间'; COMMENT ON COLUMN asynch_models.updater IS '更新人'; COMMENT ON COLUMN asynch_models.updated_at IS '更新时间'; COMMENT ON COLUMN asynch_models.deleted_at IS '删除时间(软删)'; COMMENT ON COLUMN asynch_models.model_name IS '模型名称'; COMMENT ON COLUMN asynch_models.model_type IS '模型类型'; COMMENT ON COLUMN asynch_models.base_url IS '模型地址'; COMMENT ON COLUMN asynch_models.http_method IS '请求方式 GET/POST'; COMMENT ON COLUMN asynch_models.head_msg IS '请求头绑定(支持多个,逗号分隔)示例 X-API:xxx,operation:true'; COMMENT ON COLUMN asynch_models.is_private IS '是否私有化 0-私有 1-公共'; COMMENT ON COLUMN asynch_models.enabled IS '是否启用 0停用 1-启用'; COMMENT ON COLUMN asynch_models.is_chat_model IS '是否为对话模型 0-否 1-是'; COMMENT ON COLUMN asynch_models.is_owner IS '1=当前用户创建的,0=超级管理员的'; COMMENT ON COLUMN asynch_models.api_key IS '调用凭证,密钥'; COMMENT ON COLUMN asynch_models.prompt IS '提示词内容(文本)'; COMMENT ON COLUMN asynch_models.form_json IS '表单结构(用于前端渲染,也用于后端校验)'; COMMENT ON COLUMN asynch_models.request_mapping IS '请求映射'; COMMENT ON COLUMN asynch_models.response_mapping IS '返回映射'; COMMENT ON COLUMN asynch_models.response_body IS '返回主体'; COMMENT ON COLUMN asynch_models.max_concurrency IS '单模型最大并发'; COMMENT ON COLUMN asynch_models.queue_limit IS '排队上限(近似控制)'; COMMENT ON COLUMN asynch_models.timeout_seconds IS '调用模型服务超时(秒)'; COMMENT ON COLUMN asynch_models.expected_seconds IS '模型预计执行时间(秒)'; COMMENT ON COLUMN asynch_models.retry_times IS '失败重试次数'; COMMENT ON COLUMN asynch_models.retry_queue_max_seconds IS '失败重试最大排队时间(秒 0=插队到队首;>0=排队超过该时间后插队,否则仍到队尾)'; COMMENT ON COLUMN asynch_models.auto_clean_seconds IS '已下载(state=4 后的保留时间(秒),到期清理)'; COMMENT ON COLUMN asynch_models.remark IS '备注'; COMMENT ON COLUMN asynch_models.response_token_field IS '响应中消耗token的字段映射'; COMMENT ON COLUMN asynch_models.operator_name IS '运营商名称'; COMMENT ON COLUMN asynch_models.extend_mapping IS '附加映射(请求时候额外字段)'; COMMENT ON COLUMN asynch_models.query_config IS '查询结果配置(通过task_id查询结果相关配置)'; COMMENT ON COLUMN asynch_models.token_config IS '{ "zh_ratio": 1.0, // 中文字符→token系数 "en_ratio": 1.3, // 英文单词→token系数 "space_ratio": 0.1, // 空格系数 "punctuation_ratio": 0.1, // 标点系数 "max_window_size": 8192, // 模型最大窗口 "reserve_ratio": 0.2, // 预留回复空间比例 "min_reserve": 512, // 最少预留token数 }'; -- ========================= -- 2) asynch_task -- ========================= CREATE TABLE IF NOT EXISTS asynch_task ( -- 基础字段 id BIGINT PRIMARY KEY, -- 主键ID(非自增) tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID creator VARCHAR(64) NOT NULL, -- 创建人 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间 updater VARCHAR(64) NOT NULL, -- 更新人 updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间 deleted_at TIMESTAMP(6), -- 删除时间(软删) -- 业务字段 model_name VARCHAR(128) NOT NULL, -- 模型名称 task_id VARCHAR(64) NOT NULL, -- 任务ID(对外返回) biz_name VARCHAR(128) NOT NULL DEFAULT '', -- 业务名称(调用方模块/系统) callback_url VARCHAR(512) DEFAULT '', -- 回调地址(可选,用于后续业务通知) model_key VARCHAR(1024) DEFAULT '', -- 动态请求头(用于覆盖/补充模型配置 head_msg),如 X-API-Key:xxx state SMALLINT NOT NULL DEFAULT 0, -- 0排队中/1执行中/2成功/3失败/4已下载 oss_file VARCHAR(512) DEFAULT '', -- 结果文件OSS地址 file_type VARCHAR(32) DEFAULT '', -- 文件类型(mp3/mp4/png/...) file_size BIGINT NOT NULL DEFAULT 0, -- 文件大小(字节) error_msg TEXT DEFAULT '', -- 错误信息 started_at TIMESTAMP, -- 开始执行时间 finished_at TIMESTAMP, -- 执行结束时间 duration_seconds BIGINT NOT NULL DEFAULT 0, -- 耗时(秒):从创建到完成(成功/失败)整体耗时 expire_at TIMESTAMP, -- state=4 后写入,用于清理 retry_count INT NOT NULL DEFAULT 0, -- 已重试次数(不含首次) enqueue_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 入队时间(用于排队顺序) phase SMALLINT NOT NULL DEFAULT 0, -- 0模型阶段/1OSS阶段 tmp_file TEXT DEFAULT '', -- 临时结果文件路径(phase=1 时仅重试 OSS 上传) input_ref TEXT DEFAULT '', -- 输入引用(如OSS/业务资源ID等) request_payload JSONB, -- 请求参数(可选) text_result TEXT DEFAULT '', -- 文本类结果(可选,支持直接回调) epicycle_id VARCHAR(64) DEFAULT '', -- 轮次ID expend_tokens BIGINT NOT NULL DEFAULT 0 -- 消耗 token 数 ); CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_task_tenant_task_id ON asynch_task(tenant_id, task_id); CREATE INDEX IF NOT EXISTS idx_asynch_task_tenant_id ON asynch_task(tenant_id); CREATE INDEX IF NOT EXISTS idx_asynch_task_model_name ON asynch_task(model_name); CREATE INDEX IF NOT EXISTS idx_asynch_task_biz_name ON asynch_task(biz_name); CREATE INDEX IF NOT EXISTS idx_asynch_task_model_key ON asynch_task(model_key); CREATE INDEX IF NOT EXISTS idx_asynch_task_state ON asynch_task(state); CREATE INDEX IF NOT EXISTS idx_asynch_task_enqueue_at ON asynch_task(enqueue_at); CREATE INDEX IF NOT EXISTS idx_asynch_task_updated_at ON asynch_task(updated_at); CREATE INDEX IF NOT EXISTS idx_asynch_task_expire_at ON asynch_task(expire_at); CREATE INDEX IF NOT EXISTS idx_asynch_task_deleted_at ON asynch_task(deleted_at); CREATE INDEX IF NOT EXISTS idx_asynch_task_epicycle_id ON asynch_task(epicycle_id); CREATE INDEX IF NOT EXISTS idx_asynch_task_expend_tokens ON asynch_task(expend_tokens); COMMENT ON TABLE asynch_task IS '异步任务表'; COMMENT ON COLUMN asynch_task.id IS '主键ID(非自增)'; COMMENT ON COLUMN asynch_task.tenant_id IS '租户ID'; COMMENT ON COLUMN asynch_task.creator IS '创建人'; COMMENT ON COLUMN asynch_task.created_at IS '创建时间'; COMMENT ON COLUMN asynch_task.updater IS '更新人'; COMMENT ON COLUMN asynch_task.updated_at IS '更新时间'; COMMENT ON COLUMN asynch_task.deleted_at IS '删除时间(软删)'; COMMENT ON COLUMN asynch_task.model_name IS '模型名称'; COMMENT ON COLUMN asynch_task.task_id IS '任务ID(对外返回)'; COMMENT ON COLUMN asynch_task.biz_name IS '业务名称(调用方模块/系统)'; COMMENT ON COLUMN asynch_task.callback_url IS '回调地址(可选,用于后续业务通知)'; COMMENT ON COLUMN asynch_task.model_key IS '动态请求头(用于覆盖/补充模型配置 head_msg),如 X-API-Key:xxx'; COMMENT ON COLUMN asynch_task.state IS '0排队中/1执行中/2成功/3失败/4已下载'; COMMENT ON COLUMN asynch_task.oss_file IS '结果文件OSS地址'; COMMENT ON COLUMN asynch_task.file_type IS '文件类型(mp3/mp4/png/...)'; COMMENT ON COLUMN asynch_task.file_size IS '文件大小(字节)'; COMMENT ON COLUMN asynch_task.error_msg IS '错误信息'; COMMENT ON COLUMN asynch_task.started_at IS '开始执行时间'; COMMENT ON COLUMN asynch_task.finished_at IS '执行结束时间'; COMMENT ON COLUMN asynch_task.duration_seconds IS '耗时(秒):从创建到完成(成功/失败)整体耗时'; COMMENT ON COLUMN asynch_task.expire_at IS 'state=4 后写入,用于清理'; COMMENT ON COLUMN asynch_task.retry_count IS '已重试次数(不含首次)'; COMMENT ON COLUMN asynch_task.enqueue_at IS '入队时间(用于排队顺序)'; COMMENT ON COLUMN asynch_task.phase IS '执行阶段 模型阶段/1OSS阶段(模型已成功,等待上传OSS)'; COMMENT ON COLUMN asynch_task.tmp_file IS '临时结果文件路径(phase=1 时仅重试 OSS 上传)'; COMMENT ON COLUMN asynch_task.input_ref IS '输入引用(如OSS/业务资源ID等)'; COMMENT ON COLUMN asynch_task.request_payload IS '请求参数(可选,JSON)'; COMMENT ON COLUMN asynch_task.text_result IS '文本类结果(可选,支持直接回调)'; COMMENT ON COLUMN asynch_task.epicycle_id IS '轮次ID(用于标识同一轮次的任务)'; COMMENT ON COLUMN asynch_task.expend_tokens IS '消耗 token 数'; -- ========================= -- 3) logs_model_op -- ========================= CREATE TABLE IF NOT EXISTS logs_model_op ( -- 基础字段 id BIGINT PRIMARY KEY, tenant_id BIGINT NOT NULL DEFAULT 0, creator VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updater VARCHAR(64) NOT NULL, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP(6), -- 基础审计信息 ip VARCHAR(64) DEFAULT '', user_agent VARCHAR(256) DEFAULT '', api_path VARCHAR(256) DEFAULT '', http_method VARCHAR(16) DEFAULT '', -- 业务信息 biz_name VARCHAR(128) NOT NULL DEFAULT '', -- 调用方业务模块/系统 model_name VARCHAR(128) NOT NULL DEFAULT '', task_id VARCHAR(64) NOT NULL DEFAULT '', -- 统计字段 op_type VARCHAR(64) NOT NULL DEFAULT 'createTask', -- 操作类型(默认创建任务) success SMALLINT NOT NULL DEFAULT 1, -- 1成功/0失败 error_msg TEXT DEFAULT '', cost_ms BIGINT NOT NULL DEFAULT 0, -- 耗时(毫秒) -- 请求/响应 JSON(用于后期统计分析) request_payload JSONB, response_payload JSONB ); CREATE INDEX IF NOT EXISTS idx_logs_model_op_tenant_time ON logs_model_op(tenant_id, created_at); CREATE INDEX IF NOT EXISTS idx_logs_model_op_model_name ON logs_model_op(model_name); CREATE INDEX IF NOT EXISTS idx_logs_model_op_biz_name ON logs_model_op(biz_name); CREATE INDEX IF NOT EXISTS idx_logs_model_op_task_id ON logs_model_op(task_id); CREATE INDEX IF NOT EXISTS idx_logs_model_op_op_type ON logs_model_op(op_type); CREATE INDEX IF NOT EXISTS idx_logs_model_op_deleted_at ON logs_model_op(deleted_at); COMMENT ON TABLE logs_model_op IS '操作记录日志表(创建任务等,用于统计)'; COMMENT ON COLUMN logs_model_op.id IS '主键ID(非自增)'; COMMENT ON COLUMN logs_model_op.tenant_id IS '租户ID'; COMMENT ON COLUMN logs_model_op.creator IS '创建人'; COMMENT ON COLUMN logs_model_op.created_at IS '创建时间'; COMMENT ON COLUMN logs_model_op.updater IS '更新人'; COMMENT ON COLUMN logs_model_op.updated_at IS '更新时间'; COMMENT ON COLUMN logs_model_op.deleted_at IS '删除时间(软删)'; COMMENT ON COLUMN logs_model_op.ip IS '客户端IP'; COMMENT ON COLUMN logs_model_op.user_agent IS 'User-Agent'; COMMENT ON COLUMN logs_model_op.api_path IS '接口路径'; COMMENT ON COLUMN logs_model_op.http_method IS 'HTTP方法'; COMMENT ON COLUMN logs_model_op.biz_name IS '业务名称(调用方模块/系统)'; COMMENT ON COLUMN logs_model_op.model_name IS '模型名称'; COMMENT ON COLUMN logs_model_op.task_id IS '任务ID'; COMMENT ON COLUMN logs_model_op.op_type IS '操作类型(如 createTask/getTaskResult/getTaskBatch 等)'; COMMENT ON COLUMN logs_model_op.success IS '是否成功:1成功/0失败'; COMMENT ON COLUMN logs_model_op.error_msg IS '错误信息(失败时)'; COMMENT ON COLUMN logs_model_op.cost_ms IS '耗时(毫秒)'; COMMENT ON COLUMN logs_model_op.request_payload IS '请求 JSON'; COMMENT ON COLUMN logs_model_op.response_payload IS '响应 JSON'; -- ========================= -- 4) logs_model_stat -- ========================= CREATE TABLE IF NOT EXISTS logs_model_stat ( day DATE NOT NULL, -- 天(YYYY-MM-DD) tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID creator VARCHAR(64) NOT NULL DEFAULT '', -- 创建人 model_name VARCHAR(128) NOT NULL DEFAULT '', -- 模型名称 request_count BIGINT NOT NULL DEFAULT 0, -- 请求次数 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(day, tenant_id, creator, model_name) ); -- 便于时间段/租户/人/模型过滤 CREATE INDEX IF NOT EXISTS idx_logs_model_stat_tenant_day ON logs_model_stat(tenant_id, day); CREATE INDEX IF NOT EXISTS idx_logs_model_stat_day ON logs_model_stat(day); CREATE INDEX IF NOT EXISTS idx_logs_model_stat_model_name ON logs_model_stat(model_name); CREATE INDEX IF NOT EXISTS idx_logs_model_stat_creator ON logs_model_stat(creator); COMMENT ON TABLE logs_model_stat IS '按天模型请求统计(用于限流/监控)'; COMMENT ON COLUMN logs_model_stat.day IS '天(YYYY-MM-DD)'; COMMENT ON COLUMN logs_model_stat.tenant_id IS '租户ID'; COMMENT ON COLUMN logs_model_stat.creator IS '创建人'; COMMENT ON COLUMN logs_model_stat.model_name IS '模型名称'; COMMENT ON COLUMN logs_model_stat.request_count IS '请求次数'; COMMENT ON COLUMN logs_model_stat.created_at IS '创建时间'; COMMENT ON COLUMN logs_model_stat.updated_at IS '更新时间';