Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2025
18
0
175 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.87 KB | None | 0 0
  1. src/modules/aifn/autotitle/autoTitle.ts весь файл
  2.  
  3.  
  4.  
  5.  
  6. import { aixChatGenerateText_Simple } from '~/modules/aix/client/aix.client';
  7.  
  8. import { excludeSystemMessages } from '~/common/stores/chat/chat.conversation';
  9. import { getConversation, useChatStore } from '~/common/stores/chat/store-chats';
  10. import { getDomainModelIdOrThrow } from '~/common/stores/llms/store-llms';
  11. import { messageFragmentsReduceText } from '~/common/stores/chat/chat.message';
  12.  
  13.  
  14. /**
  15. * Creates the AI titles for conversations, by taking snippets of recent messages and asking AI what's that about.
  16. * @returns true if the title was actually replaced (for instance, it may not be needed)
  17. */
  18. export async function autoConversationTitle(conversationId: string, forceReplace: boolean): Promise<boolean> {
  19.  
  20. // use valid fast model
  21. let autoTitleLlmId;
  22. try {
  23. autoTitleLlmId = getDomainModelIdOrThrow(['fastUtil'], false, false, 'conversation-titler');
  24. } catch (error) {
  25. console.log(`autoConversationTitle: ${error}`);
  26. return false;
  27. }
  28.  
  29. // only operate on valid conversations, without any title
  30. const conversation = getConversation(conversationId);
  31. if (!conversation || (!forceReplace && (conversation.autoTitle || conversation.userTitle)))
  32. return false;
  33.  
  34. const { setAutoTitle, setUserTitle } = useChatStore.getState();
  35. if (forceReplace) {
  36. setUserTitle(conversationId, '');
  37. setAutoTitle(conversationId, '✏️...');
  38. }
  39.  
  40. // --- MODIFICATION START ---
  41. const MAX_MESSAGES_TO_CONSIDER = 5; // How many of the latest messages to look at
  42. const MAX_CHARS_PER_MESSAGE_SNIPPET = 3500; // Max characters to take from each message
  43.  
  44. const messagesToProcess = excludeSystemMessages(conversation.messages).slice(-MAX_MESSAGES_TO_CONSIDER);
  45.  
  46. const historyLines: string[] = messagesToProcess.map(m => {
  47. const rolePrefix = m.role === 'user' ? 'You' : 'Assistant';
  48. let messageText = messageFragmentsReduceText(m.fragments).trim(); // Get full message text and trim whitespace
  49.  
  50. // Truncate the message text if it's longer than our desired snippet length
  51. if (messageText.length > MAX_CHARS_PER_MESSAGE_SNIPPET) {
  52. messageText = messageText.substring(0, MAX_CHARS_PER_MESSAGE_SNIPPET) + '...';
  53. }
  54.  
  55. // Replace newlines within the snippet with spaces to make it a single "line" for the LLM prompt
  56. // This helps keep the input format clean and prevents the LLM from misinterpreting parts of a single message as separate messages.
  57. messageText = messageText.replace(/\n+/g, ' ');
  58.  
  59. return `- ${rolePrefix}: ${messageText}`;
  60. });
  61. // --- MODIFICATION END ---
  62.  
  63.  
  64. // If no history lines could be generated (e.g., all considered messages were empty)
  65. if (historyLines.length === 0 && messagesToProcess.length > 0) {
  66. // This case might happen if all messages were empty strings after processing.
  67. // Or if messagesToProcess was empty to begin with.
  68. console.log('autoConversationTitle: No history lines generated for LLM, though messages were present or none to process.');
  69. if (forceReplace) setAutoTitle(conversationId, ''); // Clear the "✏️..."
  70. return false;
  71. }
  72. // If there were no messages to process at all
  73. if (messagesToProcess.length === 0) {
  74. console.log('autoConversationTitle: No messages to process for title generation.');
  75. if (forceReplace) setAutoTitle(conversationId, '');
  76. return false;
  77. }
  78.  
  79.  
  80. try {
  81. // LLM chat-generate call
  82. // Adjusted the prompt to reflect that we are sending "snippets" which might be truncated.
  83. let title = await aixChatGenerateText_Simple(
  84. autoTitleLlmId,
  85. 'You are an AI Conversation Titles Assistant, an expert in creating CLEAR, INFORMATIVE, and EASILY SEARCHABLE chat titles.',
  86. `Your primary goal is to craft a title that not only summarizes the core subject but also makes the chat easily identifiable and searchable among many others. The title field is limited, so conciseness is crucial.
  87.  
  88. Analyze the given conversation snippets (each snippet is from a message and may be truncated if the original message was long) and extract a compelling and informative title.
  89.  
  90. **Key Requirements for the Title:**
  91.  
  92. 1. **Content Focus & Searchability:** Prioritize key information, entities, or the main purpose/outcome of the discussion. The title MUST be meaningful enough to distinguish this chat from others when searching.
  93. 2. **Specific Topics/Articles:** If the discussion CLEARLY revolves around a specific article, document, project, or named topic, YOU MUST STRIVE to include its name (or a concise, recognizable version of it) in the title. This is critical for later retrieval.
  94. 3. **Length:** Strictly aim for approximately **3-6 words**. Brevity combined with maximum informativeness is key.
  95. 4. **Style:** You are ENCOURAGED to use relevant EMOJIS and appropriate CAPITALIZATION to make titles more expressive and visually distinct, aiding quick scanning.
  96.  
  97. Respond ONLY with the generated title itself. Do not include any other text, explanations, or introductory phrases.
  98.  
  99. \`\`\`
  100. ${historyLines.join('\n')}
  101. \`\`\``,
  102. 'chat-ai-title', conversationId,
  103. );
  104.  
  105. // parse title
  106. title = title
  107. ?.trim()
  108. ?.replaceAll('"', '')
  109. ?.replace('Title: ', '')
  110. ?.replace('title: ', '');
  111.  
  112. // data write
  113. if (title) {
  114. setAutoTitle(conversationId, title);
  115. return true;
  116. }
  117.  
  118. } catch (error: any) {
  119. // not critical at all
  120. console.log('Failed to auto-title conversation', conversationId, { error });
  121. if (forceReplace)
  122. setAutoTitle(conversationId, '');
  123. }
  124.  
  125. return false;
  126. }
  127.  
  128.  
  129.  
  130. =============================
  131.  
  132. src/modules/blocks/markdown/CustomMarkdownRenderer.tsx только preprocessMarkdown
  133.  
  134.  
  135.  
  136. function preprocessMarkdown(markdownText: string) {
  137. try {
  138. // for performance, disable the preprocessor if the text is too long
  139. if (markdownText.length > MAX_PREPROCESSOR_LENGTH) {
  140. if (!warnedAboutLength) {
  141. console.warn('[DEV] Preprocessing markdown: text too long, skipping');
  142. warnedAboutLength = true;
  143. }
  144. return markdownText;
  145. }
  146. return markdownText
  147. // NEW: Replace underscores with spaces within \text{} and similar LaTeX commands
  148. // e.g., \text{first_order} becomes \text{first order}
  149. // This is to address specific KaTeX parsing issues where '_' inside \text is problematic.
  150. .replace(/\\(text|mathrm|mathbf|mathit|textit|mathsf|texttt|operatorname)\{([^}]*)\}/g, (match, command, content) => {
  151. const modifiedContent = content.replace(/_/g, ' ');
  152. return `\\${command}{${modifiedContent}}`;
  153. })
  154. // Replace LaTeX delimiters with $$...$$
  155. // Replace inline LaTeX delimiters \( and \) with $$
  156. // [2025-04-20] NOTE: it was reported that we had infinite recursion on the (.*?) version of inline math; as such, we now stay on the same line
  157. .replace(INLINE_LATEX_REGEX, (_match, leadingSpace, mathContent) =>
  158. `${leadingSpace}$$${mathContent}$$`,
  159. )
  160. // Replace block LaTeX delimiters \[ and \] with $$
  161. .replace(BLOCK_LATEX_REGEX, (_match, leadingSpace, mathContent) =>
  162. `${leadingSpace}$$${mathContent}$$`,
  163. )
  164. // Replace <mark>...</mark> with ==...==, but not in multiple lines, or if preceded by a backtick (disabled, was (?<!`))
  165. .replace(/<mark>([\s\S]*?)<\/mark>/g, (_match, p1) => wrapWithMarkdownSyntax(p1, '=='))
  166. // Replace <del>...</del> with ~~...~~, but not in multiple lines, or if preceded by a backtick (disabled, was (?<!`))
  167. .replace(/<del>([\s\S]*?)<\/del>/g, (_match, p1) => wrapWithMarkdownSyntax(p1, '~~'));
  168. } catch (error: any) {
  169. if (!warnedAboutPreprocessor) {
  170. console.warn('[DEV] Issue with the markdown preprocessor. Please open a bug with the offending text.', { error, markdownText });
  171. warnedAboutPreprocessor = true;
  172. }
  173. return markdownText;
  174. }
  175. }
  176.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement