From 0d341f0513ad444378ee1a9d022b41af9e0de0aa Mon Sep 17 00:00:00 2001 From: silk Date: Mon, 1 Jun 2026 14:15:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E7=BD=B2=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ddl-init.sql | 555 ++++++++++++++++++++++++++++++++++++++++ readme.md | 101 ++++++++ sql.txt | 675 ------------------------------------------------- test_main.http | 11 - update-ddl.txt | 73 ------ 5 files changed, 656 insertions(+), 759 deletions(-) create mode 100644 ddl-init.sql create mode 100644 readme.md delete mode 100644 sql.txt delete mode 100644 test_main.http delete mode 100644 update-ddl.txt diff --git a/ddl-init.sql b/ddl-init.sql new file mode 100644 index 0000000..4be6824 --- /dev/null +++ b/ddl-init.sql @@ -0,0 +1,555 @@ +-- public.chat_messages definition + +-- Drop table + +-- DROP TABLE public.chat_messages; + +CREATE TABLE public.chat_messages ( + id serial4 NOT NULL, + thread_id varchar(255) NOT NULL, + checkpoint_id varchar(255) NOT NULL, + message_index int4 NOT NULL, + "role" varchar(20) NOT NULL, + "content" text NOT NULL, + injected_content text NULL, + has_files bool DEFAULT false NULL, + metadata jsonb NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + "name" varchar(255) NULL, + CONSTRAINT chat_messages_pkey PRIMARY KEY (id), + CONSTRAINT uk_checkpoint_message UNIQUE (checkpoint_id, message_index) +); +CREATE INDEX idx_chat_messages_checkpoint_id ON public.chat_messages USING btree (checkpoint_id); +CREATE INDEX idx_chat_messages_content_search ON public.chat_messages USING gin (to_tsvector('simple'::regconfig, content)); +CREATE INDEX idx_chat_messages_has_files ON public.chat_messages USING btree (has_files); +CREATE INDEX idx_chat_messages_metadata ON public.chat_messages USING gin (metadata); +CREATE INDEX idx_chat_messages_role ON public.chat_messages USING btree (role); +CREATE INDEX idx_chat_messages_thread_created ON public.chat_messages USING btree (thread_id, created_at DESC); +CREATE INDEX idx_chat_messages_thread_id ON public.chat_messages USING btree (thread_id); + + +-- public.checkpoint_blobs definition + +-- Drop table + +-- DROP TABLE public.checkpoint_blobs; + +CREATE TABLE public.checkpoint_blobs ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + channel text NOT NULL, + "version" text NOT NULL, + "type" text NOT NULL, + "blob" bytea NULL, + CONSTRAINT checkpoint_blobs_pkey PRIMARY KEY (thread_id, checkpoint_ns, channel, version) +); +CREATE INDEX checkpoint_blobs_thread_id_idx ON public.checkpoint_blobs USING btree (thread_id); + + +-- public.checkpoint_migrations definition + +-- Drop table + +-- DROP TABLE public.checkpoint_migrations; + +CREATE TABLE public.checkpoint_migrations ( + v int4 NOT NULL, + CONSTRAINT checkpoint_migrations_pkey PRIMARY KEY (v) +); + + +-- public.checkpoint_writes definition + +-- Drop table + +-- DROP TABLE public.checkpoint_writes; + +CREATE TABLE public.checkpoint_writes ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + checkpoint_id text NOT NULL, + task_id text NOT NULL, + idx int4 NOT NULL, + channel text NOT NULL, + "type" text NULL, + "blob" bytea NOT NULL, + task_path text DEFAULT ''::text NOT NULL, + CONSTRAINT checkpoint_writes_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx) +); +CREATE INDEX checkpoint_writes_thread_id_idx ON public.checkpoint_writes USING btree (thread_id); + + +-- public.checkpoints definition + +-- Drop table + +-- DROP TABLE public.checkpoints; + +CREATE TABLE public.checkpoints ( + thread_id text NOT NULL, + checkpoint_ns text DEFAULT ''::text NOT NULL, + checkpoint_id text NOT NULL, + parent_checkpoint_id text NULL, + "type" text NULL, + "checkpoint" jsonb NOT NULL, + metadata jsonb DEFAULT '{}'::jsonb NOT NULL, + CONSTRAINT checkpoints_pkey PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id) +); +CREATE INDEX checkpoints_thread_id_idx ON public.checkpoints USING btree (thread_id); + + +-- public.enterprise definition + +-- Drop table + +-- DROP TABLE public.enterprise; + +CREATE TABLE public.enterprise ( + id serial4 NOT NULL, + "name" varchar(255) NOT NULL, + code varchar(64) NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + ai_display_name varchar(128) DEFAULT '智能助手 AI'::character varying NOT NULL, + CONSTRAINT enterprise_code_key UNIQUE (code), + CONSTRAINT enterprise_pkey PRIMARY KEY (id) +); + + +-- public.chat_message_file definition + +-- Drop table + +-- DROP TABLE public.chat_message_file; + +CREATE TABLE public.chat_message_file ( + id serial4 NOT NULL, + thread_id varchar(255) NOT NULL, + checkpoint_id varchar(255) NOT NULL, + message_index int4 NOT NULL, + file_id int4 NOT NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + CONSTRAINT chat_message_file_pkey PRIMARY KEY (id), + CONSTRAINT uk_message_file UNIQUE (checkpoint_id, message_index, file_id) +); +CREATE INDEX idx_chat_message_file_checkpoint ON public.chat_message_file USING btree (checkpoint_id, message_index); +CREATE INDEX idx_chat_message_file_file_id ON public.chat_message_file USING btree (file_id); +CREATE INDEX idx_chat_message_file_thread_checkpoint ON public.chat_message_file USING btree (thread_id, checkpoint_id); +CREATE INDEX idx_chat_message_file_thread_id ON public.chat_message_file USING btree (thread_id); + + +-- public.chat_thread_chunk definition + +-- Drop table + +-- DROP TABLE public.chat_thread_chunk; + +CREATE TABLE public.chat_thread_chunk ( + id serial4 NOT NULL, + file_id int4 NOT NULL, + thread_id varchar(255) NOT NULL, + chunk_index int4 NOT NULL, + "content" text NOT NULL, + metadata jsonb NULL, + vector_id varchar(255) NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + summary text NULL, + CONSTRAINT chat_thread_chunk_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_chat_thread_chunk_created_at ON public.chat_thread_chunk USING btree (created_at); +CREATE INDEX idx_chat_thread_chunk_file_id ON public.chat_thread_chunk USING btree (file_id); +CREATE INDEX idx_chat_thread_chunk_file_thread ON public.chat_thread_chunk USING btree (file_id, thread_id); +CREATE INDEX idx_chat_thread_chunk_thread_id ON public.chat_thread_chunk USING btree (thread_id); +CREATE INDEX idx_chat_thread_chunk_vector_id ON public.chat_thread_chunk USING btree (vector_id); + + +-- public.chat_thread_file definition + +-- Drop table + +-- DROP TABLE public.chat_thread_file; + +CREATE TABLE public.chat_thread_file ( + id serial4 NOT NULL, + thread_id varchar(255) NOT NULL, + user_id int4 NOT NULL, + file_name varchar(255) NOT NULL, + file_path varchar(500) NOT NULL, + file_size int4 DEFAULT 0 NULL, + file_type varchar(50) DEFAULT 'pdf'::character varying NULL, + status varchar(20) DEFAULT 'processing'::character varying NULL, + chunk_count int4 DEFAULT 0 NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + is_deleted bool DEFAULT false NULL, + deleted_at timestamptz NULL, + CONSTRAINT chat_thread_file_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_chat_thread_file_created_at ON public.chat_thread_file USING btree (created_at); +CREATE INDEX idx_chat_thread_file_is_deleted ON public.chat_thread_file USING btree (is_deleted); +CREATE INDEX idx_chat_thread_file_status ON public.chat_thread_file USING btree (status); +CREATE INDEX idx_chat_thread_file_thread_deleted ON public.chat_thread_file USING btree (thread_id, is_deleted); +CREATE INDEX idx_chat_thread_file_thread_id ON public.chat_thread_file USING btree (thread_id); +CREATE INDEX idx_chat_thread_file_thread_user ON public.chat_thread_file USING btree (thread_id, user_id); +CREATE INDEX idx_chat_thread_file_user_id ON public.chat_thread_file USING btree (user_id); +CREATE UNIQUE INDEX uk_chat_thread_file_thread_name_active ON public.chat_thread_file USING btree (thread_id, file_name) WHERE (is_deleted = false); + + +-- public.chat_threads definition + +-- Drop table + +-- DROP TABLE public.chat_threads; + +CREATE TABLE public.chat_threads ( + id serial4 NOT NULL, + thread_id varchar(255) NOT NULL, + user_id int4 NOT NULL, + title varchar(50) NOT NULL, + first_query text NOT NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + message_count int4 DEFAULT 1 NULL, + is_deleted bool DEFAULT false NULL, + knowledge_base_id int4 NULL, + novel_graph_id int4 NULL, + knowledge_graph_id int4 NULL, + ip varchar(128) NULL, + CONSTRAINT chat_threads_pkey PRIMARY KEY (id), + CONSTRAINT uk_thread_id UNIQUE (thread_id) +); +CREATE INDEX idx_chat_threads_created_at ON public.chat_threads USING btree (created_at DESC); +CREATE INDEX idx_chat_threads_knowledge_graph_id ON public.chat_threads USING btree (knowledge_graph_id); +CREATE INDEX idx_chat_threads_novel_graph_id ON public.chat_threads USING btree (novel_graph_id); +CREATE INDEX idx_chat_threads_user_created ON public.chat_threads USING btree (user_id, created_at DESC); +CREATE INDEX idx_chat_threads_user_id ON public.chat_threads USING btree (user_id); + + +-- public.department definition + +-- Drop table + +-- DROP TABLE public.department; + +CREATE TABLE public.department ( + id serial4 NOT NULL, + enterprise_id int4 NOT NULL, + "name" varchar(255) NOT NULL, + parent_id int4 NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + leader_user_id int4 NULL, + CONSTRAINT department_pkey PRIMARY KEY (id), + CONSTRAINT uq_department_enterprise_name UNIQUE (enterprise_id, name) +); +CREATE INDEX idx_department_enterprise_id ON public.department USING btree (enterprise_id); +CREATE INDEX idx_department_leader_user_id ON public.department USING btree (leader_user_id); + + +-- public.graphs definition + +-- Drop table + +-- DROP TABLE public.graphs; + +CREATE TABLE public.graphs ( + id serial4 NOT NULL, + user_id int4 NOT NULL, + "name" varchar(255) NOT NULL, + description text NULL, + csv_file_name varchar(255) NULL, + node_count int4 DEFAULT 0 NULL, + edge_count int4 DEFAULT 0 NULL, + neo4j_graph_id varchar(100) NOT NULL, + graph_type varchar(20) DEFAULT 'knowledge'::character varying NOT NULL, + build_status varchar(20) NULL, + build_error text NULL, + rag_chunk_count int4 DEFAULT 0 NOT NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + enterprise_id int4 NOT NULL, + department_id int4 NULL, + creator_id int4 NOT NULL, + visibility varchar(32) DEFAULT 'private'::character varying NOT NULL, + CONSTRAINT ck_graphs_visibility CHECK (((visibility)::text = ANY ((ARRAY['private'::character varying, 'department'::character varying, 'enterprise'::character varying])::text[]))), + CONSTRAINT graphs_neo4j_graph_id_key UNIQUE (neo4j_graph_id), + CONSTRAINT graphs_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_graphs_created_at ON public.graphs USING btree (created_at DESC); +CREATE INDEX idx_graphs_creator ON public.graphs USING btree (creator_id); +CREATE INDEX idx_graphs_ent_vis ON public.graphs USING btree (enterprise_id, visibility); +CREATE INDEX idx_graphs_enterprise ON public.graphs USING btree (enterprise_id); +CREATE INDEX idx_graphs_graph_type ON public.graphs USING btree (user_id, graph_type); +CREATE INDEX idx_graphs_neo4j_id ON public.graphs USING btree (neo4j_graph_id); +CREATE INDEX idx_graphs_user_id ON public.graphs USING btree (user_id); + + +-- public.kb_audit_log definition + +-- Drop table + +-- DROP TABLE public.kb_audit_log; + +CREATE TABLE public.kb_audit_log ( + id serial4 NOT NULL, + enterprise_id int4 NOT NULL, + actor_id int4 NOT NULL, + target_user_id int4 NULL, + department_id int4 NULL, + kb_id int4 NULL, + file_id int4 NULL, + "action" varchar(50) NOT NULL, + ip varchar(128) NULL, + user_agent text NULL, + metadata jsonb NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT kb_audit_log_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_kb_audit_log_action ON public.kb_audit_log USING btree (action); +CREATE INDEX idx_kb_audit_log_actor_id ON public.kb_audit_log USING btree (actor_id); +CREATE INDEX idx_kb_audit_log_created_at ON public.kb_audit_log USING btree (created_at DESC); +CREATE INDEX idx_kb_audit_log_department_id ON public.kb_audit_log USING btree (department_id); +CREATE INDEX idx_kb_audit_log_ent_dept_created ON public.kb_audit_log USING btree (enterprise_id, department_id, created_at DESC); +CREATE INDEX idx_kb_audit_log_enterprise_id ON public.kb_audit_log USING btree (enterprise_id); +CREATE INDEX idx_kb_audit_log_kb_id ON public.kb_audit_log USING btree (kb_id); +CREATE INDEX idx_kb_audit_log_target_user_id ON public.kb_audit_log USING btree (target_user_id); + + +-- public.knowledge_base definition + +-- Drop table + +-- DROP TABLE public.knowledge_base; + +CREATE TABLE public.knowledge_base ( + id serial4 NOT NULL, + user_id int4 NOT NULL, + "name" varchar(255) NOT NULL, + description text NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + is_deleted bool DEFAULT false NULL, + deleted_at timestamptz NULL, + enterprise_id int4 DEFAULT 1 NOT NULL, + department_id int4 NULL, + creator_id int4 NULL, + visibility varchar(32) DEFAULT 'private'::character varying NOT NULL, + CONSTRAINT ck_knowledge_base_visibility CHECK (((visibility)::text = ANY ((ARRAY['private'::character varying, 'department'::character varying, 'enterprise'::character varying])::text[]))), + CONSTRAINT knowledge_base_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_knowledge_base_created_at ON public.knowledge_base USING btree (created_at); +CREATE INDEX idx_knowledge_base_creator ON public.knowledge_base USING btree (creator_id); +CREATE INDEX idx_knowledge_base_ent_vis ON public.knowledge_base USING btree (enterprise_id, visibility) WHERE (is_deleted = false); +CREATE INDEX idx_knowledge_base_enterprise ON public.knowledge_base USING btree (enterprise_id); +CREATE INDEX idx_knowledge_base_is_deleted ON public.knowledge_base USING btree (is_deleted); +CREATE INDEX idx_knowledge_base_user_deleted ON public.knowledge_base USING btree (user_id, is_deleted); +CREATE INDEX idx_knowledge_base_user_id ON public.knowledge_base USING btree (user_id); +CREATE INDEX idx_knowledge_base_user_name ON public.knowledge_base USING btree (user_id, name); +CREATE UNIQUE INDEX uk_user_knowledge_base_name_active ON public.knowledge_base USING btree (user_id, name) WHERE (is_deleted = false); + + +-- public.knowledge_base_chunk definition + +-- Drop table + +-- DROP TABLE public.knowledge_base_chunk; + +CREATE TABLE public.knowledge_base_chunk ( + id serial4 NOT NULL, + file_id int4 NOT NULL, + knowledge_base_id int4 NOT NULL, + chunk_index int4 NOT NULL, + "content" text NOT NULL, + metadata jsonb NULL, + vector_id varchar(255) NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + summary text NULL, + CONSTRAINT knowledge_base_chunk_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_kb_chunk_file_id ON public.knowledge_base_chunk USING btree (file_id); +CREATE INDEX idx_kb_chunk_kb_id ON public.knowledge_base_chunk USING btree (knowledge_base_id); +CREATE INDEX idx_kb_chunk_metadata ON public.knowledge_base_chunk USING gin (metadata); +CREATE INDEX idx_kb_chunk_vector_id ON public.knowledge_base_chunk USING btree (vector_id); + + +-- public.knowledge_base_file definition + +-- Drop table + +-- DROP TABLE public.knowledge_base_file; + +CREATE TABLE public.knowledge_base_file ( + id serial4 NOT NULL, + knowledge_base_id int4 NOT NULL, + user_id int4 NOT NULL, + file_name varchar(255) NOT NULL, + file_path varchar(500) NOT NULL, + file_size int8 NOT NULL, + file_type varchar(50) DEFAULT 'pdf'::character varying NOT NULL, + status varchar(20) DEFAULT 'processing'::character varying NOT NULL, + chunk_count int4 DEFAULT 0 NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + is_deleted bool DEFAULT false NULL, + deleted_at timestamptz NULL, + CONSTRAINT knowledge_base_file_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_kb_file_created_at ON public.knowledge_base_file USING btree (created_at); +CREATE INDEX idx_kb_file_kb_id ON public.knowledge_base_file USING btree (knowledge_base_id); +CREATE INDEX idx_kb_file_status ON public.knowledge_base_file USING btree (status); +CREATE UNIQUE INDEX idx_kb_file_unique_active ON public.knowledge_base_file USING btree (knowledge_base_id, file_name) WHERE (is_deleted = false); +CREATE INDEX idx_kb_file_user_id ON public.knowledge_base_file USING btree (user_id); + + +-- public.knowledge_processing_task definition + +-- Drop table + +-- DROP TABLE public.knowledge_processing_task; + +CREATE TABLE public.knowledge_processing_task ( + id serial4 NOT NULL, + user_id int4 NOT NULL, + knowledge_base_id int4 NOT NULL, + task_name varchar(255) NOT NULL, + instruction text NOT NULL, + file_ids _int4 NOT NULL, + task_type varchar(50) NOT NULL, + status varchar(20) DEFAULT 'pending'::character varying NULL, + "result" text NULL, + result_file_url text NULL, + error_message text NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + started_at timestamptz NULL, + completed_at timestamptz NULL, + CONSTRAINT knowledge_processing_task_pkey PRIMARY KEY (id) +); +CREATE INDEX idx_kb_processing_created_at ON public.knowledge_processing_task USING btree (created_at DESC); +CREATE INDEX idx_kb_processing_kb_id ON public.knowledge_processing_task USING btree (knowledge_base_id); +CREATE INDEX idx_kb_processing_status ON public.knowledge_processing_task USING btree (status); +CREATE INDEX idx_kb_processing_user_id ON public.knowledge_processing_task USING btree (user_id); +CREATE INDEX idx_kb_processing_user_status ON public.knowledge_processing_task USING btree (user_id, status); + + +-- public.user_list definition + +-- Drop table + +-- DROP TABLE public.user_list; + +CREATE TABLE public.user_list ( + id serial4 NOT NULL, + username varchar(50) NOT NULL, + email varchar(255) NOT NULL, + phone varchar(255) NOT NULL, + github_id varchar(100) NULL, + github_username varchar(100) NULL, + github_avatar_url text NULL, + github_access_token text NULL, + github_token_expires_at timestamptz NULL, + display_name varchar(100) NULL, + avatar_url text NULL, + bio text NULL, + is_active bool DEFAULT true NULL, + email_verified bool DEFAULT false NULL, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NULL, + last_login_at timestamptz NULL, + hashed_password varchar(255) NULL, + is_search bool DEFAULT false NULL, + is_reasoner bool DEFAULT false NULL, + enterprise_id int4 DEFAULT 1 NOT NULL, + department_id int4 NULL, + "role" varchar(32) DEFAULT 'employee'::character varying NOT NULL, + is_first_login bool DEFAULT true NOT NULL, + allow_kb_upload bool DEFAULT true NOT NULL, + CONSTRAINT unique_email UNIQUE (email), + CONSTRAINT unique_github_id UNIQUE (github_id), + CONSTRAINT user_list_phone_key UNIQUE (phone), + CONSTRAINT user_list_pkey PRIMARY KEY (id), + CONSTRAINT user_list_username_key UNIQUE (username) +); +CREATE INDEX idx_user_list_created_at ON public.user_list USING btree (created_at); +CREATE INDEX idx_user_list_department_id ON public.user_list USING btree (department_id); +CREATE INDEX idx_user_list_email ON public.user_list USING btree (email); +CREATE INDEX idx_user_list_enterprise_id ON public.user_list USING btree (enterprise_id); +CREATE INDEX idx_user_list_github_id ON public.user_list USING btree (github_id); +CREATE INDEX idx_user_list_role ON public.user_list USING btree (role); +CREATE INDEX idx_user_list_username ON public.user_list USING btree (username); + + +-- public.chat_message_file foreign keys + +ALTER TABLE public.chat_message_file ADD CONSTRAINT fk_chat_message_file_file FOREIGN KEY (file_id) REFERENCES public.chat_thread_file(id) ON DELETE CASCADE; + + +-- public.chat_thread_chunk foreign keys + +ALTER TABLE public.chat_thread_chunk ADD CONSTRAINT fk_chat_thread_chunk_file FOREIGN KEY (file_id) REFERENCES public.chat_thread_file(id) ON DELETE CASCADE; + + +-- public.chat_thread_file foreign keys + +ALTER TABLE public.chat_thread_file ADD CONSTRAINT fk_chat_thread_file_user FOREIGN KEY (user_id) REFERENCES public.user_list(id) ON DELETE CASCADE; + + +-- public.chat_threads foreign keys + +ALTER TABLE public.chat_threads ADD CONSTRAINT fk_chat_threads_knowledge_graph FOREIGN KEY (knowledge_graph_id) REFERENCES public.graphs(id) ON DELETE SET NULL; +ALTER TABLE public.chat_threads ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES public.user_list(id) ON DELETE CASCADE; + + +-- public.department foreign keys + +ALTER TABLE public.department ADD CONSTRAINT department_enterprise_id_fkey FOREIGN KEY (enterprise_id) REFERENCES public.enterprise(id) ON DELETE CASCADE; +ALTER TABLE public.department ADD CONSTRAINT department_leader_user_id_fkey FOREIGN KEY (leader_user_id) REFERENCES public.user_list(id) ON DELETE SET NULL; +ALTER TABLE public.department ADD CONSTRAINT department_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES public.department(id) ON DELETE SET NULL; + + +-- public.graphs foreign keys + +ALTER TABLE public.graphs ADD CONSTRAINT fk_graphs_user FOREIGN KEY (user_id) REFERENCES public.user_list(id) ON DELETE CASCADE; +ALTER TABLE public.graphs ADD CONSTRAINT graphs_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES public.user_list(id) ON DELETE SET NULL; +ALTER TABLE public.graphs ADD CONSTRAINT graphs_department_id_fkey FOREIGN KEY (department_id) REFERENCES public.department(id) ON DELETE SET NULL; +ALTER TABLE public.graphs ADD CONSTRAINT graphs_enterprise_id_fkey FOREIGN KEY (enterprise_id) REFERENCES public.enterprise(id); + + +-- public.kb_audit_log foreign keys + +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_actor_id_fkey FOREIGN KEY (actor_id) REFERENCES public.user_list(id) ON DELETE CASCADE; +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_department_id_fkey FOREIGN KEY (department_id) REFERENCES public.department(id) ON DELETE SET NULL; +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_enterprise_id_fkey FOREIGN KEY (enterprise_id) REFERENCES public.enterprise(id) ON DELETE CASCADE; +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_file_id_fkey FOREIGN KEY (file_id) REFERENCES public.knowledge_base_file(id) ON DELETE SET NULL; +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_kb_id_fkey FOREIGN KEY (kb_id) REFERENCES public.knowledge_base(id) ON DELETE SET NULL; +ALTER TABLE public.kb_audit_log ADD CONSTRAINT kb_audit_log_target_user_id_fkey FOREIGN KEY (target_user_id) REFERENCES public.user_list(id) ON DELETE SET NULL; + + +-- public.knowledge_base foreign keys + +ALTER TABLE public.knowledge_base ADD CONSTRAINT knowledge_base_creator_id_fkey FOREIGN KEY (creator_id) REFERENCES public.user_list(id) ON DELETE CASCADE; +ALTER TABLE public.knowledge_base ADD CONSTRAINT knowledge_base_department_id_fkey FOREIGN KEY (department_id) REFERENCES public.department(id) ON DELETE SET NULL; +ALTER TABLE public.knowledge_base ADD CONSTRAINT knowledge_base_enterprise_id_fkey FOREIGN KEY (enterprise_id) REFERENCES public.enterprise(id); + + +-- public.knowledge_base_chunk foreign keys + +ALTER TABLE public.knowledge_base_chunk ADD CONSTRAINT fk_kb FOREIGN KEY (knowledge_base_id) REFERENCES public.knowledge_base(id) ON DELETE CASCADE; +ALTER TABLE public.knowledge_base_chunk ADD CONSTRAINT fk_kb_file FOREIGN KEY (file_id) REFERENCES public.knowledge_base_file(id) ON DELETE CASCADE; + + +-- public.knowledge_base_file foreign keys + +ALTER TABLE public.knowledge_base_file ADD CONSTRAINT fk_knowledge_base FOREIGN KEY (knowledge_base_id) REFERENCES public.knowledge_base(id) ON DELETE CASCADE; + + +-- public.knowledge_processing_task foreign keys + +ALTER TABLE public.knowledge_processing_task ADD CONSTRAINT fk_kb_processing_kb FOREIGN KEY (knowledge_base_id) REFERENCES public.knowledge_base(id) ON DELETE CASCADE; +ALTER TABLE public.knowledge_processing_task ADD CONSTRAINT fk_kb_processing_user FOREIGN KEY (user_id) REFERENCES public.user_list(id) ON DELETE CASCADE; + + +-- public.user_list foreign keys + +ALTER TABLE public.user_list ADD CONSTRAINT user_list_department_id_fkey FOREIGN KEY (department_id) REFERENCES public.department(id) ON DELETE SET NULL; +ALTER TABLE public.user_list ADD CONSTRAINT user_list_enterprise_id_fkey FOREIGN KEY (enterprise_id) REFERENCES public.enterprise(id); \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6d34858 --- /dev/null +++ b/readme.md @@ -0,0 +1,101 @@ +# 如何部署 Backend + +本仓库的 HTTP API 由 `backend/` 目录下的 **FastAPI** 服务提供,`frontend` 与 `admin-frontend` 均请求同一套后端接口。 + +--- + +## 一、环境准备 + +### 1.1 运行环境 + +| 组件 | 版本 / 说明 | +|------|-------------| +| Python | **3.11**(与 `backend/pyproject.toml` 中 `requires-python` 一致) | +| 包管理 | 推荐 [uv](https://docs.astral.sh/uv/)(项目含 `uv.lock`) | +| PostgreSQL | **14+**(主库,必选) | +| Redis | **6+**(短信验证码、图形验证码等,可选) | +| ChromaDB | 向量检索(知识库 RAG,按业务需要部署,必选) | +| Neo4j | 知识图谱(按业务需要部署,必选) | + + +--- + +## 二、数据库初始化 + +后端依赖 PostgreSQL。首次部署请在**空库**上执行项目根目录的初始化脚本: + + +`ddl-init.sql` 会创建完整表结构 + +初始化完成后,在 `backend/.env` 中配置与上述库一致的数据库连接(见下文)。 + +--- + +## 三、配置环境变量 + +在 `backend/` 目录复制示例配置并修改: + +```bash +cd backend +cp .env.example .env +``` + +至少修改以下项(生产环境务必使用强密码与随机 `JWT_SECRET_KEY`): + +| 变量 | 说明 | +|------|------| +| `API.HOST` / `API.PORT` | 监听地址与端口(默认 `0.0.0.0:7862`) | +| `DB_HOST`、`DB_PORT`、`DB_NAME`、`DB_USER`、`DB_PASSWORD` | PostgreSQL,需与 `ddl-init.sql` 执行的库一致 | +| `JWT_SECRET_KEY` | JWT 签名密钥 | +| `REDIS_HOST`、`REDIS_PORT` | Redis(未在 `.env.example` 列出时,默认 `127.0.0.1:6379`,可在 `.env` 中显式配置) | +| `CHROMA_HOST`、`CHROMA_PORT` | ChromaDB 地址(启用知识库向量检索时) | +| `NEO4J_URI`、`NEO4J_USER`、`NEO4J_PASSWORD` | Neo4j(启用知识图谱时) | +| `DASHSCOPE_API_KEY` / `DEEPSEEK_API_KEY` 等 | 大模型与 Embedding(聊天、RAG 必需) | +| `OSS_*` | 阿里云 OSS(文件上传,按需) | +| `MODERATION_ENABLED` | 内容审核;关闭时可不配置阿里云审核密钥 | + +完整字段说明见 `backend/.env.example` 与 `backend/core/config.py`。 + +--- + +## 四、本地部署(推荐开发 / 单机生产) + +### 4.1 安装依赖 + +```bash +cd backend +uv sync --frozen +``` + +仅安装生产依赖(与 Docker 构建一致): + +```bash +uv sync --frozen --no-dev +``` + +### 4.2 启动服务 + +在 **`backend` 目录**下执行(会读取 `backend/.env` 中的 `API.HOST` / `API.PORT`): + +```bash +uv run python -m main +``` + +开发热重载(同样需在 `backend` 目录): + +```bash +uv run python -m main +# 或显式指定端口(须与 .env 中 API.PORT 一致) +uv run uvicorn main:app --reload --host 0.0.0.0 --port 7862 +``` + +> **注意**:若直接运行 `uvicorn main:app` 且未传 `--port`,默认端口为 **8000**,不会自动读取 `.env` 中的 `API.PORT`。生产环境请使用 `python -m main` 或显式传入 `--port`。 + +### 4.3 验证 + +- 健康:查看启动日志中是否有「数据库健康检查通过」 +- API 文档:浏览器打开 `http://<主机>:<端口>/docs`(根路径 `/` 会重定向到 Swagger) +- 管理端接口:前缀为 `/api/admin/...`,需 `role=admin` 用户登录后携带 JWT + +--- + diff --git a/sql.txt b/sql.txt deleted file mode 100644 index 27e92ae..0000000 --- a/sql.txt +++ /dev/null @@ -1,675 +0,0 @@ -create table public.chat_messages -( - id serial - primary key, - thread_id varchar(255) not null, - checkpoint_id varchar(255) not null, - message_index integer not null, - role varchar(20) not null, - content text not null, - injected_content text, - has_files boolean default false, - metadata jsonb, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - name varchar(255), - constraint uk_checkpoint_message - unique (checkpoint_id, message_index) -); - -comment on table public.chat_messages is '聊天消息表,存储用户原始消息和AI响应的关键信息'; - -comment on column public.chat_messages.thread_id is '会话线程ID'; - -comment on column public.chat_messages.checkpoint_id is '关联的checkpoint ID'; - -comment on column public.chat_messages.message_index is '消息在checkpoint中的索引(从0开始)'; - -comment on column public.chat_messages.role is '消息角色:user、assistant、system、tool'; - -comment on column public.chat_messages.content is '用户的原始问题或AI的响应'; - -comment on column public.chat_messages.injected_content is '注入给AI的完整内容(包含文件内容)'; - -comment on column public.chat_messages.has_files is '是否关联了文件'; - -comment on column public.chat_messages.metadata is '额外信息:token、模型、推理内容等'; - -comment on column public.chat_messages.name is '工具消息时的工具名称(如 internet_search、text_to_image)'; - -alter table public.chat_messages - owner to zuoleiroot; - -create index idx_chat_messages_thread_id - on public.chat_messages (thread_id); - -create index idx_chat_messages_checkpoint_id - on public.chat_messages (checkpoint_id); - -create index idx_chat_messages_thread_created - on public.chat_messages (thread_id asc, created_at desc); - -create index idx_chat_messages_role - on public.chat_messages (role); - -create index idx_chat_messages_has_files - on public.chat_messages (has_files); - -create index idx_chat_messages_metadata - on public.chat_messages using gin (metadata); - -create index idx_chat_messages_content_search - on public.chat_messages using gin (to_tsvector('simple'::regconfig, content)); - -create table public.checkpoint_migrations -( - v integer not null - primary key -); - -alter table public.checkpoint_migrations - owner to zuoleiroot; - -create table public.checkpoints -( - thread_id text not null, - checkpoint_ns text default ''::text not null, - checkpoint_id text not null, - parent_checkpoint_id text, - type text, - checkpoint jsonb not null, - metadata jsonb default '{}'::jsonb not null, - primary key (thread_id, checkpoint_ns, checkpoint_id) -); - -alter table public.checkpoints - owner to zuoleiroot; - -create index checkpoints_thread_id_idx - on public.checkpoints (thread_id); - -create table public.checkpoint_blobs -( - thread_id text not null, - checkpoint_ns text default ''::text not null, - channel text not null, - version text not null, - type text not null, - blob bytea, - primary key (thread_id, checkpoint_ns, channel, version) -); - -alter table public.checkpoint_blobs - owner to zuoleiroot; - -create index checkpoint_blobs_thread_id_idx - on public.checkpoint_blobs (thread_id); - -create table public.checkpoint_writes -( - thread_id text not null, - checkpoint_ns text default ''::text not null, - checkpoint_id text not null, - task_id text not null, - idx integer not null, - channel text not null, - type text, - blob bytea not null, - task_path text default ''::text not null, - primary key (thread_id, checkpoint_ns, checkpoint_id, task_id, idx) -); - -alter table public.checkpoint_writes - owner to zuoleiroot; - -create index checkpoint_writes_thread_id_idx - on public.checkpoint_writes (thread_id); - -create table public.enterprise -( - id serial - primary key, - name varchar(255) not null, - code varchar(64) - unique, - created_at timestamp with time zone default CURRENT_TIMESTAMP not null, - updated_at timestamp with time zone default CURRENT_TIMESTAMP not null -); - -comment on table public.enterprise is '企业(单租户部署通常仅一条记录)'; - -alter table public.enterprise - owner to zuoleiroot; - -create table public.department -( - id serial - primary key, - enterprise_id integer not null - references public.enterprise - on delete cascade, - name varchar(255) not null, - parent_id integer - references public.department - on delete set null, - created_at timestamp with time zone default CURRENT_TIMESTAMP not null, - updated_at timestamp with time zone default CURRENT_TIMESTAMP not null, - constraint uq_department_enterprise_name - unique (enterprise_id, name) -); - -comment on table public.department is '部门'; - -alter table public.department - owner to zuoleiroot; - -create table public.user_list -( - id serial - primary key, - username varchar(50) not null - unique, - email varchar(255) not null - constraint unique_email - unique, - phone varchar(255) not null - unique, - github_id varchar(100) - constraint unique_github_id - unique, - github_username varchar(100), - github_avatar_url text, - github_access_token text, - github_token_expires_at timestamp with time zone, - display_name varchar(100), - avatar_url text, - bio text, - is_active boolean default true, - email_verified boolean default false, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - last_login_at timestamp with time zone, - hashed_password varchar(255), - is_search boolean default false, - is_reasoner boolean default false, - enterprise_id integer default 1 not null - references public.enterprise, - department_id integer - references public.department - on delete set null, - role varchar(32) default 'employee'::character varying not null, - is_first_login boolean default true not null -); - -comment on column public.user_list.role is 'admin | leader | employee'; - -comment on column public.user_list.is_first_login is '首次登录可强制改密(可选业务)'; - -alter table public.user_list - owner to zuoleiroot; - -create index idx_user_list_github_id - on public.user_list (github_id); - -create index idx_user_list_email - on public.user_list (email); - -create index idx_user_list_username - on public.user_list (username); - -create index idx_user_list_created_at - on public.user_list (created_at); - -create index idx_user_list_enterprise_id - on public.user_list (enterprise_id); - -create index idx_user_list_department_id - on public.user_list (department_id); - -create index idx_user_list_role - on public.user_list (role); - -create table public.knowledge_base -( - id serial - primary key, - user_id integer not null, - name varchar(255) not null, - description text, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - is_deleted boolean default false, - deleted_at timestamp with time zone, - enterprise_id integer default 1 not null - references public.enterprise, - department_id integer - references public.department - on delete set null, - creator_id integer not null - references public.user_list - on delete set null, - visibility varchar(32) default 'private'::character varying not null - constraint ck_knowledge_base_visibility - check ((visibility)::text = ANY - ((ARRAY ['private'::character varying, 'department'::character varying, 'enterprise'::character varying])::text[])) -); - -comment on column public.knowledge_base.creator_id is '创建者(与 user_id 通常一致,用于权限判断)'; - -comment on column public.knowledge_base.visibility is 'private | department | enterprise'; - -alter table public.knowledge_base - owner to zuoleiroot; - -create index idx_knowledge_base_user_id - on public.knowledge_base (user_id); - -create index idx_knowledge_base_user_name - on public.knowledge_base (user_id, name); - -create index idx_knowledge_base_created_at - on public.knowledge_base (created_at); - -create index idx_knowledge_base_is_deleted - on public.knowledge_base (is_deleted); - -create index idx_knowledge_base_user_deleted - on public.knowledge_base (user_id, is_deleted); - -create unique index uk_user_knowledge_base_name_active - on public.knowledge_base (user_id, name) - where (is_deleted = false); - -create index idx_knowledge_base_enterprise - on public.knowledge_base (enterprise_id); - -create index idx_knowledge_base_creator - on public.knowledge_base (creator_id); - -create index idx_knowledge_base_ent_vis - on public.knowledge_base (enterprise_id, visibility) - where (is_deleted = false); - -create table public.knowledge_base_file -( - id serial - primary key, - knowledge_base_id integer not null - constraint fk_knowledge_base - references public.knowledge_base - on delete cascade, - user_id integer not null, - file_name varchar(255) not null, - file_path varchar(500) not null, - file_size bigint not null, - file_type varchar(50) default 'pdf'::character varying not null, - status varchar(20) default 'processing'::character varying not null, - chunk_count integer default 0, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - is_deleted boolean default false, - deleted_at timestamp with time zone -); - -alter table public.knowledge_base_file - owner to zuoleiroot; - -create index idx_kb_file_kb_id - on public.knowledge_base_file (knowledge_base_id); - -create index idx_kb_file_user_id - on public.knowledge_base_file (user_id); - -create index idx_kb_file_status - on public.knowledge_base_file (status); - -create index idx_kb_file_created_at - on public.knowledge_base_file (created_at); - -create unique index idx_kb_file_unique_active - on public.knowledge_base_file (knowledge_base_id, file_name) - where (is_deleted = false); - -create table public.knowledge_base_chunk -( - id serial - primary key, - file_id integer not null - constraint fk_kb_file - references public.knowledge_base_file - on delete cascade, - knowledge_base_id integer not null - constraint fk_kb - references public.knowledge_base - on delete cascade, - chunk_index integer not null, - content text not null, - metadata jsonb, - vector_id varchar(255), - created_at timestamp with time zone default CURRENT_TIMESTAMP, - summary text -); - -alter table public.knowledge_base_chunk - owner to zuoleiroot; - -create index idx_kb_chunk_file_id - on public.knowledge_base_chunk (file_id); - -create index idx_kb_chunk_kb_id - on public.knowledge_base_chunk (knowledge_base_id); - -create index idx_kb_chunk_vector_id - on public.knowledge_base_chunk (vector_id); - -create index idx_kb_chunk_metadata - on public.knowledge_base_chunk using gin (metadata); - -create table public.chat_thread_file -( - id serial - primary key, - thread_id varchar(255) not null, - user_id integer not null - constraint fk_chat_thread_file_user - references public.user_list - on delete cascade, - file_name varchar(255) not null, - file_path varchar(500) not null, - file_size integer default 0, - file_type varchar(50) default 'pdf'::character varying, - status varchar(20) default 'processing'::character varying, - chunk_count integer default 0, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - is_deleted boolean default false, - deleted_at timestamp with time zone -); - -alter table public.chat_thread_file - owner to zuoleiroot; - -create index idx_chat_thread_file_thread_id - on public.chat_thread_file (thread_id); - -create index idx_chat_thread_file_user_id - on public.chat_thread_file (user_id); - -create index idx_chat_thread_file_thread_user - on public.chat_thread_file (thread_id, user_id); - -create index idx_chat_thread_file_status - on public.chat_thread_file (status); - -create index idx_chat_thread_file_is_deleted - on public.chat_thread_file (is_deleted); - -create index idx_chat_thread_file_created_at - on public.chat_thread_file (created_at); - -create index idx_chat_thread_file_thread_deleted - on public.chat_thread_file (thread_id, is_deleted); - -create unique index uk_chat_thread_file_thread_name_active - on public.chat_thread_file (thread_id, file_name) - where (is_deleted = false); - -create table public.chat_thread_chunk -( - id serial - primary key, - file_id integer not null - constraint fk_chat_thread_chunk_file - references public.chat_thread_file - on delete cascade, - thread_id varchar(255) not null, - chunk_index integer not null, - content text not null, - metadata jsonb, - vector_id varchar(255), - created_at timestamp with time zone default CURRENT_TIMESTAMP, - summary text -); - -alter table public.chat_thread_chunk - owner to zuoleiroot; - -create index idx_chat_thread_chunk_file_id - on public.chat_thread_chunk (file_id); - -create index idx_chat_thread_chunk_thread_id - on public.chat_thread_chunk (thread_id); - -create index idx_chat_thread_chunk_file_thread - on public.chat_thread_chunk (file_id, thread_id); - -create index idx_chat_thread_chunk_vector_id - on public.chat_thread_chunk (vector_id); - -create index idx_chat_thread_chunk_created_at - on public.chat_thread_chunk (created_at); - -create table public.chat_message_file -( - id serial - primary key, - thread_id varchar(255) not null, - checkpoint_id varchar(255) not null, - message_index integer not null, - file_id integer not null - constraint fk_chat_message_file_file - references public.chat_thread_file - on delete cascade, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - constraint uk_message_file - unique (checkpoint_id, message_index, file_id) -); - -alter table public.chat_message_file - owner to zuoleiroot; - -create index idx_chat_message_file_thread_id - on public.chat_message_file (thread_id); - -create index idx_chat_message_file_checkpoint - on public.chat_message_file (checkpoint_id, message_index); - -create index idx_chat_message_file_file_id - on public.chat_message_file (file_id); - -create index idx_chat_message_file_thread_checkpoint - on public.chat_message_file (thread_id, checkpoint_id); - -create table public.graphs -( - id serial - primary key, - user_id integer not null - constraint fk_graphs_user - references public.user_list - on delete cascade, - name varchar(255) not null, - description text, - csv_file_name varchar(255), - node_count integer default 0, - edge_count integer default 0, - neo4j_graph_id varchar(100) not null - unique, - graph_type varchar(20) default 'knowledge'::character varying not null, - build_status varchar(20), - build_error text, - rag_chunk_count integer default 0 not null, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - enterprise_id integer not null - references public.enterprise, - department_id integer - references public.department - on delete set null, - creator_id integer not null - references public.user_list - on delete set null, - visibility varchar(32) default 'private'::character varying not null - constraint ck_graphs_visibility - check ((visibility)::text = ANY - ((ARRAY ['private'::character varying, 'department'::character varying, 'enterprise'::character varying])::text[])) -); - -comment on table public.graphs is '知识图谱元数据表,图数据在 Neo4j;向量块数量见 rag_chunk_count'; - -comment on column public.graphs.neo4j_graph_id is 'Neo4j 中图谱唯一标识'; - -comment on column public.graphs.graph_type is '兼容字段,默认 knowledge'; - -comment on column public.graphs.build_status is '构建状态:pending/processing/completed/failed'; - -comment on column public.graphs.build_error is '构建失败时的错误信息'; - -comment on column public.graphs.rag_chunk_count is 'Chroma 中知识图谱 RAG 分块数量'; - -comment on column public.graphs.creator_id is '创建者(与 user_id 通常一致,用于权限判断)'; - -comment on column public.graphs.visibility is 'private | department | enterprise'; - -alter table public.graphs - owner to zuoleiroot; - -create index idx_graphs_user_id - on public.graphs (user_id); - -create index idx_graphs_created_at - on public.graphs (created_at desc); - -create index idx_graphs_neo4j_id - on public.graphs (neo4j_graph_id); - -create index idx_graphs_graph_type - on public.graphs (user_id, graph_type); - -create index idx_graphs_enterprise - on public.graphs (enterprise_id); - -create index idx_graphs_creator - on public.graphs (creator_id); - -create index idx_graphs_ent_vis - on public.graphs (enterprise_id, visibility); - -create table public.chat_threads -( - id serial - primary key, - thread_id varchar(255) not null - constraint uk_thread_id - unique, - user_id integer not null - constraint fk_user_id - references public.user_list - on delete cascade, - title varchar(50) not null, - first_query text not null, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - message_count integer default 1, - is_deleted boolean default false, - knowledge_base_id integer, - novel_graph_id integer, - knowledge_graph_id integer - constraint fk_chat_threads_knowledge_graph - references public.graphs - on delete set null, - ip varchar(128) -); - -comment on table public.chat_threads is '聊天会话记录表,记录每个用户的会话基本信息'; - -comment on column public.chat_threads.id is '主键 ID'; - -comment on column public.chat_threads.thread_id is '会话线程 ID(UUID 格式)'; - -comment on column public.chat_threads.user_id is '用户 ID,关联 user_list 表'; - -comment on column public.chat_threads.title is '会话标题(首次请求内容的前10个字)'; - -comment on column public.chat_threads.first_query is '首次请求的完整内容'; - -comment on column public.chat_threads.created_at is '会话创建时间'; - -comment on column public.chat_threads.updated_at is '最后更新时间'; - -comment on column public.chat_threads.message_count is '该会话的消息总数'; - -comment on column public.chat_threads.is_deleted is '是否已删除(软删除标记)'; - -comment on column public.chat_threads.knowledge_graph_id is '绑定的知识图谱 graphs.id,与 knowledge_base_id 二选一'; - -comment on column public.chat_threads.ip is '最近一次发起聊天时的客户端 IP(可选)'; - -alter table public.chat_threads - owner to zuoleiroot; - -create index idx_chat_threads_user_id - on public.chat_threads (user_id); - -create index idx_chat_threads_created_at - on public.chat_threads (created_at desc); - -create index idx_chat_threads_user_created - on public.chat_threads (user_id asc, created_at desc); - -create index idx_chat_threads_novel_graph_id - on public.chat_threads (novel_graph_id); - -create index idx_chat_threads_knowledge_graph_id - on public.chat_threads (knowledge_graph_id); - -create table public.knowledge_processing_task -( - id serial - primary key, - user_id integer not null - constraint fk_kb_processing_user - references public.user_list - on delete cascade, - knowledge_base_id integer not null - constraint fk_kb_processing_kb - references public.knowledge_base - on delete cascade, - task_name varchar(255) not null, - instruction text not null, - file_ids integer[] not null, - task_type varchar(50) not null, - status varchar(20) default 'pending'::character varying, - result text, - result_file_url text, - error_message text, - created_at timestamp with time zone default CURRENT_TIMESTAMP, - updated_at timestamp with time zone default CURRENT_TIMESTAMP, - started_at timestamp with time zone, - completed_at timestamp with time zone -); - -comment on table public.knowledge_processing_task is '知识加工任务表:合并、对比、总结等异步任务'; - -comment on column public.knowledge_processing_task.result_file_url is '加工结果文件的 OSS 下载链接'; - -alter table public.knowledge_processing_task - owner to zuoleiroot; - -create index idx_kb_processing_user_id - on public.knowledge_processing_task (user_id); - -create index idx_kb_processing_kb_id - on public.knowledge_processing_task (knowledge_base_id); - -create index idx_kb_processing_status - on public.knowledge_processing_task (status); - -create index idx_kb_processing_created_at - on public.knowledge_processing_task (created_at desc); - -create index idx_kb_processing_user_status - on public.knowledge_processing_task (user_id, status); - -create index idx_department_enterprise_id - on public.department (enterprise_id); - diff --git a/test_main.http b/test_main.http deleted file mode 100644 index a2d81a9..0000000 --- a/test_main.http +++ /dev/null @@ -1,11 +0,0 @@ -# Test your FastAPI endpoints - -GET http://127.0.0.1:8000/ -Accept: application/json - -### - -GET http://127.0.0.1:8000/hello/User -Accept: application/json - -### diff --git a/update-ddl.txt b/update-ddl.txt deleted file mode 100644 index b9d08c6..0000000 --- a/update-ddl.txt +++ /dev/null @@ -1,73 +0,0 @@ --- ================================================================ --- 权限方案 A 升级 DDL(在已有表结构基础上执行) --- 执行顺序:按文件从上到下顺序执行 --- ================================================================ - --- ------------------------------------------------------------ --- 1. department:新增部门负责人字段 --- ------------------------------------------------------------ -ALTER TABLE public.department - ADD COLUMN IF NOT EXISTS leader_user_id INTEGER - REFERENCES public.user_list(id) ON DELETE SET NULL; - -COMMENT ON COLUMN public.department.leader_user_id IS '部门负责人 user_id,对应 role=leader 的用户'; - -CREATE INDEX IF NOT EXISTS idx_department_leader_user_id - ON public.department (leader_user_id); - --- ------------------------------------------------------------ --- 2. user_list:新增「是否允许上传文件到知识库」开关 --- ------------------------------------------------------------ -ALTER TABLE public.user_list - ADD COLUMN IF NOT EXISTS allow_kb_upload BOOLEAN NOT NULL DEFAULT TRUE; - -COMMENT ON COLUMN public.user_list.allow_kb_upload IS '是否允许上传文件到知识库(上级领导或 admin 可关闭)'; - --- ------------------------------------------------------------ --- 3. kb_audit_log:知识库操作审计日志表(新建) --- ------------------------------------------------------------ -CREATE TABLE IF NOT EXISTS public.kb_audit_log -( - id SERIAL PRIMARY KEY, - enterprise_id INTEGER NOT NULL - REFERENCES public.enterprise ON DELETE CASCADE, - actor_id INTEGER NOT NULL - REFERENCES public.user_list (id) ON DELETE CASCADE, - target_user_id INTEGER - REFERENCES public.user_list (id) ON DELETE SET NULL, - department_id INTEGER - REFERENCES public.department (id) ON DELETE SET NULL, - kb_id INTEGER - REFERENCES public.knowledge_base (id) ON DELETE SET NULL, - file_id INTEGER - REFERENCES public.knowledge_base_file (id) ON DELETE SET NULL, - action VARCHAR(50) NOT NULL, - -- upload | download | delete | archive | create_kb | delete_kb | permission_change - ip VARCHAR(128), - user_agent TEXT, - metadata JSONB, - created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL -); - -COMMENT ON TABLE public.kb_audit_log IS '知识库操作审计日志'; -COMMENT ON COLUMN public.kb_audit_log.action IS - 'upload | download | delete | archive | create_kb | delete_kb | permission_change'; - -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_enterprise_id - ON public.kb_audit_log (enterprise_id); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_actor_id - ON public.kb_audit_log (actor_id); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_target_user_id - ON public.kb_audit_log (target_user_id); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_department_id - ON public.kb_audit_log (department_id); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_kb_id - ON public.kb_audit_log (kb_id); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_action - ON public.kb_audit_log (action); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_created_at - ON public.kb_audit_log (created_at DESC); -CREATE INDEX IF NOT EXISTS idx_kb_audit_log_ent_dept_created - ON public.kb_audit_log (enterprise_id, department_id, created_at DESC); - -ALTER TABLE public.kb_audit_log OWNER TO zuoleiroot;