Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| from utils import get_doc_content, call_openrouter | |
| from config import DOCS | |
| custom_css = """ | |
| /* 1. Importação da Fonte (Estilo Google Sans) */ | |
| @import url('https://fonts.googleapis.com/css2?family=Alegreya+Sans:ital,wght@400;700&display=swap'); | |
| :root, .gradio-container, * { | |
| font-family: 'Alegreya Sans', sans-serif !important; | |
| } | |
| /* 2. O TÍTULO DA SANFONA (Accordion) */ | |
| /* Miramos na classe .label-wrap que você encontrou na inspeção */ | |
| .label-wrap, | |
| .label-wrap span, | |
| button.label-wrap { | |
| font-size: 22px !important; | |
| font-weight: bold !important; | |
| color: #2d2d2d !important; | |
| } | |
| /* 3. O CONTEÚDO DENTRO DA SANFONA */ | |
| /* Miramos na classe .prose que envolve a lista de modelos */ | |
| .prose ul, | |
| .prose li, | |
| .prose p { | |
| font-size: 20px !important; | |
| line-height: 1.5 !important; | |
| color: #444 !important; | |
| } | |
| /* 4. OUTROS ELEMENTOS (Labels, Botões, etc) */ | |
| /* Unifica o tamanho de todos os títulos de componentes */ | |
| label span, | |
| [data-testid="block-info"] { | |
| font-size: 22px !important; | |
| font-weight: bold !important; | |
| color: #2d2d2d !important; | |
| /* Adiciona um pequeno espaço entre o título e as opções */ | |
| margin-bottom: 10px !important; | |
| display: block !important; | |
| } | |
| /* Garante que o texto dentro das opções do Radio também seja legível */ | |
| .svelte-1bx8sav span { | |
| font-size: 18px !important; | |
| } | |
| button.primary, button.secondary { font-size: 20px !important; font-weight: bold !important; } | |
| /* 5. ÍCONE (A setinha ou o 'i') */ | |
| .icon.svelte-1w6vloh, .icon { | |
| transform: scale(1.5) !important; | |
| } | |
| /* 1. Melhora o contraste da opção selecionada no Radio */ | |
| .selected.svelte-1bx8sav, | |
| .selected { | |
| background-color: #2b5797 !important; /* Um azul mais nobre */ | |
| border-color: #1a3a5f !important; | |
| } | |
| /* 2. FORÇA a cor do texto para BRANCO quando selecionado */ | |
| .selected span, | |
| .selected input + span { | |
| color: white !important; | |
| font-weight: bold !important; | |
| } | |
| /* 3. Estilo para as opções NÃO selecionadas (fundo claro) */ | |
| label.svelte-1bx8sav { | |
| background-color: #f5f5f5 !important; | |
| color: #2d2d2d !important; | |
| border: 1px solid #ddd !important; | |
| transition: all 0.2s ease; | |
| } | |
| /* 4. Efeito de "hover" (passar o mouse) */ | |
| label.svelte-1bx8sav:hover { | |
| background-color: #e8e8e8 !important; | |
| } | |
| /* 1. Opções dentro do menu suspenso (Dropdown) */ | |
| .item.svelte-1hfxrpf, | |
| .option, | |
| ul.options li { | |
| font-weight: bold !important; | |
| font-size: 18px !important; | |
| color: #2d2d2d !important; | |
| } | |
| /* 2. Quando a opção está selecionada ou com o mouse em cima */ | |
| .item.selected.svelte-1hfxrpf, | |
| .item:hover { | |
| background-color: #2b5797 !important; /* Mesmo azul do Radio para harmonia */ | |
| color: white !important; /* Letras brancas para contraste total */ | |
| } | |
| /* 3. O texto que fica visível no botão do Dropdown após selecionar */ | |
| .secondary-wrap input { | |
| font-weight: bold !important; | |
| font-size: 18px !important; | |
| color: #2d2d2d !important; | |
| } | |
| /* 1. Aumenta o texto que o usuário digita (Input) */ | |
| textarea, | |
| .input-container textarea { | |
| font-size: 22px !important; | |
| line-height: 1.6 !important; | |
| font-family: 'Alegreya Sans', sans-serif !important; | |
| color: #2d2d2d !important; | |
| } | |
| /* 2. Aumenta o texto da análise gerada (Output) */ | |
| /* O Gradio usa 'disabled' ou 'interactive-false' para a caixa de saída */ | |
| textarea:disabled, | |
| [data-testid="textbox"]:disabled { | |
| font-size: 22px !important; | |
| line-height: 1.6 !important; | |
| font-family: 'Alegreya Sans', sans-serif !important; | |
| color: #1a1a1a !important; /* Um pouco mais escuro para facilitar a leitura */ | |
| -webkit-text-fill-color: #1a1a1a !important; /* Necessário para alguns navegadores */ | |
| opacity: 1 !important; /* Remove o aspecto acinzentado de 'desabilitado' */ | |
| } | |
| /* 3. Garante que o placeholder (ex: "Insira o texto...") também seja legível */ | |
| ::placeholder { | |
| font-size: 20px !important; | |
| opacity: 0.7; | |
| } | |
| """ | |
| # 2. FUNÇÃO PARA SALVAR O TXT | |
| def salvar_txt(conteudo): | |
| if not conteudo: | |
| return None | |
| file_path = "analise_classica.txt" | |
| with open(file_path, "w", encoding="utf-8") as f: | |
| f.write(conteudo) | |
| return file_path | |
| # 3. FUNÇÃO PRINCIPAL | |
| def processar_analise(texto_usuario, modo, categoria_pergunta): | |
| if not texto_usuario.strip(): | |
| return "Por favor, insira um texto.", "Aguardando...", None | |
| url = DOCS.get(categoria_pergunta) | |
| perguntas_guia_ingles = get_doc_content(url) | |
| # Prompt REFORÇADO para garantir tradução em modelos menores | |
| prompt_completo = f""" | |
| ### INSTRUÇÃO CRÍTICA DE IDIOMA ### | |
| Toda a sua resposta DEVE ser em PORTUGUÊS. | |
| Você deve traduzir as perguntas abaixo do Inglês para o Português antes de respondê-las. | |
| ### TAREFA ### | |
| 1. Leia o PROTOCOLO em inglês. | |
| 2. TRADUZA cada pergunta para o Português. | |
| 3. RESPONDA cada pergunta em Português analisando o TEXTO fornecido. | |
| 4. Mantenha os termos em Grego/Latim originais e intactos. | |
| ### PROTOCOLO ORIGINAL (INGLÊS) ### | |
| {perguntas_guia_ingles} | |
| ### TEXTO ORIGINAL PARA ANÁLISE ### | |
| {texto_usuario} | |
| ### FORMATO DESEJADO ### | |
| Pergunta [Pergunta traduzida]: (Sua tradução aqui) | |
| Resposta: (Sua análise detalhada em português) | |
| """ | |
| resposta_ia, modelo_vencedor = call_openrouter(prompt_completo, modo) | |
| exibicao_final = f"--- RELATORIO DE ANALISE ---\n\n{resposta_ia}" | |
| caminho_arquivo = salvar_txt(exibicao_final) | |
| return exibicao_final, f"Modelo: {modelo_vencedor}", caminho_arquivo | |
| # 4. INTERFACE | |
| with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo: | |
| gr.Markdown("# 🏛️ AI for Classics") | |
| with gr.Accordion("ℹ️ Modelos e Estratégias", open=False): | |
| gr.Markdown(""" | |
| - **Alta Precisão:** Claude 3.5, GPT-4o, Gemini Pro. | |
| - **Custo-Benefício:** Gemini Flash, Command R, Mistral. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| input_text = gr.Textbox(label="1. Insira o texto", lines=10) | |
| modo_radio = gr.Radio( | |
| choices=["Alta Precisão (Filológica)", "Custo-Benefício (Triagem)"], | |
| label="2. Selecione a estratégia/modelo", | |
| value="Alta Precisão (Filológico)" | |
| ) | |
| cat_perguntas = gr.Dropdown( | |
| choices=["SYNTAX", "MORPHOLOGY", "SEMANTICS"], | |
| label="3. Selecione: Sintaxe, Morfologia ou Semântica", | |
| value="SYNTAX" | |
| ) | |
| with gr.Row(): | |
| btn_limpar = gr.Button("Limpar") | |
| btn_rodar = gr.Button("🚀 EXECUTAR", variant="primary") | |
| with gr.Column(scale=1): | |
| output_res = gr.Textbox(label="Análise Gerada", lines=18, interactive=False) | |
| output_model = gr.Label(label="Status") | |
| file_download = gr.File(label="Baixar TXT") | |
| btn_rodar.click( | |
| processar_analise, | |
| inputs=[input_text, modo_radio, cat_perguntas], | |
| outputs=[output_res, output_model, file_download] | |
| ) | |
| btn_limpar.click( | |
| lambda: ("", "Aguardando...", "", None), | |
| outputs=[input_text, output_model, output_res, file_download] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |