diff --git a/extensions/chatgpt2lollms/chatgpt2lollms.py b/extensions/chatgpt2lollms/chatgpt2lollms.py
new file mode 100644
index 00000000..40dbae76
--- /dev/null
+++ b/extensions/chatgpt2lollms/chatgpt2lollms.py
@@ -0,0 +1,67 @@
+import json
+import argparse
+from datetime import datetime
+
+def convert_discussions(input_data, flatten=False):
+ discussions = []
+
+ for discussion in input_data:
+ converted_discussion = {
+ "id": discussion['id'],
+ "messages": [],
+ "title": discussion['title']
+ }
+
+ mapping = discussion['mapping']
+ message_ids = list(mapping.keys())
+
+ messages = [mapping[message_id]['message'] for message_id in message_ids if mapping[message_id]['message']]
+
+ for i, message in enumerate(messages):
+ created_at = ''
+ create_time = message.get('create_time')
+
+ if create_time is not None:
+ created_at = datetime.fromtimestamp(create_time).strftime("%Y-%m-%d %H:%M:%S")
+
+ content = message['content'].get('parts', [''])[0]
+ if content:
+ parent = i - 1 if flatten and i > 0 else mapping[message_ids[i]]['parent'] or -1
+
+ converted_message = {
+ "binding": message['content'].get('binding', ''),
+ "content": content,
+ "created_at": created_at,
+ "finished_generating_at": '',
+ "model": '',
+ "parent": parent,
+ "personality": '',
+ "rank": 0,
+ "sender": message['author']['role'],
+ "type": 0
+ }
+
+ converted_discussion['messages'].append(converted_message)
+
+ discussions.append(converted_discussion)
+
+ return discussions
+
+def convert_json(input_file, output_file, flatten=False):
+ with open(input_file, 'r') as file:
+ input_json = file.read()
+
+ input_data = json.loads(input_json)
+ converted_data = convert_discussions(input_data, flatten=flatten)
+
+ with open(output_file, 'w') as file:
+ json.dump(converted_data, file, indent=4)
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Convert JSON files from the first format to the second format.')
+ parser.add_argument('input_file', help='Input JSON file path')
+ parser.add_argument('output_file', help='Output JSON file path')
+ parser.add_argument('--flatten', action='store_true', help='Flatten the discussion hierarchy')
+
+ args = parser.parse_args()
+ convert_json(args.input_file, args.output_file, flatten=args.flatten)
diff --git a/extensions/chatgpt2lollms/converted.json b/extensions/chatgpt2lollms/converted.json
new file mode 100644
index 00000000..71cd9a20
--- /dev/null
+++ b/extensions/chatgpt2lollms/converted.json
@@ -0,0 +1,28700 @@
+[
+ {
+ "id": "510f2605-f631-4a82-828a-54fd3dce9c98",
+ "messages": [
+ {
+ "binding": "",
+ "content": "are you familiar with vu.js?",
+ "created_at": "2023-07-05 22:28:33",
+ "finished_generating_at": "",
+ "model": "",
+ "parent": 0,
+ "personality": "",
+ "rank": 0,
+ "sender": "user",
+ "type": 0
+ },
+ {
+ "binding": "",
+ "content": "I believe you are referring to Vue.js, which is a popular JavaScript framework for building user interfaces. Vue.js is designed to be approachable and versatile, allowing developers to create interactive web applications efficiently.\n\nVue.js follows a component-based architecture, where you can build reusable components with their own logic and structure. These components can be combined to form complex user interfaces. Vue.js also provides a declarative syntax for connecting the data and the DOM, making it easy to track changes and update the UI accordingly.\n\nSome key features of Vue.js include:\n\n1. **Reactivity**: Vue.js uses a reactive data-binding system, allowing you to declaratively define dependencies between the data and the UI. When the data changes, the UI automatically updates to reflect the changes.\n\n2. **Component-based**: Vue.js encourages building applications using components, which are self-contained units that can be reused throughout the application. Components make it easier to manage and organize the codebase.\n\n3. **Directives**: Vue.js provides a set of built-in directives that allow you to manipulate the DOM in a declarative manner. Directives are used to apply special behaviors to elements or components.\n\n4. **Routing**: Vue Router is the official routing library for Vue.js. It enables you to build single-page applications with client-side routing, allowing for dynamic navigation without refreshing the entire page.\n\n5. **Vuex**: Vuex is the official state management library for Vue.js applications. It provides a centralized store to manage the application's state and facilitates communication between components.\n\nOverall, Vue.js is known for its simplicity, performance, and ease of integration with existing projects. It has a growing ecosystem of libraries and tools, making it a popular choice for web development.",
+ "created_at": "2023-07-05 22:28:43",
+ "finished_generating_at": "",
+ "model": "",
+ "parent": 1,
+ "personality": "",
+ "rank": 0,
+ "sender": "assistant",
+ "type": 0
+ },
+ {
+ "binding": "",
+ "content": "i have a socketio connection with a server. the server performs a task in multiple steps.\nThe server emits messages each message has content and type. Some messages are special. Like step start and step end messages\nFor each step I receive a message saying that the step has started, then when it finishes It sends a step end message.\nLet's create a component that we call step that has an unchecked square and the message content as well as a loader animation, the component has a boolean called done, if it is false, the square is unchecked and the loader is shown, else the square is checked and the loader is hidden. ",
+ "created_at": "2023-07-05 22:44:58",
+ "finished_generating_at": "",
+ "model": "",
+ "parent": 2,
+ "personality": "",
+ "rank": 0,
+ "sender": "user",
+ "type": 0
+ },
+ {
+ "binding": "",
+ "content": "Sure! I can help you create a Vue.js component called \"Step\" that represents a step with an unchecked square, message content, and a loader animation. The component will have a boolean property called \"done\" that determines whether the step is completed or not.\n\nHere's an example implementation of the \"Step\" component:\n\n```vue\n\n
Error: ${error.message}
`;\n outputDiv.scrollTop = outputDiv.scrollHeight;\n // Toggle button visibility\n generateButton.classList.remove('hidden');\n stopButton.classList.add('hidden');\n\n });\n\n // Event handler for error during text generation\n socket.on('generation_canceled', error => {\n // Toggle button visibility\n generateButton.classList.remove('hidden');\n stopButton.classList.add('hidden');\n\n });\n\n // Triggered when the \"Generate Text\" button is clicked\n generateButton.addEventListener('click', () => {\n const outputDiv = document.getElementById('text');\n var prompt = outputDiv.value\n console.log(prompt)\n // Trigger the 'generate_text' event with the prompt\n socket.emit('generate_text', { prompt, personality: -1, n_predicts: 1024 });\n\n // Toggle button visibility\n generateButton.classList.add('hidden');\n stopButton.classList.remove('hidden');\n });\n\n // Triggered when the \"Stop Generation\" button is clicked\n stopButton.addEventListener('click', () => {\n // Trigger the 'cancel_generation' event\n socket.emit('cancel_generation',{});\n\n });", + "created_at": "2023-07-05 09:07:08", + "finished_generating_at": "", + "model": "", + "parent": 4, + "personality": "", + "rank": 0, + "sender": "user", + "type": 0 + }, + { + "binding": "", + "content": "Certainly! Here's a full object-oriented example in C++ that connects to a Socket.IO server and listens for events:\n\n```cpp\n#include in my text and the returns are not rendered as returns",
+ "created_at": "2023-07-02 22:32:55",
+ "finished_generating_at": "",
+ "model": "",
+ "parent": 14,
+ "personality": "",
+ "rank": 0,
+ "sender": "user",
+ "type": 0
+ },
+ {
+ "binding": "",
+ "content": "I apologize for the confusion. It seems I misunderstood your requirement. To preserve line breaks and render them as actual line breaks, you can use the `markdown-it` option `html: true` when creating the `markdownIt` instance. This option allows HTML tags to be recognized and rendered as expected.\n\nHere's the modified code snippet with the `html: true` option:\n\n```javascript\nconst markdownIt = new MarkdownIt('commonmark', {\n html: true, // Enable HTML tags\n // ...\n}).use(emoji).use(attrs).use(heading).use(anchor);\n```\n\nWith this modification, line breaks in your Markdown content will be transformed into `
` tags, and other HTML tags will be recognized and rendered accordingly.\n\nAdditionally, ensure that the rendered Markdown content is wrapped in a `
\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n
\n\n\n Nullam vitae velit sed sapien vestibulum tincidunt.\n
\n\n```\n\nThe plugin will automatically wrap the image and caption within a `