File size: 11,404 Bytes
3ba989c 747720a 3ba989c 12654ba bdbc697 12654ba bdbc697 12654ba bdbc697 12654ba bdbc697 12654ba 747720a 12654ba 78b9b84 12654ba a173bf9 12654ba a173bf9 efdd6c6 a173bf9 12654ba 528c393 12654ba 3951ea6 12654ba 528c393 f79a832 a173bf9 bc5512a a173bf9 bdbc697 a173bf9 747720a 3d9121f 12654ba 1c5f7dd 528c393 e9a5c04 528c393 eb4924a 12654ba 747720a 12654ba a77a669 12654ba eb4924a bdbc697 1c5f7dd 528c393 12654ba eb4924a bdbc697 eb4924a f79a832 eb4924a f79a832 eb4924a bdbc697 eb4924a bdbc697 eb4924a 528c393 eb4924a 76a13b9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# ===================================================================================================
# Note: chainlit==0.7.500 <โโโโwas | isโโโโ> chainlit==2.0.603 / Demo Daysoff kundeservice ๐ผ๐ support
# title: ๐ฟ๐๐ฎ๐จ๐ค๐๐ ๐ผ๐จ๐จ๐๐จ๐ฉ๐๐ฃ๐ฉ-API-v2.0.603| custom starters | API error handling
# file: app.py
# ===================================================================================================
import os
import re
import json
import asyncio
import requests
from pathlib import Path
from datetime import datetime
from dotenv import load_dotenv
import chainlit as cl
from concurrent.futures import ThreadPoolExecutor
from chainlit import user_session
from chainlit.session import WebsocketSession
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
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/"
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โ.
By default, you respond using Norwegian.
Provide a conversational answer.
This way you directly address the user's question in a manner that reflects the professionalism and warmth of a a female customer support representative archetype.
============================
Chat History: {chat_history}
Question: {question}
============================
Answer in Markdown:
"""
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):
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.set_starters
async def set_starters():
return [
cl.Starter(
label="Booking ID request",
message="Kan du gi meg info om en reservasjon?",
icon="/public/booking_id.svg",
),
cl.Starter(
label="Metric Space Self-Identity Framework",
message="Explain the Metric Space Self-Identity Framework like I'm six years old.",
icon="/public/learn.svg",
),
cl.Starter(
label="Python script for daily email reports",
message="Write a script to automate sending daily email reports in Python, and walk me through how I would set it up.",
icon="/public/terminal.svg",
),
cl.Starter(
label="Morning routine ideation",
message="Can you help me create a personalized Yoga/pranayama/meditation morning routine that would help increase my productivity throughout the day? Start by asking me about my current habits and what activities energize me in the morning.",
icon="/public/idea.svg",
)
]
#------?-----@cl.Step
#------?-----@cl.Context
@cl.on_chat_start
async def main():
res = await cl.AskUserMessage(content="Hva er navnet ditt?", timeout=10).send()
if res:
await cl.Message(
content=f"Aha, sรฅ du heter: {res['output']}",
).send()
cl.user_session.set("socket_auth", True)
cl.user_session.set("max_retries", 3)
cl.user_session.set("connection_attempts", 0)
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)
#asyncio.create_task(keep_alive())
async def long_running_task(message_content: str):
loop = asyncio.get_running_loop()
with ThreadPoolExecutor() as pool:
llm_chain = cl.user_session.get("llm_chain")
return await loop.run_in_executor(
pool,
lambda: llm_chain.invoke({
"question": message_content,
"chat_history": ""
})
)
@cl.on_message
async def handle_message(message: cl.Message):
try:
if not cl.user_session.get("socket_auth"):
await cl.Message(content="Session authentication failed โโโโ> refresh the page.").send()
return
user_message = message.content
llm_chain = cl.user_session.get("llm_chain")
#languages = cl.user_session.get("languages")
if sys.version_info >= (3, 11):
from asyncio import timeout
else:
from async_timeout import timeout
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:
response = await async_post_request(API_URL, headers, payload)
response.raise_for_status()
booking_data = response.json()
if not booking_data:
raise BookingNotFoundError("Ingen booking informasjon ble funnet.")
if "error" in booking_data:
raise APIResponseError(booking_data["error"])
#table = (
#"| ๐ญ๐๐๐๐
| ๐๐ป๐ณ๐ผ |\n"
#"|:----------------|:-------------------------------------------|\n"
#f"| ๐๐ง๐๐๐ง ๐๐ช๐ข๐๐๐ง | {booking_data.get('order_number', 'N/A')} |\n"
#f"| ๐ผ๐๐๐๐ฅ๐ฉ๐๐ | {booking_data.get('accepted', 'N/A')} |\n"
#f"| ๐๐ช๐๐จ๐ฉ๐จ | {booking_data.get('guests', 'N/A')} |\n"
#f"| ๐๐๐ข๐ ๐๐ง๐ค๐ข | {booking_data.get('time_from', 'N/A')} |\n"
#f"| ๐๐๐ข๐ ๐๐ค | {booking_data.get('time_to', 'N/A')} |\n"
#f"| ๐พ๐๐ฃ๐๐๐ก๐ก๐๐ | {'Yes' if booking_data.get('cancelled', 0) else 'No'} |\n"
#f"| ๐ฟ๐๐จ๐๐ง๐๐ฅ๐ฉ๐๐ค๐ฃ | {booking_data.get('description', 'N/A')} |\n"
#f"| ๐ผ๐ง๐ง๐๐ซ๐๐ก | {booking_data.get('arrival', 'N/A')} |\n"
#f"| ๐ฟ๐๐ฅ๐๐ง๐ฉ๐ช๐ง๐ | {booking_data.get('departure', 'N/A')} |\n"
#f"| ๐ฝ๐๐๐๐๐ฃ๐ | {booking_data.get('bedding', 'N/A')} |\n"
#f"| ๐๐ค๐๐๐ฉ๐๐ค๐ฃ | Lat: {booking_data.get('lat', 'N/A')}, Long: {booking_data.get('long', 'N/A')} |\n"
#f"| ๐๐๐ข๐ | {booking_data.get('name', 'N/A')} |\n"
#f"| ๐พ๐ค๐ฃ๐ฉ๐๐๐ฉ ๐๐๐ข๐ | {booking_data.get('contactname', 'N/A')} |\n"
#f"| ๐พ๐ค๐ฃ๐ฉ๐๐๐ฉ ๐๐ข๐๐๐ก| {booking_data.get('contactemail', 'N/A')} |\n"
#f"| ๐พ๐ค๐ฃ๐ฉ๐๐๐ฉ ๐๐๐ค๐ฃ๐| {booking_data.get('contactphone', 'N/A')} |\n"
#f"| ๐พ๐ค๐ช๐ฃ๐ฉ๐ง๐ฎ ๐พ๐ค๐๐ | {booking_data.get('country_code', 'N/A')} |\n"
#)
#combined_message = f"### Informasjon om booking:\n\n{table}"
#await cl.Message(content=combined_message).send()
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 informasjon ble funnet med dette bookingnummeret."
}
await cl.Message(content=f"โ {error_messages[type(e)]}\n\nPrรธv igjen, kanskje du feilstavet eller glemte ett siffer eller en bokstav?\n\nHvis du ser denne feilmedlingen gjentatte ganger, vennligst kontakt kundeservice@daysoff.no sรฅ de kan hjelpe deg.").send()
return None
else:
try:
response = await long_running_task(message.content)
await cl.Message(content=response["text"]).send()
except Exception as e:
await cl.Message(content=f"Error: {str(e)}").send()
except Exception as e:
await cl.Message(content=f"Whot?! eh..rr..or: {str(e)}").send()
|