mockMessageApi.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. // services/mockMessageApi.ts
  2. import type {
  3. CreateMessageRequest,
  4. MessageListResponse,
  5. ApiResponse,
  6. MessageNode,
  7. } from "../types/chat";
  8. import { system_prompt } from "./agentApi";
  9. // Mock 消息数据库
  10. // System 消息 (根节点)
  11. const rootMessage: MessageNode = {
  12. id: 1,
  13. uid: "msg-system-001",
  14. chat_id: "chat-001",
  15. session_id: "system-session",
  16. role: "system",
  17. content: system_prompt,
  18. is_active: true,
  19. created_at: "2025-01-15T10:00:00Z",
  20. updated_at: "2025-01-15T10:00:00Z",
  21. };
  22. const teamArgs = JSON.stringify({ term: "dhamma" });
  23. 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}]}}}`;
  24. let mockMessages: MessageNode[] = [
  25. // System 消息 (根节点)
  26. {
  27. id: 1,
  28. uid: "msg-system-001",
  29. chat_id: "chat-001",
  30. session_id: "system-session",
  31. role: "system",
  32. content:
  33. "你是一个巴利语专家和佛教术语解释助手。当用户询问佛教术语时,你可以调用 searchTerm 函数来查询详细信息。",
  34. is_active: true,
  35. created_at: "2025-01-15T10:00:00Z",
  36. updated_at: "2025-01-15T10:00:00Z",
  37. },
  38. // 第一轮对话 - 用户询问佛教术语
  39. {
  40. id: 2,
  41. uid: "msg-user-001",
  42. chat_id: "chat-001",
  43. parent_id: "msg-system-001",
  44. session_id: "session-001",
  45. role: "user",
  46. content: "什么是 dhamma?请详细解释一下。",
  47. is_active: true,
  48. created_at: "2025-01-15T10:01:00Z",
  49. updated_at: "2025-01-15T10:01:00Z",
  50. },
  51. // AI 回答 - 带 Function Call
  52. {
  53. id: 3,
  54. uid: "msg-assistant-001",
  55. chat_id: "chat-001",
  56. parent_id: "msg-user-001",
  57. session_id: "session-001",
  58. role: "assistant",
  59. model_id: "gpt-4",
  60. tool_calls: [
  61. {
  62. id: "call_dhamma_001",
  63. index: 0,
  64. type: "function",
  65. function: {
  66. name: "searchTerm",
  67. arguments: teamArgs,
  68. },
  69. },
  70. ],
  71. is_active: true,
  72. metadata: {
  73. generation_params: {
  74. temperature: 0.7,
  75. max_tokens: 2048,
  76. },
  77. },
  78. created_at: "2025-01-15T10:01:30Z",
  79. updated_at: "2025-01-15T10:01:30Z",
  80. },
  81. // Tool 调用结果
  82. {
  83. id: 4,
  84. uid: "msg-tool-001",
  85. chat_id: "chat-001",
  86. parent_id: "msg-assistant-001",
  87. session_id: "session-001",
  88. role: "tool",
  89. content: jsonString,
  90. tool_call_id: "call_dhamma_001",
  91. is_active: true,
  92. created_at: "2025-01-15T10:01:35Z",
  93. updated_at: "2025-01-15T10:01:35Z",
  94. },
  95. // AI 最终回答
  96. {
  97. id: 5,
  98. uid: "msg-assistant-002",
  99. chat_id: "chat-001",
  100. parent_id: "msg-tool-001",
  101. session_id: "session-001",
  102. role: "assistant",
  103. content:
  104. 'Dhamma(法)是佛教中最重要的概念之一。根据巴利语词典,Dhamma有以下几层含义:\n\n1. **佛陀的教导**:指佛陀所传授的教法和智慧\n2. **宇宙法则**:指支配宇宙运行的自然规律\n3. **正义与真理**:指正确的行为准则和道德标准\n\nDhamma来自梵语"dharma",在不同语境下可以指代教法、法则、正义、真理等。对于佛教修行者来说,学习和实践Dhamma是走向解脱的根本途径。',
  105. model_id: "gpt-4",
  106. is_active: true,
  107. metadata: {
  108. generation_params: {
  109. temperature: 0.7,
  110. max_tokens: 2048,
  111. },
  112. token_usage: {
  113. prompt_tokens: 180,
  114. completion_tokens: 220,
  115. total_tokens: 400,
  116. },
  117. performance: {
  118. response_time_ms: 1500,
  119. first_token_time_ms: 600,
  120. },
  121. },
  122. created_at: "2025-01-15T10:01:45Z",
  123. updated_at: "2025-01-15T10:01:45Z",
  124. },
  125. // 第二轮对话 - 用户追问
  126. {
  127. id: 6,
  128. uid: "msg-user-002",
  129. chat_id: "chat-001",
  130. parent_id: "msg-assistant-002",
  131. session_id: "session-002",
  132. role: "user",
  133. content: "那 karma 和 dhamma 有什么关系呢?",
  134. is_active: true,
  135. created_at: "2025-01-15T10:02:00Z",
  136. updated_at: "2025-01-15T10:02:00Z",
  137. },
  138. // AI 第二次回答(第一个版本,当前激活)
  139. {
  140. id: 7,
  141. uid: "msg-assistant-003",
  142. chat_id: "chat-001",
  143. parent_id: "msg-user-002",
  144. session_id: "session-002",
  145. role: "assistant",
  146. content:
  147. "Karma(业)和 Dhamma(法)是密切相关的佛教概念:\n\n**Karma(业力法则)**是 Dhamma 的重要组成部分。Karma 描述了行为与后果之间的因果关系,而这个因果法则本身就是宇宙运行的 Dhamma 之一。\n\n简单来说:\n- Dhamma 是更大的框架,包含了所有佛教教义和宇宙法则\n- Karma 是 Dhamma 中的具体法则之一,专门解释行为的因果关系\n\n通过理解 Karma,我们能更好地实践 Dhamma;通过实践 Dhamma,我们能更好地净化 Karma。",
  148. model_id: "gpt-4",
  149. is_active: true,
  150. metadata: {
  151. generation_params: {
  152. temperature: 0.7,
  153. max_tokens: 2048,
  154. },
  155. token_usage: {
  156. prompt_tokens: 420,
  157. completion_tokens: 150,
  158. total_tokens: 570,
  159. },
  160. },
  161. created_at: "2025-01-15T10:02:15Z",
  162. updated_at: "2025-01-15T10:02:15Z",
  163. },
  164. // 第二个版本的AI回答(用户点了刷新,但当前未激活)
  165. {
  166. id: 8,
  167. uid: "msg-assistant-004",
  168. chat_id: "chat-001",
  169. parent_id: "msg-user-002",
  170. session_id: "session-v2-002",
  171. role: "assistant",
  172. content:
  173. "Karma 和 Dhamma 的关系可以从三个层面来理解:\n\n1. **本质关系**:Karma 法则本身就是 Dhamma 的体现,它揭示了宇宙中行为与结果的必然联系\n\n2. **实践关系**:\n - 学习 Dhamma → 了解 Karma 的运作机制\n - 正确认识 Karma → 能够依 Dhamma 而行\n\n3. **解脱关系**:通过 Dhamma 的指导,我们可以创造善业、净化恶业,最终超越业力束缚\n\n总的来说,Dhamma 为我们提供了理解和转化 Karma 的智慧工具。",
  174. model_id: "claude-3-sonnet",
  175. is_active: false, // 这是第二个版本,当前不激活
  176. metadata: {
  177. generation_params: {
  178. temperature: 0.8,
  179. max_tokens: 2048,
  180. },
  181. token_usage: {
  182. prompt_tokens: 420,
  183. completion_tokens: 180,
  184. total_tokens: 600,
  185. },
  186. },
  187. created_at: "2025-01-15T10:03:00Z",
  188. updated_at: "2025-01-15T10:03:00Z",
  189. },
  190. // 第三轮对话 - 用户继续提问
  191. {
  192. id: 9,
  193. uid: "msg-user-003",
  194. chat_id: "chat-001",
  195. parent_id: "msg-assistant-003", // 基于第一个版本的回答
  196. session_id: "session-003",
  197. role: "user",
  198. content: "佛教的八正道具体包括哪些内容?",
  199. is_active: true,
  200. created_at: "2025-01-15T10:04:00Z",
  201. updated_at: "2025-01-15T10:04:00Z",
  202. },
  203. {
  204. id: 10,
  205. uid: "msg-assistant-005",
  206. chat_id: "chat-001",
  207. parent_id: "msg-user-003",
  208. session_id: "session-003",
  209. role: "assistant",
  210. content:
  211. "八正道(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这八个方面需要同时修习,相互支持,共同导向解脱。",
  212. model_id: "gpt-4",
  213. is_active: true,
  214. metadata: {
  215. generation_params: {
  216. temperature: 0.7,
  217. max_tokens: 2048,
  218. },
  219. token_usage: {
  220. prompt_tokens: 600,
  221. completion_tokens: 250,
  222. total_tokens: 850,
  223. },
  224. },
  225. created_at: "2025-01-15T10:04:20Z",
  226. updated_at: "2025-01-15T10:04:20Z",
  227. },
  228. // 分支路径 - 用户编辑了第一个问题
  229. {
  230. id: 11,
  231. uid: "msg-user-004",
  232. chat_id: "chat-001",
  233. parent_id: "msg-system-001", // 回到系统消息后
  234. session_id: "session-v2-004",
  235. role: "user",
  236. content: "请解释一下佛教中的 nirvana(涅槃)概念。", // 用户编辑了第一个问题
  237. is_active: false, // 用户当前查看的是主线路,这条是分支
  238. created_at: "2025-01-15T10:05:00Z",
  239. updated_at: "2025-01-15T10:05:00Z",
  240. },
  241. {
  242. id: 12,
  243. uid: "msg-assistant-006",
  244. chat_id: "chat-001",
  245. parent_id: "msg-user-004",
  246. session_id: "session-004",
  247. role: "assistant",
  248. content:
  249. 'Nirvana(涅槃)是佛教修行的最终目标,具有深刻的内涵:\n\n**字面含义**:\n- 巴利语 "Nibbāna",梵语 "Nirvāṇa"\n- 原意为"熄灭"、"吹灭",指烦恼之火的熄灭\n\n**实质内容**:\n1. **烦恼的熄灭**:贪、嗔、痴等根本烦恼的彻底断除\n2. **轮回的终止**:不再受业力牵引而轮回生死\n3. **痛苦的止息**:一切苦的根源得到根除\n4. **究竟的解脱**:获得绝对的自由和安宁\n\n**两种涅槃**:\n- **有余涅槃**:烦恼已断,但身心仍存\n- **无余涅槃**:身心俱灭,彻底解脱\n\n涅槃不是虚无,而是超越一切对立和限制的究竟实相。',
  250. model_id: "gpt-4",
  251. is_active: false,
  252. metadata: {
  253. generation_params: {
  254. temperature: 0.7,
  255. },
  256. token_usage: {
  257. prompt_tokens: 150,
  258. completion_tokens: 280,
  259. total_tokens: 430,
  260. },
  261. },
  262. created_at: "2025-01-15T10:05:20Z",
  263. updated_at: "2025-01-15T10:05:20Z",
  264. },
  265. ];
  266. // Mock 数据生成工具
  267. const generateMockId = () => {
  268. const ids = mockMessages.map((m) => m.id);
  269. return Math.max(...ids) + 1;
  270. };
  271. const generateUuid = () =>
  272. `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  273. const mockDelay = (ms: number = 200) =>
  274. new Promise((resolve) => setTimeout(resolve, ms));
  275. export const mockMessageApi = {
  276. // 获取聊天消息列表
  277. async getMessages(chatId: string): Promise<ApiResponse<MessageListResponse>> {
  278. await mockDelay();
  279. console.log(`[Mock API] Getting messages for chat: ${chatId}`);
  280. if (!chatId || chatId.trim() === "") {
  281. mockMessages = [rootMessage];
  282. }
  283. return {
  284. ok: true,
  285. message: "Messages retrieved successfully",
  286. data: {
  287. rows: mockMessages,
  288. total: mockMessages.length,
  289. },
  290. };
  291. },
  292. //
  293. /**
  294. * 创建新消息
  295. * 检查request.messages里面每一项的parent_id。如果parent_id是mockMessages里面有的。那么保留这个parent_id.
  296. * 如果这个parent_id是mockMessages里面没有的,但是是request.messages里面有的。修改为输入messages的修改过的uuid
  297. * @param chatId
  298. * @param request
  299. * @returns
  300. */
  301. async createMessages(
  302. chatId: string,
  303. request: CreateMessageRequest
  304. ): Promise<ApiResponse<MessageNode[]>> {
  305. await mockDelay();
  306. console.log(`[Mock API] Creating messages for chat: ${chatId}`, request);
  307. const createdMessages: MessageNode[] = [];
  308. const now = new Date().toISOString();
  309. const uidMap = new Map<string, string>();
  310. for (const msgRequest of request.messages) {
  311. const uuid = generateUuid();
  312. msgRequest.uid && uidMap.set(msgRequest.uid, uuid);
  313. let parent_id = msgRequest.parent_id;
  314. if (parent_id && uidMap.has(parent_id)) {
  315. parent_id = uidMap.get(parent_id);
  316. }
  317. const newMessage: MessageNode = {
  318. id: generateMockId(),
  319. uid: uuid,
  320. chat_id: chatId,
  321. parent_id: parent_id,
  322. session_id: msgRequest.session_id ?? generateUuid(), // 在实际应用中,这可能由前端或后端逻辑确定
  323. role: msgRequest.role,
  324. content: msgRequest.content,
  325. model_id: msgRequest.model_id,
  326. tool_calls: msgRequest.tool_calls,
  327. tool_call_id: msgRequest.tool_call_id,
  328. metadata: msgRequest.metadata,
  329. is_active: true,
  330. created_at: now,
  331. updated_at: now,
  332. save_status: "saved",
  333. };
  334. createdMessages.push(newMessage);
  335. mockMessages.push(newMessage);
  336. }
  337. return {
  338. ok: true,
  339. message: "Messages created successfully",
  340. data: createdMessages,
  341. };
  342. },
  343. // 切换消息版本
  344. async switchVersion(
  345. chatId: string,
  346. messageUids: string[]
  347. ): Promise<ApiResponse<void>> {
  348. await mockDelay();
  349. console.log(
  350. `[Mock API] Switching version for chat: ${chatId}`,
  351. messageUids
  352. );
  353. // 首先将所有消息设为非活跃
  354. mockMessages.forEach((msg) => {
  355. if (msg.chat_id === chatId) {
  356. msg.is_active = false;
  357. }
  358. });
  359. // 然后激活指定的消息链
  360. messageUids.forEach((uid) => {
  361. const message = mockMessages.find((msg) => msg.uid === uid);
  362. if (message) {
  363. message.is_active = true;
  364. }
  365. });
  366. return {
  367. ok: true,
  368. message: "Version switched successfully",
  369. data: undefined,
  370. };
  371. },
  372. // 点赞消息
  373. async likeMessage(messageId: string): Promise<ApiResponse<void>> {
  374. await mockDelay();
  375. console.log(`[Mock API] Liking message: ${messageId}`);
  376. const message = mockMessages.find((msg) => msg.uid === messageId);
  377. if (!message) {
  378. return {
  379. ok: false,
  380. message: "Message not found",
  381. data: undefined,
  382. };
  383. }
  384. // 模拟点赞逻辑 - 可以在 metadata 中记录
  385. if (!message.metadata) {
  386. message.metadata = {};
  387. }
  388. if (!message.metadata.custom_data) {
  389. message.metadata.custom_data = {};
  390. }
  391. message.metadata.custom_data.liked = true;
  392. message.metadata.custom_data.disliked = false;
  393. return {
  394. ok: true,
  395. message: "Message liked successfully",
  396. data: undefined,
  397. };
  398. },
  399. // 踩消息
  400. async dislikeMessage(messageId: string): Promise<ApiResponse<void>> {
  401. await mockDelay();
  402. console.log(`[Mock API] Disliking message: ${messageId}`);
  403. const message = mockMessages.find((msg) => msg.uid === messageId);
  404. if (!message) {
  405. return {
  406. ok: false,
  407. message: "Message not found",
  408. data: undefined,
  409. };
  410. }
  411. // 模拟踩的逻辑
  412. if (!message.metadata) {
  413. message.metadata = {};
  414. }
  415. if (!message.metadata.custom_data) {
  416. message.metadata.custom_data = {};
  417. }
  418. message.metadata.custom_data.liked = false;
  419. message.metadata.custom_data.disliked = true;
  420. return {
  421. ok: true,
  422. message: "Message disliked successfully",
  423. data: undefined,
  424. };
  425. },
  426. // 分享消息
  427. async shareMessage(
  428. messageId: string
  429. ): Promise<ApiResponse<{ shareUrl: string }>> {
  430. await mockDelay();
  431. console.log(`[Mock API] Sharing message: ${messageId}`);
  432. const message = mockMessages.find((msg) => msg.uid === messageId);
  433. if (!message) {
  434. return {
  435. ok: false,
  436. message: "Message not found",
  437. data: { shareUrl: "" },
  438. };
  439. }
  440. // 生成模拟的分享链接
  441. const shareUrl = `https://chat.example.com/share/${messageId}`;
  442. return {
  443. ok: true,
  444. message: "Message shared successfully",
  445. data: { shareUrl },
  446. };
  447. },
  448. // 删除消息
  449. async deleteMessage(messageId: string): Promise<ApiResponse<void>> {
  450. await mockDelay();
  451. console.log(`[Mock API] Deleting message: ${messageId}`);
  452. const messageIndex = mockMessages.findIndex((msg) => msg.uid === messageId);
  453. if (messageIndex === -1) {
  454. return {
  455. ok: false,
  456. message: "Message not found",
  457. data: undefined,
  458. };
  459. }
  460. // 软删除 - 设置 deleted_at
  461. mockMessages[messageIndex].deleted_at = new Date().toISOString();
  462. return {
  463. ok: true,
  464. message: "Message deleted successfully",
  465. data: undefined,
  466. };
  467. },
  468. };
  469. // 工具函数:获取 mock 数据用于调试
  470. export const mockMessageUtils = {
  471. // 获取所有 mock 消息
  472. getAllMessages: () => [...mockMessages],
  473. // 重置 mock 数据
  474. resetMessages: () => {
  475. mockMessages = mockMessages.slice(0, 8); // 保留初始数据
  476. },
  477. // 添加新的 mock 消息
  478. addMockMessage: (message: Partial<MessageNode>) => {
  479. const fullMessage: MessageNode = {
  480. id: generateMockId(),
  481. uid: generateUuid(),
  482. chat_id: "chat-1",
  483. session_id: generateUuid(),
  484. role: "user",
  485. content: "",
  486. is_active: true,
  487. created_at: new Date().toISOString(),
  488. updated_at: new Date().toISOString(),
  489. save_status: "saved",
  490. ...message,
  491. };
  492. mockMessages.push(fullMessage);
  493. return fullMessage;
  494. },
  495. // 设置特定消息的活跃状态
  496. setMessageActive: (messageId: string, isActive: boolean) => {
  497. const message = mockMessages.find((msg) => msg.uid === messageId);
  498. if (message) {
  499. message.is_active = isActive;
  500. }
  501. },
  502. // 获取特定会话的消息
  503. getSessionMessages: (chatId: string, sessionId: string) => {
  504. return mockMessages.filter(
  505. (msg) => msg.chat_id === chatId && msg.session_id === sessionId
  506. );
  507. },
  508. // 模拟创建完整的对话会话(用户问题 + AI回答)
  509. createMockSession: (
  510. chatId: string,
  511. userContent: string,
  512. assistantContent: string,
  513. parentId?: string
  514. ) => {
  515. const sessionId = generateUuid();
  516. const now = new Date().toISOString();
  517. const userMessage = mockMessageUtils.addMockMessage({
  518. chat_id: chatId,
  519. parent_id: parentId,
  520. session_id: sessionId,
  521. role: "user",
  522. content: userContent,
  523. created_at: now,
  524. updated_at: now,
  525. });
  526. const assistantMessage = mockMessageUtils.addMockMessage({
  527. chat_id: chatId,
  528. parent_id: userMessage.uid,
  529. session_id: sessionId,
  530. role: "assistant",
  531. content: assistantContent,
  532. model_id: "gpt-4",
  533. metadata: {
  534. token_usage: {
  535. prompt_tokens: Math.floor(Math.random() * 200) + 50,
  536. completion_tokens: Math.floor(Math.random() * 150) + 30,
  537. total_tokens: 0,
  538. },
  539. performance: {
  540. response_time_ms: Math.floor(Math.random() * 2000) + 500,
  541. first_token_time_ms: Math.floor(Math.random() * 300) + 100,
  542. },
  543. },
  544. created_at: new Date(Date.now() + 1000).toISOString(),
  545. updated_at: new Date(Date.now() + 1000).toISOString(),
  546. });
  547. // 计算总 token
  548. if (assistantMessage.metadata?.token_usage) {
  549. assistantMessage.metadata.token_usage.total_tokens =
  550. assistantMessage.metadata.token_usage.prompt_tokens! +
  551. assistantMessage.metadata.token_usage.completion_tokens!;
  552. }
  553. return { userMessage, assistantMessage };
  554. },
  555. };
  556. /**
  557. * 调用范例
  558. * // 在 useChatData 或其他地方
  559. import { mockMessageApi } from './services/mockMessageApi';
  560. // 条件性使用 mock API
  561. const messageApi = process.env.NODE_ENV === 'development'
  562. ? mockMessageApi
  563. : realMessageApi;
  564. */