convert-to-csv / app.py
Threadbourne's picture
Update app.py
87edaf4 verified
Raw
History Blame Contribute Delete
3.3 kB
import re
import pandas as pd
import gradio as gr
def parse_transcript(text: str, user_marker: str, assistant_marker: str) -> pd.DataFrame:
pattern = re.compile(
rf"({re.escape(user_marker)}|{re.escape(assistant_marker)})\s*",
re.IGNORECASE
)
parts = pattern.split(text)
rows = []
turn = 0
for i in range(1, len(parts), 2):
marker = parts[i].strip().lower()
content = parts[i + 1].strip()
if not content:
continue
speaker = "user" if marker == user_marker.lower() else "gpt"
turn += 1
chars = len(content)
words = len(content.split())
tokens_est = int(round(words * 1.33))
rows.append({
"turn": turn,
"speaker": speaker,
"chars": chars,
"words": words,
"tokens_est": tokens_est
})
return pd.DataFrame(rows)
def convert(file_path, user_marker, assistant_marker, preview_rows):
try:
if not file_path:
return None, None, "Upload a .md or .txt transcript."
with open(file_path, "r", encoding="utf-8", errors="replace") as f:
text = f.read()
if user_marker.lower() not in text.lower() and assistant_marker.lower() not in text.lower():
return None, None, (
"No markers found in the file.\n"
"Update the marker strings to match your transcript format "
f"(e.g., '{user_marker}' / '{assistant_marker}')."
)
df = parse_transcript(text, user_marker=user_marker, assistant_marker=assistant_marker)
if df.empty:
return None, None, (
"Parsed 0 turns. Markers may not match the transcript format, "
"or content blocks may be empty."
)
pr = int(preview_rows)
pr = max(5, min(pr, 100))
preview = df.head(pr)
out_path = "converted_turns.csv"
df.to_csv(out_path, index=False)
msg = f"Parsed {len(df)} turns. Download the CSV below."
return preview, out_path, msg
except Exception as e:
return None, None, f"Conversion failed: {type(e).__name__}: {e}"
with gr.Blocks(title="Markdown → CSV Converter") as demo:
gr.Markdown(
"### Markdown → CSV Converter\n"
"Upload a transcript (.md/.txt) and convert it into a canonical turn-level CSV.\n\n"
"**Privacy:** Files are processed in-session and not stored."
)
# IMPORTANT: type="filepath" makes this stable on HF/Gradio
file = gr.File(label="Upload transcript", file_types=[".md", ".txt"], type="filepath")
with gr.Row():
user_marker = gr.Textbox(value="You said:", label="User marker")
assistant_marker = gr.Textbox(value="ChatGPT said:", label="Assistant marker")
preview_rows = gr.Slider(5, 100, value=20, step=1, label="Preview rows")
btn = gr.Button("Convert")
preview = gr.Dataframe(label="Preview", interactive=False, wrap=True)
out_file = gr.File(label="Download CSV")
status = gr.Textbox(label="Status", interactive=False)
btn.click(
fn=convert,
inputs=[file, user_marker, assistant_marker, preview_rows],
outputs=[preview, out_file, status],
)
demo.launch()