Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 53 additions & 38 deletions lpm_frontend/src/app/dashboard/playground/chat/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Message = StorageMessage;

type ModelType = 'chat' | 'thinking';

interface PlaygroundSettings {
export interface PlaygroundSettings {
enableL0Retrieval: boolean;
enableL1Retrieval: boolean;
enableHelperModel: boolean;
Expand All @@ -30,9 +30,6 @@ interface PlaygroundSettings {
temperature: number;
}

// Constants
const STORAGE_KEY_SETTINGS = 'playgroundSettings';

// Function to generate unique ID
const generateMessageId = () => {
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
Expand All @@ -47,6 +44,7 @@ export default function PlaygroundChat() {
const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
const [messages, setMessages] = useState<Message[]>([]);
const [modelType, setModelType] = useState<ModelType | undefined>(undefined);
const [initLoading, setInitLoading] = useState<boolean>(true);

const originPrompt = useMemo(() => {
const name = loadInfo?.name || 'user';
Expand Down Expand Up @@ -92,18 +90,8 @@ export default function PlaygroundChat() {
const [settings, setSettings] = useState<PlaygroundSettings>(originSettings);
const messagesEndRef = useRef<HTMLDivElement>(null);

useEffect(() => {
setSettings((prev) => {
const newSettings = { ...prev, systemPrompt: originPrompt };

localStorage.setItem(STORAGE_KEY_SETTINGS, JSON.stringify(newSettings));

return newSettings;
});
}, [originPrompt]);

useEffect(() => {
getTrainingParams()
const fetchModelType = () => {
return getTrainingParams()
.then((res) => {
if (res.data.code === 0) {
const data = res.data.data;
Expand All @@ -117,7 +105,7 @@ export default function PlaygroundChat() {
.catch((error) => {
console.error(error.message);
});
}, []);
};

const scrollToBottom = () => {
if (messagesEndRef.current) {
Expand All @@ -140,13 +128,7 @@ export default function PlaygroundChat() {
}
};

// When messages are updated, scroll to the bottom
useEffect(() => {
scrollToBottom();
}, [messages, streamContent]);

// First initialization
useEffect(() => {
const firstLoadSessions = () => {
const storedSessions = chatStorage.getSessions();

setSessions(storedSessions);
Expand All @@ -156,28 +138,35 @@ export default function PlaygroundChat() {
} else {
setActiveSessionId(storedSessions[0].id);
setMessages(storedSessions[0].messages);
setSettings(storedSessions[0].setting);
}
}, []);
};

// Load sessions, messages, and settings from storage on mount
// When messages are updated, scroll to the bottom
useEffect(() => {
const storedSettings = localStorage.getItem(STORAGE_KEY_SETTINGS);
scrollToBottom();
}, [messages, streamContent]);

if (storedSettings) {
try {
setSettings(JSON.parse(storedSettings));
} catch (error) {
console.error('Failed to parse stored settings:', error);
}
}
// First initialization
useEffect(() => {
fetchModelType().then(() => {
setInitLoading(false);
});
}, []);

useEffect(() => {
if (!initLoading) {
firstLoadSessions();
}
}, [initLoading]);

const handleNewChat = () => {
const newSession = chatStorage.createSession();
const newSession = chatStorage.createSession({ originPrompt: originPrompt });

setSessions((prev) => [newSession, ...prev]);
setActiveSessionId(newSession.id);
setMessages([]);
setSettings(originSettings);
};

const handleSessionClick = (sessionId: string) => {
Expand All @@ -188,12 +177,18 @@ export default function PlaygroundChat() {

if (session) {
setMessages(session.messages);
setSettings(session.setting);
}
};

const handleSettingsChange = (newSettings: PlaygroundSettings) => {
setSettings(newSettings);
localStorage.setItem(STORAGE_KEY_SETTINGS, JSON.stringify(newSettings));

if (activeSessionId) {
chatStorage.updateSession(activeSessionId, {
setting: newSettings
});
}
};

const handleSendMessage = async (content: string) => {
Expand Down Expand Up @@ -224,7 +219,7 @@ export default function PlaygroundChat() {

const systemMessage: Message = {
id: generateMessageId(),
content: originPrompt,
content: settings.systemPrompt,
role: 'system',
timestamp: new Date().toLocaleTimeString([], {
hour: '2-digit',
Expand All @@ -237,7 +232,7 @@ export default function PlaygroundChat() {
} else {
newMessages = newMessages.map((msg) => {
if (msg.role === 'system') {
return { ...msg, content: originPrompt };
return { ...msg, content: settings.systemPrompt };
}

return msg;
Expand Down Expand Up @@ -319,6 +314,26 @@ export default function PlaygroundChat() {
}
};

if (initLoading) {
return (
<div className="h-full w-full flex items-center justify-center bg-gray-50">
<div className="flex flex-col items-center space-y-4">
<div className="relative w-16 h-16">
<div className="absolute w-16 h-16 rounded-full border-4 border-gray-200" />
<div
className="absolute w-16 h-16 rounded-full border-4 border-t-blue-500 animate-spin"
style={{
animationTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
animationDuration: '1.5s'
}}
/>
</div>
<p className="text-gray-600 font-medium">Loading Chat...</p>
</div>
</div>
);
}

return (
<div className="h-full w-full flex">
<ChatHistory
Expand Down
20 changes: 17 additions & 3 deletions lpm_frontend/src/utils/chatStorage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { PlaygroundSettings } from '@/app/dashboard/playground/chat/page';

// Storage keys for different chat types
const STORAGE_KEYS = {
PLAYGROUND: 'playgroundChat',
Expand All @@ -18,6 +20,7 @@ export interface ChatSession {
lastMessage: string;
timestamp: string;
messages: ChatMessage[];
setting: PlaygroundSettings;
}

// Type for playground chat which only stores messages
Expand Down Expand Up @@ -136,13 +139,24 @@ export const chatWithUploadStorage = {
return data.sessions;
},

createSession: (title: string = 'New Conversation'): ChatSession => {
createSession: (props: { title?: string; originPrompt?: string }): ChatSession => {
const { title = 'New Conversation', originPrompt = "You are User's Second Me" } = props;

const newSession: ChatSession = {
id: Date.now().toString(),
title,
lastMessage: '',
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
messages: []
messages: [],
setting: {
enableL0Retrieval: true,
enableL1Retrieval: true,
enableHelperModel: false,
selectedModel: 'ollama',
apiKey: 'http://localhost:11434',
systemPrompt: originPrompt,
temperature: 0.3
}
};

const sessions = chatWithUploadStorage.getSessions();
Expand Down Expand Up @@ -218,7 +232,7 @@ export const roleplayChatStorage = {
getMessages: (role_id: string): ChatMessage[] => {
const data = getStorageData<RoleplayChatData>(STORAGE_KEYS.ROLEPLAY, {});

return data[role_id]?.messages || [];
return data[role_id].messages || [];
},

saveMessages: (role_id: string, messages: ChatMessage[]) => {
Expand Down