mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 05:17:10 +00:00
* feat: memory basic * fix: chaite ver * fix: update prompt * fix: memory cursor and extract prompt * fix: memory retrieval bug * fix: memory retrieval bug * fix: one more attempt by codex * fix: messages prompt error * fix: one more time by codex * fix: metrics by codex * fix: memory forward * fix: memory show update time
129 lines
3.6 KiB
JavaScript
129 lines
3.6 KiB
JavaScript
import { Chaite } from 'chaite'
|
|
import * as crypto from 'node:crypto'
|
|
import { extractUserMemories } from './extractor.js'
|
|
import { memoryService } from './service.js'
|
|
|
|
const USER_MEMORY_CONTEXT_LIMIT = 6
|
|
|
|
export function extractTextFromContents (contents) {
|
|
if (!Array.isArray(contents)) {
|
|
return ''
|
|
}
|
|
return contents
|
|
.filter(item => item && item.type === 'text')
|
|
.map(item => item.text || '')
|
|
.join('\n')
|
|
.trim()
|
|
}
|
|
|
|
export function extractTextFromUserMessage (userMessage) {
|
|
if (!userMessage?.content) {
|
|
return ''
|
|
}
|
|
return userMessage.content
|
|
.filter(item => item.type === 'text')
|
|
.map(item => item.text || '')
|
|
.join('\n')
|
|
.trim()
|
|
}
|
|
|
|
function normaliseMemoriesInput (memories, sourceId) {
|
|
return (memories || []).map(mem => {
|
|
if (typeof mem === 'string') {
|
|
return {
|
|
value: mem,
|
|
source_message_id: sourceId
|
|
}
|
|
}
|
|
if (mem && typeof mem === 'object') {
|
|
const cloned = { ...mem }
|
|
if (!cloned.source_message_id && sourceId) {
|
|
cloned.source_message_id = sourceId
|
|
}
|
|
if (!cloned.value && cloned.fact) {
|
|
cloned.value = cloned.fact
|
|
}
|
|
if (!cloned.value && cloned.text) {
|
|
cloned.value = cloned.text
|
|
}
|
|
return cloned
|
|
}
|
|
return {
|
|
value: String(mem),
|
|
source_message_id: sourceId
|
|
}
|
|
})
|
|
}
|
|
|
|
export async function processUserMemory ({ event, userMessage, userText, conversationId, assistantContents, assistantMessageId }) {
|
|
const e = event
|
|
if (!memoryService.isUserMemoryEnabled(e.sender.user_id)) {
|
|
return
|
|
}
|
|
const snippets = []
|
|
const userMessageId = e.message_id || e.seq || userMessage?.id || crypto.randomUUID()
|
|
const senderName = e.sender?.card || e.sender?.nickname || String(e.sender?.user_id || '')
|
|
|
|
try {
|
|
const historyManager = Chaite.getInstance()?.getHistoryManager?.()
|
|
if (historyManager && conversationId) {
|
|
const history = await historyManager.getHistory(null, conversationId)
|
|
const filtered = (history || [])
|
|
.filter(msg => ['user', 'assistant'].includes(msg.role))
|
|
.map(msg => ({
|
|
role: msg.role,
|
|
text: extractTextFromContents(msg.content),
|
|
nickname: msg.role === 'user' ? senderName : '机器人',
|
|
message_id: msg.id
|
|
}))
|
|
.filter(item => item.text)
|
|
if (filtered.length > 0) {
|
|
const limited = filtered.slice(-USER_MEMORY_CONTEXT_LIMIT * 2)
|
|
snippets.push(...limited)
|
|
}
|
|
}
|
|
} catch (err) {
|
|
logger.warn('Failed to collect user memory context:', err)
|
|
}
|
|
|
|
if (assistantContents) {
|
|
const assistantText = extractTextFromContents(assistantContents)
|
|
if (assistantText) {
|
|
snippets.push({
|
|
role: 'assistant',
|
|
text: assistantText,
|
|
nickname: '机器人',
|
|
message_id: assistantMessageId || crypto.randomUUID()
|
|
})
|
|
}
|
|
}
|
|
|
|
if (userText && !snippets.some(item => item.message_id === userMessageId)) {
|
|
snippets.push({
|
|
role: 'user',
|
|
text: userText,
|
|
nickname: senderName,
|
|
message_id: userMessageId
|
|
})
|
|
}
|
|
|
|
if (snippets.length === 0) {
|
|
return
|
|
}
|
|
|
|
const existingRecords = memoryService.listUserMemories(e.sender.user_id, e.isGroup ? e.group_id : null, 50)
|
|
const existingTexts = existingRecords.map(record => record.value).filter(Boolean)
|
|
const memories = await extractUserMemories(snippets, existingTexts)
|
|
if (!memories || memories.length === 0) {
|
|
return
|
|
}
|
|
|
|
const enriched = normaliseMemoriesInput(memories, userMessageId)
|
|
memoryService.upsertUserMemories(
|
|
e.sender.user_id,
|
|
e.isGroup ? e.group_id : null,
|
|
enriched
|
|
)
|
|
}
|
|
|
|
export { USER_MEMORY_CONTEXT_LIMIT }
|