promptlab / utils.py
auroprashad's picture
Upload folder using huggingface_hub
bed2998 verified
Raw
History Blame Contribute Delete
3.78 kB
import difflib
import html
import tempfile
import json
import os
def generate_html_diff(old_text: str, new_text: str) -> str:
"""
Compares original prompt with optimized prompt.
Returns a beautifully styled HTML block mimicking GitHub's code diff view.
"""
if not old_text.strip():
return "<p style='color: #64748b;'>Enter a prompt to compare changes.</p>"
old_lines = old_text.splitlines()
new_lines = new_text.splitlines()
diff = list(difflib.ndiff(old_lines, new_lines))
html_out = [
'<div style="font-family: \'Fira Code\', Consolas, Monaco, monospace; font-size: 13px; line-height: 1.6; '
'background-color: #0b0f19; border: 1px solid #1e293b; padding: 16px; border-radius: 8px; overflow-x: auto; color: #cbd5e1;">'
]
for idx, line in enumerate(diff):
if line.startswith('+ '):
content = html.escape(line[2:])
html_out.append(
f'<div style="background-color: rgba(16, 185, 129, 0.1); color: #34d399; padding: 2px 8px; '
f'border-left: 3px solid #10b981; white-space: pre-wrap; margin: 1px 0;"><span style="user-select: none; color: #059669; margin-right: 12px;">+</span>{content}</div>'
)
elif line.startswith('- '):
content = html.escape(line[2:])
html_out.append(
f'<div style="background-color: rgba(239, 68, 68, 0.1); color: #f87171; padding: 2px 8px; '
f'border-left: 3px solid #ef4444; white-space: pre-wrap; margin: 1px 0; text-decoration: line-through;"><span style="user-select: none; color: #dc2626; margin-right: 12px;">-</span>{content}</div>'
)
elif line.startswith(' '):
content = html.escape(line[2:])
html_out.append(
f'<div style="padding: 2px 8px; white-space: pre-wrap; margin: 1px 0; color: #94a3b8;"><span style="user-select: none; color: #475569; margin-right: 12px;"> </span>{content}</div>'
)
# We ignore '? ' line details to keep clean visual aesthetics
html_out.append('</div>')
return "\n".join(html_out)
def estimate_tokens(text: str) -> dict:
"""
Returns an estimation dictionary containing word count, character count,
and estimated LLM tokens (approx 1 token per 4 characters).
"""
chars = len(text)
words = len(text.split())
tokens = max(0, round(chars / 4.0))
return {
"characters": chars,
"words": words,
"tokens": tokens
}
import uuid
def create_export_file(prompt_text: str, format_type: str) -> str:
"""
Saves the prompt into a temporary file of the selected format
and returns the file path for Gradio download.
"""
# Create temporary files under a unique name to ensure multi-user safety
temp_dir = tempfile.gettempdir()
unique_id = uuid.uuid4().hex[:8]
if format_type.lower() == "markdown":
file_path = os.path.join(temp_dir, f"promptlab_export_{unique_id}.md")
with open(file_path, "w", encoding="utf-8") as f:
f.write(f"# Optimized Prompt\n\nGenerated by PromptLab\n\n```markdown\n{prompt_text}\n```\n")
elif format_type.lower() == "json":
file_path = os.path.join(temp_dir, f"promptlab_export_{unique_id}.json")
with open(file_path, "w", encoding="utf-8") as f:
json.dump({
"source": "PromptLab",
"optimized_prompt": prompt_text
}, f, indent=2)
else: # TXT default
file_path = os.path.join(temp_dir, f"promptlab_export_{unique_id}.txt")
with open(file_path, "w", encoding="utf-8") as f:
f.write(prompt_text)
return file_path