convoviz 0.1.7__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- convoviz/__init__.py +25 -5
- convoviz/__main__.py +6 -5
- convoviz/analysis/__init__.py +9 -0
- convoviz/analysis/graphs.py +98 -0
- convoviz/analysis/wordcloud.py +142 -0
- convoviz/assets/colormaps.txt +15 -16
- convoviz/cli.py +101 -94
- convoviz/config.py +88 -0
- convoviz/exceptions.py +47 -0
- convoviz/interactive.py +178 -0
- convoviz/io/__init__.py +21 -0
- convoviz/io/loaders.py +135 -0
- convoviz/io/writers.py +96 -0
- convoviz/models/__init__.py +26 -6
- convoviz/models/collection.py +107 -0
- convoviz/models/conversation.py +149 -0
- convoviz/models/message.py +77 -0
- convoviz/models/node.py +66 -0
- convoviz/pipeline.py +120 -0
- convoviz/renderers/__init__.py +10 -0
- convoviz/renderers/markdown.py +182 -0
- convoviz/renderers/yaml.py +42 -0
- convoviz/utils.py +68 -237
- {convoviz-0.1.7.dist-info → convoviz-0.2.1.dist-info}/METADATA +65 -39
- {convoviz-0.1.7.dist-info → convoviz-0.2.1.dist-info}/RECORD +27 -17
- convoviz-0.2.1.dist-info/WHEEL +4 -0
- convoviz-0.2.1.dist-info/entry_points.txt +3 -0
- convoviz/configuration.py +0 -125
- convoviz/data_analysis.py +0 -119
- convoviz/long_runs.py +0 -93
- convoviz/models/_conversation.py +0 -289
- convoviz/models/_conversation_set.py +0 -191
- convoviz/models/_message.py +0 -89
- convoviz/models/_node.py +0 -74
- convoviz-0.1.7.dist-info/LICENSE +0 -21
- convoviz-0.1.7.dist-info/WHEEL +0 -4
convoviz/utils.py
CHANGED
|
@@ -1,274 +1,105 @@
|
|
|
1
|
-
"""Utility functions for
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
1
|
+
"""Utility functions for convoviz."""
|
|
4
2
|
|
|
3
|
+
import re
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from re import compile as re_compile
|
|
7
|
-
from re import sub as re_sub
|
|
8
|
-
from typing import Any, Literal, TypedDict
|
|
9
|
-
from zipfile import ZipFile
|
|
10
|
-
|
|
11
|
-
DOWNLOADS = Path.home() / "Downloads"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def latest_zip() -> Path:
|
|
15
|
-
"""Path to the most recently created zip file in the Downloads folder."""
|
|
16
|
-
zip_files = list(DOWNLOADS.glob("*.zip"))
|
|
17
|
-
|
|
18
|
-
if not zip_files:
|
|
19
|
-
err_msg = f"No zip files found in {DOWNLOADS}"
|
|
20
|
-
raise FileNotFoundError(err_msg)
|
|
21
|
-
|
|
22
|
-
return max(zip_files, key=lambda x: x.stat().st_ctime)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def latest_bookmarklet_json() -> Path | None:
|
|
26
|
-
"""Path to the most recent JSON file in Downloads with 'bookmarklet' in the name."""
|
|
27
|
-
bkmrklet_files = [x for x in DOWNLOADS.glob("*.json") if "bookmarklet" in x.name]
|
|
28
|
-
|
|
29
|
-
if not bkmrklet_files:
|
|
30
|
-
return None
|
|
31
|
-
|
|
32
|
-
return max(bkmrklet_files, key=lambda x: x.stat().st_ctime)
|
|
33
5
|
|
|
34
6
|
|
|
35
7
|
def sanitize(filename: str) -> str:
|
|
36
|
-
"""
|
|
37
|
-
anti_pattern = re_compile(r'[<>:"/\\|?*\n\r\t\f\v]+')
|
|
38
|
-
|
|
39
|
-
return anti_pattern.sub("_", filename.strip()) or "untitled"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def close_code_blocks(text: str) -> str:
|
|
43
|
-
"""Ensure that all code blocks are closed."""
|
|
44
|
-
# A code block can be opened with triple backticks, possibly followed by a lang name
|
|
45
|
-
# It can only be closed however with triple backticks, with nothing else on the line
|
|
46
|
-
|
|
47
|
-
open_code_block = False
|
|
48
|
-
|
|
49
|
-
lines = text.split("\n")
|
|
50
|
-
|
|
51
|
-
for line in lines:
|
|
52
|
-
if line.startswith("```") and not open_code_block:
|
|
53
|
-
open_code_block = True
|
|
54
|
-
continue
|
|
55
|
-
|
|
56
|
-
if line == "```" and open_code_block:
|
|
57
|
-
open_code_block = False
|
|
58
|
-
|
|
59
|
-
if open_code_block:
|
|
60
|
-
text += "\n```"
|
|
61
|
-
|
|
62
|
-
return text
|
|
8
|
+
"""Sanitize a string to be safe for use as a filename.
|
|
63
9
|
|
|
10
|
+
Replaces invalid characters with underscores.
|
|
64
11
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
text = re_sub(r"\\\[", "$$", text)
|
|
68
|
-
text = re_sub(r"\\\]", "$$", text)
|
|
69
|
-
text = re_sub(r"\\\(", "$", text)
|
|
12
|
+
Args:
|
|
13
|
+
filename: The string to sanitize
|
|
70
14
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def stem(path: Path | str) -> str:
|
|
75
|
-
"""Return the `stem` of the given path."""
|
|
76
|
-
return Path(path).stem
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def root_dir() -> Path:
|
|
80
|
-
"""Path to the root directory of the project.
|
|
81
|
-
|
|
82
|
-
might change when refactoring, currently it's `convoviz/`
|
|
15
|
+
Returns:
|
|
16
|
+
A filename-safe string, or "untitled" if empty
|
|
83
17
|
"""
|
|
84
|
-
|
|
18
|
+
pattern = re.compile(r'[<>:"/\\|?*\n\r\t\f\v]+')
|
|
19
|
+
result = pattern.sub("_", filename.strip())
|
|
20
|
+
return result or "untitled"
|
|
85
21
|
|
|
86
22
|
|
|
87
|
-
def
|
|
88
|
-
"""
|
|
89
|
-
fonts_path = root_dir() / "assets" / "fonts"
|
|
90
|
-
return [font.stem for font in fonts_path.iterdir()]
|
|
23
|
+
def validate_header(text: str) -> bool:
|
|
24
|
+
"""Check if text is a valid markdown header.
|
|
91
25
|
|
|
26
|
+
Args:
|
|
27
|
+
text: The text to validate
|
|
92
28
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`font_name` should be the stem of the font file, without the extension
|
|
29
|
+
Returns:
|
|
30
|
+
True if it's a valid header (1-6 # followed by space and content)
|
|
97
31
|
"""
|
|
98
|
-
return root_dir() / "assets" / "fonts" / f"{font_name}.ttf"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def default_font_path() -> Path:
|
|
102
|
-
"""Path to the default font in the `assets/fonts` folder."""
|
|
103
|
-
return font_path("RobotoSlab-Thin")
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def colormaps() -> list[str]:
|
|
107
|
-
"""List of colormaps in the `assets/colormaps.txt` file."""
|
|
108
|
-
colormaps_path = root_dir() / "assets" / "colormaps.txt"
|
|
109
|
-
with colormaps_path.open(encoding="utf-8") as file:
|
|
110
|
-
return file.read().splitlines()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def validate_header(text: str) -> bool:
|
|
114
|
-
"""Return True if the given text is a valid markdown header."""
|
|
115
32
|
max_header_level = 6
|
|
116
|
-
|
|
117
|
-
1 <= text.count("#") <= max_header_level
|
|
118
|
-
and text.startswith("#")
|
|
119
|
-
and text[len(text.split()[0])] == " "
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def validate_zip(filepath: str | Path) -> bool:
|
|
124
|
-
"""Return True if the given path is a zip file with a `conversations.json` file."""
|
|
125
|
-
filepath = Path(filepath)
|
|
126
|
-
if not filepath.is_file() or filepath.suffix != ".zip":
|
|
33
|
+
if not text.startswith("#"):
|
|
127
34
|
return False
|
|
128
|
-
with ZipFile(filepath) as zip_ref:
|
|
129
|
-
if "conversations.json" in zip_ref.namelist():
|
|
130
|
-
return True
|
|
131
|
-
return False
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def get_archive(filepath: Path | str) -> Path:
|
|
135
|
-
"""Extract the zip and return the path to the extracted folder."""
|
|
136
|
-
filepath = Path(filepath)
|
|
137
|
-
folder = filepath.with_suffix("")
|
|
138
|
-
|
|
139
|
-
with ZipFile(filepath) as file:
|
|
140
|
-
file.extractall(folder)
|
|
141
|
-
|
|
142
|
-
return folder
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def code_block(text: str, lang: str = "python") -> str:
|
|
146
|
-
"""Wrap the given string in a code block."""
|
|
147
|
-
return f"```{lang}\n{text}\n```"
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
# default configs
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
class AuthorHeaders(TypedDict):
|
|
154
|
-
"""Type hint for the author headers configs."""
|
|
155
|
-
|
|
156
|
-
system: str
|
|
157
|
-
user: str
|
|
158
|
-
assistant: str
|
|
159
|
-
tool: str
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
class MessageConfigs(TypedDict):
|
|
163
|
-
"""Type hint for the message configs."""
|
|
164
|
-
|
|
165
|
-
author_headers: AuthorHeaders
|
|
166
35
|
|
|
36
|
+
parts = text.split(maxsplit=1)
|
|
37
|
+
if len(parts) < 2:
|
|
38
|
+
return False
|
|
167
39
|
|
|
168
|
-
|
|
169
|
-
"
|
|
170
|
-
"system": "### System",
|
|
171
|
-
"user": "# Me",
|
|
172
|
-
"assistant": "# ChatGPT",
|
|
173
|
-
"tool": "### Tool output",
|
|
174
|
-
},
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
class MarkdownConfigs(TypedDict):
|
|
179
|
-
"""Type hint for the markdown configs."""
|
|
180
|
-
|
|
181
|
-
latex_delimiters: Literal["default", "dollars"]
|
|
182
|
-
|
|
40
|
+
hashes = parts[0]
|
|
41
|
+
return hashes == "#" * len(hashes) and 1 <= len(hashes) <= max_header_level
|
|
183
42
|
|
|
184
|
-
class YAMLConfigs(TypedDict):
|
|
185
|
-
"""Type hint for the yaml configs."""
|
|
186
43
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
chat_link: bool
|
|
190
|
-
create_time: bool
|
|
191
|
-
update_time: bool
|
|
192
|
-
model: bool
|
|
193
|
-
used_plugins: bool
|
|
194
|
-
message_count: bool
|
|
195
|
-
content_types: bool
|
|
196
|
-
custom_instructions: bool
|
|
44
|
+
def root_dir() -> Path:
|
|
45
|
+
"""Get the path to the convoviz package directory.
|
|
197
46
|
|
|
47
|
+
Returns:
|
|
48
|
+
Path to the package root
|
|
49
|
+
"""
|
|
50
|
+
return Path(__file__).parent
|
|
198
51
|
|
|
199
|
-
class ConversationConfigs(TypedDict):
|
|
200
|
-
"""Type hint for the conversation configs."""
|
|
201
52
|
|
|
202
|
-
|
|
203
|
-
|
|
53
|
+
def font_dir() -> Path:
|
|
54
|
+
"""Get the path to the fonts directory.
|
|
204
55
|
|
|
56
|
+
Returns:
|
|
57
|
+
Path to the assets/fonts directory
|
|
58
|
+
"""
|
|
59
|
+
return root_dir() / "assets" / "fonts"
|
|
205
60
|
|
|
206
|
-
DEFAULT_CONVERSATION_CONFIGS: ConversationConfigs = {
|
|
207
|
-
"markdown": {"latex_delimiters": "default"},
|
|
208
|
-
"yaml": {
|
|
209
|
-
"title": True,
|
|
210
|
-
"tags": False,
|
|
211
|
-
"chat_link": True,
|
|
212
|
-
"create_time": True,
|
|
213
|
-
"update_time": True,
|
|
214
|
-
"model": True,
|
|
215
|
-
"used_plugins": True,
|
|
216
|
-
"message_count": True,
|
|
217
|
-
"content_types": True,
|
|
218
|
-
"custom_instructions": True,
|
|
219
|
-
},
|
|
220
|
-
}
|
|
221
61
|
|
|
62
|
+
def font_names() -> list[str]:
|
|
63
|
+
"""Get available font names.
|
|
222
64
|
|
|
223
|
-
|
|
224
|
-
|
|
65
|
+
Returns:
|
|
66
|
+
List of font names (without .ttf extension)
|
|
67
|
+
"""
|
|
68
|
+
fonts_path = font_dir()
|
|
69
|
+
if not fonts_path.exists():
|
|
70
|
+
return []
|
|
71
|
+
return [font.stem for font in fonts_path.glob("*.ttf")]
|
|
225
72
|
|
|
226
73
|
|
|
227
|
-
|
|
228
|
-
"""
|
|
74
|
+
def font_path(font_name: str) -> Path:
|
|
75
|
+
"""Get the path to a font file.
|
|
229
76
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
custom_stopwords: str
|
|
233
|
-
background_color: str | None
|
|
234
|
-
mode: Literal["RGB", "RGBA"]
|
|
235
|
-
include_numbers: bool
|
|
236
|
-
width: int
|
|
237
|
-
height: int
|
|
77
|
+
Args:
|
|
78
|
+
font_name: Name of the font (without extension)
|
|
238
79
|
|
|
80
|
+
Returns:
|
|
81
|
+
Path to the font file
|
|
82
|
+
"""
|
|
83
|
+
return font_dir() / f"{font_name}.ttf"
|
|
239
84
|
|
|
240
|
-
DEFAULT_WORDCLOUD_CONFIGS: WordCloudKwargs = {
|
|
241
|
-
"font_path": str(default_font_path()),
|
|
242
|
-
"colormap": "prism",
|
|
243
|
-
"custom_stopwords": "use, file, ",
|
|
244
|
-
"background_color": None,
|
|
245
|
-
"mode": "RGBA",
|
|
246
|
-
"include_numbers": False,
|
|
247
|
-
"width": 1000,
|
|
248
|
-
"height": 1000,
|
|
249
|
-
}
|
|
250
85
|
|
|
86
|
+
def default_font_path() -> Path:
|
|
87
|
+
"""Get the path to the default font.
|
|
251
88
|
|
|
252
|
-
|
|
253
|
-
|
|
89
|
+
Returns:
|
|
90
|
+
Path to RobotoSlab-Thin.ttf
|
|
91
|
+
"""
|
|
92
|
+
return font_path("RobotoSlab-Thin")
|
|
254
93
|
|
|
255
|
-
zip_filepath: str
|
|
256
|
-
output_folder: str
|
|
257
|
-
message: MessageConfigs
|
|
258
|
-
conversation: ConversationConfigs
|
|
259
|
-
wordcloud: WordCloudKwargs
|
|
260
|
-
graph: GraphKwargs
|
|
261
|
-
node: dict[str, Any]
|
|
262
|
-
conversation_set: dict[str, Any]
|
|
263
94
|
|
|
95
|
+
def colormaps() -> list[str]:
|
|
96
|
+
"""Get available colormap names.
|
|
264
97
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
"
|
|
268
|
-
"
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
"conversation_set": {},
|
|
274
|
-
}
|
|
98
|
+
Returns:
|
|
99
|
+
List of colormap names from colormaps.txt
|
|
100
|
+
"""
|
|
101
|
+
colormaps_path = root_dir() / "assets" / "colormaps.txt"
|
|
102
|
+
if not colormaps_path.exists():
|
|
103
|
+
return []
|
|
104
|
+
with colormaps_path.open(encoding="utf-8") as f:
|
|
105
|
+
return f.read().splitlines()
|
|
@@ -1,26 +1,46 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: convoviz
|
|
3
|
-
Version: 0.1
|
|
4
|
-
Summary: Get analytics and visualizations on your ChatGPT data
|
|
5
|
-
|
|
6
|
-
License: MIT
|
|
7
|
-
Keywords: markdown,advanced-data-analysis,json,zip,openai,chatgpt,bookmarklet,obsidian-md,code-interpreter
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Get analytics and visualizations on your ChatGPT data!
|
|
5
|
+
Keywords: markdown,chatgpt,openai,visualization,analytics,json,export,data-analysis,obsidian
|
|
8
6
|
Author: Mohamed Cheikh Sidiya
|
|
9
|
-
Author-email: mohamedcheikhsidiya77@gmail.com
|
|
10
|
-
|
|
7
|
+
Author-email: Mohamed Cheikh Sidiya <mohamedcheikhsidiya77@gmail.com>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2023 Mohamed Cheikh Sidiya
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
11
29
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
30
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
31
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Requires-Dist: matplotlib
|
|
18
|
-
Requires-Dist: nltk
|
|
19
|
-
Requires-Dist: orjson
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
32
|
+
Requires-Dist: matplotlib>=3.9.4
|
|
33
|
+
Requires-Dist: nltk>=3.9.2
|
|
34
|
+
Requires-Dist: orjson>=3.11.5
|
|
35
|
+
Requires-Dist: pillow>=11.3.0
|
|
36
|
+
Requires-Dist: pydantic>=2.12.5
|
|
37
|
+
Requires-Dist: pydantic-settings>=2.7.0
|
|
38
|
+
Requires-Dist: questionary>=2.1.1
|
|
39
|
+
Requires-Dist: rich>=14.2.0
|
|
40
|
+
Requires-Dist: tqdm>=4.67.1
|
|
41
|
+
Requires-Dist: typer>=0.21.0
|
|
42
|
+
Requires-Dist: wordcloud>=1.9.5
|
|
43
|
+
Requires-Python: >=3.12
|
|
24
44
|
Project-URL: Repository, https://github.com/mohamed-chs/chatgpt-history-export-to-md
|
|
25
45
|
Description-Content-Type: text/markdown
|
|
26
46
|
|
|
@@ -51,41 +71,54 @@ See examples [here](demo).
|
|
|
51
71
|
|
|
52
72
|
### 2. Install the tool 🛠
|
|
53
73
|
|
|
54
|
-
|
|
74
|
+
Try it without installing using uv ([astral-sh/uv](https://github.com/astral-sh/uv)):
|
|
55
75
|
|
|
56
76
|
```bash
|
|
57
|
-
|
|
77
|
+
uvx convoviz
|
|
58
78
|
```
|
|
59
79
|
|
|
60
|
-
|
|
80
|
+
You can install it with uv (Recommended):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
uv tool install convoviz
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
or pipx:
|
|
87
|
+
```bash
|
|
88
|
+
pipx install convoviz
|
|
89
|
+
```
|
|
61
90
|
|
|
62
91
|
### 3. Run the Script 🏃♂️
|
|
63
92
|
|
|
64
|
-
|
|
93
|
+
Simply run the command and follow the prompts:
|
|
65
94
|
|
|
66
95
|
```bash
|
|
67
|
-
|
|
96
|
+
convoviz
|
|
68
97
|
```
|
|
69
98
|
|
|
70
|
-
|
|
99
|
+
#### Command Line Arguments
|
|
71
100
|
|
|
72
|
-
|
|
101
|
+
You can provide arguments directly to skip the prompts:
|
|
73
102
|
|
|
74
|
-
|
|
103
|
+
```bash
|
|
104
|
+
convoviz --zip path/to/your/export.zip --output path/to/output/folder
|
|
105
|
+
```
|
|
75
106
|
|
|
76
|
-
|
|
107
|
+
For more options, run:
|
|
77
108
|
|
|
78
|
-
|
|
109
|
+
```bash
|
|
110
|
+
convoviz --help
|
|
111
|
+
```
|
|
79
112
|
|
|
80
|
-
###
|
|
113
|
+
### 4. Check the Output 🎉
|
|
81
114
|
|
|
82
|
-
|
|
115
|
+
And that's it! After running the script, head over to the output folder to see your nice word clouds, graphs, and neatly formatted Markdown files. Enjoy !
|
|
83
116
|
|
|
84
117
|
## Share Your Feedback! 💌
|
|
85
118
|
|
|
86
119
|
I hope you find this tool useful. I'm continuously looking to improve on this, but I need your help for that.
|
|
87
120
|
|
|
88
|
-
Whether you're a tech wizard or you're new to all this
|
|
121
|
+
Whether you're a tech wizard or you're new to all this, I'd love to hear about your journey with the tool. Found a quirk? Have a suggestion? Or just want to send some good vibes? I'm all ears!
|
|
89
122
|
|
|
90
123
|
**Here's how you can share your thoughts:**
|
|
91
124
|
|
|
@@ -95,12 +128,8 @@ Whether you're a tech wizard or you're new to all this (especially if you're new
|
|
|
95
128
|
|
|
96
129
|
And if you've had a great experience, consider giving the project a star ⭐. It keeps me motivated and helps others discover it!
|
|
97
130
|
|
|
98
|
-
Thank you for being awesome! 🌟
|
|
99
|
-
|
|
100
131
|
## Notes
|
|
101
132
|
|
|
102
|
-
This project requires Python 3.8.7 or higher if on Windows. See [known issue](https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1023#issue-534396318)
|
|
103
|
-
|
|
104
133
|
This is just a small thing I coded to help me see my convos in beautiful markdown, in [Obsidian](https://obsidian.md/) (my go-to note-taking app).
|
|
105
134
|
|
|
106
135
|
I wasn't a fan of the clunky, and sometimes paid, browser extensions.
|
|
@@ -109,7 +138,4 @@ It was also a great opportunity to learn more about Python and type annotations.
|
|
|
109
138
|
|
|
110
139
|
It also works as package, so you can **import** it in your own projects, and use the models and functions as you wish. I need to add more documentation for that tho. Feel free to reach out if you need help.
|
|
111
140
|
|
|
112
|
-
I'm working on automating it to add new conversations and updating old ones. Had some luck with a JavaScript bookmarklet, still ironing it out tho.
|
|
113
|
-
|
|
114
|
-
> for an older version with zero dependencies, see https://github.com/mohamed-chs/chatgpt-history-export-to-md/tree/fe13a701fe8653c9f946b1e12979ce3bfe7104b8.
|
|
115
|
-
|
|
141
|
+
I'm working on automating it to add new conversations and updating old ones. Had some luck with a JavaScript bookmarklet, still ironing it out tho.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
convoviz/__init__.py,sha256=
|
|
2
|
-
convoviz/__main__.py,sha256=
|
|
3
|
-
convoviz/
|
|
1
|
+
convoviz/__init__.py,sha256=bQLCHO2U9EyMTGqNgsYiCtBQKTKNj4iIM3-TwIkrnRY,612
|
|
2
|
+
convoviz/__main__.py,sha256=1qiGW13_SgL7wJi8iioIN-AAHGkNGnEl5q_RcPUrI0s,143
|
|
3
|
+
convoviz/analysis/__init__.py,sha256=FxgH5JJpyypiLJpMQn_HlM51jnb8lQdP63_C_W3Dlx4,241
|
|
4
|
+
convoviz/analysis/graphs.py,sha256=hMJmNX4ejFl_yl_kldA91EACpQjfkq-7sTiVnrBQx_w,2653
|
|
5
|
+
convoviz/analysis/wordcloud.py,sha256=ZucezsDlgaOgYpjm_S7wKYmk7crD-MM83s4eVex-Bl8,4034
|
|
6
|
+
convoviz/assets/colormaps.txt,sha256=59TSGz428AxY14AEvymAH2IJ2RT9Mlp7Sy0N12NEdXQ,108
|
|
4
7
|
convoviz/assets/fonts/AmaticSC-Regular.ttf,sha256=83clh7a3urnTLud0_yZofuIb6BdyC2LMI9jhE6G2LvU,142696
|
|
5
8
|
convoviz/assets/fonts/ArchitectsDaughter-Regular.ttf,sha256=fnrj5_N_SlY2Lj3Ehqz5aKECPZVJlJAflgsOU94_qIM,37756
|
|
6
9
|
convoviz/assets/fonts/BebasNeue-Regular.ttf,sha256=gw6hhqz_wjFu0aTkIxkka6O0awTjOiEQeSSb-QEZPwQ,57676
|
|
@@ -32,18 +35,25 @@ convoviz/assets/fonts/YsabeauOffice-Regular.ttf,sha256=RnW2erC5p6s2YxvWmwa019hYT
|
|
|
32
35
|
convoviz/assets/fonts/YsabeauSC-Regular.ttf,sha256=G4lkq34KKqZOaoomtxFz_KlwVmxg56UbFXFnWgijkDM,116980
|
|
33
36
|
convoviz/assets/fonts/YsabeauSC-Thin.ttf,sha256=hZGOZNTRrxbiUPE2VDeLbtnaRwkMOBaVQbq7Fwx-34c,116932
|
|
34
37
|
convoviz/assets/fonts/Zeyada-Regular.ttf,sha256=fKhkrp9VHt_3Aw8JfkfkPeC2j3CilLWuPUudzBeawPQ,57468
|
|
35
|
-
convoviz/cli.py,sha256=
|
|
36
|
-
convoviz/
|
|
37
|
-
convoviz/
|
|
38
|
-
convoviz/
|
|
39
|
-
convoviz/
|
|
40
|
-
convoviz/
|
|
41
|
-
convoviz/
|
|
42
|
-
convoviz/models/
|
|
43
|
-
convoviz/models/
|
|
38
|
+
convoviz/cli.py,sha256=JqNk2rV1rjver8A7tWtjPeLaw1nYOze4fjghY6ohpCA,3371
|
|
39
|
+
convoviz/config.py,sha256=QQ0KAyiacKLMCM1asFrNr6JQH1rVxyhGwNjSFqt_gSc,2445
|
|
40
|
+
convoviz/exceptions.py,sha256=bQpIKls48uOQpagEJAxpXf5LF7QoagRRfbD0MjWC7Ak,1476
|
|
41
|
+
convoviz/interactive.py,sha256=XFSjBW-8EhEAC6UkGdcML10MIA5ZfToM24A98pWpryI,5500
|
|
42
|
+
convoviz/io/__init__.py,sha256=y70TYypJ36_kaEA04E2wa1EDaKQVjprKItoKR6MMs4M,471
|
|
43
|
+
convoviz/io/loaders.py,sha256=Bwat6pmRExuGfBbpWoVqZXcGbWoTN9qaTEcJYtc505M,3653
|
|
44
|
+
convoviz/io/writers.py,sha256=aLPmnLpbcho65Wy4ePzP6xoGWYVV0_owxbxv67ojBpA,2880
|
|
45
|
+
convoviz/models/__init__.py,sha256=R78W7FvRLhPx36HJmIh1dPv2mNQGOF8X0fGMTpEagkA,628
|
|
46
|
+
convoviz/models/collection.py,sha256=aUQq0dgFXCEEqPCBl4l9A99MZdWWunSO2b79-VyR2qY,4033
|
|
47
|
+
convoviz/models/conversation.py,sha256=G0wxrcIhY5JzWeIOkGtkELSzc7J32W2wxJVbNOord58,5145
|
|
48
|
+
convoviz/models/message.py,sha256=Jc92vXowU2qzMaEH2Sa96nx65sGWsZpF5rj8BXwjK5E,2090
|
|
49
|
+
convoviz/models/node.py,sha256=1vBAtKVscYsUBDnKAOyLxuZaK9KoVF1dFXiKXRHxUnY,1946
|
|
50
|
+
convoviz/pipeline.py,sha256=KRSE-aVYppO-2YhvIzSQqcMfnJPxN-4ggnJ0h2xj2EA,4133
|
|
44
51
|
convoviz/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
-
convoviz/
|
|
46
|
-
convoviz
|
|
47
|
-
convoviz
|
|
48
|
-
convoviz
|
|
49
|
-
convoviz-0.1.
|
|
52
|
+
convoviz/renderers/__init__.py,sha256=IQgwD9NqtUgbS9zwyPBNZbBIZcFrbZ9C7WMAV-X3Xdg,261
|
|
53
|
+
convoviz/renderers/markdown.py,sha256=4DLXPiZe_56cUNf1xGbcuw_qHq03CUMLCEdsIOhjq_Y,4836
|
|
54
|
+
convoviz/renderers/yaml.py,sha256=FqO2zToXp96gQRDrjALgchESWLg49LxuehXP59SEFeU,1522
|
|
55
|
+
convoviz/utils.py,sha256=6LqoTEHgZg7ICkepxkNqr44LKgztiS37O6RkMsHHNbw,2363
|
|
56
|
+
convoviz-0.2.1.dist-info/WHEEL,sha256=KSLUh82mDPEPk0Bx0ScXlWL64bc8KmzIPNcpQZFV-6E,79
|
|
57
|
+
convoviz-0.2.1.dist-info/entry_points.txt,sha256=HYsmsw5vt36yYHB05uVU48AK2WLkcwshly7m7KKuZMY,54
|
|
58
|
+
convoviz-0.2.1.dist-info/METADATA,sha256=YKlday7GkHWEuc3C6IC5tZpLoPgXhhk-THkcExjXSqQ,5894
|
|
59
|
+
convoviz-0.2.1.dist-info/RECORD,,
|