diff --git a/main.py b/main.py index 8f91f12..7cc4b89 100644 --- a/main.py +++ b/main.py @@ -108,21 +108,42 @@ async def transcreve_audios(request: Request): "source": audio_source }) + # Carregar configurações de formatação + output_mode = get_config("output_mode", "both") + summary_header = get_config("summary_header", "🤖 *Resumo do áudio:*") + transcription_header = get_config("transcription_header", "🔊 *Transcrição do áudio:*") + character_limit = int(get_config("character_limit", "500")) + # Transcrever áudio storage.add_log("INFO", "Iniciando transcrição") transcription_text, _ = await transcribe_audio(audio_source) - # Resumir se necessário - summary_text = await summarize_text_if_needed(transcription_text) + # Determinar se precisa de resumo baseado no modo de saída + summary_text = None + if output_mode in ["both", "summary_only"] or ( + output_mode == "smart" and len(transcription_text) > character_limit + ): + summary_text = await summarize_text_if_needed(transcription_text) + + # Construir mensagem baseada no modo de saída + message_parts = [] - # Formatar mensagem - summary_message = ( - f"🤖 *Resumo do áudio:*\n\n" - f"{summary_text}\n\n" - f"🔊 *Transcrição do áudio:*\n\n" - f"{transcription_text}\n\n" - f"{dynamic_settings['BUSINESS_MESSAGE']}" - ) + if output_mode == "smart": + if len(transcription_text) > character_limit: + message_parts.append(f"{summary_header}\n\n{summary_text}") + else: + message_parts.append(f"{transcription_header}\n\n{transcription_text}") + else: + if output_mode in ["both", "summary_only"] and summary_text: + message_parts.append(f"{summary_header}\n\n{summary_text}") + if output_mode in ["both", "transcription_only"]: + message_parts.append(f"{transcription_header}\n\n{transcription_text}") + + # Adicionar mensagem de negócio + message_parts.append(dynamic_settings['BUSINESS_MESSAGE']) + + # Juntar todas as partes da mensagem + summary_message = "\n\n".join(message_parts) # Enviar resposta await send_message_to_whatsapp( diff --git a/manager.py b/manager.py index 7368179..6617174 100644 --- a/manager.py +++ b/manager.py @@ -342,131 +342,251 @@ def manage_blocks(): else: st.info("Nenhum usuário bloqueado.") +# manager.py - Adicionar na seção de configurações +def message_settings_section(): + st.subheader("📝 Configurações de Mensagem") + + # Carregar configurações atuais + message_settings = storage.get_message_settings() + + # Headers personalizados + col1, col2 = st.columns(2) + with col1: + summary_header = st.text_input( + "Cabeçalho do Resumo", + value=message_settings["summary_header"], + help="Formato do cabeçalho para o resumo do áudio" + ) + with col2: + transcription_header = st.text_input( + "Cabeçalho da Transcrição", + value=message_settings["transcription_header"], + help="Formato do cabeçalho para a transcrição do áudio" + ) + + # Modo de saída + output_mode = st.selectbox( + "Modo de Saída", + options=["both", "summary_only", "transcription_only", "smart"], + format_func=lambda x: { + "both": "Resumo e Transcrição", + "summary_only": "Apenas Resumo", + "transcription_only": "Apenas Transcrição", + "smart": "Modo Inteligente (baseado no tamanho)" + }[x], + value=message_settings["output_mode"] + ) + + # Configuração do limite de caracteres (visível apenas no modo inteligente) + if output_mode == "smart": + character_limit = st.number_input( + "Limite de Caracteres para Modo Inteligente", + min_value=100, + max_value=5000, + value=int(message_settings["character_limit"]), + help="Se a transcrição exceder este limite, será enviado apenas o resumo" + ) + else: + character_limit = message_settings["character_limit"] + + # Botão de salvar + if st.button("💾 Salvar Configurações de Mensagem"): + try: + new_settings = { + "summary_header": summary_header, + "transcription_header": transcription_header, + "output_mode": output_mode, + "character_limit": character_limit + } + storage.save_message_settings(new_settings) + st.success("Configurações de mensagem salvas com sucesso!") + except Exception as e: + st.error(f"Erro ao salvar configurações: {str(e)}") + def manage_settings(): st.title("⚙️ Configurações") - st.subheader("Configurações do Sistema") - - # Seção de chaves GROQ com sistema de rodízio - st.subheader("🔑 Gerenciamento de Chaves GROQ") - # Campo para chave principal (mantendo compatibilidade) - main_key = st.text_input( - "GROQ API Key Principal", - value=st.session_state.settings["GROQ_API_KEY"], - key="groq_api_key", - type="password", - help="Chave GROQ principal do sistema" - ) - - # Seção de chaves adicionais - st.markdown("---") - st.subheader("Chaves GROQ Adicionais (Sistema de Rodízio)") + # Criar tabs para melhor organização + tab1, tab2, tab3 = st.tabs(["🔑 Chaves API", "🌐 Configurações Gerais", "📝 Formatação de Mensagens"]) - # Exibir chaves existentes - groq_keys = storage.get_groq_keys() - if groq_keys: - st.write("Chaves configuradas para rodízio:") - for key in groq_keys: - col1, col2 = st.columns([4, 1]) - with col1: - masked_key = f"{key[:10]}...{key[-4:]}" - st.code(masked_key, language=None) - with col2: - if st.button("🗑️", key=f"remove_{key}", help="Remover esta chave"): - storage.remove_groq_key(key) - st.success(f"Chave removida do rodízio!") - st.experimental_rerun() + with tab1: + st.subheader("Gerenciamento de Chaves GROQ") + # Campo para gerenciamento de chaves GROQ + main_key = st.text_input( + "GROQ API Key Principal", + value=st.session_state.settings["GROQ_API_KEY"], + key="groq_api_key", + type="password", + help="Chave GROQ principal do sistema" + ) - # Adicionar nova chave - new_key = st.text_input( - "Adicionar Nova Chave GROQ", - key="new_groq_key", - type="password", - help="Insira uma nova chave GROQ para adicionar ao sistema de rodízio" - ) - col1, col2 = st.columns([4, 1]) - with col1: - if st.button("➕ Adicionar ao Rodízio", help="Adicionar esta chave ao sistema de rodízio"): - if new_key: - if new_key.startswith("gsk_"): - storage.add_groq_key(new_key) - st.success("Nova chave adicionada ao sistema de rodízio!") - st.experimental_rerun() + # Seção de chaves adicionais + st.markdown("---") + st.subheader("Chaves GROQ Adicionais (Sistema de Rodízio)") + + # Exibir chaves existentes + groq_keys = storage.get_groq_keys() + if groq_keys: + st.write("Chaves configuradas para rodízio:") + for key in groq_keys: + col1, col2 = st.columns([4, 1]) + with col1: + masked_key = f"{key[:10]}...{key[-4:]}" + st.code(masked_key, language=None) + with col2: + if st.button("🗑️", key=f"remove_{key}", help="Remover esta chave"): + storage.remove_groq_key(key) + st.success(f"Chave removida do rodízio!") + st.experimental_rerun() + + # Adicionar nova chave + new_key = st.text_input( + "Adicionar Nova Chave GROQ", + key="new_groq_key", + type="password", + help="Insira uma nova chave GROQ para adicionar ao sistema de rodízio" + ) + col1, col2 = st.columns([4, 1]) + with col1: + if st.button("➕ Adicionar ao Rodízio", help="Adicionar esta chave ao sistema de rodízio"): + if new_key: + if new_key.startswith("gsk_"): + storage.add_groq_key(new_key) + st.success("Nova chave adicionada ao sistema de rodízio!") + st.experimental_rerun() + else: + st.error("Chave inválida! A chave deve começar com 'gsk_'") else: - st.error("Chave inválida! A chave deve começar com 'gsk_'") - else: - st.warning("Por favor, insira uma chave válida") + st.warning("Por favor, insira uma chave válida") + pass + + with tab2: + st.subheader("Configurações do Sistema") + + # Business Message + st.text_input( + "Mensagem de Serviço no Rodapé", + value=st.session_state.settings["BUSINESS_MESSAGE"], + key="business_message" + ) + + # Process Group Messages + st.selectbox( + "Processar Mensagens em Grupos", + options=["true", "false"], + index=["true", "false"].index(st.session_state.settings["PROCESS_GROUP_MESSAGES"]), + key="process_group_messages" + ) + + # Process Self Messages + st.selectbox( + "Processar Mensagens Próprias", + options=["true", "false"], + index=["true", "false"].index(st.session_state.settings["PROCESS_SELF_MESSAGES"]), + key="process_self_messages" + ) - # Outras configurações do sistema - st.markdown("---") - st.subheader("Outras Configurações") + # Configuração de idioma + st.markdown("---") + st.subheader("🌐 Idioma") - # Business Message - st.text_input( - "Mensagem de Serviço no Rodapé", - value=st.session_state.settings["BUSINESS_MESSAGE"], - key="business_message" - ) + # Dicionário de idiomas em português + IDIOMAS = { + "pt": "Português", + "en": "Inglês", + "es": "Espanhol", + "fr": "Francês", + "de": "Alemão", + "it": "Italiano", + "ja": "Japonês", + "ko": "Coreano", + "zh": "Chinês", + "ro": "Romeno", + "ru": "Russo", + "ar": "Árabe", + "hi": "Hindi", + "nl": "Holandês", + "pl": "Polonês", + "tr": "Turco" + } + + # Carregar configuração atual de idioma + current_language = get_from_redis("TRANSCRIPTION_LANGUAGE", "pt") + + # Seleção de idioma + selected_language = st.selectbox( + "Idioma para Transcrição e Resumo", + options=list(IDIOMAS.keys()), + format_func=lambda x: IDIOMAS[x], + index=list(IDIOMAS.keys()).index(current_language) if current_language in IDIOMAS else 0, + help="Selecione o idioma para transcrição dos áudios e geração dos resumos", + key="transcription_language" + ) + pass - # Process Group Messages - st.selectbox( - "Processar Mensagens em Grupos", - options=["true", "false"], - index=["true", "false"].index(st.session_state.settings["PROCESS_GROUP_MESSAGES"]), - key="process_group_messages" - ) - - # Process Self Messages - st.selectbox( - "Processar Mensagens Próprias", - options=["true", "false"], - index=["true", "false"].index(st.session_state.settings["PROCESS_SELF_MESSAGES"]), - key="process_self_messages" - ) + with tab3: + st.subheader("Formatação de Mensagens") + + # Headers personalizados + col1, col2 = st.columns(2) + with col1: + summary_header = st.text_input( + "Cabeçalho do Resumo", + value=get_from_redis("summary_header", "🤖 *Resumo do áudio:*"), + key="summary_header", + help="Formato do cabeçalho para o resumo do áudio" + ) + with col2: + transcription_header = st.text_input( + "Cabeçalho da Transcrição", + value=get_from_redis("transcription_header", "🔊 *Transcrição do áudio:*"), + key="transcription_header", + help="Formato do cabeçalho para a transcrição do áudio" + ) + + # Modo de saída - Corrigido para usar index + output_modes = ["both", "summary_only", "transcription_only", "smart"] + output_mode_labels = { + "both": "Resumo e Transcrição", + "summary_only": "Apenas Resumo", + "transcription_only": "Apenas Transcrição", + "smart": "Modo Inteligente (baseado no tamanho)" + } + + current_mode = get_from_redis("output_mode", "both") + mode_index = output_modes.index(current_mode) if current_mode in output_modes else 0 + + output_mode = st.selectbox( + "Modo de Saída", + options=output_modes, + format_func=lambda x: output_mode_labels[x], + index=mode_index, + key="output_mode", + help="Selecione como deseja que as mensagens sejam enviadas" + ) + + if output_mode == "smart": + character_limit = st.number_input( + "Limite de Caracteres para Modo Inteligente", + min_value=100, + max_value=5000, + value=int(get_from_redis("character_limit", "500")), + help="Se a transcrição exceder este limite, será enviado apenas o resumo" + ) - # Nova seção de configuração de idioma - st.markdown("---") - st.subheader("🌐 Configuração de Idioma") - - # Dicionário de idiomas em português - IDIOMAS = { - "pt": "Português", - "en": "Inglês", - "es": "Espanhol", - "fr": "Francês", - "de": "Alemão", - "it": "Italiano", - "ja": "Japonês", - "ko": "Coreano", - "zh": "Chinês", - "ro": "Romeno", - "ru": "Russo", - "ar": "Árabe", - "hi": "Hindi", - "nl": "Holandês", - "pl": "Polonês", - "tr": "Turco" - } - - # Carregar configuração atual de idioma - current_language = get_from_redis("TRANSCRIPTION_LANGUAGE", "pt") - - # Seleção de idioma - selected_language = st.selectbox( - "Idioma para Transcrição e Resumo", - options=list(IDIOMAS.keys()), - format_func=lambda x: IDIOMAS[x], - index=list(IDIOMAS.keys()).index(current_language) if current_language in IDIOMAS else 0, - help="Selecione o idioma para transcrição dos áudios e geração dos resumos", - key="transcription_language" - ) - - # Botão de salvar com feedback visual + # Botão de salvar unificado if st.button("💾 Salvar Todas as Configurações"): try: - # Salvar configurações principais + # Salvar configurações existentes save_settings() + # Salvar novas configurações de mensagem + save_to_redis("summary_header", summary_header) + save_to_redis("transcription_header", transcription_header) + save_to_redis("output_mode", output_mode) + if output_mode == "smart": + save_to_redis("character_limit", str(character_limit)) + # Se há uma chave principal, adicionar ao sistema de rodízio if main_key and main_key.startswith("gsk_"): storage.add_groq_key(main_key) @@ -476,10 +596,11 @@ def manage_settings(): st.success("✅ Todas as configurações foram salvas com sucesso!") - # Mostrar resumo das chaves ativas e idioma selecionado + # Mostrar resumo total_keys = len(storage.get_groq_keys()) st.info(f"""Sistema configurado com {total_keys} chave(s) GROQ no rodízio - Idioma definido: {IDIOMAS[selected_language]}""") + Idioma definido: {IDIOMAS[selected_language]} + Modo de saída: {output_mode_labels[output_mode]}""") except Exception as e: st.error(f"Erro ao salvar configurações: {str(e)}") diff --git a/services.py b/services.py index ec8cc29..ebe6a3f 100644 --- a/services.py +++ b/services.py @@ -355,4 +355,35 @@ async def get_audio_base64(server_url, instance, apikey, message_id): "type": type(e).__name__, "message_id": message_id }) - raise \ No newline at end of file + raise + +async def format_message(transcription_text, summary_text=None): + """Formata a mensagem baseado nas configurações.""" + settings = storage.get_message_settings() + message_parts = [] + + # Determinar modo de saída + output_mode = settings["output_mode"] + char_limit = int(settings["character_limit"]) + + if output_mode == "smart": + # Modo inteligente baseado no tamanho + if len(transcription_text) > char_limit: + if summary_text: + message_parts.append(f"{settings['summary_header']}\n\n{summary_text}") + else: + message_parts.append(f"{settings['transcription_header']}\n\n{transcription_text}") + elif output_mode == "summary_only": + if summary_text: + message_parts.append(f"{settings['summary_header']}\n\n{summary_text}") + elif output_mode == "transcription_only": + message_parts.append(f"{settings['transcription_header']}\n\n{transcription_text}") + else: # both + if summary_text: + message_parts.append(f"{settings['summary_header']}\n\n{summary_text}") + message_parts.append(f"{settings['transcription_header']}\n\n{transcription_text}") + + # Adicionar mensagem de negócio + message_parts.append(dynamic_settings['BUSINESS_MESSAGE']) + + return "\n\n".join(message_parts) \ No newline at end of file diff --git a/storage.py b/storage.py index b6ef965..3c65a5f 100644 --- a/storage.py +++ b/storage.py @@ -199,4 +199,18 @@ class StorageHandler: next_counter = (counter + 1) % len(keys) self.redis.set(self._get_redis_key("groq_key_counter"), str(next_counter)) - return keys[counter % len(keys)] \ No newline at end of file + return keys[counter % len(keys)] + + def get_message_settings(self): + """Obtém as configurações de mensagens.""" + return { + "summary_header": self.redis.get(self._get_redis_key("summary_header")) or "🤖 *Resumo do áudio:*", + "transcription_header": self.redis.get(self._get_redis_key("transcription_header")) or "🔊 *Transcrição do áudio:*", + "output_mode": self.redis.get(self._get_redis_key("output_mode")) or "both", + "character_limit": int(self.redis.get(self._get_redis_key("character_limit")) or "500"), + } + + def save_message_settings(self, settings: dict): + """Salva as configurações de mensagens.""" + for key, value in settings.items(): + self.redis.set(self._get_redis_key(key), str(value)) \ No newline at end of file