refac
This commit is contained in:
+43
-18
@@ -677,7 +677,9 @@ export const calculateSHA256 = async (file) => {
|
|||||||
|
|
||||||
export const getImportOrigin = (_chats) => {
|
export const getImportOrigin = (_chats) => {
|
||||||
// Check what external service chat imports are from
|
// Check what external service chat imports are from
|
||||||
if ('mapping' in _chats[0]) {
|
// ChatGPT exports may include folder/project metadata entries without 'mapping',
|
||||||
|
// so we check if ANY item has a 'mapping' key instead of only the first one.
|
||||||
|
if (_chats.some((chat) => 'mapping' in chat)) {
|
||||||
return 'openai';
|
return 'openai';
|
||||||
}
|
}
|
||||||
return 'webui';
|
return 'webui';
|
||||||
@@ -706,6 +708,21 @@ export const getUserPosition = async (raw = false) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const extractOpenAIMessageContent = (message): string => {
|
||||||
|
// Extract text content from a ChatGPT message, handling various content formats
|
||||||
|
// (string parts, object parts like DALL-E images, text field fallback)
|
||||||
|
try {
|
||||||
|
const parts = message?.['content']?.['parts'];
|
||||||
|
if (Array.isArray(parts)) {
|
||||||
|
const textParts = parts.filter((p) => typeof p === 'string');
|
||||||
|
if (textParts.length > 0) return textParts.join('\n');
|
||||||
|
}
|
||||||
|
return message?.['content']?.['text'] || '';
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const convertOpenAIMessages = (convo) => {
|
const convertOpenAIMessages = (convo) => {
|
||||||
// Parse OpenAI chat messages and create chat dictionary for creating new chats
|
// Parse OpenAI chat messages and create chat dictionary for creating new chats
|
||||||
const mapping = convo['mapping'];
|
const mapping = convo['mapping'];
|
||||||
@@ -726,15 +743,18 @@ const convertOpenAIMessages = (convo) => {
|
|||||||
// Skip chat messages with no content
|
// Skip chat messages with no content
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
const role = message['message']?.['author']?.['role'];
|
||||||
|
// Skip system and tool messages — they don't map to user/assistant
|
||||||
|
if (role === 'system' || role === 'tool') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const new_chat = {
|
const new_chat = {
|
||||||
id: message_id,
|
id: message_id,
|
||||||
parentId: lastId,
|
parentId: lastId,
|
||||||
childrenIds: message['children'] || [],
|
childrenIds: message['children'] || [],
|
||||||
role: message['message']?.['author']?.['role'] !== 'user' ? 'assistant' : 'user',
|
role: role !== 'user' ? 'assistant' : 'user',
|
||||||
content:
|
content: extractOpenAIMessageContent(message['message']),
|
||||||
message['message']?.['content']?.['parts']?.[0] ||
|
|
||||||
message['message']?.['content']?.['text'] ||
|
|
||||||
'',
|
|
||||||
model: 'gpt-3.5-turbo',
|
model: 'gpt-3.5-turbo',
|
||||||
done: true,
|
done: true,
|
||||||
context: null
|
context: null
|
||||||
@@ -747,6 +767,12 @@ const convertOpenAIMessages = (convo) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix up the last message's childrenIds to be empty (it's the leaf node in our
|
||||||
|
// linear chain regardless of what the original tree structure had)
|
||||||
|
if (messages.length > 0) {
|
||||||
|
messages[messages.length - 1].childrenIds = [];
|
||||||
|
}
|
||||||
|
|
||||||
const history: Record<PropertyKey, (typeof messages)[number]> = {};
|
const history: Record<PropertyKey, (typeof messages)[number]> = {};
|
||||||
messages.forEach((obj) => (history[obj.id] = obj));
|
messages.forEach((obj) => (history[obj.id] = obj));
|
||||||
|
|
||||||
@@ -773,18 +799,6 @@ const validateChat = (chat) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last message's children should be an empty array
|
|
||||||
const lastMessage = messages[messages.length - 1];
|
|
||||||
if (lastMessage.childrenIds.length !== 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First message's parent should be null
|
|
||||||
const firstMessage = messages[0];
|
|
||||||
if (firstMessage.parentId !== null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every message's content should be a string
|
// Every message's content should be a string
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
if (typeof message.content !== 'string') {
|
if (typeof message.content !== 'string') {
|
||||||
@@ -799,7 +813,15 @@ export const convertOpenAIChats = (_chats) => {
|
|||||||
// Create a list of dictionaries with each conversation from import
|
// Create a list of dictionaries with each conversation from import
|
||||||
const chats = [];
|
const chats = [];
|
||||||
let failed = 0;
|
let failed = 0;
|
||||||
|
let skipped = 0;
|
||||||
for (const convo of _chats) {
|
for (const convo of _chats) {
|
||||||
|
// Skip folder/project metadata entries that lack a 'mapping' key
|
||||||
|
if (!('mapping' in convo)) {
|
||||||
|
skipped++;
|
||||||
|
console.log('Skipping non-conversation entry (folder/project):', convo['title'] ?? convo['id']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const chat = convertOpenAIMessages(convo);
|
const chat = convertOpenAIMessages(convo);
|
||||||
|
|
||||||
if (validateChat(chat)) {
|
if (validateChat(chat)) {
|
||||||
@@ -815,6 +837,9 @@ export const convertOpenAIChats = (_chats) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(failed, 'Conversations could not be imported');
|
console.log(failed, 'Conversations could not be imported');
|
||||||
|
if (skipped > 0) {
|
||||||
|
console.log(skipped, 'Non-conversation entries (folders/projects) were skipped');
|
||||||
|
}
|
||||||
return chats;
|
return chats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user