camparchimedes's picture
Update app.py
0720180 verified
# ===========================================
# 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).
# If users have more in-depth queries about their booking information, politely suggest they contact **[email protected]** to enquire further.
daysoff_assistant_template = """
You are a customer support assistant for Daysoff ('Daysoff Kundeservice AI Support') who helps users retrieve booking information based on their bookingnummer.
You should concisely use the term โ€™bookingnummerโ€™. 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)}")
# =============================================================================================================
@cl.on_chat_start
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)
@cl.on_message
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()