# ============================================================================== # Projeto: Analisador Multilíngue ISD & FrameNet # Desenvolvimento Colaborativo: Anise Ferreira & Google Gemini (IA Generativa / LLM) # Papel da IA: Assistente de Codificação e Engenharia de Prompts # Data: Junho de 2026 # ============================================================================== import os import json import streamlit as st from transformers import pipeline from huggingface_hub import InferenceClient # 1. Configuração da página do Streamlit st.set_page_config(page_title="Analisador Multilíngue ISD & FrameNet", layout="wide") st.title("🔬 Analisador Linguístico Avançado (PT / FR)") st.subheader("Arquitetura Textual do ISD (Bronckart) + Semântica de Frames (Fillmore)") # 2. Configurar o cliente da API do Hugging Face usando o Token Seguro token_seguro = os.environ.get("HF_TOKEN") client = InferenceClient( model="Qwen/Qwen2.5-7B-Instruct", token=token_seguro ) # 3. Inicialização do modelo complementar (Mundos Discursivos) @st.cache_resource def load_models(): classifier = pipeline( "zero-shot-classification", model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli" ) return classifier classifier = load_models() # 4. Interface do Usuário na Barra Lateral (Fontes Ampliadas) st.sidebar.header("📝 Contexto Inicial Declarado") # --- AJUSTE: Idioma do Corpus --- st.sidebar.markdown("
Idioma do Corpus
", unsafe_allow_html=True) idioma = st.sidebar.selectbox("", ["Português", "Français"], label_visibility="collapsed") # --- AJUSTE: Estatuto do Autor/Emissor --- st.sidebar.markdown("Estatuto do Autor/Emissor
", unsafe_allow_html=True) autor = st.sidebar.text_input("", placeholder="Ex: Jornalista, Cientista...", label_visibility="collapsed") # --- AJUSTE: Objetivo Estimado --- st.sidebar.markdown("Objetivo Estimado
", unsafe_allow_html=True) objetivo_input = st.sidebar.text_input("", placeholder="Ex: Persuadir, Denunciar...", label_visibility="collapsed") # >>> COLE AS LINHAS DE CRÉDITO EXATAMENTE AQUI <<< st.sidebar.markdown("---") st.sidebar.caption("Idealizado por Anise Ferreira. Desenvolvido em colaboração com IA Generativa (LLM Gemini 1.5 Pro).") # 5. Entrada do Texto Principal (Fonte Ampliada) # --- AJUSTE: Insira o fragmento de texto... --- st.markdown("Insira o fragmento de texto para análise em Português ou Francês
", unsafe_allow_html=True) texto_input = st.text_area( "", height=200, placeholder="Digite ou cole seu texto aqui...", label_visibility="collapsed" ) # 6. O Botão que Dispara a Análise Combinada if st.button("Analisar Texto Completo"): if texto_input: col1, col2 = st.columns(2) # ---------------------------------------------------- # COLUNA 1: Relatório Completo de Bronckart (ISD) # ---------------------------------------------------- with col1: st.header("📊 Camada de Bronckart (ISD)") labels = ["Discurso Teórico / Discours Théorique", "Narração / Narration", "Discurso Interativo / Discours Interactif"] res = classifier(texto_input, candidate_labels=labels) # Prompt blindado com definições teóricas do ISD (Bronckart e Adam) # Prompt avançado com desdobramento rigoroso entre Textualização e Enunciação prompt_isd = ( "Você é um linguista sênior especialista no Interacionismo Sociodiscursivo (ISD) de Jean-Paul Bronckart e Jean-Michel Adam.\n" f"Analise o texto considerando que o autor declarado é '{autor}' e o objetivo estimado é '{objetivo_input}'.\n" "Responda EXCLUSIVAMENTE em um formato JSON estrito, sem markdown, sem introduções. " "Siga rigorosamente as seguintes diretrizes teóricas estruturadas em camadas para preencher o JSON:\n\n" "1. 'contexto_produção': Mapeie o emissor (estatuto social), receptor (público-alvo), suporte (onde circula), o objetivo (efeito na sociedade) e o 'genero_textual' (identifique o gênero específico do texto com base nas suas características sociodiscursivas, ex: Artigo de Opinião, Relatório Científico, Editorial, etc.).\n\n" "2. 'sequencias_textuais': Atribua porcentagens (0 a 100) para a presença das 5 sequências de Jean-Michel Adam no texto: narrativa, descritiva, argumentativa, explicativa e injuntiva.\n\n" "3. 'mecanismos_textualizacao':\n" " - Focus apenas na amarração linear do texto. Não misture com vozes ou opiniões.\n" " - 'coesao_nominal': Analise as cadeias de referência anafórica. Como pronomes, sinônimos, repetições ou elipses são usados para retomar os referentes textuais sem gerar ambiguidade. Dê exemplos exatos do texto.\n" " - 'coesao_verbal': Analise a ordenação e a correlação dos tempos verbais (ex: presente do indicativo para exposição, alternância de pretérito perfeito/imperfeito para eixos temporais). Explique o papel deles na progressão textual.\n\n" "4. 'mecanismos_enunciativos':\n" " - Identifique como a subjetividade e as perspectivas são encenadas no texto.\n" " - 'gerenciamento_vozes': Identifique rigorosamente a polifonia textual. Classifique a presença e a alternância das vozes textuais de acordo com o ISD: Voz do Narrador/Expositor, Voz de Personagem, Voz de Instância Social (leis, ciência, senso comum/doxa) ou Voz do Autor Empírico. Dê exemplos de trechos textuais e cite como são introduzidas (direta, indireta ou implícita).\n" " - 'modalizacoes': Rastreie as marcas de avaliação presentes. Classifique-as estritamente em suas subcategorias se houverem: Modalizações Apreciativas (julgamentos de valor/afetivos), Lógicas (certeza, probabilidade, possibilidade), Deônticas (dever, obrigação, permissão) ou Pragmáticas (utilidade, eficácia, responsabilidade). Indique os itens lexicais exatos extraídos do texto original.\n\n" "Estrutura exata do JSON esperado:\n" "{\n" ' "contexto_produção": {"emissor": "", "receptor": "", "suporte_circulacao": "", "objetivo_sociedade": "", "genero_textual": ""},\n' ' "sequencias_textuais": {"narrativa": 0, "descritiva": 0, "argumentativa": 0, "explicativa": 0, "injuntiva": 0},\n' ' "mecanismos_textualizacao": {"coesao_nominal": "", "coesao_verbal": ""},\n' ' "mecanismos_enunciativos": {"gerenciamento_vozes": "", "modalizacoes": ""}\n' "}" ) with st.spinner("Decodificando camadas do ISD..."): try: resposta_isd = client.chat_completion( messages=[{"role": "system", "content": prompt_isd}, {"role": "user", "content": texto_input}], max_tokens=800 ) texto_isd = resposta_isd.choices[0].message.content.strip() if texto_isd.startswith("```"): texto_isd = texto_isd.replace("```json", "").replace("```", "").strip() dados_isd = json.loads(texto_isd) st.subheader("1. Contexto de Produção Pragmático") cp = dados_isd.get('contexto_produção', {}) # NOVA LINHA: Exibição do Gênero Textual Detectado st.write(f"📂 **Gênero Textual Detectado:** {cp.get('genero_textual', 'Não identificado')}") st.write(f"✍️ **Emissor (Estatuto):** {cp.get('emissor', 'Não identificado')}") st.write(f"👥 **Receptor (Público-Alvo):** {cp.get('receptor', 'Não identificado')}") st.write(f"📍 **Suporte e Circulação:** {cp.get('suporte_circulacao', 'Não identificado')}") st.write(f"🎯 **Efeito Pretendido na Sociedade:** {cp.get('objetivo_sociedade', 'Não identificado')}") st.divider() st.subheader("2. Infraestrutura: Mundos & Sequências") st.write(f"🔮 **Mundo Discursivo Predominante:** {res['labels'][0]} ({res['scores'][0]*100:.1f}%)") st.write("**Tipologia de Sequências (Adam):**") for seq, valor in dados_isd.get('sequencias_textuais', {}).items(): st.text(f"- Sequência {seq.capitalize()}:") st.progress(float(valor)/100 if isinstance(valor, (int, float)) else 0.0) st.divider() st.subheader("3. Mecanismos de Textualização") mt = dados_isd.get('mecanismos_textualizacao', {}) st.write(f"🔗 **Coesão Nominal:** {mt.get('coesao_nominal', 'Não analisado')}") st.write(f"⏳ **Coesão Verbal:** {mt.get('coesao_verbal', 'Não analisado')}") st.divider() st.subheader("4. Mecanismos Enunciativos") me = dados_isd.get('mecanismos_enunciativos', {}) st.write(f"🗣️ **Gerenciamento de Vozes:** {me.get('gerenciamento_vozes', 'Não analisado')}") st.write(f"🦉 **Modalizações Detectadas:** {me.get('modalizacoes', 'Não analisado')}") except Exception as e: st.error(f"Erro ao processar camada ISD: {e}") # ---------------------------------------------------- # COLUNA 2: Análise de Semântica de Frames Universal (Fillmore) # ---------------------------------------------------- with col2: st.header("🧠 Semântica de Frames Universal") prompt_frame = ( "Você é um linguista computacional especialista na Semântica de Frames de Fillmore, " "utilizando estritamente as taxonomias oficiais da Berkeley FrameNet (para inglês/geral) " "e da Asfalda French FrameNet (para termos em francês).\n\n" "Instruções de análise:\n" "1. Identifique a Unidade Lexical (palavra-gatilho) principal do texto.\n" "2. Determine o nome oficial do Frame ativado (ex: Commerce_buy, Statement, Motion).\n" "3. Mapeie os Elementos de Frame (FEs) extraindo as palavras exatas do texto original.\n" "4. Se o texto for em francês, use a correspondência conceitual validada pela Asfalda.\n\n" "Responda EXCLUSIVAMENTE com um objeto JSON válido, sem comentários e sem marcações markdown:\n" "{\n" ' "frame": "NOME_OFICIAL_DO_FRAME",\n' ' "unidade_lexical": "palavra_gatilho",\n' ' "elementos": {"Nome_Do_Elemento_Oficial": "trecho do texto"}\n' "}" ) with st.spinner("Analisando frames..."): try: resposta_frame = client.chat_completion( messages=[{"role": "system", "content": prompt_frame}, {"role": "user", "content": texto_input}], max_tokens=400 ) texto_frame = resposta_frame.choices[0].message.content.strip() if texto_frame.startswith("```"): texto_frame = texto_frame.replace("```json", "").replace("```", "").strip() dados_frame = json.loads(texto_frame) st.success(f"🔓 **Frame Detectado:** `{dados_frame.get('frame', 'Desconhecido')}`") st.write("**Elementos mapeados no texto:**") for elemento, valor in dados_frame.get('elementos', {}).items(): st.write(f"- *{elemento}:* {valor}") except Exception as e: st.error(f"Erro ao processar Frame: {e}") else: st.error("Por favor, insira um texto para análise.")