# AIA - AI智能问答模块：数据库设计

> **版本：** v1.0  
> **更新时间：** 2025-11-12  
> **数据库Schema：** `aia_schema`  
> **状态：** ✅ 已实施并迁移  

---

## 📋 目录

1. [模块概述](#模块概述)
2. [Schema信息](#schema信息)
3. [数据库表设计](#数据库表设计)
4. [表关系图](#表关系图)
5. [索引设计](#索引设计)
6. [数据类型说明](#数据类型说明)
7. [变更历史](#变更历史)

---

## 模块概述

### 功能定位

**AIA（AI Intelligent Assistant）- AI智能问答模块**是平台的核心对话引擎，提供：

1. **项目管理** - 研究项目的创建和管理
2. **智能对话** - 基于LLM的专业领域对话
3. **通用问答** - 不绑定项目的通用AI对话
4. **消息管理** - 对话历史记录和检索

### 核心业务场景

- 用户创建临床研究项目
- 在项目内与AI进行专业对话
- 使用通用对话功能快速咨询
- 查看和管理对话历史

---

## Schema信息

### Schema名称
```sql
aia_schema
```

### 创建语句
```sql
CREATE SCHEMA IF NOT EXISTS aia_schema;
GRANT ALL ON SCHEMA aia_schema TO aiclinical_admin;
```

### 数据迁移
- **迁移时间：** 2025-11-12
- **源Schema：** public
- **迁移脚本：** `docs/09-架构实施/migration-scripts/003-migrate-aia.sql`
- **数据完整性：** ✅ 100%迁移成功

---

## 数据库表设计

### 表列表

| 表名 | 用途 | 行数（估计） | 状态 |
|------|------|------------|------|
| `projects` | 研究项目 | 1-100/用户 | ✅ 已部署 |
| `conversations` | 项目对话 | 10-500/项目 | ✅ 已部署 |
| `messages` | 对话消息 | 10-1000/对话 | ✅ 已部署 |
| `general_conversations` | 通用对话 | 10-100/用户 | ✅ 已部署 |
| `general_messages` | 通用对话消息 | 10-1000/对话 | ✅ 已部署 |

**总计：** 5个表

---

### 1. projects - 研究项目表

**用途：** 存储用户创建的临床研究项目

#### 表结构

| 字段名 | 数据类型 | 约束 | 说明 |
|--------|---------|------|------|
| id | TEXT | PRIMARY KEY | 项目唯一标识（UUID） |
| user_id | TEXT | NOT NULL, FK | 所属用户ID |
| name | TEXT | NOT NULL | 项目名称 |
| background | TEXT | NULL | 研究背景 |
| research_type | TEXT | NULL | 研究类型（observational/experimental等） |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL | 更新时间 |
| deleted_at | TIMESTAMPTZ | NULL | 软删除时间 |

#### Prisma Model

```prisma
model Project {
  id                String   @id @default(uuid())
  userId            String   @map("user_id")
  name              String
  background        String?
  researchType      String?  @map("research_type")
  
  createdAt         DateTime @default(now()) @map("created_at")
  updatedAt         DateTime @updatedAt @map("updated_at")
  deletedAt         DateTime? @map("deleted_at")
  
  user              User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  conversations     Conversation[]
  
  @@index([userId])
  @@index([createdAt])
  @@index([deletedAt])
  @@map("projects")
  @@schema("aia_schema")
}
```

#### 业务规则

1. **软删除机制** - 使用`deleted_at`标记删除，不物理删除
2. **级联删除** - 删除项目时，关联的对话也被软删除
3. **用户隔离** - 通过`user_id`实现数据隔离

---

### 2. conversations - 项目对话表

**用途：** 存储项目内的AI对话会话

#### 表结构

| 字段名 | 数据类型 | 约束 | 说明 |
|--------|---------|------|------|
| id | TEXT | PRIMARY KEY | 对话唯一标识（UUID） |
| user_id | TEXT | NOT NULL, FK | 所属用户ID |
| project_id | TEXT | NULL, FK | 所属项目ID（可选） |
| agent_id | TEXT | NOT NULL | 智能体ID |
| title | TEXT | NOT NULL | 对话标题 |
| model_name | TEXT | NOT NULL, DEFAULT 'deepseek-v3' | 使用的LLM模型 |
| message_count | INTEGER | NOT NULL, DEFAULT 0 | 消息数量 |
| total_tokens | INTEGER | NOT NULL, DEFAULT 0 | 累计token数 |
| metadata | JSONB | NULL | 扩展元数据 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL | 更新时间 |
| deleted_at | TIMESTAMPTZ | NULL | 软删除时间 |

#### Prisma Model

```prisma
model Conversation {
  id           String   @id @default(uuid())
  userId       String   @map("user_id")
  projectId    String?  @map("project_id")
  agentId      String   @map("agent_id")
  title        String
  modelName    String   @default("deepseek-v3") @map("model_name")
  messageCount Int      @default(0) @map("message_count")
  totalTokens  Int      @default(0) @map("total_tokens")
  metadata     Json?
  
  createdAt    DateTime @default(now()) @map("created_at")
  updatedAt    DateTime @updatedAt @map("updated_at")
  deletedAt    DateTime? @map("deleted_at")
  
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  project      Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
  messages     Message[]
  
  @@index([userId])
  @@index([projectId])
  @@index([agentId])
  @@index([createdAt])
  @@index([deletedAt])
  @@map("conversations")
  @@schema("aia_schema")
}
```

#### 业务规则

1. **项目关联可选** - `project_id`可为空，支持项目内外对话
2. **计数器字段** - `message_count`和`total_tokens`用于统计，需要实时更新
3. **模型选择** - 支持多种LLM模型（deepseek-v3/gpt-5-pro/claude-4.5等）
4. **扩展元数据** - `metadata`用于存储配置参数、上下文等

---

### 3. messages - 对话消息表

**用途：** 存储对话中的每条消息

#### 表结构

| 字段名 | 数据类型 | 约束 | 说明 |
|--------|---------|------|------|
| id | TEXT | PRIMARY KEY | 消息唯一标识（UUID） |
| conversation_id | TEXT | NOT NULL, FK | 所属对话ID |
| role | TEXT | NOT NULL | 角色（user/assistant/system） |
| content | TEXT | NOT NULL | 消息内容 |
| model | TEXT | NULL | 使用的模型（assistant消息） |
| metadata | JSONB | NULL | 扩展元数据 |
| tokens | INTEGER | NULL | 消息token数 |
| is_pinned | BOOLEAN | NOT NULL, DEFAULT false | 是否置顶 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |

#### Prisma Model

```prisma
model Message {
  id             String   @id @default(uuid())
  conversationId String   @map("conversation_id")
  role           String
  content        String   @db.Text
  model          String?
  metadata       Json?
  tokens         Int?
  isPinned       Boolean  @default(false) @map("is_pinned")
  
  createdAt      DateTime @default(now()) @map("created_at")
  
  conversation   Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
  
  @@index([conversationId])
  @@index([createdAt])
  @@index([isPinned])
  @@map("messages")
  @@schema("aia_schema")
}
```

#### 业务规则

1. **角色类型** - `role`固定为`user`、`assistant`或`system`
2. **只读性** - 消息一旦创建不可修改（只有`is_pinned`可修改）
3. **级联删除** - 删除对话时，消息自动删除
4. **置顶功能** - 重要消息可通过`is_pinned`标记

---

### 4. general_conversations - 通用对话表

**用途：** 存储不绑定项目的通用AI对话

#### 表结构

| 字段名 | 数据类型 | 约束 | 说明 |
|--------|---------|------|------|
| id | TEXT | PRIMARY KEY | 对话唯一标识（UUID） |
| user_id | TEXT | NOT NULL, FK | 所属用户ID |
| title | TEXT | NOT NULL | 对话标题 |
| model_name | TEXT | NOT NULL, DEFAULT 'qwen-long' | 使用的LLM模型 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL | 更新时间 |
| deleted_at | TIMESTAMPTZ | NULL | 软删除时间 |

#### Prisma Model

```prisma
model GeneralConversation {
  id            String   @id @default(uuid())
  userId        String   @map("user_id")
  title         String
  modelName     String   @default("qwen-long") @map("model_name")
  
  createdAt     DateTime @default(now()) @map("created_at")
  updatedAt     DateTime @updatedAt @map("updated_at")
  deletedAt     DateTime? @map("deleted_at")
  
  user          User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  messages      GeneralMessage[]
  
  @@index([userId])
  @@index([createdAt])
  @@index([updatedAt])
  @@map("general_conversations")
  @@schema("aia_schema")
}
```

#### 业务规则

1. **轻量级对话** - 不需要项目和智能体关联
2. **快速咨询** - 用于用户的临时问题和快速查询
3. **独立管理** - 与项目对话分开管理

---

### 5. general_messages - 通用对话消息表

**用途：** 存储通用对话中的每条消息

#### 表结构

| 字段名 | 数据类型 | 约束 | 说明 |
|--------|---------|------|------|
| id | TEXT | PRIMARY KEY | 消息唯一标识（UUID） |
| conversation_id | TEXT | NOT NULL, FK | 所属对话ID |
| role | TEXT | NOT NULL | 角色（user/assistant/system） |
| content | TEXT | NOT NULL | 消息内容 |
| metadata | JSONB | NULL | 扩展元数据 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT now() | 创建时间 |

#### Prisma Model

```prisma
model GeneralMessage {
  id             String   @id @default(uuid())
  conversationId String   @map("conversation_id")
  role           String
  content        String   @db.Text
  metadata       Json?
  
  createdAt      DateTime @default(now()) @map("created_at")
  
  conversation   GeneralConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
  
  @@index([conversationId])
  @@index([createdAt])
  @@map("general_messages")
  @@schema("aia_schema")
}
```

#### 业务规则

1. **简化设计** - 相比项目消息，去掉了token统计和置顶功能
2. **级联删除** - 删除对话时，消息自动删除

---

## 表关系图

```mermaid
erDiagram
    PLATFORM_USERS ||--o{ PROJECTS : "owns"
    PLATFORM_USERS ||--o{ CONVERSATIONS : "owns"
    PLATFORM_USERS ||--o{ GENERAL_CONVERSATIONS : "owns"
    
    PROJECTS ||--o{ CONVERSATIONS : "contains"
    CONVERSATIONS ||--o{ MESSAGES : "contains"
    GENERAL_CONVERSATIONS ||--o{ GENERAL_MESSAGES : "contains"

    PLATFORM_USERS {
        text id PK
        text email
        text password
    }

    PROJECTS {
        text id PK
        text user_id FK
        text name
        text research_type
        timestamptz created_at
        timestamptz deleted_at
    }

    CONVERSATIONS {
        text id PK
        text user_id FK
        text project_id FK
        text agent_id
        text title
        text model_name
        int message_count
        timestamptz created_at
    }

    MESSAGES {
        text id PK
        text conversation_id FK
        text role
        text content
        int tokens
        boolean is_pinned
        timestamptz created_at
    }

    GENERAL_CONVERSATIONS {
        text id PK
        text user_id FK
        text title
        text model_name
        timestamptz created_at
    }

    GENERAL_MESSAGES {
        text id PK
        text conversation_id FK
        text role
        text content
        timestamptz created_at
    }
```

### 跨Schema引用

**外键关系：**
- `projects.user_id` → `platform_schema.users.id`
- `conversations.user_id` → `platform_schema.users.id`
- `general_conversations.user_id` → `platform_schema.users.id`

**说明：** Prisma自动处理跨Schema外键，应用代码无需关心Schema前缀

---

## 索引设计

### 主键索引
所有表的`id`字段自动创建B-tree主键索引。

### 外键索引

| 表名 | 索引字段 | 用途 |
|------|---------|------|
| projects | user_id | 查询用户的所有项目 |
| conversations | user_id | 查询用户的所有对话 |
| conversations | project_id | 查询项目内的对话 |
| conversations | agent_id | 按智能体过滤对话 |
| messages | conversation_id | 查询对话的所有消息 |
| general_conversations | user_id | 查询用户的通用对话 |
| general_messages | conversation_id | 查询对话的所有消息 |

### 时间索引

| 表名 | 索引字段 | 用途 |
|------|---------|------|
| projects | created_at | 按时间排序项目 |
| projects | deleted_at | 过滤已删除项目 |
| conversations | created_at | 按时间排序对话 |
| conversations | updated_at | 按更新时间排序 |
| conversations | deleted_at | 过滤已删除对话 |
| messages | created_at | 按时间排序消息 |
| general_conversations | created_at | 按时间排序对话 |
| general_conversations | updated_at | 按更新时间排序 |
| general_messages | created_at | 按时间排序消息 |

### 功能索引

| 表名 | 索引字段 | 用途 |
|------|---------|------|
| messages | is_pinned | 快速查询置顶消息 |

---

## 数据类型说明

### 主键类型：TEXT vs UUID

**当前实现：** TEXT
```sql
id TEXT PRIMARY KEY
```

**UUID生成：** Prisma `@default(uuid())`
```prisma
id String @id @default(uuid())
```

**说明：**
- 存储格式：字符串形式的UUID（如`"a6ce8b46-bac6-4284-a9ae-031d636086bc"`）
- 优点：与现有代码兼容，无需迁移
- 索引性能：与原生UUID类型相当

### 时间类型：TIMESTAMPTZ

**所有时间字段使用`TIMESTAMPTZ`（带时区的时间戳）：**
- 自动存储UTC时间
- 支持时区转换
- Prisma映射为`DateTime`

### JSONB类型

**用途：** 存储扩展元数据和配置
- `conversations.metadata`
- `messages.metadata`
- `general_messages.metadata`

**优点：**
- 灵活的数据结构
- 支持GIN索引（按需添加）
- 支持JSONB操作符查询

---

## 变更历史

### v1.0 - 2025-11-12 - 初始版本 ✅

**变更内容：**
1. 从`public` schema迁移到`aia_schema`
2. 5个表全部迁移：
   - projects
   - conversations
   - messages
   - general_conversations
   - general_messages
3. 在Prisma中添加`@@schema("aia_schema")`标签
4. 所有数据100%完整迁移

**迁移脚本：** `docs/09-架构实施/migration-scripts/003-migrate-aia.sql`

**验证状态：** ✅ 已验证，功能正常

---

## 📚 相关文档

- [Schema隔离架构设计](../../../09-架构实施/01-Schema隔离架构设计（10个）.md)
- [Schema迁移完成报告](../../../09-架构实施/Schema迁移完成报告.md)
- [Prisma配置完成报告](../../../09-架构实施/Prisma配置完成报告.md)
- [快速功能测试报告](../../../09-架构实施/快速功能测试报告.md)

---

**文档维护者：** AI助手  
**最后更新：** 2025-11-12  
**文档状态：** ✅ 已完成并验证






