注意注意,别把这个语句放在有隐私的笔记里面!!!
原有功能与实现教程:
思源笔记页面内实现 ai 聊天与 ai 读取笔记内容进行回复(自动)! - 链滴
让 ai 根据当前笔记内容进行回复
代码功能:
在创建日记的时候进行回复
在每天写完日记以后,让 ai 根据日记内容进行回复
//!js // Function to get context from recently updated documents (Keep as is) async function getDocumentContext() { try { let currentDocId = Query.root_id(protyle); const sqlQuery = ` select * from blocks where root_id = '${currentDocId}' order by sort ASC limit 9999 `; let blocks = await Query.sql(sqlQuery); if (blocks && blocks.length > 0) { let contextEntries = blocks.map(block => { const content = block.markdown || block.content || '[No Content]'; return `Document Path: ${block.hpath || 'N/A'}\nContent:\n---\n${content}\n---`; }); return "以下是当前文档的内容,请参考:\n==========\n" + contextEntries.join('\n\n') + "\n==========\n"; } else { return "当前文档没有内容可供参考。\n"; } } catch (error) { console.error("查询文档时出错:", error); return "查询参考文档时出现错误。\n"; } } // Function to create the UI elements (Keep as is) const ui = () => { const textarea = document.createElement('textarea'); textarea.className = "fn__block b3-text-field"; textarea.rows = 3; textarea.placeholder = "继续提问..."; const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'flex-end'; buttonContainer.style.gap = '8px'; buttonContainer.style.marginTop = '8px'; const removeLastButton = document.createElement('button'); removeLastButton.className = "b3-button"; removeLastButton.textContent = "我不会和别人说的🌹"; buttonContainer.appendChild(removeLastButton); const sendButton = document.createElement('button'); sendButton.className = "b3-button"; sendButton.textContent = "是这样的😄"; buttonContainer.appendChild(sendButton); return { textarea, buttonContainer, sendButton, removeLastButton }; } // Main chat function (Modified to fix null querySelector error) const chat = async () => { let dv = Query.DataView(protyle, item, top); const messages = dv.useState('messages', []); const msgIds = dv.useState('msgIds', []); // --- Initial Rendering Structure --- dv.addmd(`#### 向我分享你的一天吧!`); // 1. Render existing messages from state const initialMsgIds = []; messages().forEach(msg => { try { let el = dv.addmd(`**${msg.role === 'user' ? 'You' : 'GPT'}**: ${msg.content}`); if (el && el.dataset && el.dataset.id) { initialMsgIds.push(el.dataset.id); } } catch (e) { console.error("Error rendering message:", e); } }); if (msgIds().length === 0 && initialMsgIds.length > 0) { msgIds(initialMsgIds); } // 2. Add Separator dv.addmd('---'); // 3. Create UI Elements but don't store unnecessary references const { textarea, buttonContainer, sendButton, removeLastButton } = ui(); // Just add them directly without storing the references dv.addele(textarea); dv.addele(buttonContainer); // --- Function to perform AI query (Modified with better error handling) --- const performAIQuery = async (prompt, isInitialQuery = false) => { try { sendButton.disabled = true; removeLastButton.disabled = true; // Add placeholder with better error handling let respondPlaceholder; let gptMsgId = null; try { respondPlaceholder = dv.addmd(`**GPT**: 正在检索参考资料并思考... 🤔`); if (respondPlaceholder && respondPlaceholder.dataset) { gptMsgId = respondPlaceholder.dataset.id; // Add placeholder ID to state only if it's valid if (gptMsgId) { msgIds([...msgIds(), gptMsgId]); } } } catch (e) { console.error("Error adding placeholder:", e); // If we can't add a placeholder, we'll just add a new message later } // Safe function to replace or add content const updateContent = (id, content) => { try { if (id) { dv.replaceView(id, dv.md(`**GPT**: ${content}`)); } else { // If no ID, add as new message let newEl = dv.addmd(`**GPT**: ${content}`); if (newEl && newEl.dataset && newEl.dataset.id) { msgIds([...msgIds(), newEl.dataset.id]); } } } catch (e) { console.error("Error updating content:", e); // Last resort fallback - just add a new message try { dv.addmd(`**GPT**: ${content}`); } catch (e) { console.error("Failed to add fallback message:", e); } } }; const docReference = await getDocumentContext(); const prefixText = `${docReference}\n这是我的提问背景信息:`; const suffixText = "\n请基于以上参考信息,回复我的问题。注意:多用表情,尽量简短且切中要点。"; const fullPrompt = `${prefixText}\n${prompt}\n${suffixText}`; const response = await Query.gpt(fullPrompt, { stream: true, streamInterval: 3, streamMsg: (content) => { // Safely update with streaming content updateContent(gptMsgId, content); } }); // Update state with final response const gptMessage = { role: 'assistant', content: response }; const currentMessages = messages(); if (isInitialQuery) { messages([gptMessage]); } else { messages([...currentMessages, gptMessage]); } // Final update with safe function updateContent(gptMsgId, response); } catch (error) { console.error("GPT 调用或处理失败:", error); const errorMessageContent = `抱歉,处理时遇到问题: ${error.message}`; try { if (gptMsgId) { dv.replaceView(gptMsgId, dv.md(`**GPT**: ${errorMessageContent}`)); } else { dv.addmd(`**GPT**: ${errorMessageContent}`); } const errorMessage = { role: 'assistant', content: errorMessageContent }; const currentMessages = messages(); if (isInitialQuery) { messages([errorMessage]); } else { messages([...currentMessages, errorMessage]); } } catch (e) { console.error("Error handling GPT failure:", e); // Try one more time with a simple message try { dv.addmd(`**Error**: ${error.message}`); } catch (finalError) { console.error("Failed all error handling attempts:", finalError); } } } finally { // Re-enable buttons regardless of outcome try { sendButton.disabled = false; removeLastButton.disabled = false; // Safely repaint dv.repaint(); } catch (e) { console.error("Error in finally block:", e); } } }; // --- Initial Query Logic --- if (messages().length === 0) { const predefinedPrompt = "今天真是美好的一天,请你基于参考内容,激励我度过美好的一天吧!请你用满满的正能量激励我,并且要加入很多的表情,让我的心情愉快!"; try { await performAIQuery(predefinedPrompt, true); } catch (e) { console.error("Initial query failed:", e); // Try to add a fallback message dv.addmd("**System**: 初始查询失败,但你仍然可以开始对话。"); } } // --- Button Handlers --- sendButton.onclick = async () => { const userInput = textarea.value.trim(); if (!userInput) return; // 1. Add user message to state and UI with better error handling const userMessage = { role: 'user', content: userInput }; messages([...messages(), userMessage]); let userEl; let userMsgId = null; try { userEl = dv.addmd(`**You**: ${userInput}`); if (userEl && userEl.dataset) { userMsgId = userEl.dataset.id; if (userMsgId) { msgIds([...msgIds(), userMsgId]); } } } catch (e) { console.error("Error adding user message:", e); } textarea.value = ''; // 2. Perform AI query with error handling try { await performAIQuery(userInput, false); } catch (e) { console.error("Query failed:", e); dv.addmd(`**System**: 查询失败,请重试。错误: ${e.message}`); } }; // Remove last button click handler (with better error handling) removeLastButton.onclick = () => { try { const currentMessages = messages(); let currentMsgIds = [...msgIds()]; if (currentMessages.length < 2 || currentMsgIds.length < 2) return; // Update messages state first (in case view operations fail) messages(currentMessages.slice(0, -2)); // Then try to remove the views try { const lastGptId = currentMsgIds.pop(); const lastUserId = currentMsgIds.pop(); if (lastGptId) dv.removeView(lastGptId); if (lastUserId) dv.removeView(lastUserId); // Update msgIds state only after successful removal msgIds(currentMsgIds); } catch (e) { console.error("Error removing views:", e); } // Always try to repaint dv.repaint(); } catch (e) { console.error("Error in removeLastButton handler:", e); } }; // --- Final Render --- try { dv.render(); } catch (e) { console.error("Error rendering DataView:", e); } } // Execute the chat function with error handling try { return chat(); } catch (e) { console.error("Fatal error in chat function:", e); return "Error initializing chat. Please check console for details."; }
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于