Compare commits

..

3 Commits

17 changed files with 125 additions and 4714 deletions

View File

@@ -1,12 +1,15 @@
FROM python:3.11-slim FROM python:3.11-slim
RUN pip install poetry==1.6.1 RUN pip install poetry==1.8.4
RUN poetry config virtualenvs.create false RUN poetry config virtualenvs.create false
WORKDIR /code WORKDIR /code
COPY ./pyproject.toml ./README.md ./poetry.lock* ./ COPY ./pyproject.toml ./README.md ./
# Generar el archivo lock desde cero
RUN poetry lock --no-update
COPY ./package[s] ./packages COPY ./package[s] ./packages

View File

@@ -1 +0,0 @@
{"installed":{"client_id":"19011937557-bi5nh4afvg4tuqr87v6dp55qj9a9o1h2.apps.googleusercontent.com","project_id":"oc-aassistent","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}

View File

@@ -1 +0,0 @@
{"installed":{"client_id":"629922809906-pl9l1ipout6d5hh19ku50sfvnqgu8ir2.apps.googleusercontent.com","project_id":"calendar-424503","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}

View File

@@ -2,15 +2,12 @@ from dotenv import load_dotenv
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from langchain_core.tools import tool from langchain_core.tools import tool
from datetime import datetime, timezone from datetime import datetime, timezone
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build from googleapiclient.discovery import build
from app.rag.split_docs import load_split_docs from app.rag.split_docs import load_split_docs
from app.rag.llm import load_llm_openai from app.rag.llm import load_llm_openai
from app.rag.embeddings import load_embeddins from app.rag.embeddings import load_embeddins
from app.rag.retriever import create_retriever from app.rag.retriever import create_retriever
from app.rag.vectorstore import create_verctorstore from app.rag.vectorstore import create_vectorstore
from app.rag.rag_chain import create_rag_chain from app.rag.rag_chain import create_rag_chain
import pytz import pytz
import telebot import telebot
@@ -32,12 +29,6 @@ class LangChainTools:
return llm return llm
@tool
def multiply(first_int: int, second_int: int) -> int:
"""Multiply two integers together."""
return first_int * second_int
@tool @tool
def redact_email(topic: str) -> str: def redact_email(topic: str) -> str:
"""Use this tool to draft the content of an email based on a topic.""" """Use this tool to draft the content of an email based on a topic."""
@@ -57,232 +48,6 @@ def redact_email(topic: str) -> str:
return response return response
@tool
def list_calendar_events(max_results: int = 50) -> list:
"""Use this tool to list upcoming calendar events."""
# Define los alcances que necesitamos para acceder a
# la API de Google Calendar
SCOPES = ['https://www.googleapis.com/auth/calendar']
creds = None
# La ruta al archivo token.json, que contiene
# los tokens de acceso y actualización
token_path = 'token.json'
# La ruta al archivo de credenciales de OAuth 2.1
creds_path = 'credentials.json'
# Cargar las credenciales desde el archivo token.json, si existe
if os.path.exists(token_path):
creds = Credentials.from_authorized_user_file(token_path, SCOPES)
# Si no hay credenciales válidas disponibles, inicia el flujo de OAuth 2.0
# para obtener nuevas credenciales
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
creds_path, SCOPES)
creds = flow.run_local_server(port=0)
# Guarda las credenciales para la próxima ejecución
with open(token_path, 'w') as token_file:
token_file.write(creds.to_json())
# Construye el objeto de servicio para interactuar
# con la API de Google Calendar
service = build('calendar', 'v3', credentials=creds)
# Identificador del calendario que deseas consultar.
# 'primary' se refiere al calendario principal del usuario.
calendar_id = 'primary'
# Realiza una llamada a la API para obtener una lista de eventos.
now = datetime.now(timezone.utc).isoformat() # 'Z' indica UTC
events_result = service.events().list(
calendarId=calendar_id, timeMin=now,
maxResults=max_results, singleEvents=True,
orderBy='startTime').execute()
# Extrae los eventos de la respuesta de la API.
events = events_result.get('items', [])
# Si no se encuentran eventos, imprime un mensaje.
if not events:
print('No upcoming events found.')
return
# Recorre la lista de eventos y muestra la hora de inicio
# y el resumen de cada evento.
for event in events:
# Obtiene la fecha y hora de inicio del evento.
# Puede ser 'dateTime' o 'date'.
start = event['start'].get('dateTime', event['start'].get('date'))
# Imprime la hora de inicio y el resumen (título) del evento.
print(start, event['summary'])
return events
@tool
def create_calendar_event(
title: str, start_time: datetime,
end_time: datetime, attendees: list) -> dict:
"""Use this tool to create an event in the calendar.
Parameters:
- title: str - The title of the event.
- start_time: datetime - The start time of the event.
- end_time: datetime - The end time of the event.
- attendees: list - A list of attendee emails (required).
Returns:
- dict - The created event details.
"""
if not attendees:
raise ValueError(
"El campo 'attendees' es obligatorio y no puede estar vacío.")
SCOPES = ['https://www.googleapis.com/auth/calendar']
creds = None
# La ruta al archivo token.json,
# que contiene los tokens de acceso y actualización
token_path = 'token_2.json'
# La ruta al archivo de credenciales de OAuth 2.0
creds_path = 'credentials_2.json'
# Cargar las credenciales desde el archivo token.json, si existe
if os.path.exists(token_path):
creds = Credentials.from_authorized_user_file(token_path, SCOPES)
# Si no hay credenciales válidas disponibles,
# inicia el flujo de OAuth 2.0 para obtener nuevas credenciales
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
creds_path, SCOPES)
creds = flow.run_local_server(port=0)
# Guarda las credenciales para la próxima ejecución
with open(token_path, 'w') as token_file:
token_file.write(creds.to_json())
# Construye el objeto de servicio para
# interactuar con la API de Google Calendar
service = build('calendar', 'v3', credentials=creds)
# Validar y filtrar asistentes
valid_attendees = []
for email in attendees:
if isinstance(email, str) and '@' in email:
valid_attendees.append({'email': email})
else:
raise ValueError(f"'{email}' no es un correo electrónico válido.")
# Identificador del calendario que deseas modificar.
# 'primary' se refiere al calendario principal del usuario.
calendar_id = 'primary'
# Define el cuerpo del evento con el título,
# la hora de inicio y la hora de finalización
event = {
'summary': title,
'start': {
'dateTime': start_time.strftime('%Y-%m-%dT%H:%M:%S'),
'timeZone': 'America/Bogota',
},
'end': {
'dateTime': end_time.strftime('%Y-%m-%dT%H:%M:%S'),
'timeZone': 'America/Bogota',
},
'attendees': valid_attendees
}
try:
# Crea el evento en el calendario
event = service.events().insert(
calendarId=calendar_id, body=event).execute()
print('Event created: %s' % (event.get('htmlLink')))
except Exception as e:
print(f"Error al crear el evento: {e}")
return {}
return event
@tool
def create_quick_add_event(quick_add_text: str):
"""
Use this tool to create events in the calendar from natural language,
using the Quick Add feature of Google Calendar.
"""
quick_add_text: str = input(
"- Escribe la descripcion del evento que quieres crear: ")
SCOPES = ['https://www.googleapis.com/auth/calendar']
creds = None
# La ruta al archivo token.json,
# que contiene los tokens de acceso y actualización
token_path = 'token_2.json'
# La ruta al archivo de credenciales de OAuth 2.0
creds_path = 'credentials_2.json'
# Cargar las credenciales desde el archivo token.json, si existe
if os.path.exists(token_path):
creds = Credentials.from_authorized_user_file(token_path, SCOPES)
# Si no hay credenciales válidas disponibles,
# inicia el flujo de OAuth 2.0 para obtener nuevas credenciales
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
creds_path, SCOPES)
creds = flow.run_local_server(port=0)
# Guarda las credenciales para la próxima ejecución
with open(token_path, 'w') as token_file:
token_file.write(creds.to_json())
# Construye el objeto de servicio para interactuar
# con la API de Google Calendar
service = build('calendar', 'v3', credentials=creds)
# Identificador del calendario que deseas modificar.
# 'primary' se refiere al calendario principal del usuario.
calendar_id = 'primary'
# Crea el evento utilizando la funcionalidad Quick Add
event = service.events().quickAdd(
calendarId=calendar_id, text=quick_add_text).execute()
print('Event created: %s' % (event.get('htmlLink')))
return event
# @tool
# def send_message(message: str):
# """Use this function when you need to communicate with the user."""
# # Configuración del bot
# load_dotenv()
# API_TOKEN_BOT = os.getenv("API_TOKEN_BOT")
# bot = telebot.TeleBot(API_TOKEN_BOT)
#
# bot.send_message(chat_id="5076346205", text=message)
#
@tool @tool
def send_message(message: str): def send_message(message: str):
"""Use this function when you need to communicate with Cristian.""" """Use this function when you need to communicate with Cristian."""
@@ -293,6 +58,7 @@ def send_message(message: str):
# Escapar caracteres especiales en Markdown # Escapar caracteres especiales en Markdown
from telebot.util import escape_markdown from telebot.util import escape_markdown
safe_message = escape_markdown(message) safe_message = escape_markdown(message)
# Enviar mensaje usando MarkdownV2 # Enviar mensaje usando MarkdownV2
@@ -306,31 +72,27 @@ def get_company_info(prompt: str) -> str:
Use this function when you need more information Use this function when you need more information
about the services offered by OneCluster. about the services offered by OneCluster.
""" """
file_path: str = 'onecluster_info.pdf' file_path: str = "onecluster_info.pdf"
try:
docs_split: list = load_split_docs(file_path) docs_split: list = load_split_docs(file_path)
embeddings_model = load_embeddins() embeddings_model = load_embeddins()
llm = load_llm_openai() llm = load_llm_openai()
create_verctorstore(
docs_split,
embeddings_model,
file_path
)
retriever = create_retriever(
embeddings_model,
persist_directory="embeddings/onecluster_info"
)
qa = create_rag_chain(
llm, retriever)
# prompt: str = "Escribe un parrarfo describiendo cuantos son y # Usar el nombre corregido de la función
# cuales son los servicios que ofrece OneCluster create_vectorstore(docs_split, embeddings_model, file_path)
# y brinda detalles sobre cada uno."
response = qa.invoke( retriever = create_retriever(
{"input": prompt, "chat_history": []} embeddings_model, persist_directory="embeddings/onecluster_info"
) )
qa = create_rag_chain(llm, retriever)
response = qa.invoke({"input": prompt, "chat_history": []})
return response["answer"] return response["answer"]
except Exception as e:
print(f"Error en get_company_info: {e}")
return f"Lo siento, hubo un error al procesar la información: {str(e)}"
@tool @tool
@@ -341,6 +103,6 @@ def get_current_date_and_time():
Returns: Returns:
str: Current date and time in Bogotá, Colombia. str: Current date and time in Bogotá, Colombia.
""" """
bogota_tz = pytz.timezone('America/Bogota') bogota_tz = pytz.timezone("America/Bogota")
current_date_and_time = datetime.now(bogota_tz) current_date_and_time = datetime.now(bogota_tz)
return current_date_and_time.strftime('%Y-%m-%d %H:%M:%S') return current_date_and_time.strftime("%Y-%m-%d %H:%M:%S")

View File

@@ -2,12 +2,14 @@ from langchain_chroma import Chroma
import os import os
def create_verctorstore(docs_split: list, embeddings, file_name: str): def create_vectorstore(docs_split: list, embeddings, file_name: str):
db_name: str = file_name.replace(".pdf", "").replace(" ", "_").lower() db_name: str = file_name.replace(".pdf", "").replace(" ", "_").lower()
persist_directory: str = f"embeddings/{db_name}" persist_directory: str = f"embeddings/{db_name}"
if not os.path.exists(persist_directory): # Crear el directorio si no existe
os.makedirs(persist_directory, exist_ok=True)
# Siempre crear/actualizar el vectorstore
vectordb = Chroma.from_documents( vectordb = Chroma.from_documents(
persist_directory=persist_directory, persist_directory=persist_directory,
documents=docs_split, documents=docs_split,

View File

@@ -6,17 +6,13 @@ from langserve import add_routes
from langchain_core.prompts import ChatPromptTemplate from langchain_core.prompts import ChatPromptTemplate
from langchain_community.tools.tavily_search import TavilySearchResults from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_community.tools.gmail.utils import ( from langchain_community.tools.gmail.utils import build_resource_service
build_resource_service,
get_gmail_credentials)
from langchain_community.agent_toolkits import GmailToolkit from langchain_community.agent_toolkits import GmailToolkit
from app.langchain_tools.agent_tools import ( from app.langchain_tools.agent_tools import (
redact_email, redact_email,
list_calendar_events,
create_calendar_event,
get_company_info, get_company_info,
get_current_date_and_time get_current_date_and_time,
) )
from langgraph.graph.message import add_messages from langgraph.graph.message import add_messages
@@ -26,33 +22,24 @@ from langgraph.checkpoint.memory import MemorySaver
from typing import Annotated from typing import Annotated
from typing_extensions import TypedDict from typing_extensions import TypedDict
from dotenv import load_dotenv from dotenv import load_dotenv
import os
load_dotenv() load_dotenv()
app = FastAPI() app = FastAPI()
llm = ChatOpenAI( llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.9)
model="gpt-4o-mini",
temperature=0.9
)
# # Configuración de Gmail
toolkit = GmailToolkit()
credentials = get_gmail_credentials(
token_file="token.json",
scopes=["https://mail.google.com/"],
client_secrets_file="credentials.json",
)
api_resource = build_resource_service(credentials=credentials)
toolkit = GmailToolkit(api_resource=api_resource)
# # Crear herramientas # # Crear herramientas
tools = toolkit.get_tools() tools = []
search = TavilySearchResults(max_results=2) search = TavilySearchResults(max_results=2)
tools.extend([ tools.extend(
search, redact_email, list_calendar_events, [
create_calendar_event, get_company_info, search,
get_current_date_and_time]) get_company_info,
get_current_date_and_time,
]
)
# # Definir el sistema prompt # # Definir el sistema prompt
system_prompt = ChatPromptTemplate.from_messages( system_prompt = ChatPromptTemplate.from_messages(
@@ -61,42 +48,49 @@ system_prompt = ChatPromptTemplate.from_messages(
"system", "system",
"Eres Mariana, el asistente virtual de OneCluster, una empresa de " "Eres Mariana, el asistente virtual de OneCluster, una empresa de "
"software que ofrece soluciones personalizadas. Asume el tono de " "software que ofrece soluciones personalizadas. Asume el tono de "
"J.A.R.V.I.S.: cordial, atento y con tacto en todo momento." "J.A.R.V.I.S.: cordial, atento y con tacto en todo momento.",
), ),
("system", (
"system",
"Preséntate como Mariana en el primer mensaje y pregunta el nombre " "Preséntate como Mariana en el primer mensaje y pregunta el nombre "
"del usuario si no lo tienes registrado." "del usuario si no lo tienes registrado.",
), ),
("system", (
"system",
"Si el usuario ya ha interactuado antes, usa su nombre sin necesidad " "Si el usuario ya ha interactuado antes, usa su nombre sin necesidad "
"de volver a preguntar." "de volver a preguntar.",
), ),
("system", (
"system",
"Si el primer mensaje del usuario es una solicitud, pregúntale su " "Si el primer mensaje del usuario es una solicitud, pregúntale su "
"nombre antes de responder si aún no lo conoces." "nombre antes de responder si aún no lo conoces.",
), ),
("system", (
"system",
"OneCluster es una empresa de software especializada en desarrollo a " "OneCluster es una empresa de software especializada en desarrollo a "
"medida. Solo responde a preguntas y solicitudes relacionadas con la " "medida. Solo responde a preguntas y solicitudes relacionadas con la "
"empresa y sus servicios." "empresa y sus servicios.",
), ),
("system", (
"system",
"Si necesitas información adicional sobre la empresa, usa la función " "Si necesitas información adicional sobre la empresa, usa la función "
"get_company_info." "get_company_info.",
), ),
("system", (
"system",
"Antes de enviar correos o crear eventos, muestra los detalles al " "Antes de enviar correos o crear eventos, muestra los detalles al "
"usuario para que los confirme antes de ejecutar la tarea." "usuario para que los confirme antes de ejecutar la tarea.",
), ),
("system", (
"system",
"Si te preguntan algo no relacionado con los servicios de OneCluster," "Si te preguntan algo no relacionado con los servicios de OneCluster,"
" responde que solo puedes ayudar con temas relacionados con la " " responde que solo puedes ayudar con temas relacionados con la "
"empresa y sus soluciones." "empresa y sus soluciones.",
), ),
( (
"system", "system",
"Evita mencionar o hacer alusión a las herramientas que utilizas " "Evita mencionar o hacer alusión a las herramientas que utilizas "
"internamente. Esa información es confidencial." "internamente. Esa información es confidencial.",
), ),
("placeholder", "{messages}"), ("placeholder", "{messages}"),
] ]
@@ -115,7 +109,7 @@ graph = create_react_agent(
tools=tools, tools=tools,
state_schema=State, state_schema=State,
state_modifier=system_prompt, state_modifier=system_prompt,
checkpointer=MemorySaver() checkpointer=MemorySaver(),
) )
@@ -125,11 +119,7 @@ async def redirect_root_to_docs():
# # Edit this to add the chain you want to add # # Edit this to add the chain you want to add
add_routes( add_routes(app, llm, path="/openai")
app,
llm,
path="/openai"
)
@app.post("/process_text") @app.post("/process_text")
@@ -140,9 +130,8 @@ async def process_text(request: Request):
# Procesar el texto con LangChain # Procesar el texto con LangChain
events = graph.stream( events = graph.stream(
{"messages": [("user", user_input)], "is_last_step": False}, {"messages": [("user", user_input)], "is_last_step": False},
config={"configurable": { config={"configurable": {"thread_id": "thread-1", "recursion_limit": 50}},
"thread_id": "thread-1", "recursion_limit": 50}}, stream_mode="updates",
stream_mode="updates"
) )
# Preparar la respuesta # Preparar la respuesta
@@ -151,24 +140,33 @@ async def process_text(request: Request):
if "agent" in event: if "agent" in event:
response.append(event["agent"]["messages"][-1].content) response.append(event["agent"]["messages"][-1].content)
return JSONResponse(content={'response': response}) return JSONResponse(content={"response": response})
if __name__ == "__main__": if __name__ == "__main__":
config = {"configurable": {"thread_id": "thread-1", "recursion_limit": 50}} config = {"configurable": {"thread_id": "thread-1", "recursion_limit": 50}}
# Modo interactivo por defecto
import sys
if "--server" not in sys.argv:
while True: while True:
user_input = input("User: ") user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]: if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!") print("Goodbye!")
break break
events = graph.stream({ events = graph.stream(
"messages": [("user", user_input)], {"messages": [("user", user_input)], "is_last_step": False},
"is_last_step": False}, config,
config, stream_mode="updates") stream_mode="updates",
)
for event in events: for event in events:
if "agent" in event: if "agent" in event:
print( print(f"\nAsistente: {event['agent']['messages'][-1].content}\n")
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)

View File

View File

@@ -1,27 +0,0 @@
from fastapi.testclient import TestClient
from app.server import app # Asegúrate de importar tu aplicación FastAPI
# Crea un cliente de prueba
client = TestClient(app)
def test_process_text():
# Define el texto de entrada
input_text = {"text": "Hola, ¿cómo estás?"}
# Realiza una solicitud POST al endpoint
response = client.post("/process_text", json=input_text)
# Verifica que la respuesta tenga un código de estado 200
assert response.status_code == 200
# Verifica que la respuesta contenga la clave 'response'
assert 'response' in response.json()
# Verifica que la respuesta sea una lista
assert isinstance(response.json()['response'], list)
# Aquí puedes agregar más verificaciones
# según lo que esperas en la respuesta
# Por ejemplo, verificar que la lista no esté vacía
assert len(response.json()['response']) > 0

View File

@@ -1 +0,0 @@
{"token": "ya29.a0AeDClZCbHA_Ubcy6IrJJZgcHOb95xrUDMIjoNryaK6DaV7RH93INeBAeKIAfaDw73grkGnBD2Ub2QuvqvRMJO6DvivonA6yoLj7hFvDgSLsfNXo5xcLJqsgiIiOfExr74m4WcT5jnpZswxk3ZuEtAoXuPDW7hzLXnTwk6sFDmAaCgYKAeoSARASFQHGX2MiPDgm1tQCv4YbN3Bq9f4zvg0177", "refresh_token": "1//05Hc2PufwLWe2CgYIARAAGAUSNwF-L9IrU2s--kkp6Q2fCzN5uf2vLBvEcYHyJOFZjCQAUpBSC0FWiCUg9wgm8cCMccEGe4Q7MPg", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "19011937557-bi5nh4afvg4tuqr87v6dp55qj9a9o1h2.apps.googleusercontent.com", "client_secret": "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", "scopes": ["https://mail.google.com/"], "universe_domain": "googleapis.com", "account": "", "expiry": "2024-11-07T23:37:58.891983Z"}

View File

@@ -1 +0,0 @@
{"token": "ya29.a0AeDClZC30_gM1YE3u8XHKpmLqIcABYBZzJOVQfrNyUJrFuOPxNpt96IbTeCIM266Es--v34aMA70oZG1GIELbcuExSSQ25_pzdHd9yS18vDOgdz8OtuG24_2DGnaCy7FOQBZzFr5GxgLJ_657Zal3RF8lreEFLyVLKdGf6TiaCgYKATMSARASFQHGX2MiirXKmKxKPjAWuSG0af_xmw0175", "refresh_token": "1//05akITlwASya5CgYIARAAGAUSNwF-L9IryPh1Y647Eim5KZZhD3DKCuUtkAp28N30ed1TALtax5TkflyKGxDtBmayKowuMZkaT9k", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "629922809906-pl9l1ipout6d5hh19ku50sfvnqgu8ir2.apps.googleusercontent.com", "client_secret": "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", "scopes": ["https://www.googleapis.com/auth/calendar"], "universe_domain": "googleapis.com", "account": "", "expiry": "2024-11-02T23:47:30.521929Z"}

View File

@@ -1 +0,0 @@
{"installed":{"client_id":"19011937557-bi5nh4afvg4tuqr87v6dp55qj9a9o1h2.apps.googleusercontent.com","project_id":"oc-aassistent","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}

View File

@@ -1 +0,0 @@
{"installed":{"client_id":"629922809906-pl9l1ipout6d5hh19ku50sfvnqgu8ir2.apps.googleusercontent.com","project_id":"calendar-424503","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}

View File

@@ -13,8 +13,11 @@ services:
- "8080:8080" - "8080:8080"
volumes: volumes:
- .:/code - .:/code
- ./google_credentials.json:/code/google_credentials.json
- ./tokens:/code/tokens
environment: environment:
- PYTHONUNBUFFERED=1 - PYTHONUNBUFFERED=1
- GOOGLE_APPLICATION_CREDENTIALS=/code/google_credentials.json
command: > command: >
uvicorn app.server:app --host 0.0.0.0 --port 8080 uvicorn app.server:app --host 0.0.0.0 --port 8080
env_file: env_file:

4322
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,18 +9,20 @@ packages = [
] ]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.11" python = "^3.9"
uvicorn = "^0.23.2" uvicorn = "^0.23.2"
langserve = {extras = ["server"], version = ">=0.0.30"} langserve = {extras = ["server"], version = ">=0.0.30"}
pydantic = "<3" pydantic = "<3"
langgraph = "^0.2.28" langgraph = "^0.2.28"
langchain-community = "^0.3.1" langchain = "^0.3.8"
langchain-community = "^0.3.8"
langchain-openai = "^0.2.5" langchain-openai = "^0.2.5"
langchain-chroma = "^0.1.4" langchain-chroma = "^0.1.4"
google = "^3.0.0" google = "^3.0.0"
google-auth = "^2.35.0" google-auth = "^2.35.0"
google-auth-oauthlib = "^1.2.0" google-auth-oauthlib = "^1.1.0"
google-api-python-client = "^2.131.0" google-auth-httplib2 = "^0.1.0"
google-api-python-client = "^2.108.0"
flake8 = "^7.1.1" flake8 = "^7.1.1"
httpx = "^0.27.2" httpx = "^0.27.2"
pytest = "^8.3.3" pytest = "^8.3.3"
@@ -31,8 +33,6 @@ pytz = "^2024.2"
telebot = "^0.0.5" telebot = "^0.0.5"
pypdf = "^5.1.0" pypdf = "^5.1.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
langchain-cli = ">=0.0.15" langchain-cli = ">=0.0.15"

View File

@@ -1 +0,0 @@
{"token": "ya29.a0AeDClZCbHA_Ubcy6IrJJZgcHOb95xrUDMIjoNryaK6DaV7RH93INeBAeKIAfaDw73grkGnBD2Ub2QuvqvRMJO6DvivonA6yoLj7hFvDgSLsfNXo5xcLJqsgiIiOfExr74m4WcT5jnpZswxk3ZuEtAoXuPDW7hzLXnTwk6sFDmAaCgYKAeoSARASFQHGX2MiPDgm1tQCv4YbN3Bq9f4zvg0177", "refresh_token": "1//05Hc2PufwLWe2CgYIARAAGAUSNwF-L9IrU2s--kkp6Q2fCzN5uf2vLBvEcYHyJOFZjCQAUpBSC0FWiCUg9wgm8cCMccEGe4Q7MPg", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "19011937557-bi5nh4afvg4tuqr87v6dp55qj9a9o1h2.apps.googleusercontent.com", "client_secret": "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", "scopes": ["https://mail.google.com/"], "universe_domain": "googleapis.com", "account": "", "expiry": "2024-11-07T23:37:58.891983Z"}

View File

@@ -1 +0,0 @@
{"token": "ya29.a0AeDClZC30_gM1YE3u8XHKpmLqIcABYBZzJOVQfrNyUJrFuOPxNpt96IbTeCIM266Es--v34aMA70oZG1GIELbcuExSSQ25_pzdHd9yS18vDOgdz8OtuG24_2DGnaCy7FOQBZzFr5GxgLJ_657Zal3RF8lreEFLyVLKdGf6TiaCgYKATMSARASFQHGX2MiirXKmKxKPjAWuSG0af_xmw0175", "refresh_token": "1//05akITlwASya5CgYIARAAGAUSNwF-L9IryPh1Y647Eim5KZZhD3DKCuUtkAp28N30ed1TALtax5TkflyKGxDtBmayKowuMZkaT9k", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "629922809906-pl9l1ipout6d5hh19ku50sfvnqgu8ir2.apps.googleusercontent.com", "client_secret": "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", "scopes": ["https://www.googleapis.com/auth/calendar"], "universe_domain": "googleapis.com", "account": "", "expiry": "2024-11-02T23:47:30.521929Z"}