Spaces:
Sleeping
Sleeping
| 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() |