本项目旨在重构一个类似 Claude 的 AI 聊天系统前端,支持以下核心功能:
is_active 字段标记用户当前查看的消息链session_id 的消息在前端显示为一个对话组parent_id 的消息作为不同版本├── types/
│ └── chat.ts # 所有类型定义
├── hooks/ # 数据管理层
│ ├── useChatData.ts # 主要数据管理
│ ├── useActivePath.ts # 激活路径计算
│ ├── useSessionGroups.ts # Session 分组管理
│ └── mockChatData.ts # Mock 测试数据
├── services/ # API调用层
│ ├── chatApi.ts # 聊天 API
│ ├── messageApi.ts # 消息 API
│ └── modelAdapters/ # 模型适配器
│ ├── base.ts # 基础适配器
│ ├── openai.ts # OpenAI 适配器
│ └── index.ts # 适配器工厂
├── components/ #
│ └── chat # 显示层
│ ├── ChatContainer.tsx # 主容器组件
│ ├── SessionGroup.tsx # Session 消息组
│ ├── UserMessage.tsx # 用户消息
│ ├── AssistantMessage.tsx # AI 回答
│ ├── MessageActions.tsx # 消息操作
│ ├── ChatInput.tsx # 输入组件
│ └── VersionSwitcher.tsx # 版本切换
└── mockChatData.ts # Mock 测试数据
// 工具调用相关类型
export interface ToolCall {
id: string;
function: string;
arguments: Record<string, any>;
}
// 消息元数据
export interface MessageMetadata {
generation_params?: {
temperature?: number;
max_tokens?: number;
top_p?: number;
frequency_penalty?: number;
presence_penalty?: number;
};
token_usage?: {
prompt_tokens?: number;
completion_tokens?: number;
total_tokens?: number;
};
performance?: {
response_time_ms?: number;
first_token_time_ms?: number;
};
tool_stats?: {
total_calls?: number;
successful_calls?: number;
execution_time_ms?: number;
};
custom_data?: Record<string, any>;
}
// 消息节点(对应数据库结构)
export interface MessageNode {
id: number; // DB自增ID,用于版本排序
uid: string; // UUID
chat_id: string;
parent_id?: string;
session_id: string;
role: "system" | "user" | "assistant" | "tool";
content?: string;
model_id?: string;
tool_calls?: ToolCall[];
tool_call_id?: string;
metadata?: MessageMetadata;
is_active: boolean;
editor_id?: string;
created_at: string;
updated_at: string;
deleted_at?: string;
// 临时状态字段(前端使用)
save_status?: "saved" | "pending" | "failed";
temp_id?: string; // 临时ID,用于未保存消息
}
// 版本信息
export interface VersionInfo {
version_index: number; // 版本索引(0,1,2...)
model_id?: string; // 该版本使用的模型
model_name?: string; // 模型显示名称
created_at: string; // 版本创建时间
message_count: number; // 该版本包含的消息数量
token_usage?: number; // 该版本的token使用量
}
// Session 信息
export interface SessionInfo {
session_id: string;
messages: MessageNode[]; // 该session的所有消息(按激活路径过滤)
versions: VersionInfo[]; // 该session所有版本信息
current_version: number; // 当前显示的版本索引
user_message?: MessageNode; // 该session的用户消息(便于访问)
ai_messages: MessageNode[]; // 该session的AI消息列表
}
// 待保存消息组
export interface PendingMessage {
temp_id: string;
session_id: string;
messages: MessageNode[]; // 待保存的消息组
retry_count: number;
error?: string;
created_at: string;
}
// 聊天状态
export interface ChatState {
chat_id: string;
title: string;
raw_messages: MessageNode[]; // 从DB加载的原始线性数据
active_path: MessageNode[]; // 当前激活路径上的消息
session_groups: SessionInfo[]; // 按session分组的显示数据
pending_messages: PendingMessage[]; // 待保存的消息组
is_loading: boolean;
streaming_message?: string;
streaming_session_id?: string;
current_model: string;
error?: string;
}
// 聊天操作接口
export interface ChatActions {
switchVersion: (sessionId: string, versionIndex: number) => Promise<void>;
editMessage: (
sessionId: string,
content: string,
role?: "user" | "assistant"
) => Promise<void>;
retryMessage: (tempId: string) => Promise<void>;
refreshResponse: (sessionId: string, modelId?: string) => Promise<void>;
loadMessages: () => Promise<void>;
likeMessage: (messageId: string) => Promise<void>;
dislikeMessage: (messageId: string) => Promise<void>;
copyMessage: (messageId: string) => void;
shareMessage: (messageId: string) => Promise<string>;
deleteMessage: (messageId: string) => Promise<void>;
}
// API 请求类型
export interface CreateMessageRequest {
messages: Array<{
parent_id?: string;
role: "user" | "assistant" | "tool";
content?: string;
model_id?: string;
tool_calls?: ToolCall[];
tool_call_id?: string;
metadata?: MessageMetadata;
}>;
}
export interface CreateChatRequest {
title: string;
user_id?: string;
}
// API 响应类型
export interface ApiResponse<T> {
ok: boolean;
message: string;
data: T;
}
export interface ChatResponse {
id: string;
title: string;
user_id?: string;
created_at: string;
updated_at: string;
}
export interface MessageListResponse {
rows: MessageNode[];
total: number;
}
// 模型适配器相关类型
export interface ModelAdapter {
name: string;
supportsFunctionCall: boolean;
sendMessage(
messages: OpenAIMessage[],
options: SendOptions
): Promise<AsyncIterable<string>>;
parseStreamChunk(chunk: string): ParsedChunk | null;
handleFunctionCall(functionCall: ToolCall): Promise<any>;
}
export interface OpenAIMessage {
role: "system" | "user" | "assistant" | "function" | "tool";
content?: string;
name?: string;
tool_calls?: ToolCall[];
tool_call_id?: string;
}
export interface SendOptions {
temperature?: number;
max_tokens?: number;
top_p?: number;
functions?: Array<{
name: string;
description: string;
parameters: any;
}>;
function_call?: string | { name: string };
}
export interface ParsedChunk {
content?: string;
function_call?: {
name?: string;
arguments?: string;
};
finish_reason?: string;
}
// 组件 Props 类型
export interface SessionGroupProps {
session: SessionInfo;
onVersionSwitch: (sessionId: string, versionIndex: number) => void;
onRefresh: (sessionId: string, modelId?: string) => void;
onEdit: (sessionId: string, content: string) => void;
onRetry?: (tempId: string) => void;
onLike?: (messageId: string) => void;
onDislike?: (messageId: string) => void;
onCopy?: (messageId: string) => void;
onShare?: (messageId: string) => Promise<string>;
}
export interface UserMessageProps {
message: MessageNode;
onEdit?: (content: string) => void;
onCopy?: () => void;
}
export interface AssistantMessageProps {
messages: MessageNode[];
onRefresh?: () => void;
onEdit?: (content: string) => void;
isPending?: boolean;
onLike?: (messageId: string) => void;
onDislike?: (messageId: string) => void;
onCopy?: (messageId: string) => void;
onShare?: (messageId: string) => Promise<string>;
}
export interface VersionSwitcherProps {
versions: VersionInfo[];
currentVersion: number;
onSwitch: (versionIndex: number) => void;
}
export interface ChatInputProps {
onSend: (content: string) => void;
disabled?: boolean;
placeholder?: string;
}
// Mock 数据支持
export interface UseChatDataOptions {
useMockData?: boolean;
mockDelay?: number;
}
核心功能:从线性消息数组计算当前激活的消息链
算法说明:
is_active=true 的路径构建消息链parent_id 关系链接父子消息接口:
export function useActivePath(rawMessages: MessageNode[]): MessageNode[];
核心功能:将激活路径上的消息按 session_id 分组,计算版本信息
算法说明:
session_id 对激活消息分组(排除 system 消息)接口:
export function useSessionGroups(
activePath: MessageNode[],
rawMessages: MessageNode[]
): SessionInfo[];
核心功能:主要的聊天数据管理 Hook,支持 Mock 模式
主要职责:
接口:
export function useChatData(
chatId: string,
options?: UseChatDataOptions
): { chatState: ChatState; actions: ChatActions };
Mock 模式支持:
useMockData: true 启用 Mock 模式功能:聊天会话相关的 API 调用
主要接口:
createChat(request: CreateChatRequest): Promise<ApiResponse<ChatResponse>>getChat(chatId: string): Promise<ApiResponse<ChatResponse>>updateChat(chatId: string, updates: Partial<CreateChatRequest>): Promise<ApiResponse<ChatResponse>>deleteChat(chatId: string): Promise<ApiResponse<void>>功能:消息相关的 API 调用
主要接口:
getMessages(chatId: string): Promise<ApiResponse<MessageListResponse>>createMessages(chatId: string, request: CreateMessageRequest): Promise<ApiResponse<MessageNode[]>>switchVersion(chatId: string, messageUids: string[]): Promise<ApiResponse<void>>likeMessage/dislikeMessage/shareMessage/deleteMessage: 消息操作接口设计模式:适配器模式,支持多模型厂商
功能:定义模型适配器的基础抽象类
核心方法:
sendMessage: 发送消息,返回流式响应parseStreamChunk: 解析流数据块handleFunctionCall: 处理函数调用功能:OpenAI 模型的具体实现
关键特性:
实现要点:
// sendMessage 返回 Promise<AsyncIterable<string>>
async sendMessage(messages: OpenAIMessage[], options: SendOptions): Promise<AsyncIterable<string>> {
// 创建内部流生成器
return this.createStreamIterable(payload);
}
private async *createStreamIterable(payload: any): AsyncIterable<string> {
// 实际的流处理逻辑
}
功能:适配器工厂,管理不同模型的适配器实例
主要接口:
getModelAdapter(modelId: string): ModelAdapterregisterAdapter(modelId: string, adapter: ModelAdapter): void功能:主容器组件,协调整个聊天界面
职责:
Props:{ chatId: string }
功能:渲染单个对话 session,包含用户问题和 AI 完整回答
核心特性:
Props:SessionGroupProps
功能:用户消息显示和编辑
特性:
Props:UserMessageProps
功能:AI 回答显示,支持多消息组合(Function Call 场景)
特性:
Props:AssistantMessageProps
功能:版本切换控制器
特性:
Props:VersionSwitcherProps
功能:用户输入组件
特性:
Props:ChatInputProps
功能:提供完整的测试数据集,支持各种场景
数据场景:
主要导出:
mockChatState: 正常对话状态mockChatStateWithPending: 带待发送消息mockChatStateWithError: 错误状态mockChatStateStreaming: 流式输出状态工具函数:
getActivePath(): 获取激活路径mockApiDelay(): 模拟网络延迟mockStreamResponse(): 模拟流式响应mockFunctionCallResponse: 模拟函数调用结果ChatInput.onSend → actions.editMessage('new', content)streaming_message 状态VersionSwitcher.onSwitch启用方式:
const { chatState, actions } = useChatData(chatId, {
useMockData: process.env.NODE_ENV === "development",
mockDelay: 500,
});
Mock 特性:
这个设计提供了完整的架构蓝图,支持快速开发和调试,同时保持了良好的可维护性和扩展性。Mock 数据支持让开发者无需依赖后端 API 即可完成前端功能开发。