Spaces:
Paused
Paused
Commit
·
e1835d3
1
Parent(s):
a1cc0a4
Upload 3 files
Browse files- app.py +122 -0
- requirements.txt +2 -0
- utils.py +110 -0
app.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import openai
|
| 3 |
+
import json
|
| 4 |
+
import time
|
| 5 |
+
from utils import get_trip
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
openai.api_key = "sk-"+os.environ["OPENAI_API_KEY"]
|
| 9 |
+
|
| 10 |
+
# Tu función get_trip aquí
|
| 11 |
+
|
| 12 |
+
context = [{'role': 'system', 'content': """
|
| 13 |
+
Eres CegaperGPT, un servicio automatizado para recomendar la mejor opción de transporte de la compañía Cegaper y ayudar a los usuarios a comprar sus tickets.
|
| 14 |
+
Cegaper es una compañía de transporte terrestre (autobuses, vans y camiones) que opera en México.
|
| 15 |
+
Primero, saludas al cliente diciendo tu nombre, luego preguntas por los detalles del viaje y después solicitas la información personal del comprador.
|
| 16 |
+
Esperas hasta recopilar todo el pedido, luego lo resumes y verificas.
|
| 17 |
+
Finalmente, recoges el pago.
|
| 18 |
+
Asegúrate de aclarar todas las opciones para seleccionar el viaje correcto para el usuario.
|
| 19 |
+
Respondes en un estilo amigable, conversacional y breve. \
|
| 20 |
+
"""}]
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def get_completion_from_messages(messages, temperature=0.1):
|
| 24 |
+
functions = [{
|
| 25 |
+
"name": "get_trip",
|
| 26 |
+
"description": "Encuentra el mejor plan de viaje desde el origen hasta el destino en un rango de fechas dado.",
|
| 27 |
+
"parameters": {
|
| 28 |
+
"type": "object",
|
| 29 |
+
"properties": {
|
| 30 |
+
"origin": {
|
| 31 |
+
"type": "string",
|
| 32 |
+
"description": "La dirección de origen, debe cumplir con el estándar de Google Maps.",
|
| 33 |
+
},
|
| 34 |
+
"destination": {
|
| 35 |
+
"type": "string",
|
| 36 |
+
"description": "La dirección de origen, debe cumplir con el estándar de Google Maps.",
|
| 37 |
+
},
|
| 38 |
+
"date_from": {
|
| 39 |
+
"type": "string",
|
| 40 |
+
"description": "La fecha de inicio del rango a considerar para el viaje en formato YYYY-MM-DD",
|
| 41 |
+
},
|
| 42 |
+
"date_to": {
|
| 43 |
+
"type": "string",
|
| 44 |
+
"description": "La fecha de fin del rango a considerar para el viaje en formato YYYY-MM-DD",
|
| 45 |
+
},
|
| 46 |
+
"pax": {
|
| 47 |
+
"type": "integer",
|
| 48 |
+
"description": "El número de pasajeros para el viaje",
|
| 49 |
+
},
|
| 50 |
+
"round_trip": {
|
| 51 |
+
"type": "boolean",
|
| 52 |
+
"description": "Si el viaje debe ser de ida y vuelta o no. Si es verdadero, se requiere date_to.",
|
| 53 |
+
}
|
| 54 |
+
},
|
| 55 |
+
"required": ["origin", "destination", "date_from", "pax"],
|
| 56 |
+
}
|
| 57 |
+
}]
|
| 58 |
+
|
| 59 |
+
response = openai.ChatCompletion.create(
|
| 60 |
+
model="gpt-4-0613",
|
| 61 |
+
messages=messages,
|
| 62 |
+
functions=functions,
|
| 63 |
+
function_call="auto",
|
| 64 |
+
)
|
| 65 |
+
response_message = response["choices"][0]["message"]
|
| 66 |
+
|
| 67 |
+
if response_message.get("function_call"):
|
| 68 |
+
available_functions = {
|
| 69 |
+
"get_trip": get_trip,
|
| 70 |
+
}
|
| 71 |
+
function_name = response_message["function_call"]["name"]
|
| 72 |
+
function_to_call = available_functions[function_name]
|
| 73 |
+
function_args = json.loads(
|
| 74 |
+
response_message["function_call"]["arguments"])
|
| 75 |
+
function_response = function_to_call(
|
| 76 |
+
origin=function_args.get("origin"),
|
| 77 |
+
destination=function_args.get("destination"),
|
| 78 |
+
date_from=function_args.get("date_from"),
|
| 79 |
+
date_to=function_args.get("date_to"),
|
| 80 |
+
round_trip=function_args.get("round_trip"),
|
| 81 |
+
pax=function_args.get("pax"),
|
| 82 |
+
)
|
| 83 |
+
|
| 84 |
+
messages.append(response_message)
|
| 85 |
+
messages.append(
|
| 86 |
+
{
|
| 87 |
+
"role": "function",
|
| 88 |
+
"name": function_name,
|
| 89 |
+
"content": function_response,
|
| 90 |
+
}
|
| 91 |
+
)
|
| 92 |
+
second_response = openai.ChatCompletion.create(
|
| 93 |
+
model="gpt-4-0613",
|
| 94 |
+
messages=messages
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
if 'second_response' not in locals():
|
| 98 |
+
messages.append(response_message)
|
| 99 |
+
second_response = openai.ChatCompletion.create(
|
| 100 |
+
model="gpt-4-0613",
|
| 101 |
+
messages=messages
|
| 102 |
+
)
|
| 103 |
+
return second_response.choices[0].message["content"]
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def respuesta_chatbot(message, chat_history):
|
| 107 |
+
context.append({'role': 'user', 'content': f"{message}"})
|
| 108 |
+
response = get_completion_from_messages(context)
|
| 109 |
+
context.append({'role': 'assistant', 'content': f"{response}"})
|
| 110 |
+
chat_history.append((message, response))
|
| 111 |
+
time.sleep(2)
|
| 112 |
+
return "", chat_history
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
with gr.Blocks() as demo:
|
| 116 |
+
chatbot = gr.Chatbot()
|
| 117 |
+
msg = gr.Textbox()
|
| 118 |
+
clear = gr.ClearButton([msg, chatbot])
|
| 119 |
+
|
| 120 |
+
msg.submit(respuesta_chatbot, [msg, chatbot], [msg, chatbot])
|
| 121 |
+
|
| 122 |
+
demo.launch(title="Cegaper GPT", description="¡Bienvenido a Cegaper GPT! Soy CegaperGPT, un servicio automatizado para recomendar la mejor opción de transporte de la compañía Cegaper y ayudarte a comprar tus tickets.")
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
googlemaps==4.10.0
|
| 2 |
+
openai==0.27.8
|
utils.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import googlemaps
|
| 2 |
+
import datetime
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
# Crear un cliente de la API de Google Maps
|
| 6 |
+
gmaps = googlemaps.Client(key=os.environ["GOOGLE_MAPS_API_KEY"])
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Trip:
|
| 10 |
+
def __init__(self, origin, destination, departure_date, return_date, cost, car_type, pax):
|
| 11 |
+
self.origin = origin
|
| 12 |
+
self.destination = destination
|
| 13 |
+
self.departure_date = departure_date
|
| 14 |
+
self.return_date = return_date # esto puede ser None ahora
|
| 15 |
+
self.cost = cost
|
| 16 |
+
self.car_type = car_type
|
| 17 |
+
self.pax = pax
|
| 18 |
+
|
| 19 |
+
def to_dict(self):
|
| 20 |
+
trip_dict = {
|
| 21 |
+
'origin': self.origin,
|
| 22 |
+
'destination': self.destination,
|
| 23 |
+
'cost': self.cost,
|
| 24 |
+
'car_type': self.car_type,
|
| 25 |
+
'departure_date': self.departure_date.isoformat(),
|
| 26 |
+
'pax': self.pax
|
| 27 |
+
}
|
| 28 |
+
if self.return_date is not None:
|
| 29 |
+
trip_dict['return_date'] = self.return_date.isoformat()
|
| 30 |
+
return trip_dict
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def determine_car_type(pax):
|
| 34 |
+
if 0 < pax < 6:
|
| 35 |
+
return "Transporter"
|
| 36 |
+
elif pax < 16:
|
| 37 |
+
return "Crafter"
|
| 38 |
+
elif pax < 23:
|
| 39 |
+
return "Minibus"
|
| 40 |
+
elif pax < 50:
|
| 41 |
+
return "Bus"
|
| 42 |
+
else:
|
| 43 |
+
return "Invalid"
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def get_distance(origin: str, destination: str):
|
| 47 |
+
matrix = gmaps.distance_matrix(origin, destination)
|
| 48 |
+
distance_meters = matrix['rows'][0]['elements'][0]['distance']['value']
|
| 49 |
+
return distance_meters / 1000
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def calculate_cost(distance, car_type):
|
| 53 |
+
base_cost_per_km = {
|
| 54 |
+
"Transporter": 50,
|
| 55 |
+
"Crafter": 75,
|
| 56 |
+
"Minibus": 100,
|
| 57 |
+
"Bus": 150
|
| 58 |
+
}
|
| 59 |
+
cost = distance * base_cost_per_km[car_type]
|
| 60 |
+
return round(max(500, min(20000, cost)))
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def generate_trip_data(origin: str, destination: str, date_from: datetime, date_to: datetime, car_type: str, pax: int):
|
| 64 |
+
distance = get_distance(origin, destination)
|
| 65 |
+
base_cost = calculate_cost(distance, car_type)
|
| 66 |
+
trip = Trip(origin, destination, date_from,
|
| 67 |
+
date_to, base_cost, car_type, pax)
|
| 68 |
+
return trip
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def get_trip(origin: str, destination: str, date_from: str, date_to=None, pax=1, round_trip: bool = False):
|
| 72 |
+
date_from = datetime.datetime.strptime(date_from, "%Y-%m-%d")
|
| 73 |
+
|
| 74 |
+
if date_to is not None:
|
| 75 |
+
date_to = datetime.datetime.strptime(date_to, "%Y-%m-%d")
|
| 76 |
+
|
| 77 |
+
car_type = determine_car_type(pax)
|
| 78 |
+
|
| 79 |
+
trip_origin = generate_trip_data(
|
| 80 |
+
origin, destination, date_from, date_to if round_trip else None, car_type, pax)
|
| 81 |
+
|
| 82 |
+
trip_return = None
|
| 83 |
+
if round_trip and date_to is not None:
|
| 84 |
+
trip_return = generate_trip_data(
|
| 85 |
+
destination, origin, date_to, None, car_type, pax)
|
| 86 |
+
|
| 87 |
+
trip_origin_dict = trip_origin.to_dict()
|
| 88 |
+
|
| 89 |
+
trip_info = "The trip to your destination is from " + trip_origin_dict['origin'] + " to " + trip_origin_dict['destination'] + " with a cost of " + str(
|
| 90 |
+
trip_origin_dict['cost']) + " and a car type of " + trip_origin_dict['car_type'] + ". "
|
| 91 |
+
|
| 92 |
+
if trip_return is not None:
|
| 93 |
+
trip_return_dict = trip_return.to_dict()
|
| 94 |
+
trip_info += "The return trip is from " + trip_return_dict['origin'] + " to " + trip_return_dict['destination'] + " with a cost of " + str(
|
| 95 |
+
trip_return_dict['cost']) + " and a car type of " + trip_return_dict['car_type'] + "."
|
| 96 |
+
|
| 97 |
+
return trip_info
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def get_trip_info(trip_origin: Trip, trip_return: Trip = None):
|
| 101 |
+
trip_origin = trip_origin.to_dict()
|
| 102 |
+
trip_info = "The trip to your destination is from " + trip_origin['origin'] + " to " + trip_origin['destination'] + " with a cost of " + str(
|
| 103 |
+
trip_origin['cost']) + " and a car type of " + trip_origin['car_type'] + ". "
|
| 104 |
+
|
| 105 |
+
if trip_return is not None:
|
| 106 |
+
trip_return = trip_return.to_dict()
|
| 107 |
+
trip_info += "The return trip is from " + trip_return['origin'] + " to " + trip_return['destination'] + " with a cost of " + str(
|
| 108 |
+
trip_return['cost']) + " and a car type of " + trip_return['car_type'] + "."
|
| 109 |
+
|
| 110 |
+
return trip_info
|