refactor(ai): 合并ai_document表到vector_store表,切换文档ID类型为字符串

- 删除旧的ai_document表及相关索引,新增vector_store表兼容Spring AI PgVectorStore结构
- 调整实体类AiDocument映射到vector_store表,使用字符串ID代替Long类型
- 修改Mapper接口及XML中所有ID相关SQL使用字符串类型,并替换表名为vector_store
- 修改服务接口与实现类,文档ID参数类型统一为字符串
- 处理文档分块时改用UUID生成chunk ID,确保唯一且格式正确
- 禁用Spring Ai PgVectorStore的自动schema初始化,使用手动创建的表结构
- 更新配置文件OpenAI模型API key及基础URL配置,支持多模型与聊天功能
- 优化日志输出,增加分块文档ID和父文档ID显示,方便调试追踪
This commit is contained in:
2026-03-30 17:43:29 +08:00
parent 9f972f5e30
commit 37da5da044
11 changed files with 202 additions and 188 deletions

View File

@@ -8,6 +8,122 @@
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- =====================================================
-- Spring AI PgVectorStore 向量存储表
-- 用于RAG文档向量存储和相似度搜索
-- 兼容PgVectorStore默认结构同时支持完整文档管理
-- =====================================================
DROP TABLE IF EXISTS vector_store CASCADE;
CREATE TABLE vector_store (
-- PgVectorStore 核心字段
id VARCHAR(255) PRIMARY KEY,
content TEXT,
metadata JSONB,
embedding vector(1536),
-- 关联关系
project_id BIGINT,
timeline_node_id BIGINT,
kb_id BIGINT,
-- 文档来源
source_type VARCHAR(50),
source_id BIGINT,
-- 文档扩展信息
title VARCHAR(500),
content_raw TEXT,
summary TEXT,
-- 文档元数据
doc_type VARCHAR(50),
language VARCHAR(10) DEFAULT 'zh',
file_type VARCHAR(50),
file_size BIGINT,
file_path VARCHAR(500),
-- 时间信息 (用于时间维度检索)
doc_date DATE,
doc_datetime TIMESTAMP,
-- 分块信息(大文档分块存储)
chunk_index INT DEFAULT 0,
chunk_total INT DEFAULT 1,
chunk_parent_id VARCHAR(255),
-- 标签和分类
tags JSONB,
category VARCHAR(100),
-- 使用统计
view_count INT DEFAULT 0,
query_count INT DEFAULT 0,
last_queried_at TIMESTAMP,
-- 状态
status VARCHAR(20) DEFAULT 'active',
error_message TEXT,
-- 创建信息
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
-- 外键约束
CONSTRAINT fk_vs_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_timeline FOREIGN KEY (timeline_node_id) REFERENCES project_timeline(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_kb FOREIGN KEY (kb_id) REFERENCES ai_knowledge_base(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_create_by FOREIGN KEY (create_by) REFERENCES sys_user(id) ON DELETE SET NULL
);
-- 创建向量索引使用IVFFlat算法适合中等数据量
CREATE INDEX idx_vector_store_embedding ON vector_store
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- 创建其他常用索引
CREATE INDEX idx_vs_project ON vector_store(project_id) WHERE deleted = 0;
CREATE INDEX idx_vs_timeline ON vector_store(timeline_node_id) WHERE deleted = 0;
CREATE INDEX idx_vs_kb ON vector_store(kb_id) WHERE deleted = 0;
CREATE INDEX idx_vs_source ON vector_store(source_type, source_id) WHERE deleted = 0;
CREATE INDEX idx_vs_status ON vector_store(status);
CREATE INDEX idx_vs_type ON vector_store(doc_type);
CREATE INDEX idx_vs_tags ON vector_store USING GIN(tags);
CREATE INDEX idx_vs_chunk_parent ON vector_store(chunk_parent_id) WHERE chunk_parent_id IS NOT NULL;
COMMENT ON TABLE vector_store IS '向量存储表 - 用于RAG文档检索和知识库管理';
COMMENT ON COLUMN vector_store.id IS '文档ID字符串类型兼容PgVectorStore';
COMMENT ON COLUMN vector_store.content IS '文档内容文本';
COMMENT ON COLUMN vector_store.metadata IS '文档元数据JSONB格式兼容PgVectorStore';
COMMENT ON COLUMN vector_store.embedding IS '向量嵌入1536维';
COMMENT ON COLUMN vector_store.project_id IS '关联项目ID';
COMMENT ON COLUMN vector_store.timeline_node_id IS '关联时间节点ID';
COMMENT ON COLUMN vector_store.kb_id IS '关联知识库ID';
COMMENT ON COLUMN vector_store.source_type IS '来源类型: project-项目文档, risk-风险文档, ticket-工单, report-日报, upload-上传文件, knowledge-知识库, chat-对话记录';
COMMENT ON COLUMN vector_store.source_id IS '来源记录ID';
COMMENT ON COLUMN vector_store.title IS '文档标题';
COMMENT ON COLUMN vector_store.content_raw IS '原始内容(带格式)';
COMMENT ON COLUMN vector_store.summary IS 'AI生成的摘要';
COMMENT ON COLUMN vector_store.doc_type IS '文档类型: requirement-需求, design-设计, plan-计划, report-报告, contract-合同, photo-照片, other-其他';
COMMENT ON COLUMN vector_store.language IS '语言: zh-中文, en-英文';
COMMENT ON COLUMN vector_store.file_type IS '文件类型: pdf, doc, txt, md, jpg, png等';
COMMENT ON COLUMN vector_store.file_size IS '文件大小(字节)';
COMMENT ON COLUMN vector_store.file_path IS '文件存储路径';
COMMENT ON COLUMN vector_store.doc_date IS '文档日期(如日报日期、照片拍摄日期)';
COMMENT ON COLUMN vector_store.doc_datetime IS '文档时间戳';
COMMENT ON COLUMN vector_store.chunk_index IS '分块序号';
COMMENT ON COLUMN vector_store.chunk_total IS '总分块数';
COMMENT ON COLUMN vector_store.chunk_parent_id IS '父文档ID(分块时使用)';
COMMENT ON COLUMN vector_store.tags IS '标签数组';
COMMENT ON COLUMN vector_store.category IS '分类';
COMMENT ON COLUMN vector_store.view_count IS '查看次数';
COMMENT ON COLUMN vector_store.query_count IS '被检索次数';
COMMENT ON COLUMN vector_store.last_queried_at IS '最后被检索时间';
COMMENT ON COLUMN vector_store.status IS '状态: active-可用, processing-处理中, error-错误, archived-归档';
COMMENT ON COLUMN vector_store.error_message IS '错误信息';
-- 设置时区
SET timezone = 'Asia/Shanghai';
@@ -969,118 +1085,8 @@ COMMENT ON COLUMN ai_knowledge_base.status IS '状态: active-可用, archived-
-- 11. AI服务相关表
-- =====================================================
-- AI文档向量表 (用于RAG知识库)
DROP TABLE IF EXISTS ai_document CASCADE;
CREATE TABLE ai_document (
id BIGSERIAL PRIMARY KEY,
doc_id UUID DEFAULT uuid_generate_v4(),
-- 关联关系
project_id BIGINT,
timeline_node_id BIGINT,
kb_id BIGINT,
-- 文档来源
source_type VARCHAR(50) NOT NULL,
source_id BIGINT,
-- 文档内容
title VARCHAR(500),
content TEXT NOT NULL,
content_raw TEXT,
summary TEXT,
-- 向量嵌入 (1536维适配OpenAI, 可调整为其他维度)
embedding vector(1536),
-- 文档元数据
doc_type VARCHAR(50),
language VARCHAR(10) DEFAULT 'zh',
file_type VARCHAR(50),
file_size BIGINT,
file_path VARCHAR(500),
-- 时间信息 (用于时间维度检索)
doc_date DATE,
doc_datetime TIMESTAMP,
-- 分块信息(大文档分块存储)
chunk_index INT DEFAULT 0,
chunk_total INT DEFAULT 1,
chunk_parent_id BIGINT,
-- 标签和分类
tags JSONB,
category VARCHAR(100),
-- 使用统计
view_count INT DEFAULT 0,
query_count INT DEFAULT 0,
last_queried_at TIMESTAMP,
-- 状态
status VARCHAR(20) DEFAULT 'active',
error_message TEXT,
-- 创建信息
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
-- 外键约束
CONSTRAINT fk_ai_doc_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE SET NULL,
CONSTRAINT fk_ai_doc_timeline FOREIGN KEY (timeline_node_id) REFERENCES project_timeline(id) ON DELETE SET NULL,
CONSTRAINT fk_ai_doc_kb FOREIGN KEY (kb_id) REFERENCES ai_knowledge_base(id) ON DELETE SET NULL
);
-- 创建向量索引 (使用IVFFlat或HNSW)
-- IVFFlat: 适合中等数据量, 内存占用小
-- HNSW: 适合大数据量, 查询更快但内存占用大
CREATE INDEX idx_ai_document_embedding ON ai_document
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- 创建其他常用索引
CREATE INDEX idx_ai_doc_project ON ai_document(project_id) WHERE deleted = 0;
CREATE INDEX idx_ai_doc_timeline ON ai_document(timeline_node_id) WHERE deleted = 0;
CREATE INDEX idx_ai_doc_kb ON ai_document(kb_id) WHERE deleted = 0;
CREATE INDEX idx_ai_doc_source ON ai_document(source_type, source_id) WHERE deleted = 0;
CREATE INDEX idx_ai_doc_status ON ai_document(status);
CREATE INDEX idx_ai_doc_type ON ai_document(doc_type);
CREATE INDEX idx_ai_doc_tags ON ai_document USING GIN(tags);
COMMENT ON TABLE ai_document IS 'AI文档向量表 - 存储所有用于RAG的文档向量';
COMMENT ON COLUMN ai_document.doc_id IS '文档唯一标识';
COMMENT ON COLUMN ai_document.project_id IS '关联项目ID';
COMMENT ON COLUMN ai_document.timeline_node_id IS '关联时间节点ID';
COMMENT ON COLUMN ai_document.kb_id IS '关联知识库ID';
COMMENT ON COLUMN ai_document.source_type IS '来源类型: project-项目文档, risk-风险文档, ticket-工单, report-日报, upload-上传文件, knowledge-知识库, chat-对话记录';
COMMENT ON COLUMN ai_document.source_id IS '来源记录ID';
COMMENT ON COLUMN ai_document.title IS '文档标题';
COMMENT ON COLUMN ai_document.content IS '文档内容(纯文本)';
COMMENT ON COLUMN ai_document.content_raw IS '原始内容(带格式)';
COMMENT ON COLUMN ai_document.summary IS 'AI生成的摘要';
COMMENT ON COLUMN ai_document.embedding IS '向量嵌入';
COMMENT ON COLUMN ai_document.doc_type IS '文档类型: requirement-需求, design-设计, plan-计划, report-报告, contract-合同, photo-照片, other-其他';
COMMENT ON COLUMN ai_document.language IS '语言: zh-中文, en-英文';
COMMENT ON COLUMN ai_document.file_type IS '文件类型: pdf, doc, txt, md, jpg, png等';
COMMENT ON COLUMN ai_document.file_size IS '文件大小(字节)';
COMMENT ON COLUMN ai_document.file_path IS '文件存储路径';
COMMENT ON COLUMN ai_document.doc_date IS '文档日期(如日报日期、照片拍摄日期)';
COMMENT ON COLUMN ai_document.doc_datetime IS '文档时间戳';
COMMENT ON COLUMN ai_document.chunk_index IS '分块序号';
COMMENT ON COLUMN ai_document.chunk_total IS '总分块数';
COMMENT ON COLUMN ai_document.chunk_parent_id IS '父文档ID(分块时使用)';
COMMENT ON COLUMN ai_document.tags IS '标签数组';
COMMENT ON COLUMN ai_document.category IS '分类';
COMMENT ON COLUMN ai_document.view_count IS '查看次数';
COMMENT ON COLUMN ai_document.query_count IS '被检索次数';
COMMENT ON COLUMN ai_document.last_queried_at IS '最后被检索时间';
COMMENT ON COLUMN ai_document.status IS '状态: active-可用, processing-处理中, error-错误, archived-归档';
COMMENT ON COLUMN ai_document.error_message IS '错误信息';
-- AI对话记录表 (合并会话管理功能无需单独的session表)
-- 注ai_document表已合并到vector_store表中
DROP TABLE IF EXISTS ai_chat_history CASCADE;
CREATE TABLE ai_chat_history (
id BIGSERIAL PRIMARY KEY,