Spaces:
Sleeping
Sleeping
# =========================================== | |
# title: daysoff-assistant-API-v2 | |
# file: app.py | |
# =========================================== | |
import json | |
import asyncio | |
import os | |
import re | |
import requests | |
from dotenv import load_dotenv | |
import chainlit as cl | |
from langchain import hub | |
from langchain_openai import OpenAI | |
from langchain.chains import LLMChain | |
from langchain_core.prompts import PromptTemplate | |
from langchain.memory.buffer import ConversationBufferMemory | |
# ---------------------------------------------------for backend looks, example file:---------------------------------- | |
#with open('/usr/local/lib/python3.10/site-packages/transformers/utils/chat_template_utils.py', 'r') as file: | |
#content = file.read() | |
#print("base.py:", content) | |
# ------------------------------------------------------the end-------------------------------------------------------- | |
load_dotenv() | |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") | |
auth_token = os.environ.get("DAYSOFF_API_TOKEN") | |
API_URL = "https://aivisions.no/data/daysoff/api/v1/booking/" | |
# and help users retrieve booking information associated with their bookingnr | |
# Provide a conversational answer. | |
# This way you directly address the user's question in a manner that reflects the professionalism and warmth | |
# of a customer support representative (female). | |
daysoff_assistant_template = """ | |
You are a customer support assistant for Daysoff kundeservice and help users retrieve their booking information based on a bookingnr they give you. | |
It is important that you use the term "bookingnr". | |
Users may reference their bookingnr in different ways. | |
# examples | |
Norwegian Terms: | |
- booking | |
- bookingnr | |
- bestillingsnummer | |
- bookingen | |
- ordrenummer | |
- bookingreferanse | |
- bestilling | |
- booket | |
English Terms: | |
- reservation | |
- reservation number | |
- order number | |
- booking ID | |
Polish Terms: | |
- rezerwacji | |
- rezerwacja | |
- identyfikacyjny pลatnoลci | |
If there is no booking information available for a booking ID, just say so and politely suggest they contact **[email protected]** | |
to enquire further. | |
Maintain a conversational and professional tone, **reflecting the warmth of | |
a female customer support representative archetype.** | |
By default, you answer in **Norwegian**. | |
Chat History: {chat_history} | |
Question: {question} | |
Answer: | |
""" | |
daysoff_assistant_prompt = PromptTemplate( | |
input_variables=["chat_history", "question"], | |
template=daysoff_assistant_template, | |
) | |
# ============================================================================================================= | |
class APIConnectionError(Exception): | |
"""Raised when API connection fails""" | |
pass | |
class APIResponseError(Exception): | |
"""Raised when API returns invalid response""" | |
pass | |
class BookingNotFoundError(Exception): | |
"""Raised when booking ID is not found""" | |
pass | |
# ============================================================================================================= | |
#async def async_post_request(url, headers, data): | |
#return await asyncio.to_thread(requests.post, url, headers=headers, json=data) | |
# ============================================================================================================= | |
async def async_post_request(url, headers, data): | |
try: | |
response = await asyncio.to_thread(requests.post, url, headers=headers, json=data) | |
response.raise_for_status() | |
return response | |
except requests.ConnectionError: | |
raise APIConnectionError("Failed to connect to booking service") | |
except requests.Timeout: | |
raise APIConnectionError("Request timed out") | |
except requests.RequestException as e: | |
raise APIResponseError(f"API request failed: {str(e)}") | |
# ============================================================================================================= | |
def setup_multiple_chains(): | |
llm = OpenAI( | |
model="gpt-3.5-turbo-instruct", | |
temperature=0.7, | |
openai_api_key=OPENAI_API_KEY, | |
max_tokens=2048, | |
top_p=0.9, | |
frequency_penalty=0.1, | |
presence_penalty=0.1, | |
) | |
conversation_memory = ConversationBufferMemory( | |
memory_key="chat_history", | |
max_len=30, | |
return_messages=True | |
) | |
llm_chain = LLMChain( | |
llm=llm, | |
prompt=daysoff_assistant_prompt, | |
memory=conversation_memory, | |
) | |
cl.user_session.set("llm_chain", llm_chain) | |
async def handle_message(message: cl.Message): | |
user_message = message.content | |
llm_chain = cl.user_session.get("llm_chain") | |
booking_pattern = r'\b[A-Z]{6}\d{6}\b' | |
match = re.search(booking_pattern, user_message) | |
if match: | |
bestillingskode = match.group() | |
headers = { | |
"Authorization": auth_token, | |
"Content-Type": "application/json" | |
} | |
payload = {"booking_id": bestillingskode} | |
try: | |
# --async POST request | |
response = await async_post_request(API_URL, headers, payload) | |
response.raise_for_status() | |
booking_data = response.json() | |
if not booking_data: | |
raise BookingNotFoundError("No booking data returned") | |
if "error" in booking_data: | |
raise APIResponseError(booking_data["error"]) | |
# --markdown_table | |
table = ( | |
"| ๐ญ๐๐๐๐ | ๐๐ป๐ณ๐ผ |\n" | |
"|:-----------|:---------------------|\n" | |
f"| ๐ฑ๐๐๐๐๐๐๐๐๐๐๐๐๐๐ | {booking_data.get('booking_id', 'N/A')} |\n" | |
f"| ๐๐ช๐ก๐ก ๐๐๐ข๐ | {booking_data.get('full_name', 'N/A')} |\n" | |
f"| ๐ผ๐ข๐ค๐ช๐ฃ๐ฉ | {booking_data.get('amount', 0)} kr |\n" | |
f"| ๐พ๐๐๐๐ -๐๐ฃ | {booking_data.get('checkin', 'N/A')} |\n" | |
f"| ๐พ๐๐๐๐ -๐ค๐ช๐ฉ | {booking_data.get('checkout', 'N/A')} |\n" | |
f"| ๐ผ๐๐๐ง๐๐จ๐จ | {booking_data.get('address', 'N/A')} |\n" | |
f"| ๐๐จ๐๐ง ๐๐ฟ | {booking_data.get('user_id', 0)} |\n" | |
f"| ๐๐ฃ๐๐ค ๐๐๐ญ๐ฉ | {booking_data.get('infotext', 'N/A')} |\n" | |
f"| ๐๐ฃ๐๐ก๐ช๐๐๐ | {booking_data.get('included', 'N/A')} |" | |
) | |
combined_message = f"### Informasjon om booking:\n\n{table}" | |
await cl.Message(content=combined_message).send() | |
except (APIConnectionError, APIResponseError, BookingNotFoundError) as e: | |
error_messages = { | |
APIConnectionError: "Kunne ikke koble til bookingsystemet. Prรธv igjen senere.", | |
APIResponseError: "Det oppstod en feil ved henting av bookingdata.", | |
BookingNotFoundError: "Ingen booking funnet med denne koden." | |
} | |
await cl.Message(content=f"โ {error_messages[type(e)]}\n\nPrรธv igjen, kanskje du feilstavet eller glemte ett siffer?\n\nHvis du ser denne feilmedlingen gjentatte ganger, foreslรฅr jeg at du kontakt [email protected] for assistanse.").send() | |
return None | |
except requests.exceptions.RequestException as e: | |
await cl.Message(content="En uventet feil oppstod. Vennligst kontakt [email protected]").send() | |
return None | |
else: | |
try: | |
response = await llm_chain.ainvoke({ | |
"question": user_message, | |
"chat_history": "" | |
}, callbacks=[cl.AsyncLangchainCallbackHandler()]) | |
await cl.Message(content=response["text"]).send() | |
except Exception as e: | |
await cl.Message(content=f"Error: {str(e)}").send() | |