import os import json from pptx import Presentation import gradio as gr from openai import OpenAI import queue from datetime import datetime import time # Configuration for different API providers API_PROVIDERS = { "DeepSeek": "https://api.deepseek.com", "ChatGPT": "https://api.openai.com/v1", "Mistral": "https://api.mistral.ai/v1" } # List of supported languages LANGUAGES = { "Arabic": "ar", "Chinese (Simplified)": "zh", "Chinese (Traditional)": "zh-TW", "Dutch": "nl", "English": "en", "French": "fr", "German": "de", "Greek": "el", "Hindi": "hi", "Indonesian": "id", "Italian": "it", "Japanese": "ja", "Korean": "ko", "Polish": "pl", "Portuguese": "pt", "Russian": "ru", "Spanish": "es", "Swedish": "sv", "Thai": "th", "Turkish": "tr", "Vietnamese": "vi" } class TranslatorApp: def __init__(self): self.log_queue = queue.Queue() self.processing = False self.process_thread = None def load_config(self): try: with open('config.json', 'r') as f: return json.load(f) except: return {} def save_config(self, api_provider, api_key, source_lang, target_lang): config = { 'api_provider': api_provider, 'api_key': api_key, 'source_lang': source_lang, 'target_lang': target_lang } with open('config.json', 'w') as f: json.dump(config, f) def translate_text(self, text, source_lang, target_lang, api_provider, api_key): if not api_key: raise ValueError("API key is required") translation_methods = { "DeepSeek": self.translate_with_deepseek, "ChatGPT": self.translate_with_chatgpt, "Mistral": self.translate_with_mistral } translate_method = translation_methods.get(api_provider) if not translate_method: raise ValueError(f"Unsupported API provider: {api_provider}") return translate_method(text, source_lang, target_lang, api_key) def translate_with_deepseek(self, text, source_lang, target_lang, api_key): client = OpenAI(api_key=api_key, base_url=API_PROVIDERS["DeepSeek"]) response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": f"Translate from {source_lang} to {target_lang}:"}, {"role": "user", "content": text}, ] ) return response.choices[0].message.content def translate_with_chatgpt(self, text, source_lang, target_lang, api_key): client = OpenAI(api_key=api_key) response = client.chat.completions.create( model="gpt-4o", messages=[ {"role": "system", "content": f"Translate from {source_lang} to {target_lang}:"}, {"role": "user", "content": text}, ] ) return response.choices[0].message.content def translate_with_mistral(self, text, source_lang, target_lang, api_key): client = OpenAI(api_key=api_key, base_url=API_PROVIDERS["Mistral"]) response = client.chat.completions.create( model="mistral-tiny", messages=[ {"role": "system", "content": f"Translate from {source_lang} to {target_lang}:"}, {"role": "user", "content": text}, ] ) return response.choices[0].message.content def generate_review(self, translated_text, source_lang, api_provider, api_key): try: self.log("Generating review...") client = OpenAI(api_key=api_key, base_url=API_PROVIDERS[api_provider]) system_prompt = f"""Generate a comprehensive review in {source_lang} covering: 1. Main themes and key points 2. Translation quality assessment 3. Coherence and flow 4. Technical terminology accuracy 5. Recommendations for improvement""" model = { "DeepSeek": "deepseek-chat", "ChatGPT": "gpt-4o", "Mistral": "mistral-tiny" }.get(api_provider, "gpt-4o") response = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": translated_text}, ] ) return response.choices[0].message.content except Exception as e: self.log(f"Error generating review: {str(e)}") return "Failed to generate review." def log(self, message): self.log_queue.put(message) def process_pptx(self, file_path, source_lang, target_lang, api_provider, api_key, progress=gr.Progress()): try: prs = Presentation(file_path) total_slides = len(prs.slides) all_translated_text = "" start_time = time.time() for i, slide in enumerate(prs.slides): if not self.processing: self.log("Process interrupted by user") return self.log(f"Processing slide {i+1}/{total_slides}") for shape in slide.shapes: if hasattr(shape, "text") and shape.text.strip(): translated_text = self.translate_text(shape.text, source_lang, target_lang, api_provider, api_key) shape.text = translated_text all_translated_text += translated_text + "\n" # Update progress progress((i + 1) / total_slides, desc=f"Processing slide {i + 1}/{total_slides}") if self.processing: output_path = os.path.join(os.path.dirname(file_path), f"translated_{os.path.basename(file_path)}") prs.save(output_path) self.log(f"Saved translated file: {output_path}") # Generate and save review review = self.generate_review(all_translated_text, source_lang, api_provider, api_key) review_path = output_path.replace(".pptx", "_review.txt") with open(review_path, "w", encoding="utf-8") as f: f.write(review) self.log(f"Generated and saved review: {review_path}") return output_path, review_path except Exception as e: self.log(f"Error during processing: {str(e)}") raise e def run(self, file, api_provider, api_key, source_lang, target_lang): self.processing = True self.save_config(api_provider, api_key, source_lang, target_lang) try: output_path, review_path = self.process_pptx(file.name, source_lang, target_lang, api_provider, api_key) return [ f"File has been translated and saved as:\n{output_path}\nReview saved as:\n{review_path}", output_path, review_path ] except Exception as e: return [f"An error occurred during processing: {str(e)}", None, None] finally: self.processing = False # Custom CSS for styling custom_css = """ /* Style for the Translate button */ button { background-color: orange !important; color: white !important; border: none !important; } /* Style for the Upload PowerPoint file input */ .upload-area { border: 2px solid orange !important; padding: 10px !important; border-radius: 5px !important; } /* Adjust height of download file components */ .download-box { height: 70px !important; } """ def create_interface(): app = TranslatorApp() with gr.Blocks(css=custom_css) as interface: gr.Markdown("# BabelSlide by Heuristica") gr.Markdown("Translate PowerPoint presentations using various AI models.") with gr.Row(): file_input = gr.File(label="Upload PowerPoint File", elem_classes="upload-area") api_provider = gr.Dropdown(label="API Provider", choices=list(API_PROVIDERS.keys())) api_key = gr.Textbox(label="API Key", type="password") source_lang = gr.Dropdown(label="Source Language", choices=list(LANGUAGES.keys())) target_lang = gr.Dropdown(label="Target Language", choices=list(LANGUAGES.keys())) progress_bar = gr.Progress() output_text = gr.Textbox(label="Output", interactive=False) output_file = gr.File(label="Download Translated PowerPoint", elem_classes="download-box") output_review = gr.File(label="Download Review", elem_classes="download-box") run_button = gr.Button("Translate") run_button.click( fn=app.run, inputs=[file_input, api_provider, api_key, source_lang, target_lang], outputs=[output_text, output_file, output_review] ) return interface if __name__ == "__main__": interface = create_interface() interface.launch()