Achtung:
Ich habe das Script weiter ergänzt, da im Original nur ‘/’ und ‘„ ‘ als Zeichen für den Titel herausgefiltert wurden. Nun filtert das Skript auch ‘\’, ‘:’, ‘’’, ‘?’, ‘<’, ‘>’ und ‘|’, die ebenfalls in Dateinamen auf verschiedenen Plattformen Probleme bereiten.
14.02.2024
Dass ich ChatGPT nutze, habe ich schon häufiger erwähnt. Außerdem bin ich ein Freund der lokalen Datenspeicherung. Was läge also näher, als meine Interaktionen mit ChatGPT auch lokal zu speichern und zugänglich zu machen? Da ich zudem ein Obsidian-Nutzer bin, bietet es sich an, alle Chats als Markdown in meinem Obsidian-Vault zu speichern.
Nach etwas Recherche stieß ich auf ein Skript von Gavi Narra, das Chat-Verläufe in Markdown-Dateien umwandelt. Dieses Skript, das unter der MIT-Lizenz verfügbar ist, habe ich leicht modifiziert, um es an meine spezifischen Bedürfnisse anzupassen. Selbstverständlich steht das modifizierte Ergebnis ebenfalls unter der MIT-Lizenz.
Um das Skript zu verwenden, muss zuerst der Chat-Verlauf von ChatGPT exportiert werden. Folgen Sie diesen Schritten:
- Die Einstellungen von ChatGPT öffnen und zum Abschnitt „Datenkontrollen“ navigieren .
- Auf „Daten exportieren“ klicken und dann auf den „Exportieren“-Knopf.
- Nach einiger Zeit erhält man eine E‑Mail mit einem Download-Link. Über diesen Link können Sie eine ZIP-Datei herunterladen und entpacken, die die u.a. benötigte Datei „conversations.json“ enthält. Diese JSON-Datei hat eine komplexe Struktur, die alle Konversationsdaten enthält.
Das Python-Skript von Gavi benötigt den Pfad zur der „conversations.json“-Datei, den Pfad zu einem Ordner für die zu speichernden Markdown-Dateien und einen optionalen Parameter. Dieser Parameter ermöglicht es, die Dateien in Unterordnern zu speichern, die nach dem Datum der Chats benannt sind.
Der Befehl zum Ausführen des Skriptes sieht wie folgt aus:
python3 convert.py [Eingabe-datei] [Ausgabe-Ordner] [--use-date-folders]
# Ohne datumsbasierte Ordner python3 convert.py /pfad/conversations.json /pfad/Augabe-Ordner # Mit datumsbasierte Ordner python3 convert.py /pfad/conversations.json /pfad/Augabe-Ordner --use-date-folders
Ich habe an der grundlegenden Funktion des Skriptes nichts geändert. Die vorgenommenen Änderungen sind wie folgt im Skript markiert:
- Frontmatter-Ergänzung: Das Markup wird nun durch ein Frontmatter ergänzt, das ein Tag mit dem Namen „AI-Chat“ definiert.
- Datum des Chats: Als weitere Eigenschaft füge ich das Datum des Chats im Frontmatter hinzu.
- Footer mit Dataview-Statement: Am Ende der Datei füge ich einen Footer ein. Dieser enthält ein Dataview-Statement, das anzeigt, wo die Datei abgelegt ist.
- Löschen weiterer Zeichen im Titel: Ausser ‘/’ und ‘„ ‘ werden nun auch die Zeichen ‘\\’, ‘:’, ‘’’, ‘?’, ‘<’, ‘>’, und ‘|’ aus dem Titel gelöscht. Diese Zeichen können in Dateinamen Probleme machen.
Nachfolgend finden Sie meine angepasste Version des Skriptes. Der Aufruf bleibt gleich wie beim Originalskript:
import json import os import argparse from datetime import datetime # This project is open source and available under MIT by https://github.com/gavi/chatgpt-markdown # All my marked changes are still under MIT def get_conversation(node_id, mapping, list): node = mapping[node_id] if node.get('message') and 'content' in node['message'] and 'parts' in node['message']['content']: content_parts = node['message']['content']['parts'] parts_text = [] for part in content_parts: if isinstance(part, str): parts_text.append(part) elif isinstance(part, dict): # Handle the dictionary content here # For example, you might want to convert it to a string or extract specific information parts_text.append(str(part)) # Simple example: convert the dictionary to a string if parts_text: author_role = node['message']['author']['role'] if author_role == "user": author_role = "Me:" elif author_role == "assistant": author_role = "ChatGPT:" list.append(f"## {author_role}\n {''.join(parts_text)}") for child_id in node.get('children', []): get_conversation(child_id, mapping, list) def main(input_file, output_dir, use_date_folders): # Check if the directory exists if not os.path.isdir(output_dir): os.makedirs(output_dir) with open(input_file) as f: data = json.loads(f.read()) for item in data: # Änderung: Weitere Zeichen hinzugefügt, die in Dateinamen Probleme machen könnten. title = item["title"].replace("/","_").replace('"','_').replace(':','_').replace('?','_').replace('|','_').replace('\\','_').replace('<','_').replace('>','_') if title == "New chat": title = "New chat " + str(int(item["create_time"])) root_node_id = [node_id for node_id, node in item['mapping'].items() if node['parent'] is None][0] list = [] get_conversation(root_node_id, item['mapping'], list) date_folder = '' # Änderungen: # 1. date_iso definition aus dem if use_data_folder herausgeholt # 2. definition von fixed_text_start & fixed_text_end hinzugefügt date_iso = datetime.fromtimestamp(item["create_time"]).date().isoformat() fixed_text_start = [f"---\ntags:\n- AI-chat\n\ntalk-date: {date_iso}\n---"] fixed_text_end = ["---\n", "Ordner: `=this.file.folder`"] # Handle the date-based folder structure if use_date_folders: # Convert create_time to datetime and then to ISO format date_folder = f"{output_dir}/{date_iso}" if not os.path.isdir(date_folder): os.makedirs(date_folder) with open(f'{date_folder if use_date_folders else output_dir}/{title}.md', 'w') as outfile: # Änderung: # 1. Hinzufügen des Textes aus fixed_text_start am Anfang der Datei # 2. Hinzufügrn der Textes aus fixed_text_end am Ende der Datei for line in fixed_text_start: outfile.write(line + '\n') outfile.write('\n') # Optional: Add an extra newline for separation # Existing content writing logic outfile.write('\n'.join(list) + '\n') # Ensure there's a newline after the main content # Append fixed text at the end for line in fixed_text_end: outfile.write('\n' + line) # Ensure each end line starts on a new line if __name__ == '__main__': parser = argparse.ArgumentParser(description='Process conversation data.') parser.add_argument('input_file', help='JSON file containing conversations') parser.add_argument('output_dir', help='Directory to save output Markdown files') parser.add_argument('--use-date-folders', action='store_true', help='Store files under date-based folders') args = parser.parse_args() main(args.input_file, args.output_dir, args.use_date_folders)
Das ist alles zum Thema dieses Skriptes. Zusätzlich habe ich in Chrome die Erweiterung One-Click Export ChatGPT Chat Record As Markdown Text – ChatGPT Pro installiert, welche es ermöglicht, ein Markdown des aktiven Chats direkt aus der ChatGPT-Oberfläche zu generieren.
Ich möchte mich bei Gavi für die Bereitstellung seines Skriptes bedanken. Ich hoffe, dass dieser Artikel hilfreich für Sie ist. Ihr Feedback ist sehr willkommen – ich freue mich über jegliche Anmerkungen und Vorschläge, solange es kein SPAM ist. Teilen Sie Ihre Gedanken gerne in den Kommentaren mit.
Schreibe einen Kommentar