173 lines
4.9 KiB
Python
173 lines
4.9 KiB
Python
from fastapi import FastAPI, Request
|
|
from fastapi.responses import JSONResponse, RedirectResponse
|
|
from langchain_openai import ChatOpenAI
|
|
from langserve import add_routes
|
|
|
|
from langchain_core.prompts import ChatPromptTemplate
|
|
|
|
from langchain_community.tools.tavily_search import TavilySearchResults
|
|
from langchain_community.tools.gmail.utils import build_resource_service
|
|
from langchain_community.agent_toolkits import GmailToolkit
|
|
|
|
from app.langchain_tools.agent_tools import (
|
|
redact_email,
|
|
get_company_info,
|
|
get_current_date_and_time,
|
|
)
|
|
|
|
from langgraph.graph.message import add_messages
|
|
from langgraph.prebuilt import create_react_agent
|
|
from langgraph.checkpoint.memory import MemorySaver
|
|
|
|
from typing import Annotated
|
|
from typing_extensions import TypedDict
|
|
from dotenv import load_dotenv
|
|
import os
|
|
|
|
load_dotenv()
|
|
|
|
app = FastAPI()
|
|
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.9)
|
|
|
|
|
|
# # Crear herramientas
|
|
tools = []
|
|
search = TavilySearchResults(max_results=2)
|
|
tools.extend(
|
|
[
|
|
search,
|
|
get_company_info,
|
|
get_current_date_and_time,
|
|
]
|
|
)
|
|
|
|
# # Definir el sistema prompt
|
|
system_prompt = ChatPromptTemplate.from_messages(
|
|
[
|
|
(
|
|
"system",
|
|
"Eres Mariana, el asistente virtual de OneCluster, una empresa de "
|
|
"software que ofrece soluciones personalizadas. Asume el tono de "
|
|
"J.A.R.V.I.S.: cordial, atento y con tacto en todo momento.",
|
|
),
|
|
(
|
|
"system",
|
|
"Preséntate como Mariana en el primer mensaje y pregunta el nombre "
|
|
"del usuario si no lo tienes registrado.",
|
|
),
|
|
(
|
|
"system",
|
|
"Si el usuario ya ha interactuado antes, usa su nombre sin necesidad "
|
|
"de volver a preguntar.",
|
|
),
|
|
(
|
|
"system",
|
|
"Si el primer mensaje del usuario es una solicitud, pregúntale su "
|
|
"nombre antes de responder si aún no lo conoces.",
|
|
),
|
|
(
|
|
"system",
|
|
"OneCluster es una empresa de software especializada en desarrollo a "
|
|
"medida. Solo responde a preguntas y solicitudes relacionadas con la "
|
|
"empresa y sus servicios.",
|
|
),
|
|
(
|
|
"system",
|
|
"Si necesitas información adicional sobre la empresa, usa la función "
|
|
"get_company_info.",
|
|
),
|
|
(
|
|
"system",
|
|
"Antes de enviar correos o crear eventos, muestra los detalles al "
|
|
"usuario para que los confirme antes de ejecutar la tarea.",
|
|
),
|
|
(
|
|
"system",
|
|
"Si te preguntan algo no relacionado con los servicios de OneCluster,"
|
|
" responde que solo puedes ayudar con temas relacionados con la "
|
|
"empresa y sus soluciones.",
|
|
),
|
|
(
|
|
"system",
|
|
"Evita mencionar o hacer alusión a las herramientas que utilizas "
|
|
"internamente. Esa información es confidencial.",
|
|
),
|
|
("placeholder", "{messages}"),
|
|
]
|
|
)
|
|
|
|
|
|
# # Definir el estado del asistente
|
|
class State(TypedDict):
|
|
messages: Annotated[list, add_messages]
|
|
is_last_step: bool
|
|
|
|
|
|
# # Crear el graph con el estado definido
|
|
graph = create_react_agent(
|
|
model=llm,
|
|
tools=tools,
|
|
state_schema=State,
|
|
state_modifier=system_prompt,
|
|
checkpointer=MemorySaver(),
|
|
)
|
|
|
|
|
|
@app.get("/")
|
|
async def redirect_root_to_docs():
|
|
return RedirectResponse("/docs")
|
|
|
|
|
|
# # Edit this to add the chain you want to add
|
|
add_routes(app, llm, path="/openai")
|
|
|
|
|
|
@app.post("/process_text")
|
|
async def process_text(request: Request):
|
|
data = await request.json()
|
|
user_input = data.get("text")
|
|
|
|
# Procesar el texto con LangChain
|
|
events = graph.stream(
|
|
{"messages": [("user", user_input)], "is_last_step": False},
|
|
config={"configurable": {"thread_id": "thread-1", "recursion_limit": 50}},
|
|
stream_mode="updates",
|
|
)
|
|
|
|
# Preparar la respuesta
|
|
response = []
|
|
for event in events:
|
|
if "agent" in event:
|
|
response.append(event["agent"]["messages"][-1].content)
|
|
|
|
return JSONResponse(content={"response": response})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
config = {"configurable": {"thread_id": "thread-1", "recursion_limit": 50}}
|
|
|
|
# Modo interactivo por defecto
|
|
import sys
|
|
|
|
if "--server" not in sys.argv:
|
|
while True:
|
|
user_input = input("User: ")
|
|
if user_input.lower() in ["quit", "exit", "q"]:
|
|
print("Goodbye!")
|
|
break
|
|
|
|
events = graph.stream(
|
|
{"messages": [("user", user_input)], "is_last_step": False},
|
|
config,
|
|
stream_mode="updates",
|
|
)
|
|
|
|
for event in events:
|
|
if "agent" in event:
|
|
print(f"\nAsistente: {event['agent']['messages'][-1].content}\n")
|
|
else:
|
|
# Modo servidor con uvicorn
|
|
import uvicorn
|
|
|
|
uvicorn.run(app, host="0.0.0.0", port=8080)
|