| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- // 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<ApiResponse<MessageListResponse>> {
- 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<ApiResponse<MessageNode[]>> {
- await mockDelay();
- console.log(`[Mock API] Creating messages for chat: ${chatId}`, request);
- const createdMessages: MessageNode[] = [];
- const now = new Date().toISOString();
- const uidMap = new Map<string, string>();
- 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<ApiResponse<void>> {
- 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<ApiResponse<void>> {
- 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<ApiResponse<void>> {
- 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<ApiResponse<{ shareUrl: string }>> {
- 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<ApiResponse<void>> {
- 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<MessageNode>) => {
- 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;
- */
|