主要功能: - 图片上传时 OCR 内容去重(3个上传端点统一使用公共函数 _check_ocr_duplicate) - 图片管理 Tab:展示所有图片、手动删除、一键去重 - 搜索结果详情弹窗增加删除按钮(带确认弹窗) - 图片管理卡片点击查看详情(复用 showOcrDetailModal) - 搜索限制和 LLM 批量判断数量可通过网站设置 - MiniMax API 调用添加 reasoning_split=True - 企业微信机器人:WebSocket 长连接、图片搜索、配置化搜索数量 - 版本号升级至 1.2.0
130 lines
4.6 KiB
PL/PgSQL
130 lines
4.6 KiB
PL/PgSQL
-- ============================================================
|
|
-- EduBrain 数据库初始化脚本
|
|
-- 包含 pgvector 扩展、zhparser 中文分词扩展
|
|
-- ============================================================
|
|
|
|
-- 创建 pgvector 扩展(向量相似度搜索)
|
|
CREATE EXTENSION IF NOT EXISTS vector;
|
|
|
|
-- 创建 zhparser 中文分词扩展(全文搜索)
|
|
CREATE EXTENSION IF NOT EXISTS zhparser;
|
|
|
|
-- 创建基于 zhparser 的中文全文搜索配置
|
|
CREATE TEXT SEARCH CONFIGURATION chinese_zh (PARSER = zhparser);
|
|
|
|
-- 配置中文全文搜索映射:名词、动词、形容词、成语、叹词、习语使用 simple 字典
|
|
ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple;
|
|
|
|
-- ============================================================
|
|
-- 知识页面表
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS knowledge_pages (
|
|
id SERIAL PRIMARY KEY,
|
|
title VARCHAR(500) NOT NULL,
|
|
content TEXT NOT NULL,
|
|
source_file VARCHAR(500),
|
|
course_name VARCHAR(200),
|
|
teacher_name VARCHAR(100),
|
|
live_date VARCHAR(20),
|
|
page_number INTEGER,
|
|
metadata_json TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- 索引
|
|
CREATE INDEX IF NOT EXISTS idx_pages_course ON knowledge_pages(course_name);
|
|
CREATE INDEX IF NOT EXISTS idx_pages_teacher ON knowledge_pages(teacher_name);
|
|
CREATE INDEX IF NOT EXISTS idx_pages_date ON knowledge_pages(live_date);
|
|
CREATE INDEX IF NOT EXISTS idx_pages_created ON knowledge_pages(created_at DESC);
|
|
|
|
-- ============================================================
|
|
-- 知识分块表(向量检索单元)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS knowledge_chunks (
|
|
id SERIAL PRIMARY KEY,
|
|
page_id INTEGER NOT NULL REFERENCES knowledge_pages(id) ON DELETE CASCADE,
|
|
chunk_index INTEGER NOT NULL,
|
|
content TEXT NOT NULL,
|
|
embedding vector(1024), -- 嵌入向量(默认 1024 维)
|
|
search_vector TSVECTOR, -- 中文全文搜索向量
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- 索引
|
|
CREATE INDEX IF NOT EXISTS idx_chunks_page ON knowledge_chunks(page_id);
|
|
CREATE INDEX IF NOT EXISTS idx_chunks_page_index ON knowledge_chunks(page_id, chunk_index);
|
|
|
|
-- HNSW 向量索引(适合高维向量,查询速度快)
|
|
CREATE INDEX IF NOT EXISTS idx_chunks_embedding
|
|
ON knowledge_chunks
|
|
USING hnsw (embedding vector_cosine_ops)
|
|
WITH (m = 16, ef_construction = 200);
|
|
|
|
-- GIN 全文搜索索引
|
|
CREATE INDEX IF NOT EXISTS idx_chunks_search
|
|
ON knowledge_chunks
|
|
USING gin(search_vector);
|
|
|
|
-- ============================================================
|
|
-- OCR 图片记录表
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS ocr_images (
|
|
id SERIAL PRIMARY KEY,
|
|
file_path VARCHAR(500) NOT NULL,
|
|
ocr_text TEXT,
|
|
confidence FLOAT,
|
|
provider VARCHAR(50),
|
|
status VARCHAR(20) DEFAULT 'pending',
|
|
error_message TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- 索引
|
|
CREATE INDEX IF NOT EXISTS idx_ocr_status ON ocr_images(status);
|
|
CREATE INDEX IF NOT EXISTS idx_ocr_created ON ocr_images(created_at DESC);
|
|
|
|
-- ============================================================
|
|
-- updated_at 自动更新触发器
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 为所有表添加 updated_at 触发器
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM pg_trigger
|
|
WHERE tgname = 'tr_pages_updated_at'
|
|
) THEN
|
|
CREATE TRIGGER tr_pages_updated_at
|
|
BEFORE UPDATE ON knowledge_pages
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
END IF;
|
|
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM pg_trigger
|
|
WHERE tgname = 'tr_chunks_updated_at'
|
|
) THEN
|
|
CREATE TRIGGER tr_chunks_updated_at
|
|
BEFORE UPDATE ON knowledge_chunks
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
END IF;
|
|
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM pg_trigger
|
|
WHERE tgname = 'tr_ocr_updated_at'
|
|
) THEN
|
|
CREATE TRIGGER tr_ocr_updated_at
|
|
BEFORE UPDATE ON ocr_images
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
END IF;
|
|
END $$;
|