spadini commited on
Commit
46c63b7
·
verified ·
1 Parent(s): 4b78003

Upload 3 files

Browse files
Files changed (3) hide show
  1. agente_functions.py +94 -0
  2. main.py +97 -0
  3. requirements.txt +11 -0
agente_functions.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # agente_functions.py
2
+
3
+ from typing import TypedDict, List
4
+ from langchain_core.tools import tool
5
+ from langchain_community.tools.tavily_search import TavilySearchResults
6
+ from langchain.agents import load_tools
7
+ from langgraph.prebuilt import create_react_agent
8
+
9
+ # --- Define a estrutura de estado do grafo ---
10
+ class AgentState(TypedDict):
11
+ user_query: str
12
+ router_decision: str
13
+ web_answer: str
14
+ scientific_answer: str
15
+ final_answer: str
16
+
17
+ # --- Ferramentas e Funções dos Agentes ---
18
+
19
+ @tool
20
+ def busca_web(query: str) -> list:
21
+ """
22
+ Busca na web por um termo específico usando Tavily Search.
23
+ """
24
+ tavily_search = TavilySearchResults(max_results=2, search_depth='advanced', max_tokens=1000)
25
+ resultado_busca = tavily_search.invoke(query)
26
+ return resultado_busca
27
+
28
+ def funcao_agente_web(state: AgentState, llm, tools: List) -> dict:
29
+ """
30
+ Executa um agente ReAct que realiza uma busca na web.
31
+ """
32
+ system_prompt = """Atue como um assistente útil.
33
+ Use as ferramentas fornecidas para responder às perguntas do usuário.
34
+ - busca_web: Retorna os resultados de uma busca na web.
35
+ Use a busca_web sempre que o usuário fizer uma pergunta sobre um tema específico e retorne o link dos artigos na resposta.
36
+ """
37
+ agente_web = create_react_agent(model=llm, tools=tools, prompt=system_prompt)
38
+ resultado = agente_web.invoke({"messages": [("user", state["user_query"])]})
39
+ resposta_final = resultado['messages'][-1].content
40
+ return {"web_answer": resposta_final}
41
+
42
+ def funcao_agente_cientifico(state: AgentState, llm, tools: List) -> dict:
43
+ """
44
+ Executa um agente ReAct que realiza uma busca no Arxiv.
45
+ """
46
+ system_prompt = """Atue como um assistente útil.
47
+ Use as ferramentas fornecidas para responder às perguntas do usuário.
48
+ - tool_cientifica: Retorna os resultados de uma busca no arxiv.
49
+ Use a tool_cientifica sempre que o usuário fizer uma pergunta sobre um tema específico e retorne o título dos artigos na resposta.
50
+ """
51
+ agente_cientifico = create_react_agent(llm, tools, prompt=system_prompt)
52
+ resultado = agente_cientifico.invoke({"messages": [("user", state["user_query"])]})
53
+ resposta_final = resultado['messages'][-1].content
54
+ return {"scientific_answer": resposta_final}
55
+
56
+ def router_agent(state: AgentState, llm) -> dict:
57
+ """
58
+ Agente roteador que decide qual ferramenta usar com base na query do usuário.
59
+ """
60
+ router_prompt_template = """Você é um agente roteador. Sua tarefa é decidir qual o agente é mais apropriado para responder à pergunta do usuário.
61
+ Se a pergunta mencionar explicitamente "fontes da web", "notícias" ou for de natureza geral, escolha 'web_search'.
62
+ Se a pergunta mencionar "artigos científicos", "pesquisas", "estudos" ou for de natureza técnica/acadêmica, escolha 'scientific_search'.
63
+ Para perguntas gerais sem especificação, prefira 'web_search'.
64
+
65
+ Pergunta do usuário: {user_query}
66
+
67
+ Responda APENAS com o nome da opção escolhida: 'web_search' ou 'scientific_search'.
68
+ """
69
+ prompt = router_prompt_template.format(user_query=state["user_query"])
70
+ response = llm.invoke(prompt)
71
+ decision = response.content.strip().lower()
72
+
73
+ if "scientific_search" in decision:
74
+ return {"router_decision": "scientific_search"}
75
+ else:
76
+ return {"router_decision": "web_search"}
77
+
78
+ def supervisor_node(state: AgentState) -> dict:
79
+ """
80
+ Combina os resultados dos outros nós e formata a resposta final.
81
+ """
82
+ web_results = state.get("web_answer", "Não foi realizada pesquisa na Web.")
83
+ scientific_results = state.get("scientific_answer", "Não foi realizada pesquisa por artigos científicos.")
84
+
85
+ # Constrói a resposta final baseada nos resultados disponíveis
86
+ final_answer = "## Resultados da Pesquisa\n\n"
87
+ if state.get("web_answer"):
88
+ final_answer += "### Resultados da Pesquisa na Web\n"
89
+ final_answer += web_results
90
+ if state.get("scientific_answer"):
91
+ final_answer += "\n\n### Resultados de Artigos Científicos\n"
92
+ final_answer += scientific_results
93
+
94
+ return {"final_answer": final_answer}
main.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+
3
+ import os
4
+ import gradio as gr
5
+ from functools import partial
6
+
7
+ from langchain_google_genai import ChatGoogleGenerativeAI
8
+ from langchain.agents import load_tools
9
+ from langgraph.graph import StateGraph, START, END
10
+
11
+ # Importa as funções e a classe de estado do outro arquivo
12
+ from agente_functions import (
13
+ AgentState,
14
+ busca_web,
15
+ funcao_agente_web,
16
+ funcao_agente_cientifico,
17
+ supervisor_node,
18
+ router_agent
19
+ )
20
+
21
+ # --- 1. Configuração do Ambiente ---
22
+ # É recomendado carregar as chaves de um arquivo .env para segurança
23
+ # from dotenv import load_dotenv
24
+ # load_dotenv()
25
+ # api_key = os.getenv("GOOGLE_API_KEY")
26
+ # tavily_api_key = os.getenv("TAVILY_API_KEY")
27
+
28
+ # Para este exemplo, vamos supor que as chaves estão como variáveis de ambiente
29
+ os.environ["GOOGLE_API_KEY"] = "SUA_CHAVE_API_GEMINI_AQUI"
30
+ os.environ["TAVILY_API_KEY"] = "SUA_CHAVE_API_TAVILY_AQUI"
31
+
32
+ if not os.environ.get("GOOGLE_API_KEY") or not os.environ.get("TAVILY_API_KEY"):
33
+ print("Por favor, defina as variáveis de ambiente GOOGLE_API_KEY e TAVILY_API_KEY.")
34
+ exit()
35
+
36
+ # --- 2. Inicialização do Modelo e Ferramentas ---
37
+ llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash")
38
+ web_tools = [busca_web]
39
+ scientific_tools = load_tools(["arxiv"])
40
+
41
+
42
+ # --- 3. Construção do Grafo com LangGraph ---
43
+ workflow = StateGraph(AgentState)
44
+
45
+ # Usando functools.partial para passar argumentos fixos (llm, tools) para as funções dos nós
46
+ web_search_node = partial(funcao_agente_web, llm=llm, tools=web_tools)
47
+ scientific_search_node = partial(funcao_agente_cientifico, llm=llm, tools=scientific_tools)
48
+ router_node = partial(router_agent, llm=llm)
49
+
50
+ # Adiciona os nós ao grafo
51
+ workflow.add_node("router", router_node)
52
+ workflow.add_node("web_search", web_search_node)
53
+ workflow.add_node("scientific_search", scientific_search_node)
54
+ workflow.add_node("supervisor", supervisor_node)
55
+
56
+ # Define as arestas (fluxo de trabalho)
57
+ workflow.add_edge(START, "router")
58
+ workflow.add_conditional_edges(
59
+ "router",
60
+ lambda state: state['router_decision'],
61
+ {
62
+ "web_search": "web_search",
63
+ "scientific_search": "scientific_search"
64
+ }
65
+ )
66
+ workflow.add_edge("web_search", "supervisor")
67
+ workflow.add_edge("scientific_search", "supervisor")
68
+ workflow.add_edge("supervisor", END)
69
+
70
+ # Compila o grafo para torná-lo executável
71
+ app = workflow.compile()
72
+
73
+ # --- 4. Função para Interface do Gradio ---
74
+ def run_graph(user_query: str) -> str:
75
+ """
76
+ Executa o grafo do LangGraph com a pergunta do usuário e retorna a resposta final.
77
+ """
78
+ try:
79
+ result = app.invoke({"user_query": user_query})
80
+ # Retorna a resposta final do supervisor, com um fallback
81
+ return result.get("final_answer", "Não foi possível obter uma resposta final.")
82
+ except Exception as e:
83
+ return f"Ocorreu um erro: {e}"
84
+
85
+ # --- 5. Lançamento da Aplicação com Gradio ---
86
+ if __name__ == "__main__":
87
+ print("Iniciando a interface do Gradio...")
88
+ iface = gr.Interface(
89
+ fn=run_graph,
90
+ inputs=gr.Textbox(lines=2, label="Digite sua pergunta:", placeholder="Ex: Qual o impacto da IA na medicina?"),
91
+ outputs=gr.Markdown(label="Resposta do Agente"),
92
+ title="🤖 Agente de Pesquisa com LangGraph e Gemini",
93
+ description="Faça uma pergunta e o sistema decidirá se busca na web, em artigos científicos, ou ambos, para construir a melhor resposta.",
94
+ allow_flagging="never"
95
+ )
96
+
97
+ iface.launch()
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # requirements.txt
2
+
3
+ google-ai-generativelanguage==0.6.15
4
+ langchain-google-genai
5
+ langchain
6
+ langchain-pinecone
7
+ langchain-community
8
+ langgraph
9
+ arxiv
10
+ tavily-client
11
+ gradio