|
|
import gradio as gr |
|
|
import os |
|
|
from openai import OpenAI |
|
|
|
|
|
def load_system_prompt(): |
|
|
with open("system-prompt.md", "r") as f: |
|
|
return f.read() |
|
|
|
|
|
SYSTEM_PROMPT_CONTENT = load_system_prompt() |
|
|
|
|
|
|
|
|
README_CONTENT = """# Basic STT Transcript Cleanup Tool (Version 3) |
|
|
|
|
|
A foundational speech-to-text transcript remediation tool that provides purpose-agnostic text cleanup instructions. This is the **daily workhorse** for cleaning up raw speech-to-text transcripts that naturally contain undesirable material. |
|
|
|
|
|
## Purpose & Philosophy |
|
|
|
|
|
This tool implements **Version 3** of the Basic Speech-to-Text Cleanup prompt - a carefully crafted system prompt that provides sufficiently deterministic guidance without overstepping into actual content editing. The challenge in developing this prompt was ensuring it cleans up technical artifacts of speech-to-text conversion while preserving the authentic voice and intent of the original speaker. |
|
|
|
|
|
## Foundational Design |
|
|
|
|
|
This basic cleanup prompt serves as a **foundation layer** that can be combined with specialized text transformation prompts: |
|
|
|
|
|
- **Standalone Use**: Perfect for general transcript cleanup |
|
|
- **Modular Design**: Can be concatenated with purpose-specific prompts from extensive libraries |
|
|
- **Purpose-Agnostic**: Works across all content types and domains |
|
|
- **Extensible**: Hundreds of specialized transformation prompts can be layered on top |
|
|
|
|
|
## Features |
|
|
|
|
|
- **AI-Powered Cleanup**: Uses OpenAI's GPT models with a refined system prompt |
|
|
- **BYOK (Bring Your Own Key)**: Secure - uses your own OpenAI API key |
|
|
- **Copy to Clipboard**: Easy copying of cleaned text |
|
|
- **Re-run Capability**: Quickly re-process the same text |
|
|
- **System Prompt Viewer**: Transparent - see exactly how the AI processes your text |
|
|
- **Deterministic Processing**: Consistent, predictable cleanup results |
|
|
|
|
|
## How to Use |
|
|
|
|
|
1. **Enter API Key**: Provide your OpenAI API key (required for processing) |
|
|
2. **Paste Transcript**: Add your raw speech-to-text transcript |
|
|
3. **Process**: Click "Clean Up Transcript" to apply remediation |
|
|
4. **Copy Results**: Use the cleaned output or re-run if needed |
|
|
|
|
|
## What It Does |
|
|
|
|
|
The tool applies these **foundational improvements** to your transcripts: |
|
|
|
|
|
### Core Remediations |
|
|
- **Removes filler words** (like "um") |
|
|
- **Adds punctuation, sentence structure, and paragraph spacing** |
|
|
- **Fixes obvious STT hallucinations and mistranscriptions** (e.g., "McDonuts" → "McDonalds") |
|
|
- **Removes repetitive or run-on thoughts** that would not be helpful to readers |
|
|
- **Follows inferred instructions** to omit certain clauses (e.g., "wait .. scratch that from the note") |
|
|
|
|
|
### What It Preserves |
|
|
- **All important content** and meaning |
|
|
- **Original speaker's voice** and intent |
|
|
- **Factual accuracy** and details |
|
|
- **Natural flow** of conversation |
|
|
|
|
|
## Design Principles |
|
|
|
|
|
1. **Light Touch Editing**: Minimal intervention while maximizing clarity |
|
|
2. **Content Preservation**: Never removes or alters important information |
|
|
3. **Deterministic Guidance**: Consistent, predictable results |
|
|
4. **Purpose Agnostic**: Works across all content domains |
|
|
5. **Modular Foundation**: Ready for specialized prompt layering |
|
|
|
|
|
## Extended Ecosystem |
|
|
|
|
|
This basic cleanup prompt is part of a larger ecosystem: |
|
|
- **Hundreds of specialized prompts** available in shared libraries |
|
|
- **Domain-specific transformations** for various use cases |
|
|
- **Concatenation-ready design** for complex workflows |
|
|
- **Shared on Hugging Face** and other platforms |
|
|
|
|
|
## System Prompt |
|
|
|
|
|
The tool uses a carefully crafted system prompt (Version 3, September 2025) that balances cleanup effectiveness with content preservation. View the complete prompt using the "Show System Prompt" feature in the interface. |
|
|
""" |
|
|
|
|
|
def cleanup_transcript(text, api_key): |
|
|
"""Clean up STT transcript using OpenAI API""" |
|
|
if not text.strip(): |
|
|
return "Please provide text to clean up." |
|
|
|
|
|
if not api_key.strip(): |
|
|
return "Please provide your OpenAI API key." |
|
|
|
|
|
try: |
|
|
client = OpenAI(api_key=api_key) |
|
|
|
|
|
response = client.chat.completions.create( |
|
|
model="gpt-4o-mini", |
|
|
messages=[ |
|
|
{"role": "system", "content": SYSTEM_PROMPT_CONTENT}, |
|
|
{"role": "user", "content": text} |
|
|
], |
|
|
temperature=0.3, |
|
|
max_tokens=4000 |
|
|
) |
|
|
|
|
|
cleaned_text = response.choices[0].message.content |
|
|
return cleaned_text |
|
|
|
|
|
except Exception as e: |
|
|
return f"Error: {str(e)}" |
|
|
|
|
|
def copy_to_clipboard_js(): |
|
|
"""JavaScript function to copy text to clipboard""" |
|
|
return """ |
|
|
function copyToClipboard(text) { |
|
|
navigator.clipboard.writeText(text).then(function() { |
|
|
// You could add a toast notification here |
|
|
}); |
|
|
} |
|
|
""" |
|
|
|
|
|
|
|
|
with gr.Blocks( |
|
|
title="STT Transcript Cleanup Tool", |
|
|
theme=gr.themes.Soft(), |
|
|
css=""" |
|
|
.main-header { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
.attribution { |
|
|
text-align: center; |
|
|
margin-top: 2rem; |
|
|
padding: 1rem; |
|
|
background-color: #f8f9fa; |
|
|
border-radius: 8px; |
|
|
} |
|
|
""" |
|
|
) as demo: |
|
|
|
|
|
gr.HTML(""" |
|
|
<div class="main-header"> |
|
|
<h1>🎤 STT Transcript Cleanup Tool</h1> |
|
|
<p>Clean up speech-to-text transcripts by removing filler words, adding punctuation, and improving readability.</p> |
|
|
<p><strong>Note:</strong> This tool requires your own OpenAI API key (BYOK - Bring Your Own Key)</p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
with gr.Tabs(): |
|
|
with gr.TabItem("Cleanup Tool"): |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
api_key_input = gr.Textbox( |
|
|
label="OpenAI API Key", |
|
|
placeholder="sk-...", |
|
|
type="password", |
|
|
info="Your API key is not stored and only used for this session" |
|
|
) |
|
|
|
|
|
input_text = gr.Textbox( |
|
|
label="Raw STT Transcript", |
|
|
placeholder="Paste your speech-to-text transcript here...", |
|
|
lines=10, |
|
|
max_lines=20 |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
cleanup_btn = gr.Button("Clean Up Transcript", variant="primary") |
|
|
clear_btn = gr.Button("Clear", variant="secondary") |
|
|
|
|
|
with gr.Column(): |
|
|
output_text = gr.Textbox( |
|
|
label="Cleaned Transcript", |
|
|
lines=10, |
|
|
max_lines=20, |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
copy_btn = gr.Button("Copy to Clipboard", variant="secondary") |
|
|
rerun_btn = gr.Button("Run Again", variant="secondary") |
|
|
|
|
|
with gr.TabItem("System Prompt"): |
|
|
gr.Markdown("## Current System Prompt") |
|
|
gr.Markdown("This is the prompt used to instruct the AI on how to clean up your transcripts:") |
|
|
gr.Code(SYSTEM_PROMPT_CONTENT, language="markdown", label="system-prompt.md") |
|
|
|
|
|
with gr.TabItem("About"): |
|
|
gr.Markdown(README_CONTENT) |
|
|
|
|
|
|
|
|
cleanup_btn.click( |
|
|
fn=cleanup_transcript, |
|
|
inputs=[input_text, api_key_input], |
|
|
outputs=output_text |
|
|
) |
|
|
|
|
|
rerun_btn.click( |
|
|
fn=cleanup_transcript, |
|
|
inputs=[input_text, api_key_input], |
|
|
outputs=output_text |
|
|
) |
|
|
|
|
|
clear_btn.click( |
|
|
fn=lambda: ("", ""), |
|
|
outputs=[input_text, output_text] |
|
|
) |
|
|
|
|
|
|
|
|
copy_btn.click( |
|
|
fn=None, |
|
|
inputs=output_text, |
|
|
outputs=None, |
|
|
js="(text) => navigator.clipboard.writeText(text)" |
|
|
) |
|
|
|
|
|
|
|
|
gr.HTML(""" |
|
|
<div class="attribution"> |
|
|
<p><strong>Created by:</strong> <a href="https://danielrosehill.com" target="_blank">Daniel Rosehill</a></p> |
|
|
<p>This tool helps clean up speech-to-text transcripts by removing filler words, adding proper punctuation, |
|
|
and improving overall readability while preserving the original meaning and important details.</p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|