fix: metrics by codex

This commit is contained in:
ikechan8370 2025-11-05 17:55:06 +08:00
parent 685bb5a5b8
commit d0e365cb32
3 changed files with 111 additions and 45 deletions

View file

@ -250,7 +250,7 @@ class ChatGPTConfig {
historyPollInterval: 300,
historyBatchSize: 120,
promptHeader: '# 以下是一些该群聊中可能相关的事实,你可以参考,但不要主动透露这些事实。',
promptItemTemplate: '- ${fact}${topicSuffix}',
promptItemTemplate: '- ${fact}${topicSuffix}${timeSuffix}',
promptFooter: '',
extractionSystemPrompt: `You are a knowledge extraction assistant that specialises in summarising long-term facts from group chat transcripts.
Read the provided conversation and identify statements that should be stored as long-term knowledge for the group.
@ -282,7 +282,7 @@ Only include meaningful, verifiable group-specific information that is useful fo
maxRelevantItemsPerQuery: 3,
minImportanceForInjection: 0,
promptHeader: '# 用户画像',
promptItemTemplate: '- ${value}',
promptItemTemplate: '- ${value}${timeSuffix}',
promptFooter: '',
extractionSystemPrompt: `You are an assistant that extracts long-term personal preferences or persona details about a user.
Given a conversation snippet between the user and the bot, identify durable information such as preferences, nicknames, roles, speaking style, habits, or other facts that remain valid over time.
@ -453,20 +453,13 @@ Return a JSON array of **strings**, and nothing else, without any other characte
? JSON.parse(content)
: yaml.load(content)
// 只更新存在的配置项
// 处理加载的配置并和默认值合并
if (loadedConfig) {
Object.keys(loadedConfig).forEach(key => {
if (['version', 'basic', 'bym', 'llm', 'management', 'chaite', 'memory'].includes(key)) {
if (typeof loadedConfig[key] === 'object' && loadedConfig[key] !== null) {
// 对象的合并
if (!this[key]) this[key] = {}
Object.assign(this[key], loadedConfig[key])
} else {
// 基本类型直接赋值
this[key] = loadedConfig[key]
}
}
})
const mergeResult = this._mergeConfig(loadedConfig)
if (mergeResult.changed) {
logger?.debug?.('[Config] merged new defaults into persisted config; scheduling save')
this._triggerSave('code')
}
}
logger.debug('Config loaded successfully')
@ -475,6 +468,68 @@ Return a JSON array of **strings**, and nothing else, without any other characte
}
}
_mergeConfig (loadedConfig) {
let changed = false
const mergeInto = (target, source) => {
if (!source || typeof source !== 'object') {
return target
}
if (!target || typeof target !== 'object') {
target = Array.isArray(source) ? [] : {}
}
const result = Array.isArray(source) ? [] : { ...target }
if (Array.isArray(source)) {
return source.slice()
}
const targetKeys = target && typeof target === 'object'
? Object.keys(target)
: []
for (const key of targetKeys) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
changed = true
}
}
for (const key of Object.keys(source)) {
const sourceValue = source[key]
const targetValue = target[key]
if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue)) {
result[key] = mergeInto(targetValue, sourceValue)
} else {
if (targetValue === undefined || targetValue !== sourceValue) {
changed = true
}
result[key] = sourceValue
}
}
return result
}
const sections = ['version', 'basic', 'bym', 'llm', 'management', 'chaite', 'memory']
for (const key of sections) {
const loadedValue = loadedConfig[key]
if (loadedValue === undefined) {
continue
}
if (typeof loadedValue === 'object' && loadedValue !== null) {
const merged = mergeInto(this[key], loadedValue)
if (merged !== this[key]) {
this[key] = merged
}
} else {
if (this[key] !== loadedValue) {
changed = true
}
this[key] = loadedValue
}
}
return { changed }
}
// 合并触发保存,防抖处理
_triggerSave (origin) {
// 清除之前的定时器
@ -482,20 +537,18 @@ Return a JSON array of **strings**, and nothing else, without any other characte
clearTimeout(this._saveTimer)
}
// 记录保存来源
this._saveOrigin = origin || 'code'
// 设置定时器延迟保存
const originLabel = origin || 'code'
this._saveOrigin = originLabel
this._saveTimer = setTimeout(() => {
this.saveToFile()
// 保存完成后延迟一下再清除来源标记
setTimeout(() => {
this._saveOrigin = null
}, 100)
this.saveToFile(originLabel)
this._saveOrigin = null
}, 200)
}
saveToFile () {
saveToFile (origin = 'code') {
if (origin !== 'code') {
this._saveOrigin = 'external'
}
logger.debug('Saving config to file...')
try {
const config = {

View file

@ -610,15 +610,7 @@ function ensureVectorTable (db) {
let tablePresent = tableExists
let needsTableReset = false
if (storedModel && storedModel !== currentModel) {
needsTableReset = true
} else if (!storedModel && tableExists) {
// Unknown model metadata but table exists; keep it as-is.
dimension = storedDimension
}
if (tableExists && storedDimension <= 0) {
logger?.warn?.('[Memory] vec_group_facts exists but stored dimension is invalid, rebuilding table')
needsTableReset = true
}
@ -628,11 +620,11 @@ function ensureVectorTable (db) {
tablePresent = false
dimension = 0
} catch (err) {
logger?.warn?.('[Memory] failed to drop vec_group_facts during model change:', err)
logger?.warn?.('[Memory] failed to drop vec_group_facts during dimension change:', err)
}
}
if (!tablePresent) {
if (!tablePresent) {
if (dimension <= 0) {
dimension = parseDimension(preferredDimension)
}
@ -640,30 +632,36 @@ function ensureVectorTable (db) {
try {
createVectorTable(db, dimension)
tablePresent = true
setMetaValue(db, META_VECTOR_MODEL_KEY, currentModel)
setMetaValue(db, META_VECTOR_DIM_KEY, String(dimension))
cachedVectorDimension = dimension
cachedVectorModel = currentModel
return cachedVectorDimension
} catch (err) {
logger?.error?.('[Memory] failed to (re)create vec_group_facts table:', err)
dimension = 0
}
}
} else if (dimension > 0 && preferredDimension > 0 && dimension !== preferredDimension) {
logger?.debug?.('[Memory] vector table dimension (%s) differs from preferred (%s); keeping existing table', dimension, preferredDimension)
}
const metaDimensionValue = dimension > 0 ? String(dimension) : '0'
setMetaValue(db, META_VECTOR_MODEL_KEY, currentModel)
setMetaValue(db, META_VECTOR_DIM_KEY, metaDimensionValue)
if (tablePresent && storedDimension > 0) {
cachedVectorDimension = storedDimension
cachedVectorModel = storedModel || currentModel
return cachedVectorDimension
}
cachedVectorDimension = dimension > 0 ? dimension : 0
// At this point we failed to determine a valid dimension, set metadata to 0 to avoid loops.
setMetaValue(db, META_VECTOR_MODEL_KEY, currentModel)
setMetaValue(db, META_VECTOR_DIM_KEY, '0')
cachedVectorDimension = 0
cachedVectorModel = currentModel
return cachedVectorDimension
}
export function resetVectorTableDimension (dimension) {
if (!Number.isFinite(dimension) || dimension <= 0) {
throw new Error(`Invalid vector dimension: ${dimension}`)
}
const db = getMemoryDatabase()
logger?.info?.('[Memory] resetting group vector table dimension to %s', dimension)
try {
db.exec('DROP TABLE IF EXISTS vec_group_facts')
} catch (err) {
@ -726,7 +724,12 @@ export function getMemoryDatabase () {
}
export function getVectorDimension () {
if (cachedVectorDimension) {
const currentModel = ChatGPTConfig.llm?.embeddingModel || ''
if (cachedVectorModel && cachedVectorModel !== currentModel) {
cachedVectorDimension = null
cachedVectorModel = null
}
if (cachedVectorDimension !== null) {
return cachedVectorDimension
}
const db = getMemoryDatabase()

View file

@ -24,6 +24,8 @@ function formatUserMemories (memories, config) {
segments.push(header)
}
memories.forEach((item, index) => {
const timestamp = item.updated_at || item.created_at || ''
const timeSuffix = timestamp ? `(记录时间:${timestamp}` : ''
const context = {
index,
order: index + 1,
@ -33,7 +35,10 @@ function formatUserMemories (memories, config) {
sourceId: item.source_message_id || '',
groupId: item.group_id || '',
createdAt: item.created_at || '',
updatedAt: item.updated_at || ''
updatedAt: item.updated_at || '',
timestamp,
time: timestamp,
timeSuffix
}
const line = renderTemplate(itemTemplate, context)
if (line) {
@ -61,6 +66,8 @@ function formatGroupFacts (facts, config) {
}
facts.forEach((item, index) => {
const topicSuffix = item.topic ? `${item.topic}` : ''
const timestamp = item.updated_at || item.created_at || ''
const timeSuffix = timestamp ? `(记录时间:${timestamp}` : ''
const context = {
index,
order: index + 1,
@ -70,6 +77,9 @@ function formatGroupFacts (facts, config) {
importance: item.importance ?? '',
createdAt: item.created_at || '',
updatedAt: item.updated_at || '',
timestamp,
time: timestamp,
timeSuffix,
distance: item.distance ?? '',
bm25: item.bm25_score ?? '',
sourceMessages: item.source_messages || '',