// services/mockMessageApi.ts import type { CreateMessageRequest, MessageListResponse, ApiResponse, MessageNode, } from "../types/chat"; import { system_prompt } from "./agentApi"; // Mock 消息数据库 // System 消息 (根节点) const rootMessage: MessageNode = { id: 1, uid: "msg-system-001", chat_id: "chat-001", session_id: "system-session", role: "system", content: system_prompt, is_active: true, created_at: "2025-01-15T10:00:00Z", updated_at: "2025-01-15T10:00:00Z", }; const teamArgs = JSON.stringify({ term: "dhamma" }); const jsonString = `{"took":15,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":520,"relation":"eq"},"max_score":10.384174,"hits":[{"_index":"wikipali","_id":"pali_para_93_532","_score":10.384174,"_source":{"id":"pali_para_93_532","resource_id":"dfe69668-da34-11ec-b3cc-fb89202f7b35","resource_type":"paragraph","title":{"text":"Paragraph 532 of Book 93"},"summary":{"text":"314. Atha kho bhagavā te brāhmaṇe etadavoca..."},"content":{"display":"314. Atha kho bhagavā te brāhmaṇe etadavoca...","text":"314. Atha kho bhagavā te brāhmaṇe etadavoca...","exact":"314. Atha kho bhagavā te brāhmaṇe etadavoca..."},"bold_single":"","bold_multi":" ","related_id":99,"category":"pali","language":"pali","updated_at":"2025-09-24T16:14:18+00:00","granularity":"paragraph"}},{"_index":"wikipali","_id":"pali_para_93_531","_score":10.380177,"_source":{"id":"pali_para_93_531","resource_id":"dfe69665-da34-11ec-b3c9-3745b943adc6","resource_type":"paragraph","title":{"text":"Paragraph 531 of Book 93"},"summary":{"text":"313. Evaṃ vutte, te brāhmaṇā soṇadaṇḍaṃ brāhmaṇaṃ etadavocuṃ..."},"content":{"display":"313. Evaṃ vutte, te brāhmaṇā soṇadaṇḍaṃ brāhmaṇaṃ etadavocuṃ...","text":"313. Evaṃ vutte, te brāhmaṇā soṇadaṇḍaṃ brāhmaṇaṃ etadavocuṃ...","exact":"313. Evaṃ vutte, te brāhmaṇā soṇadaṇḍaṃ brāhmaṇaṃ etadavocuṃ..."},"bold_single":"","bold_multi":" ","related_id":99,"category":"pali","language":"pali","updated_at":"2025-09-24T16:14:18+00:00","granularity":"paragraph"}}]},"aggregations":{"granularity":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"paragraph","doc_count":520}]},"resource_type":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"paragraph","doc_count":520}]},"language":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"pali","doc_count":520}]},"category":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"pali","doc_count":520}]}}}`; let mockMessages: MessageNode[] = [ // System 消息 (根节点) { id: 1, uid: "msg-system-001", chat_id: "chat-001", session_id: "system-session", role: "system", content: "你是一个巴利语专家和佛教术语解释助手。当用户询问佛教术语时,你可以调用 searchTerm 函数来查询详细信息。", is_active: true, created_at: "2025-01-15T10:00:00Z", updated_at: "2025-01-15T10:00:00Z", }, // 第一轮对话 - 用户询问佛教术语 { id: 2, uid: "msg-user-001", chat_id: "chat-001", parent_id: "msg-system-001", session_id: "session-001", role: "user", content: "什么是 dhamma?请详细解释一下。", is_active: true, created_at: "2025-01-15T10:01:00Z", updated_at: "2025-01-15T10:01:00Z", }, // AI 回答 - 带 Function Call { id: 3, uid: "msg-assistant-001", chat_id: "chat-001", parent_id: "msg-user-001", session_id: "session-001", role: "assistant", model_id: "gpt-4", tool_calls: [ { id: "call_dhamma_001", index: 0, type: "function", function: { name: "searchTerm", arguments: teamArgs, }, }, ], is_active: true, metadata: { generation_params: { temperature: 0.7, max_tokens: 2048, }, }, created_at: "2025-01-15T10:01:30Z", updated_at: "2025-01-15T10:01:30Z", }, // Tool 调用结果 { id: 4, uid: "msg-tool-001", chat_id: "chat-001", parent_id: "msg-assistant-001", session_id: "session-001", role: "tool", content: jsonString, tool_call_id: "call_dhamma_001", is_active: true, created_at: "2025-01-15T10:01:35Z", updated_at: "2025-01-15T10:01:35Z", }, // AI 最终回答 { id: 5, uid: "msg-assistant-002", chat_id: "chat-001", parent_id: "msg-tool-001", session_id: "session-001", role: "assistant", content: 'Dhamma(法)是佛教中最重要的概念之一。根据巴利语词典,Dhamma有以下几层含义:\n\n1. **佛陀的教导**:指佛陀所传授的教法和智慧\n2. **宇宙法则**:指支配宇宙运行的自然规律\n3. **正义与真理**:指正确的行为准则和道德标准\n\nDhamma来自梵语"dharma",在不同语境下可以指代教法、法则、正义、真理等。对于佛教修行者来说,学习和实践Dhamma是走向解脱的根本途径。', model_id: "gpt-4", is_active: true, metadata: { generation_params: { temperature: 0.7, max_tokens: 2048, }, token_usage: { prompt_tokens: 180, completion_tokens: 220, total_tokens: 400, }, performance: { response_time_ms: 1500, first_token_time_ms: 600, }, }, created_at: "2025-01-15T10:01:45Z", updated_at: "2025-01-15T10:01:45Z", }, // 第二轮对话 - 用户追问 { id: 6, uid: "msg-user-002", chat_id: "chat-001", parent_id: "msg-assistant-002", session_id: "session-002", role: "user", content: "那 karma 和 dhamma 有什么关系呢?", is_active: true, created_at: "2025-01-15T10:02:00Z", updated_at: "2025-01-15T10:02:00Z", }, // AI 第二次回答(第一个版本,当前激活) { id: 7, uid: "msg-assistant-003", chat_id: "chat-001", parent_id: "msg-user-002", session_id: "session-002", role: "assistant", content: "Karma(业)和 Dhamma(法)是密切相关的佛教概念:\n\n**Karma(业力法则)**是 Dhamma 的重要组成部分。Karma 描述了行为与后果之间的因果关系,而这个因果法则本身就是宇宙运行的 Dhamma 之一。\n\n简单来说:\n- Dhamma 是更大的框架,包含了所有佛教教义和宇宙法则\n- Karma 是 Dhamma 中的具体法则之一,专门解释行为的因果关系\n\n通过理解 Karma,我们能更好地实践 Dhamma;通过实践 Dhamma,我们能更好地净化 Karma。", model_id: "gpt-4", is_active: true, metadata: { generation_params: { temperature: 0.7, max_tokens: 2048, }, token_usage: { prompt_tokens: 420, completion_tokens: 150, total_tokens: 570, }, }, created_at: "2025-01-15T10:02:15Z", updated_at: "2025-01-15T10:02:15Z", }, // 第二个版本的AI回答(用户点了刷新,但当前未激活) { id: 8, uid: "msg-assistant-004", chat_id: "chat-001", parent_id: "msg-user-002", session_id: "session-v2-002", role: "assistant", content: "Karma 和 Dhamma 的关系可以从三个层面来理解:\n\n1. **本质关系**:Karma 法则本身就是 Dhamma 的体现,它揭示了宇宙中行为与结果的必然联系\n\n2. **实践关系**:\n - 学习 Dhamma → 了解 Karma 的运作机制\n - 正确认识 Karma → 能够依 Dhamma 而行\n\n3. **解脱关系**:通过 Dhamma 的指导,我们可以创造善业、净化恶业,最终超越业力束缚\n\n总的来说,Dhamma 为我们提供了理解和转化 Karma 的智慧工具。", model_id: "claude-3-sonnet", is_active: false, // 这是第二个版本,当前不激活 metadata: { generation_params: { temperature: 0.8, max_tokens: 2048, }, token_usage: { prompt_tokens: 420, completion_tokens: 180, total_tokens: 600, }, }, created_at: "2025-01-15T10:03:00Z", updated_at: "2025-01-15T10:03:00Z", }, // 第三轮对话 - 用户继续提问 { id: 9, uid: "msg-user-003", chat_id: "chat-001", parent_id: "msg-assistant-003", // 基于第一个版本的回答 session_id: "session-003", role: "user", content: "佛教的八正道具体包括哪些内容?", is_active: true, created_at: "2025-01-15T10:04:00Z", updated_at: "2025-01-15T10:04:00Z", }, { id: 10, uid: "msg-assistant-005", chat_id: "chat-001", parent_id: "msg-user-003", session_id: "session-003", role: "assistant", content: "八正道(Noble Eightfold Path)是佛教修行的核心方法,包含八个相互关联的修行要素:\n\n**慧学(智慧)**:\n1. **正见**(Right View)- 正确的世界观和人生观\n2. **正思维**(Right Intention)- 正确的思考和发心\n\n**戒学(道德)**:\n3. **正语**(Right Speech)- 正确的言语\n4. **正业**(Right Action)- 正确的行为\n5. **正命**(Right Livelihood)- 正确的生活方式\n\n**定学(禅定)**:\n6. **正精进**(Right Effort)- 正确的努力\n7. **正念**(Right Mindfulness)- 正确的觉知\n8. **正定**(Right Concentration)- 正确的禅定\n\n这八个方面需要同时修习,相互支持,共同导向解脱。", model_id: "gpt-4", is_active: true, metadata: { generation_params: { temperature: 0.7, max_tokens: 2048, }, token_usage: { prompt_tokens: 600, completion_tokens: 250, total_tokens: 850, }, }, created_at: "2025-01-15T10:04:20Z", updated_at: "2025-01-15T10:04:20Z", }, // 分支路径 - 用户编辑了第一个问题 { id: 11, uid: "msg-user-004", chat_id: "chat-001", parent_id: "msg-system-001", // 回到系统消息后 session_id: "session-v2-004", role: "user", content: "请解释一下佛教中的 nirvana(涅槃)概念。", // 用户编辑了第一个问题 is_active: false, // 用户当前查看的是主线路,这条是分支 created_at: "2025-01-15T10:05:00Z", updated_at: "2025-01-15T10:05:00Z", }, { id: 12, uid: "msg-assistant-006", chat_id: "chat-001", parent_id: "msg-user-004", session_id: "session-004", role: "assistant", content: 'Nirvana(涅槃)是佛教修行的最终目标,具有深刻的内涵:\n\n**字面含义**:\n- 巴利语 "Nibbāna",梵语 "Nirvāṇa"\n- 原意为"熄灭"、"吹灭",指烦恼之火的熄灭\n\n**实质内容**:\n1. **烦恼的熄灭**:贪、嗔、痴等根本烦恼的彻底断除\n2. **轮回的终止**:不再受业力牵引而轮回生死\n3. **痛苦的止息**:一切苦的根源得到根除\n4. **究竟的解脱**:获得绝对的自由和安宁\n\n**两种涅槃**:\n- **有余涅槃**:烦恼已断,但身心仍存\n- **无余涅槃**:身心俱灭,彻底解脱\n\n涅槃不是虚无,而是超越一切对立和限制的究竟实相。', model_id: "gpt-4", is_active: false, metadata: { generation_params: { temperature: 0.7, }, token_usage: { prompt_tokens: 150, completion_tokens: 280, total_tokens: 430, }, }, created_at: "2025-01-15T10:05:20Z", updated_at: "2025-01-15T10:05:20Z", }, ]; // Mock 数据生成工具 const generateMockId = () => { const ids = mockMessages.map((m) => m.id); return Math.max(...ids) + 1; }; const generateUuid = () => `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const mockDelay = (ms: number = 200) => new Promise((resolve) => setTimeout(resolve, ms)); export const mockMessageApi = { // 获取聊天消息列表 async getMessages(chatId: string): Promise> { await mockDelay(); console.log(`[Mock API] Getting messages for chat: ${chatId}`); if (!chatId || chatId.trim() === "") { mockMessages = [rootMessage]; } return { ok: true, message: "Messages retrieved successfully", data: { rows: mockMessages, total: mockMessages.length, }, }; }, // /** * 创建新消息 * 检查request.messages里面每一项的parent_id。如果parent_id是mockMessages里面有的。那么保留这个parent_id. * 如果这个parent_id是mockMessages里面没有的,但是是request.messages里面有的。修改为输入messages的修改过的uuid * @param chatId * @param request * @returns */ async createMessages( chatId: string, request: CreateMessageRequest ): Promise> { await mockDelay(); console.log(`[Mock API] Creating messages for chat: ${chatId}`, request); const createdMessages: MessageNode[] = []; const now = new Date().toISOString(); const uidMap = new Map(); for (const msgRequest of request.messages) { const uuid = generateUuid(); msgRequest.uid && uidMap.set(msgRequest.uid, uuid); let parent_id = msgRequest.parent_id; if (parent_id && uidMap.has(parent_id)) { parent_id = uidMap.get(parent_id); } const newMessage: MessageNode = { id: generateMockId(), uid: uuid, chat_id: chatId, parent_id: parent_id, session_id: msgRequest.session_id ?? generateUuid(), // 在实际应用中,这可能由前端或后端逻辑确定 role: msgRequest.role, content: msgRequest.content, model_id: msgRequest.model_id, tool_calls: msgRequest.tool_calls, tool_call_id: msgRequest.tool_call_id, metadata: msgRequest.metadata, is_active: true, created_at: now, updated_at: now, save_status: "saved", }; createdMessages.push(newMessage); mockMessages.push(newMessage); } return { ok: true, message: "Messages created successfully", data: createdMessages, }; }, // 切换消息版本 async switchVersion( chatId: string, messageUids: string[] ): Promise> { await mockDelay(); console.log( `[Mock API] Switching version for chat: ${chatId}`, messageUids ); // 首先将所有消息设为非活跃 mockMessages.forEach((msg) => { if (msg.chat_id === chatId) { msg.is_active = false; } }); // 然后激活指定的消息链 messageUids.forEach((uid) => { const message = mockMessages.find((msg) => msg.uid === uid); if (message) { message.is_active = true; } }); return { ok: true, message: "Version switched successfully", data: undefined, }; }, // 点赞消息 async likeMessage(messageId: string): Promise> { await mockDelay(); console.log(`[Mock API] Liking message: ${messageId}`); const message = mockMessages.find((msg) => msg.uid === messageId); if (!message) { return { ok: false, message: "Message not found", data: undefined, }; } // 模拟点赞逻辑 - 可以在 metadata 中记录 if (!message.metadata) { message.metadata = {}; } if (!message.metadata.custom_data) { message.metadata.custom_data = {}; } message.metadata.custom_data.liked = true; message.metadata.custom_data.disliked = false; return { ok: true, message: "Message liked successfully", data: undefined, }; }, // 踩消息 async dislikeMessage(messageId: string): Promise> { await mockDelay(); console.log(`[Mock API] Disliking message: ${messageId}`); const message = mockMessages.find((msg) => msg.uid === messageId); if (!message) { return { ok: false, message: "Message not found", data: undefined, }; } // 模拟踩的逻辑 if (!message.metadata) { message.metadata = {}; } if (!message.metadata.custom_data) { message.metadata.custom_data = {}; } message.metadata.custom_data.liked = false; message.metadata.custom_data.disliked = true; return { ok: true, message: "Message disliked successfully", data: undefined, }; }, // 分享消息 async shareMessage( messageId: string ): Promise> { await mockDelay(); console.log(`[Mock API] Sharing message: ${messageId}`); const message = mockMessages.find((msg) => msg.uid === messageId); if (!message) { return { ok: false, message: "Message not found", data: { shareUrl: "" }, }; } // 生成模拟的分享链接 const shareUrl = `https://chat.example.com/share/${messageId}`; return { ok: true, message: "Message shared successfully", data: { shareUrl }, }; }, // 删除消息 async deleteMessage(messageId: string): Promise> { await mockDelay(); console.log(`[Mock API] Deleting message: ${messageId}`); const messageIndex = mockMessages.findIndex((msg) => msg.uid === messageId); if (messageIndex === -1) { return { ok: false, message: "Message not found", data: undefined, }; } // 软删除 - 设置 deleted_at mockMessages[messageIndex].deleted_at = new Date().toISOString(); return { ok: true, message: "Message deleted successfully", data: undefined, }; }, }; // 工具函数:获取 mock 数据用于调试 export const mockMessageUtils = { // 获取所有 mock 消息 getAllMessages: () => [...mockMessages], // 重置 mock 数据 resetMessages: () => { mockMessages = mockMessages.slice(0, 8); // 保留初始数据 }, // 添加新的 mock 消息 addMockMessage: (message: Partial) => { const fullMessage: MessageNode = { id: generateMockId(), uid: generateUuid(), chat_id: "chat-1", session_id: generateUuid(), role: "user", content: "", is_active: true, created_at: new Date().toISOString(), updated_at: new Date().toISOString(), save_status: "saved", ...message, }; mockMessages.push(fullMessage); return fullMessage; }, // 设置特定消息的活跃状态 setMessageActive: (messageId: string, isActive: boolean) => { const message = mockMessages.find((msg) => msg.uid === messageId); if (message) { message.is_active = isActive; } }, // 获取特定会话的消息 getSessionMessages: (chatId: string, sessionId: string) => { return mockMessages.filter( (msg) => msg.chat_id === chatId && msg.session_id === sessionId ); }, // 模拟创建完整的对话会话(用户问题 + AI回答) createMockSession: ( chatId: string, userContent: string, assistantContent: string, parentId?: string ) => { const sessionId = generateUuid(); const now = new Date().toISOString(); const userMessage = mockMessageUtils.addMockMessage({ chat_id: chatId, parent_id: parentId, session_id: sessionId, role: "user", content: userContent, created_at: now, updated_at: now, }); const assistantMessage = mockMessageUtils.addMockMessage({ chat_id: chatId, parent_id: userMessage.uid, session_id: sessionId, role: "assistant", content: assistantContent, model_id: "gpt-4", metadata: { token_usage: { prompt_tokens: Math.floor(Math.random() * 200) + 50, completion_tokens: Math.floor(Math.random() * 150) + 30, total_tokens: 0, }, performance: { response_time_ms: Math.floor(Math.random() * 2000) + 500, first_token_time_ms: Math.floor(Math.random() * 300) + 100, }, }, created_at: new Date(Date.now() + 1000).toISOString(), updated_at: new Date(Date.now() + 1000).toISOString(), }); // 计算总 token if (assistantMessage.metadata?.token_usage) { assistantMessage.metadata.token_usage.total_tokens = assistantMessage.metadata.token_usage.prompt_tokens! + assistantMessage.metadata.token_usage.completion_tokens!; } return { userMessage, assistantMessage }; }, }; /** * 调用范例 * // 在 useChatData 或其他地方 import { mockMessageApi } from './services/mockMessageApi'; // 条件性使用 mock API const messageApi = process.env.NODE_ENV === 'development' ? mockMessageApi : realMessageApi; */