Created
November 15, 2023 23:18
-
-
Save moyix/fbed043f2609aa8f27f442a6d04291d8 to your computer and use it in GitHub Desktop.
Render LM-Studio Chat as HTML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import argparse | |
import html | |
import os | |
from datetime import datetime | |
def generate_html(json_file, html_file="chat.html", metadata=None, date=None): | |
with open(json_file, 'r') as file: | |
data = json.load(file) | |
html_content = "" | |
html_content += '<!DOCTYPE html>' | |
html_content += '<html><head><link rel="stylesheet" href="style.css">' | |
html_content += f'<title>LM-Studio Chat with {metadata["lastUsedModel"]["title"]}</title>' | |
html_content += '<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.2/markdown-it.min.js" integrity="sha512-ohlWmsCxOu0bph1om5eDL0jm/83eH09fvqLDhiEdiqfDeJbEvz4FSbeY0gLJSVJwQAp0laRhTXbUQG+ZUuifUQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>' | |
html_content += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">' | |
html_content += '<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>' | |
html_content += '</head><body>' | |
# Header with the model name and date | |
html_content += '<div class="header">' | |
html_content += '<h1>LM-Studio Chat</h1>' | |
html_content += f'<p><strong>Model</strong>: {metadata["lastUsedModel"]["title"]}</p>' | |
html_content += f'<p><strong>Date</strong>: {date.strftime("%B %d, %Y %H:%M:%S %p")}</p>' | |
html_content += '</div>' | |
# Chat messages | |
html_content += '<div class="chat">' | |
for message in data['messages']: | |
role_class = "user" if message['role'] == "user" else "assistant" | |
html_content += f'<h3 class="{role_class}">{message["role"].title()}</h3>' | |
html_content += f'<div class="{role_class}"><div class="content">{html.escape(message["content"])}</div></div>' | |
html_content += '</div>' | |
html_content += """ | |
<script> | |
document.addEventListener('DOMContentLoaded', (event) => { | |
const md = new markdownit(); | |
document.querySelectorAll(".content").forEach(block => { | |
block.innerHTML = md.render(block.textContent); | |
}); | |
document.querySelectorAll("pre code").forEach(block => { | |
hljs.highlightElement(block); | |
}); | |
}); | |
</script> | |
""" | |
html_content += '</body></html>' | |
with open(html_file, "w") as output_file: | |
output_file.write(html_content) | |
def main(): | |
parser = argparse.ArgumentParser(description='Generate HTML file from JSON file') | |
parser.add_argument('json_file', metavar='json_file', type=str, help='JSON file') | |
parser.add_argument('-O', '--output', metavar='output_file', type=str, help='output HTML file', default="chat.html") | |
args = parser.parse_args() | |
# Load the metadata file given the chat file | |
# If args.file is '/Users/moyix/.cache/lm-studio/chats/1700066024624.chat.json' | |
# metadata will be in '/Users/moyix/.cache/lm-studio/chats/1700066024624.metadata.chat.json' | |
metadata_file = args.json_file.replace(".chat.json", ".metadata.chat.json") | |
metadata = json.load(open(metadata_file, 'r')) | |
# Get the timestamp from the filename; it's in milliseconds since epoch | |
timestamp = int(os.path.basename(args.json_file).split(".")[0]) | |
date = datetime.fromtimestamp(timestamp / 1000.0) | |
generate_html(args.json_file, args.output, metadata, date) | |
if __name__ == "__main__": | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font-family: Arial, sans-serif; | |
background-color: #f4f4f4; | |
} | |
.chat, .header { | |
max-width: 600px; | |
margin: 20px auto; | |
border: 1px solid #ddd; | |
padding: 10px; | |
background: white; | |
} | |
.user, .assistant { | |
margin-bottom: 10px; | |
} | |
.user { | |
text-align: left; | |
} | |
.assistant { | |
text-align: left; | |
} | |
.content { | |
padding: 5px 10px; | |
border-radius: 5px; | |
background: #eee; | |
} | |
pre code { | |
background-color: #f4f4f4; | |
border: 1px solid #ccc; | |
display: block; | |
padding: 10px; | |
overflow-x: auto; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment