Files
AIclinicalresearch/backend/src/modules/iit-manager/agents/SessionMemory.ts
HaHafeng 4ed67a8846 fix(admin): Fix Prompt management list not showing version info and add debug diagnostics
Summary:
- Fix Prompt list API response schema missing activeVersion and draftVersion fields
- Fastify was filtering out undefined schema fields, causing version columns to show empty
- Add detailed diagnostic logging for Prompt debug mode troubleshooting
- Verify debug mode works correctly (DRAFT version is used when debug enabled)

Changes:
- backend/src/common/prompt/prompt.routes.ts: Add activeVersion and draftVersion to response schema
- backend/src/common/prompt/prompt.service.ts: Add diagnostic logs for setDebugMode and get methods
- PKB module: Various authentication and document handling fixes from previous session

Tested: Debug mode verified working - v2 DRAFT version correctly loaded when debug enabled
2026-01-13 22:22:10 +08:00

188 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* SessionMemory - 会话记忆管理器(内存版)
*
* 功能:
* - 存储用户最近3轮对话
* - 提供上下文查询
* - 自动清理过期会话1小时
*
* 设计原则:
* - Node.js内存存储MVP阶段无需数据库
* - 单例模式(全局共享)
* - 轻量级(<100行代码
*/
import { logger } from '../../../common/logging/index.js';
/**
* 对话消息
*/
export interface ConversationMessage {
role: 'user' | 'assistant';
content: string;
timestamp: Date;
}
/**
* 对话历史
*/
export interface ConversationHistory {
userId: string;
messages: ConversationMessage[];
createdAt: Date;
updatedAt: Date;
}
/**
* 会话记忆管理器
*/
export class SessionMemory {
// 内存存储:{ userId: ConversationHistory }
private sessions: Map<string, ConversationHistory> = new Map();
private readonly MAX_HISTORY = 3; // 只保留最近3轮6条消息
private readonly SESSION_TIMEOUT = 3600000; // 1小时毫秒
/**
* 添加对话记录
*/
addMessage(userId: string, role: 'user' | 'assistant', content: string): void {
if (!this.sessions.has(userId)) {
this.sessions.set(userId, {
userId,
messages: [],
createdAt: new Date(),
updatedAt: new Date(),
});
logger.debug('[SessionMemory] 创建新会话', { userId });
}
const session = this.sessions.get(userId)!;
session.messages.push({
role,
content,
timestamp: new Date(),
});
// 只保留最近3轮6条消息3个user + 3个assistant
if (session.messages.length > this.MAX_HISTORY * 2) {
const removed = session.messages.length - this.MAX_HISTORY * 2;
session.messages = session.messages.slice(-this.MAX_HISTORY * 2);
logger.debug('[SessionMemory] 清理历史消息', { userId, removedCount: removed });
}
session.updatedAt = new Date();
logger.debug('[SessionMemory] 添加消息', {
userId,
role,
messageLength: content.length,
totalMessages: session.messages.length,
});
}
/**
* 获取用户对话历史最近N轮
*/
getHistory(userId: string, maxTurns: number = 3): ConversationMessage[] {
const session = this.sessions.get(userId);
if (!session) {
return [];
}
// 返回最近N轮2N条消息
const maxMessages = maxTurns * 2;
return session.messages.length > maxMessages
? session.messages.slice(-maxMessages)
: session.messages;
}
/**
* 获取用户上下文格式化为字符串用于LLM Prompt
*/
getContext(userId: string): string {
const history = this.getHistory(userId, 2); // 只取最近2轮
if (history.length === 0) {
return '';
}
return history
.map((m) => `${m.role === 'user' ? 'PI' : 'Assistant'}: ${m.content}`)
.join('\n');
}
/**
* 清除用户会话
*/
clearSession(userId: string): void {
const existed = this.sessions.delete(userId);
if (existed) {
logger.info('[SessionMemory] 清除会话', { userId });
}
}
/**
* 清理过期会话超过1小时未使用
*/
cleanupExpiredSessions(): void {
const now = Date.now();
let cleanedCount = 0;
for (const [userId, session] of this.sessions.entries()) {
if (now - session.updatedAt.getTime() > this.SESSION_TIMEOUT) {
this.sessions.delete(userId);
cleanedCount++;
}
}
if (cleanedCount > 0) {
logger.info('[SessionMemory] 清理过期会话', { cleanedCount });
}
}
/**
* 获取统计信息(用于监控)
*/
getStats() {
return {
totalSessions: this.sessions.size,
sessions: Array.from(this.sessions.entries()).map(([userId, session]) => ({
userId,
messageCount: session.messages.length,
createdAt: session.createdAt,
updatedAt: session.updatedAt,
})),
};
}
}
// 全局单例
export const sessionMemory = new SessionMemory();
// 定时清理过期会话(每小时)
setInterval(() => {
sessionMemory.cleanupExpiredSessions();
}, 3600000);
logger.info('[SessionMemory] 会话记忆管理器已启动', {
maxHistory: 3,
timeout: '1小时',
});