-- ============================================================================ -- 对话附件(module/agent/attachment)元数据表 -- -- 落在 **master PG**(与 chat/message 管理表同库)。附件问答三路的登记与归属锚点: -- A 内联 小文档/小表格 → 提取文本进消息 -- B Python 大表格 → 流式扫描(行数/表头/样本),Agent 用 execute_python 直读文件 -- C RAG 大文档 → sidecar 全文 + 分块向量化(chat_att_vec_{caseId}_d{dims}) -- -- 隔离:user_id/case_id/session_id 三重归属,loadForSession 校验不过即拒绝; -- 向量侧另按会话过滤(payload 里带 sessionId,检索 SQL 强制 WHERE)。 -- 设计文档:输入框附件问答设计(2026-09) -- ============================================================================ create table if not exists chat_attachment ( id bigint primary key, user_id bigint not null, -- 归属用户(加载校验) case_id bigint not null, -- 归属案件(加载校验) session_id bigint not null, -- 归属会话(加载校验 + RAG 检索过滤) file_name varchar(500) not null, -- 原始文件名(展示用) file_path varchar(1000) not null, -- 原件落盘路径(路径 B 的 execute_python 读它) sidecar_path varchar(1000), -- 衍生文本:文档全文 .txt / xlsx 转 .csv mime varchar(100), -- Tika 探测的 MIME kind varchar(20) not null, -- DOCUMENT / TABLE / UNSUPPORTED size_bytes bigint default 0, char_count integer default 0, -- 提取文本字符数(文档) row_count integer default 0, -- 数据行数(表格,不含表头) truncated integer default 0, -- 1=内容已截断(文档内联截断或索引超块数) inline_text text, -- 路径 A 的内联全文(≤inline-max-chars) index_blocks integer default 0, -- 路径 C 已向量化块数 index_status varchar(20), -- 路径 C:NONE / READY / FAILED status varchar(20) not null, -- READY / FAILED link_message_id bigint, -- 关联的消息 id(发出后回填,孤儿清理依据) fail_reason varchar(1000), create_time timestamp default current_timestamp, update_time timestamp ); create index if not exists idx_chat_att_session on chat_attachment (session_id); create index if not exists idx_chat_att_status on chat_attachment (status, link_message_id);