utils.ts 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { addFileInfos, sortAgentSorts } from '../../tools/utils'
  2. import { UUID_NIL } from './constants'
  3. import type { ChatItem } from './types'
  4. import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
  5. async function decodeBase64AndDecompress(base64String: string) {
  6. const binaryString = atob(base64String)
  7. const compressedUint8Array = Uint8Array.from(binaryString, char => char.charCodeAt(0))
  8. const decompressedStream = new Response(compressedUint8Array).body?.pipeThrough(new DecompressionStream('gzip'))
  9. const decompressedArrayBuffer = await new Response(decompressedStream).arrayBuffer()
  10. return new TextDecoder().decode(decompressedArrayBuffer)
  11. }
  12. function getProcessedInputsFromUrlParams(): Record<string, any> {
  13. const urlParams = new URLSearchParams(window.location.search)
  14. const inputs: Record<string, any> = {}
  15. urlParams.forEach(async (value, key) => {
  16. inputs[key] = await decodeBase64AndDecompress(decodeURIComponent(value))
  17. })
  18. return inputs
  19. }
  20. function getLastAnswer(chatList: ChatItem[]) {
  21. for (let i = chatList.length - 1; i >= 0; i--) {
  22. const item = chatList[i]
  23. if (item.isAnswer && !item.isOpeningStatement)
  24. return item
  25. }
  26. return null
  27. }
  28. function appendQAToChatList(chatList: ChatItem[], item: any) {
  29. // we append answer first and then question since will reverse the whole chatList later
  30. const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || []
  31. chatList.push({
  32. id: item.id,
  33. content: item.answer,
  34. agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
  35. feedback: item.feedback,
  36. isAnswer: true,
  37. citation: item.retriever_resources,
  38. message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))),
  39. })
  40. const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || []
  41. chatList.push({
  42. id: `question-${item.id}`,
  43. content: item.query,
  44. isAnswer: false,
  45. message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))),
  46. })
  47. }
  48. /**
  49. * Computes the latest thread messages from all messages of the conversation.
  50. * Same logic as backend codebase `api/core/prompt/utils/extract_thread_messages.py`
  51. *
  52. * @param fetchedMessages - The history chat list data from the backend, sorted by created_at in descending order. This includes all flattened history messages of the conversation.
  53. * @returns An array of ChatItems representing the latest thread.
  54. */
  55. function getPrevChatList(fetchedMessages: any[]) {
  56. const ret: ChatItem[] = []
  57. let nextMessageId = null
  58. for (const item of fetchedMessages) {
  59. if (!item.parent_message_id) {
  60. appendQAToChatList(ret, item)
  61. break
  62. }
  63. if (!nextMessageId) {
  64. appendQAToChatList(ret, item)
  65. nextMessageId = item.parent_message_id
  66. }
  67. else {
  68. if (item.id === nextMessageId || nextMessageId === UUID_NIL) {
  69. appendQAToChatList(ret, item)
  70. nextMessageId = item.parent_message_id
  71. }
  72. }
  73. }
  74. return ret.reverse()
  75. }
  76. export {
  77. getProcessedInputsFromUrlParams,
  78. getLastAnswer,
  79. getPrevChatList,
  80. }