You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
AI 对话系统完整实现
日期:2026-02-03
类型:功能实现
影响范围:后端服务、数据库
符合规范:jointo-tech-stack v1.0
概述
完整实现了 AI 对话系统的三个核心功能模块:
- AI 提示词系统服务 - 管理系统级 AI 提示词模板
- AI 对话记录服务 - 管理用户与 AI 的对话历史
- @ 提及与参考图系统 - 支持在对话中引用资源作为参考图
实现内容
1. AI 提示词系统服务
文件:server/app/services/ai_prompt_system_service.py
功能:
- ✅ 提示词 CRUD 操作(创建、查询、更新、删除)
- ✅ 提示词版本管理
- ✅ Skills 配置管理(支持多个 skill 文件)
- ✅ 默认提示词管理(每种类型只能有一个默认)
- ✅ 提示词列表查询(支持类型、状态、名称过滤)
核心方法:
- create_prompt() # 创建提示词
- get_prompt_by_id() # 获取提示词详情
- get_default_prompt() # 获取默认提示词
- list_prompts() # 获取提示词列表
- update_prompt() # 更新提示词
- delete_prompt() # 删除提示词(软删除)
- set_default() # 设置为默认提示词
技术规范:
- UUID v7 主键(应用层生成)
- %-formatting 日志
- exc_info=True 错误日志
- 应用层保证引用完整性
2. AI 对话记录服务
文件:server/app/services/ai_conversation_service.py
功能:
- ✅ 对话会话管理(创建、查询、列表)
- ✅ 消息管理(发送、列表)
- ✅ 多态关联 + 标签系统(支持不同类型的 AI 生成任务)
- ✅ @ 提及功能(解析、验证、构建)
- ✅ AI 生成触发(支持参考图)
核心设计:
多态关联模式:
target_type: int # 目标类型(分镜/角色/场景/道具/资源/音效/配音)
target_id: UUID # 目标对象 ID
tag_id: UUID # 标签 ID(可选,用于区分变体)
media_type: int # 媒体类型(图片/视频/音频/3D模型/文本)
隔离策略:
- 类型隔离:分镜图对话 ≠ 分镜视频对话
- 对象隔离:分镜A的对话 ≠ 分镜B的对话
- 变体隔离:角色-张三-少年装扮 ≠ 角色-张三-成年装扮
- 用户隔离:用户A的对话 ≠ 用户B的对话
核心方法:
# 对话会话管理
- create_conversation() # 创建对话会话
- get_conversation() # 获取对话详情
- list_conversations() # 获取对话列表
# 消息管理
- send_message() # 发送消息(支持自动解析提及)
- list_messages() # 获取消息列表
# @ 提及功能
- get_mentionable_resources() # 获取可提及的资源列表
- _parse_mentions() # 解析消息中的提及标记
- _validate_and_build_mention() # 验证并构建提及对象
# AI 生成触发
- trigger_ai_generation() # 触发 AI 生成任务(支持参考图)
3. @ 提及与参考图系统
核心原则:
前端职责:
- 提供 @ 自动补全,帮助用户快速输入
- 插入标准格式的提及标记到文本
- 高亮显示提及标记,提供视觉反馈
- 只发送文本,不发送 mentions 数组
后端职责:
- 解析文本中的提及标记
- 验证所有提及的资源
- 构建 metadata(mentions + reference_images)
- 存储消息到数据库
提及标记格式:
@[显示名称](类型:元素ID:标签ID:资源ID)
示例:
生成一张 @[张三-少年](character:019d1234...:019d1234...:019d1234...) 在 @[咖啡厅-白天](scene:019d1234...:019d1234...:019d1234...) 喝咖啡的图片
数据流程:
- 用户输入
@→ 前端调用 API 获取可提及的资源列表 - 用户选择资源 → 前端插入标准格式的提及标记
- 用户发送消息 → 后端解析提及标记并验证资源
- 后端构建 metadata → 存储 mentions 和 reference_images
- 用户触发生成 → 后端提取参考图 URL 传递给 AI
4. 数据库迁移
文件:server/alembic/versions/20260203_1600_create_ai_conversations_tables.py
创建的表:
ai_conversations(AI 对话会话表)
CREATE TABLE ai_conversations (
conversation_id UUID PRIMARY KEY,
user_id UUID NOT NULL,
project_id UUID,
target_type SMALLINT NOT NULL,
target_id UUID NOT NULL,
tag_id UUID,
media_type SMALLINT NOT NULL,
title TEXT,
status SMALLINT NOT NULL DEFAULT 1,
message_count INTEGER NOT NULL DEFAULT 0,
last_message_at TIMESTAMPTZ,
metadata JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
索引:
idx_ai_conversations_user_id- 用户 IDidx_ai_conversations_project_id- 项目 ID(部分索引)idx_ai_conversations_target- 目标类型 + 目标 IDidx_ai_conversations_target_tag- 目标类型 + 目标 ID + 标签 IDidx_ai_conversations_tag_id- 标签 ID(部分索引)idx_ai_conversations_media_type- 媒体类型idx_ai_conversations_status- 会话状态idx_ai_conversations_created_at- 创建时间idx_ai_conversations_last_message_at- 最后消息时间(部分索引)idx_ai_conversations_user_status- 用户 ID + 状态idx_ai_conversations_user_target_tag_media- 复合索引idx_ai_conversations_metadata_gin- JSONB GIN 索引
唯一约束:
CREATE UNIQUE INDEX idx_ai_conversations_unique_active
ON ai_conversations (user_id, target_type, target_id, tag_id, media_type)
NULLS NOT DISTINCT
WHERE status = 1;
ai_conversation_messages(AI 对话消息表)
CREATE TABLE ai_conversation_messages (
message_id UUID PRIMARY KEY,
conversation_id UUID NOT NULL,
user_id UUID NOT NULL,
ai_job_id UUID,
role SMALLINT NOT NULL,
content TEXT NOT NULL,
metadata JSONB NOT NULL DEFAULT '{}',
order_index INTEGER NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
索引:
idx_ai_conversation_messages_conversation_id- 对话会话 IDidx_ai_conversation_messages_user_id- 用户 IDidx_ai_conversation_messages_ai_job_id- AI 任务 ID(部分索引)idx_ai_conversation_messages_role- 消息角色idx_ai_conversation_messages_created_at- 创建时间idx_ai_conversation_messages_conversation_order- 对话 ID + 顺序idx_ai_conversation_messages_metadata_gin- JSONB GIN 索引idx_ai_conversation_messages_content_gin- 全文搜索索引
触发器:
update_ai_conversations_updated_at- 自动更新 updated_atupdate_ai_conversation_messages_updated_at- 自动更新 updated_atupdate_conversation_stats_trigger- 自动更新会话统计(message_count、last_message_at)
技术栈合规性
✅ 符合 jointo-tech-stack 规范
-
UUID v7 主键:
- 所有主键使用 UUID v7(应用层生成)
- 使用
uuid7()函数生成
-
TIMESTAMPTZ 时间字段:
- 所有时间字段使用
TIMESTAMPTZ类型 - 符合 ADR 006 规范
- 所有时间字段使用
-
SMALLINT 枚举类型:
- 所有枚举字段使用
SMALLINT存储 - Python 使用
IntEnum定义枚举
- 所有枚举字段使用
-
无物理外键约束:
- 数据库层不创建 FOREIGN KEY 约束
- 应用层保证引用完整性
-
日志格式:
- 使用 %-formatting 格式化日志
- 错误日志包含
exc_info=True
-
异步编程:
- 所有数据库操作使用 async/await
- 使用 AsyncSession
使用场景
场景1:分镜基础图片生成对话(无标签)
# 创建对话会话
conversation = await ai_conversation_service.create_conversation(
user_id=user_id,
target_type=TargetType.STORYBOARD,
target_id=storyboard_id,
tag_id=None, # 无标签(基础图片)
media_type=MediaType.IMAGE,
project_id=project_id
)
场景2:分镜正面角度图片生成对话(有标签)
# 创建对话会话
conversation = await ai_conversation_service.create_conversation(
user_id=user_id,
target_type=TargetType.STORYBOARD,
target_id=storyboard_id,
tag_id=angle_tag_id, # 正面角度标签
media_type=MediaType.IMAGE,
project_id=project_id
)
场景3:角色少年装扮图片生成对话
# 创建对话会话
conversation = await ai_conversation_service.create_conversation(
user_id=user_id,
target_type=TargetType.CHARACTER,
target_id=character_id,
tag_id=costume_tag_id, # 少年装扮标签
media_type=MediaType.IMAGE,
project_id=project_id
)
场景4:发送带提及的消息
# 发送消息(包含提及标记)
message = await ai_conversation_service.send_message(
conversation_id=conversation_id,
user_id=user_id,
content="生成一张 @[张三-少年](character:019d1234...:019d1234...:019d1234...) 在 @[咖啡厅-白天](scene:019d1234...:019d1234...:019d1234...) 喝咖啡的图片"
)
# 后端自动解析提及标记,构建 metadata
# message.metadata = {
# 'mentions': [...],
# 'reference_images': [url1, url2]
# }
场景5:触发 AI 生成(使用参考图)
# 触发 AI 生成
result = await ai_conversation_service.trigger_ai_generation(
conversation_id=conversation_id,
user_id=user_id,
message_id=message_id,
generation_type='image',
params={
'prompt': '生成一张张三在咖啡厅喝咖啡的图片',
'model': 'stable_diffusion',
'width': 1024,
'height': 1024
}
)
# 后端自动从消息的 metadata 中提取参考图 URL
# 传递给 AI Service 进行生成
相关文档
- AI 提示词系统服务需求文档
- AI 对话记录服务需求文档
- AI 对话 @ 提及系统需求文档
- jointo-tech-stack 规范
- ADR 001: UUID v7 迁移
- ADR 006: TIMESTAMPTZ 时间戳规范
后续工作
待实现功能
-
AI Service 集成:
- 实现 AI Service 的
generate_image()方法 - 支持参考图传递给 AI 提供商
- 实现 Stable Diffusion ControlNet 集成
- 实现 Midjourney --cref 参数集成
- 实现 AI Service 的
-
前端实现:
- 实现 MentionInput 组件
- 实现 MentionAutocomplete 组件
- 实现提及标记的高亮显示
- 实现键盘交互(↑↓ 选择、Enter 确认、ESC 取消)
-
API 路由:
- 实现 AI 对话相关的 API 路由
- 实现 AI 提示词相关的 API 路由(管理员专用)
-
测试:
- 编写单元测试
- 编写集成测试
- 编写 E2E 测试
优化建议
-
性能优化:
- 资源列表缓存(使用 Redis)
- 图片懒加载
- 搜索防抖
- 虚拟滚动
-
安全优化:
- 权限验证增强
- XSS 防护
- 参考图 URL 验证
-
用户体验优化:
- 实时反馈
- 错误提示优化
- 加载状态优化
总结
本次实现完成了 AI 对话系统的三个核心功能模块,包括:
- ✅ AI 提示词系统服务(完整实现)
- ✅ AI 对话记录服务(完整实现)
- ✅ @ 提及与参考图系统(完整实现)
- ✅ 数据库迁移(完整实现)
所有实现均符合 jointo-tech-stack 规范,包括:
- UUID v7 主键
- TIMESTAMPTZ 时间字段
- SMALLINT 枚举类型
- 无物理外键约束
- %-formatting 日志
- 异步编程
系统已具备完整的对话管理、提及解析、参考图提取功能,为后续的 AI Service 集成和前端实现奠定了坚实的基础。
文档版本:v1.0
创建日期:2026-02-03
作者:Jointo AI Team