Spaces:
Sleeping
Sleeping
| import os | |
| from dotenv import load_dotenv | |
| from langchain_openai import ChatOpenAI | |
| from langchain.prompts import PromptTemplate | |
| from langchain.chains import ConversationChain # Keep using this for now, despite deprecation | |
| from langchain.memory import ConversationBufferMemory # Keep using this for now | |
| import gradio as gr | |
| import traceback | |
| # Carrega a chave da API | |
| load_dotenv() | |
| api_key = os.getenv("OPENROUTER_API_KEY") | |
| if not api_key: | |
| raise ValueError("❌ Variável OPENROUTER_API_KEY não encontrada.") | |
| # Define variáveis do ambiente | |
| os.environ["OPENAI_API_KEY"] = api_key | |
| os.environ["OPENAI_API_BASE"] = "https://openrouter.ai/api/v1" | |
| # Instancia o modelo | |
| llm = ChatOpenAI( | |
| model="mistralai/mistral-7b-instruct:free", | |
| temperature=0.5 | |
| ) | |
| # Lista de Tutores/Matérias | |
| subjects = [ | |
| "Python", "Java", "Ruby", "Golang", "C++", "C#", "Rust", | |
| "SQL", "Tableau", "Power BI", "Excel", "Looker", "Solidity" | |
| ] | |
| # --- Template Modificado --- | |
| # Agora SÓ espera 'history' e 'input'. O contexto da matéria será parte do 'input'. | |
| template_string = """Você é um assistente virtual e tutor especialista. A especialidade desejada pelo aluno está indicada claramente no início da pergunta dele (procure por 'Especialidade Foco:'). | |
| Ajude os alunos com dúvidas sobre a especialidade mencionada na pergunta atual, sempre de forma clara, objetiva e com exemplos didáticos. | |
| Adapte a profundidade da sua resposta ao nível aparente da pergunta. Se a pergunta for muito vaga, peça mais detalhes. | |
| Concentre-se estritamente na especialidade indicada na pergunta atual, a menos que o aluno peça explicitamente para comparar com outra tecnologia. | |
| Histórico da conversa: | |
| {history} | |
| Aluno: {input} | |
| Resposta:""" | |
| # Prompt agora só precisa de 'history' e 'input' | |
| template = PromptTemplate( | |
| input_variables=["history", "input"], # APENAS history e input | |
| template=template_string | |
| ) | |
| # --- Memória da Conversa --- | |
| # Aviso de Depreciação: ConversationBufferMemory está sendo substituída. | |
| # Para agora, ela funciona, mas considere migrar para RunnableWithMessageHistory no futuro. | |
| memoria = ConversationBufferMemory(return_messages=True) # memory_key='history' é o padrão | |
| # --- Criação da Chain --- | |
| # Aviso de Depreciação: ConversationChain está sendo substituída. | |
| # Para agora, ela funciona com o prompt ajustado. | |
| chat_chain = ConversationChain( | |
| llm=llm, | |
| memory=memoria, | |
| prompt=template, # Passa o prompt que agora só espera 'history' e 'input' | |
| input_key='input', # Confirma que a chave de entrada principal é 'input' (padrão) | |
| verbose=False | |
| ) | |
| # --- Função para Responder com Contexto Formatado --- | |
| def responder(subject, user_message): | |
| """ | |
| Formata a entrada e gera a resposta do LLM. | |
| """ | |
| if not subject: | |
| return "⚠️ Por favor, selecione uma matéria primeiro." | |
| if not user_message or not user_message.strip(): # Verifica se a mensagem não está vazia ou só espaços | |
| return "⚠️ Por favor, digite sua dúvida." | |
| # **Importante:** Formata a entrada para incluir o contexto da matéria | |
| # É ESSENCIAL que o LLM veja essa informação claramente no início do input. | |
| formatted_input = f"**Especialidade Foco:** {subject}\n\n**Dúvida do Aluno:** {user_message}" | |
| try: | |
| # Passa a string formatada como a única entrada 'input' para a chain | |
| response = chat_chain.run(formatted_input) | |
| return response | |
| except Exception as e: | |
| print(f"❌ Erro ao processar a solicitação:\n{traceback.format_exc()}") | |
| return f"❌ Desculpe, ocorreu um erro ao processar sua solicitação. Detalhes: {str(e)}" | |
| # --- Interface Gradio (sem alterações na estrutura) --- | |
| with gr.Blocks(theme=gr.themes.Soft()) as app: # Adicionando um tema suave | |
| gr.Markdown("# Tutor Poliglota com IA 🤖🎓") | |
| gr.Markdown("Selecione a matéria e tire suas dúvidas com um assistente que lembra da conversa.") | |
| with gr.Row(): | |
| subject_selector = gr.Dropdown( | |
| choices=subjects, | |
| label="Selecione a Matéria", | |
| info="Escolha sobre qual linguagem ou ferramenta você quer perguntar." | |
| ) | |
| with gr.Row(): | |
| input_textbox = gr.Textbox( | |
| placeholder="Ex: Como declarar uma variável em Java?", | |
| label="Sua Dúvida", | |
| lines=3, | |
| show_copy_button=True | |
| ) | |
| with gr.Row(): | |
| submit_button = gr.Button("Perguntar ao Tutor", variant="primary") # Botão com destaque | |
| with gr.Row(): | |
| output_textbox = gr.Textbox( | |
| label="Resposta do Tutor", | |
| lines=10, # Mais espaço para resposta | |
| show_copy_button=True | |
| ) | |
| clear_button = gr.ClearButton( | |
| components=[input_textbox, output_textbox, subject_selector], # Limpa também o dropdown | |
| value="Limpar Campos e Memória" | |
| ) | |
| submit_button.click( | |
| fn=responder, | |
| inputs=[subject_selector, input_textbox], | |
| outputs=output_textbox | |
| ) | |
| def clear_memory_and_interface(): | |
| try: | |
| memoria.clear() # Limpa a memória da conversa | |
| print("Memória da conversa limpa.") | |
| except Exception as e: | |
| print(f"Erro ao limpar a memória: {e}") | |
| # Retorna valor padrão para dropdown (None) e vazio para textbox | |
| return [None, "", ""] | |
| # Atualiza a ação do clear_button para retornar valores para todos os componentes | |
| clear_button.click(fn=clear_memory_and_interface, outputs=[subject_selector, input_textbox, output_textbox]) | |
| # Lança a aplicação | |
| app.launch(share=True, debug=True) # Adiciona debug=True para mais informações no console |