mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
fix: metrics by codex
This commit is contained in:
parent
685bb5a5b8
commit
d0e365cb32
3 changed files with 111 additions and 45 deletions
103
config/config.js
103
config/config.js
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 || '',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue