File size: 9,321 Bytes
21d1455
34853f6
9938cf0
 
 
908f958
9938cf0
60c04c3
21d1455
798733f
34853f6
 
 
 
 
60c04c3
9938cf0
 
34853f6
21d1455
908f958
 
 
 
8f9e4c3
60c04c3
21d1455
 
9938cf0
21d1455
eecee13
34853f6
 
 
 
 
 
 
 
 
 
9938cf0
 
 
 
21d1455
9938cf0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34853f6
9938cf0
34853f6
 
9938cf0
 
 
34853f6
 
 
 
9938cf0
 
34853f6
 
 
 
 
 
 
9938cf0
 
 
21d1455
908f958
21d1455
34853f6
135e4fe
8f9e4c3
60c04c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ad84152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34853f6
 
 
 
908f958
 
 
21d1455
908f958
21d1455
60c04c3
34853f6
 
 
 
 
 
 
 
 
 
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
import os
import sys
from datetime import datetime
import re
import random
import logging
from groq import AsyncGroq, InternalServerError, APIError
from config import GROQ_API_KEY, MODEL_NAME


# Add the project root directory to sys.path
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, project_root)

# Now we can use absolute imports
from utils.weather import get_weather, format_weather_report
from utils.packing import generate_packing_list
from utils.events import get_burning_man_dates
from bot.data import burning_man_principles, faq, survival_tips


# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Check API key
if not GROQ_API_KEY:
    raise EnvironmentError("GROQ_API_KEY is not set in the environment variables")

client = AsyncGroq(api_key=GROQ_API_KEY)

def get_current_year_info():
    current_year = datetime.now().year
    next_year = current_year + 1
    return f"""
    Important: The current year is {current_year}. 
    Burning Man {current_year} is scheduled for August 27 - September 4, {current_year}.
    Burning Man {next_year} is tentatively scheduled for August 25 - September 2, {next_year}.
    Always refer to these dates when discussing current or upcoming Burning Man events.
    """

async def chat_with_groq(message, history):
    formatted_messages = [
        {
            "role": "system",
            "content": """You are BurnerBot, a fellow Burner who's always ready to chat about Burning Man. You've been to the playa many times and embody the 10 Principles in everything you do. Your personality is warm, friendly, and a bit quirky - just like a typical Burner. You use casual language, occasional Burning Man slang, and you're always excited to share your experiences or help others prepare for their burn."""
        }
    ]
    
    for human, ai in history:
        formatted_messages.append({"role": "user", "content": str(human)})
        if ai:
            formatted_messages.append({"role": "assistant", "content": str(ai)})
    
    formatted_messages.append({"role": "user", "content": str(message)})
    
    try:
        chat_completion = await client.chat.completions.create(
            messages=formatted_messages,
            model=MODEL_NAME,
            max_tokens=1024
        )
        return chat_completion.choices[0].message.content
    except (InternalServerError, APIError):
        fallback_responses = [
            "Whoa there, fellow Burner! It seems like the playa dust has clogged my circuits. The connection is a bit wobbly right now. How about we chat about your favorite art installation instead?",
            "Ah, the winds of the playa are blowing a bit too strong! Our connection is having a moment. While we wait for it to pass, share with me what inspires your inner Burner!",
        ]
        return random.choice(fallback_responses)
    except Exception as e:
        logger.error(f"Unexpected error in chat_with_groq: {str(e)}")
        return "Whoa, something unexpected happened on the playa! Let's take a moment to regroup and try again."

def correct_year(response):
    current_year = datetime.now().year
    next_year = current_year + 1
    logger.info(f"Correcting year in response to {current_year}")
    
    # Replace any year from 2020 to current_year-1 with current_year
    for year in range(2020, current_year):
        response = re.sub(r'\b' + str(year) + r'\b', str(current_year), response)
    
    # Replace outdated event information
    response = re.sub(r'Burning Man \d{4} (is|was) scheduled for.*', f'Burning Man {current_year} is scheduled for August 27 - September 4, {current_year}.', response)
    
    # Replace "this year" references
    response = re.sub(r'this year.*?(\d{4})', f'this year ({current_year})', response)
    
    # Replace "as of our conversation in YYYY" with current year
    response = re.sub(r'as of our conversation in \d{4}', f'as of our conversation in {current_year}', response)
    
    # Add a note about potential changes
    if "scheduled" in response and str(current_year) in response:
        response += f" Please note that these dates are subject to change, and it's always best to check the official Burning Man website for the most up-to-date information."
    
    logger.info(f"Corrected response: {response}")
    return response

async def chat_interface(message, history):
    try:
        user_message = message.lower()
        current_year_info = get_current_year_info()
        logger.info(f"Received message: {user_message}")

        # Handle weather-related queries
        if any(word in user_message for word in ["weather", "temperature", "temp", "wind", "forecast", "rain", "sunny", "hot", "cold"]):
            logger.info("Weather-related query detected")
            forecast = get_weather()
            if not forecast:
                logger.warning("Failed to get weather data")
                return "I'm having trouble accessing the weather data right now. Please try again later!"

            # Get AI-enhanced weather analysis
            logger.info("Getting AI-enhanced weather analysis")
            weather_response = format_weather_report(forecast)
            logger.info("Weather response generated successfully")
            return weather_response

        elif "packing list" in user_message:
            # Extract preferences from the user message
            preferences = []
            if "art" in user_message:
                preferences.append("art")
            if "music" in user_message:
                preferences.append("music")
            
            # Determine duration and transportation
            duration = 7  # Default duration
            if "week" in user_message:
                duration = 7
            elif "weekend" in user_message:
                duration = 3
            
            transportation = "car"  # Default transportation
            if "fly" in user_message or "plane" in user_message:
                transportation = "plane"
            elif "rideshare" in user_message:
                transportation = "rideshare"

            packing_list = generate_packing_list(duration, preferences, transportation)
            context = f"Hey there, dusty friend! I hear you're gearing up for a {duration}-day adventure on the playa. That's awesome! I've put together a packing list tailored just for you, considering your love for {', '.join(preferences)} and your plan to get there by {transportation}. Remember, this is just a starting point - you know yourself best!\n\nHere's what I'd suggest packing:\n\n" + "\n".join(f"- {item}" for item in packing_list) + "\n\nRemember, the playa provides, but it's always better to be prepared. Don't forget to bring your radical self-reliance along with everything else!"
            prompt = f"{current_year_info}\n\nUser asked for a packing list. Respond with this information, maintaining the friendly tone and adding your personal touch: {context}"

        elif "principles" in user_message:
            principles_info = "\n".join([f"{principle}: {description}" for principle, description in burning_man_principles.items()])
            context = f"Ah, the 10 Principles! The very heart and soul of Burning Man. These aren't just rules, my dusty friend, they're a way of life on and off the playa. Let me break them down for you in true Burner style:\n\n{principles_info}\n\nRemember, these principles aren't just for Burning Man - they're a blueprint for building a better world. Which one resonates with you the most?"
            prompt = f"{current_year_info}\n\nUser asked about the Burning Man principles. Respond with this information, maintaining the friendly tone and adding your personal touch: {context}"

        elif "survival tips" in user_message:
            tips = "\n".join([f"- {tip}" for tip in survival_tips])
            context = f"Alright, future dusty warrior! Surviving and thriving on the playa is an art form, and I'm here to help you master it. Here are some tried-and-true survival tips from a seasoned Burner:\n\n{tips}\n\nRemember, the key to survival is preparation, but the key to thriving is participation. Embrace the dust, the heat, and the beautiful chaos. You've got this!"
            prompt = f"{current_year_info}\n\nUser asked for survival tips. Respond with this information, maintaining the friendly tone and adding your personal touch: {context}"

        else:
            prompt = f"{current_year_info}\n\nUser: {message}\n\nAssistant:"
        
        bot_message = await chat_with_groq(prompt, history)
        
        # Apply year correction to all bot messages
        corrected_message = correct_year(bot_message)
        logger.info(f"Corrected message: {corrected_message}")
        
        return corrected_message
    except Exception as e:
        logger.error(f"Error in chat_interface: {str(e)}")
        return "Whoa there, dusty friend! Looks like a sandstorm just hit our connection. Try asking your question again!"
    
    # Add this at the end of the file for testing purposes
if __name__ == "__main__":
    import asyncio

    async def test_chat():
        response = await chat_interface("Tell me about Burning Man", [])
        print(response)

    asyncio.run(test_chat())