File size: 7,793 Bytes
d665c22
bf2a95e
aeb2715
 
 
 
 
d665c22
aeb2715
 
 
 
 
 
987baef
aeb2715
 
bf2a95e
aeb2715
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21bb05d
aeb2715
 
21bb05d
aeb2715
 
 
223938e
aeb2715
 
 
 
ee25ef1
aeb2715
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ee25ef1
aeb2715
 
fcb0322
aeb2715
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104c1bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d51a494
104c1bb
 
 
 
 
 
 
 
d51a494
104c1bb
 
d51a494
 
 
104c1bb
 
 
 
 
 
 
 
 
 
aeb2715
 
 
 
 
987baef
fcb0322
 
987baef
8bf558e
fcb0322
8bf558e
aeb2715
fcb0322
 
aeb2715
fcb0322
 
 
8bf558e
fcb0322
 
aeb2715
fcb0322
 
bf2a95e
987baef
fcb0322
 
bf2a95e
fcb0322
 
 
bf2a95e
 
 
 
fcb0322
bf2a95e
 
 
 
 
 
fcb0322
aeb2715
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcb0322
bf2a95e
aeb2715
fcb0322
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
import streamlit as st
from transformers import T5ForConditionalGeneration, T5Tokenizer
import torch
from torch.utils.data import Dataset, DataLoader
import json
import os
from datetime import datetime

# Custom dataset for fine-tuning
class TextHumanizerDataset(Dataset):
    def __init__(self, data, tokenizer, max_length=512):
        self.data = data
        self.tokenizer = tokenizer
        self.max_length = max_length

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        item = self.data[idx]
        input_encoding = self.tokenizer(
            f"reescreva em português natural, mantendo todas as informações: {item['input_text']}",
            max_length=self.max_length,
            padding='max_length',
            truncation=True,
            return_tensors='pt'
        )
        
        target_encoding = self.tokenizer(
            item['output_text'],
            max_length=self.max_length,
            padding='max_length',
            truncation=True,
            return_tensors='pt'
        )

        return {
            'input_ids': input_encoding['input_ids'].squeeze(),
            'attention_mask': input_encoding['attention_mask'].squeeze(),
            'labels': target_encoding['input_ids'].squeeze()
        }

def save_feedback(input_text, output_text, rating):
    """Salva o feedback do usuário para futuro treinamento"""
    feedback_data = {
        'input_text': input_text,
        'output_text': output_text,
        'rating': rating,
        'timestamp': datetime.now().isoformat()
    }
    
    # Cria diretório se não existir
    os.makedirs('feedback_data', exist_ok=True)
    
    # Salva em arquivo JSON
    with open('feedback_data/feedback.json', 'a') as f:
        f.write(json.dumps(feedback_data) + '\n')

def fine_tune_model():
    """Realiza fine-tuning do modelo com dados de feedback positivo"""
    if not os.path.exists('feedback_data/feedback.json'):
        return
    
    # Carrega dados de feedback
    positive_examples = []
    with open('feedback_data/feedback.json', 'r') as f:
        for line in f:
            feedback = json.loads(line)
            if feedback['rating'] >= 4:  # Usa apenas feedback positivo
                positive_examples.append({
                    'input_text': feedback['input_text'],
                    'output_text': feedback['output_text']
                })
    
    if not positive_examples:
        return
    
    # Cria dataset e dataloader
    dataset = TextHumanizerDataset(positive_examples, st.session_state.tokenizer)
    dataloader = DataLoader(dataset, batch_size=4, shuffle=True)
    
    # Configura otimizador
    optimizer = torch.optim.AdamW(st.session_state.model.parameters(), lr=1e-5)
    
    # Fine-tuning
    st.session_state.model.train()
    for batch in dataloader:
        optimizer.zero_grad()
        outputs = st.session_state.model(
            input_ids=batch['input_ids'],
            attention_mask=batch['attention_mask'],
            labels=batch['labels']
        )
        loss = outputs.loss
        loss.backward()
        optimizer.step()
    
    st.session_state.model.eval()

def clean_generated_text(text):
    """Remove comandos e limpa o texto gerado"""
    text = text.strip()

    # Lista de prefixos de comando para remover
    prefixes = [
        "reescreva o seguinte texto",
        "reescreva este texto",
        "reescreva o texto",
        "traduza",
        "humanize:",
        "humanizar:",
        "em português",
        "de forma mais natural"
    ]

    # Remove os prefixos de comando
    text_lower = text.lower()
    for prefix in prefixes:
        if text_lower.startswith(prefix):
            text = text[len(prefix):].strip()
            text_lower = text.lower()
    
    # Capitaliza a primeira letra
    if text:
        text = text[0].upper() + text[1:]
    
    return text

def humanize_text(text):
    """Humaniza o texto mantendo coerência e tamanho"""
    prompt = f"reescreva em português natural, mantendo todas as informações: {text}"
    
    input_ids = st.session_state.tokenizer(
        prompt,
        return_tensors="pt",
        max_length=512,
        truncation=True
    ).input_ids

    # Parâmetros ajustados para melhor coerência
    outputs = st.session_state.model.generate(
        input_ids,
        max_length=1024,
        min_length=len(text.split()),
        do_sample=False,
        temperature=0.1,
        top_p=0.95,
        num_beams=2,
        repetition_penalty=1.1,
        length_penalty=1.0
    )
    result = st.session_state.tokenizer.decode(outputs[0], skip_special_tokens=True)
    result = clean_generated_text(result)
    
    # Garante tamanho mínimo
    while len(result.split()) < len(text.split()):
        result += " " + " ".join(text.split()[-(len(text.split()) - len(result.split())):])
    
    return result

# Initialize session state
if 'model_loaded' not in st.session_state:
    st.session_state.tokenizer = T5Tokenizer.from_pretrained("t5-base")
    st.session_state.model = T5ForConditionalGeneration.from_pretrained("t5-base")
    st.session_state.model_loaded = True

# UI Components
st.set_page_config(page_title="Advanced Text Humanizer", page_icon="🤖")

st.title("🤖 → 🧑 Humanizador de Texto Avançado")
st.markdown("""
Este aplicativo transforma textos robotizados em linguagem mais natural e humana, 
mantendo todas as informações originais e incluindo sistema de feedback para melhoria contínua.
""")

# Input area
input_text = st.text_area(
    "Cole seu texto de robô aqui:",
    height=150,
    help="Cole seu texto aqui para transformá-lo em uma versão mais natural e humana."
)

# Process button and results
if st.button("Humanizar", type="primary"):
    if not input_text:
        st.warning("⚠️ Por favor, cole um texto primeiro!")
    else:
        with st.spinner("Processando o texto..."):
            try:
                final_text = humanize_text(input_text)
                
                # Display results
                st.success("✨ Texto humanizado:")
                col1, col2 = st.columns(2)
                
                with col1:
                    st.text("Original:")
                    st.info(input_text)
                    st.write(f"Palavras: {len(input_text.split())}")
                
                with col2:
                    st.text("Resultado:")
                    st.info(final_text)
                    st.write(f"Palavras: {len(final_text.split())}")
                
                # Feedback section
                st.markdown("### Feedback")
                rating = st.slider(
                    "Como você avalia a qualidade do texto humanizado?",
                    min_value=1,
                    max_value=5,
                    value=3,
                    help="1 = Muito ruim, 5 = Excelente"
                )
                
                if st.button("Enviar Feedback"):
                    save_feedback(input_text, final_text, rating)
                    st.success("Feedback salvo com sucesso! Obrigado pela contribuição.")
                    
                    # Trigger fine-tuning if we have enough positive feedback
                    if rating >= 4:
                        with st.spinner("Atualizando modelo com seu feedback..."):
                            fine_tune_model()
                        st.success("Modelo atualizado com sucesso!")
                
            except Exception as e:
                st.error(f"❌ Erro no processamento: {str(e)}")

# Footer
st.markdown("---")
st.markdown(
    """
    <div style='text-align: center'>
        <small>Desenvolvido com ❤️ usando Streamlit e Transformers</small>
    </div>
    """,
    unsafe_allow_html=True
)