# Project export: ReduceNow

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Research Based Ways to Incentivize Emission Reduction
- Devpost: https://devpost.com/software/reducenow
- GitHub: https://github.com/skyraal/ReduceNow
- Video: https://www.youtube.com/embed/k2IHaSHqQws?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Cyra Alesha (5 commits)

## Devpost submission (written by the team)

### Inspiration

What do you think is the most effective incentive to make people behave more sustainably? If you think it’s money, me too! But apparently we’re wrong. Multiple peer-reviewed research has shown that social framings are more effective than financial. For instance a paper by Asensio & Delmas from the Journal of Economic Behavior & Organization showed that wordings that frames energy savings with information disclosures about the environmental and health implications have a longer impact than ones that disclose the financial savings. Multiple other papers also found the same phenomenon. (link) (link) Additionally a lot of people want to make a change to make their lives more sustainable but struggle to start or even view it as a huge sacrifice. What I realized is different emission reduction methods might be easier on some then others. For instance, one person might find it easy to carry a reusable water bottle but resist lowering the thermostat. If behavioral messaging focuses on a personalized approach—such as encouraging them to bring a water bottle daily while introducing subtle changes to their heating habits—it frames sustainability as a gradual and manageable process rather than an overwhelming sacrifice. Over time, the habit of carrying a reusable bottle can evolve into larger efforts, like investing in energy-efficient appliances or using smart thermostats to regulate heat​. (link) (link) This approach leverages psychological principles of incrementalism and ease, where simpler, less demanding steps lead to greater sustainable behaviors.

### What it does

This website helps recommend the easiest "first steps" according to each user's preference and use the research recommended framing to highlight the impact. Such as highlighting the health impacts that they saved. Users will communicate with a Gemini-powered chatbot that is trained to ask questions about your preference and your habits to recommend a way to reduce emissions and pollutions that is the most comfortable for the users. It'll be doing so in five questions or less and focusing on following up and asking about scenarios. Then we will forward the user to a page where they can view more information about the method. For instance, if it's recycling, they can scan an item they want to recycle, it'll then be analyzed by Hyperbolic's AI Inference to identify the item, then the inference will also return tutorial/ideas! Finally, they will be shown to the thank you page where it'll highlight the health and environmental impact that you might've saved by doing these small steps.

### How we built it

Hyperbolic AI Inference: We used the LLAMA vision hyperbolic model to analyze the items that the user wants to recycle Then we used hyperbolic text generation to return potential recycling ideas Finally we used the AI inference to also calculate the estimated emissions or pollutions reduced by the chosen methods and use social framing to make it more effective Gemini API / Google AI Studio We used Gemini as a way to analyze the users preference through tuning the model to specifically ask case-based questions which then leads to the method-recommendations General We used Flask, Python, and Javascript for most of the project. What's next for ReduceNow This is a very simple version, but I think the principle of it can be scaled widely to help make incremental changes for people to be more sustainable. For instance, in companies, it can be used to help find the easiest and most cost-effective ways for processes or employees to reduce their emissions. Or it can be implemented in educational institutions to help build the sustainable habit.

### Challenges we ran into

Initially we wanted to add a voice component to as an option, but ran into an issue with pyaudio and audio playback, therefore we had to scrap it. Additionally it's my first solo project on a hackathon so finishing everything was a huge personal accomplishment haha.

## README (from the GitHub repository)

### Built in less than a day for fun!
Demo:
https://youtu.be/xmKQ9Jw_2Fw

### Inspiration

What do you think is the most effective incentive to make people behave more sustainably? If you think it’s money, me too! But apparently we’re wrong. Multiple peer-reviewed research has shown that social framings are more effective than financial. For instance a paper by Asensio & Delmas from the Journal of Economic Behavior & Organization showed that wordings that frames energy savings with information disclosures about the environmental and health implications have a longer impact than ones that disclose the financial savings. Multiple other papers also found the same phenomenon. (link) (link)

Additionally a lot of people want to make a change to make their lives more sustainable but struggle to start or even view it as a huge sacrifice. What I realized is different emission reduction methods might be easier on some then others. For instance, one person might find it easy to carry a reusable water bottle but resist lowering the thermostat. If behavioral messaging focuses on a personalized approach—such as encouraging them to bring a water bottle daily while introducing subtle changes to their heating habits—it frames sustainability as a gradual and manageable process rather than an overwhelming sacrifice. Over time, the habit of carrying a reusable bottle can evolve into larger efforts, like investing in energy-efficient appliances or using smart thermostats to regulate heat​. (link) (link)

This approach leverages psychological principles of incrementalism and ease, where simpler, less demanding steps lead to greater sustainable behaviors.

### What it does

This website helps recommend the easiest "first steps" according to each user's preference and use the research recommended framing to highlight the impact. Such as highlighting the health impacts that they saved.

Users will communicate with a Gemini-powered chatbot that is trained to ask questions about your preference and your habits to recommend a way to reduce emissions and pollutions that is the most comfortable for the users. It'll be doing so in five questions or less and focusing on following up and asking about scenarios.

Then we will forward the user to a page where they can view more information about the method. For instance, if it's recycling, they can scan an item they want to recycle, it'll then be analyzed by Hyperbolic's AI Inference to identify the item, then the inference will also return tutorial/ideas!

Finally, they will be shown to the thank you page where it'll highlight the health and environmental impact that you might've saved by doing these small steps.

### How we built it

Hyperbolic AI Inference:

We used the LLAMA vision hyperbolic model to analyze the items that the user wants to recycle
Then we used hyperbolic text generation to return potential recycling ideas
Finally we used the AI inference to also calculate the estimated emissions or pollutions reduced by the chosen methods and use social framing to make it more effective
Gemini API / Google AI Studio

We used Gemini as a way to analyze the users preference through tuning the model to specifically ask case-based questions which then leads to the method-recommendations
General

We used Flask, Python, and Javascript for most of the project.
What's next for ReduceNow

This is a very simple version, but I think the principle of it can be scaled widely to help make incremental changes for people to be more sustainable. For instance, in companies, it can be used to help find the easiest and most cost-effective ways for processes or employees to reduce their emissions. Or it can be implemented in educational institutions to help build the sustainable habit.

### Challenges we ran into

Initially we wanted to add a voice component to as an option, but ran into an issue with pyaudio and audio playback, therefore we had to scrap it. Additionally it's my first solo project on a hackathon so finishing everything was a huge personal accomplishment haha.



## Detected evidence (automated analysis)

Indexed codebase: 14 recognized source files, 27 KB.
- CSS (language) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code

## Codebase structure (from repository index)

### Files (17 of 17)

```
.DS_Store
.gitignore
app copy.py
app.py
README.md
requirements.txt
static/main.js
static/style.css
templates/base.html
templates/index.html
templates/recycle.html
templates/reduce_electricity.html
templates/reduce_fuel.html
templates/start.html
templates/thank_you.html
test.py
test123.py
```

### Dependencies

- requirements.txt: deepgram-sdk@==1.1.0, Flask@==2.3.2, google-ai-generativelanguage@==0.2.0, httpx@==0.23.3, python-dotenv@==1.0.1, requests@==2.26.0

### Recent commits (newest first)

- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Create README.md
- connected with pic
- add recycling
- more updates
- chat only version
- test

## Key source files (fetched from GitHub, selected and truncated for size)

### requirements.txt

```
Flask==2.3.2
requests==2.26.0
deepgram-sdk==1.1.0
google-ai-generativelanguage==0.2.0
python-dotenv==1.0.1
httpx==0.23.3


```

### app.py

```python
from flask import Flask, render_template, jsonify, request, redirect, url_for
import os
import google.generativeai as genai
from deepgram.utils import verboselogs
from deepgram import (
    DeepgramClient,
    DeepgramClientOptions,
    SpeakWebSocketEvents,
    SpeakWSOptions,
)
from dotenv import load_dotenv
from PIL import Image
from io import BytesIO
import base64
import requests


# Load environment variables (API keys)
load_dotenv()

# Configure the API keys for Gemini and Deepgram
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))

# Initialize the Gemini chat session
generation_config = {
    "temperature": 1,
    "top_p": 0.95,
    "top_k": 64,
    "max_output_tokens": 25000,
    "response_mime_type": "text/plain",
}
model = genai.GenerativeModel(
    model_name="gemini-1.5-pro",
    generation_config=generation_config,
)

# Flask app initialization
app = Flask(__name__)

# Function to connect to Deepgram WebSocket TTS and play audio
def text_to_speech_via_websocket(text):
    TTS_TEXT = text
    global warning_notice
    warning_notice = True

    try:
        # Create a Deepgram client
        config = DeepgramClientOptions(
            options={"speaker_playback": "true"},
        )
        deepgram = DeepgramClient("", config)

        # Create a WebSocket connection to Deepgram
        dg_connection = deepgram.speak.websocket.v("1")

        # WebSocket event handlers
        def on_open(self, open, **kwargs):
            print(f"WebSocket opened: {open}")

        def on_binary_data(self, data, **kwargs):
            global warning_notice
            if warning_notice:
                print("Received binary data")
                warning_notice = False
            # Here you can handle the binary data for audio (stream to a player or save to a file)

        def on_metadata(self, metadata, **kwargs):
            print(f"Metadata received: {metadata}")

        def on_close(self, close, **kwargs):
            print(f"Connection closed: {close}")

        def on_error(self, error, **kwargs):
            print(f"Error occurred: {error}")

        # Register WebSocket event handlers
        dg_connection.on(SpeakWebSocketEvents.Open, on_open)
        dg_connection.on(SpeakWebSocketEvents.AudioData, on_binary_data)
        dg_connection.on(SpeakWebSocketEvents.Metadata, on_metadata)
        dg_connection.on(SpeakWebSocketEvents.Close, on_close)
        dg_connection.on(SpeakWebSocketEvents.Error, on_error)

        # Start WebSocket connection with specified options
        options = SpeakWSOptions(
            model="aura-asteria-en",  # Select the voice model
            encoding="linear16",  # Audio encoding
            sample_rate=16000,  # Sample rate for audio
        )

        if dg_connection.start(options) is False:
            print("Failed to start WebSocket connection")
            return

        # Send text to Deepgram for TTS conversion
        dg_connection.send_text(TTS_TEXT)

        # Flush the WebSocket connection (mandatory)
        dg_connection.flush()

        # Wait for WebSocket to complete
        dg_connection.wait_for_complete()

        # Close the connection
        dg_connection.finish()

        return "Audio played successfully"

    except Exception as e:
        print(f"An error occurred during WebSocket TTS: {e}")
        return None


# Function to forward user based on the result
def forward_user_based_on_choice(result):
    if "recycling" in result.lower():
        return redirect(url_for('recycle'))
    elif "electricity" in result.lower():
        return redirect(url_for('electricity'))
    elif "fuel" in result.lower():
        return redirect(url_for('fuel'))
    else:
        return jsonify({"error": "Sorry, I couldn't understand the recommendation."})

def encode_image(image):
    if image.mode == 'RGBA':
        image = image.convert('RGB')
    
    buffered = BytesIO()
    image.save(buffered, format="JPEG")
    return base64.b64encode(buffered.getvalue()).decode('utf-8')

# Main chatbot route (frontend)
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/start')
def start():
    return render_template('start.html')
# Chatbot response route (backend logic)
@app.route('/chat', methods=['POST'])
def chat():
    user_input = request.json['message']

    # Start a chat session with Gemini
    chat_session = model.start_chat(
        history=[
            {
                "role": "user",
                "parts": [
                    """
                    You are a sustainability expert tasked with helping individuals reduce their carbon footprint.
                    Your goal is to ask the user five or less behavioral questions to determine which method of reducing emissions is most suitable for them: 
                    1. Recycling waste
                    2. Reducing electricity consumption
                    3. Reducing fuel use.

                    Ask each question one at a time, evaluating the user's preferences, habits, and comfort with each method.
                    After the fifth question, make a recommendation based on the user's responses, answer with one of the following options: 
                    Recycling, electricity, or fuel. Do not use the word recycle, electricity, or fuel in the five questions.
                    """
                ],
            },
        ]
    )

    # Send user's input to Gemini and get the response
    response = chat_session.send_message(user_input)
    result = response.text

    # Convert the chatbot's text to speech using Deepgram WebSocket TTS
    tts_result = text_to_speech_via_websocket(result)

    # Return the chatbot result and TTS result to the frontend
    return jsonify({"response": result, "tts_result": tts_result})


# Redirect routes after final decision
@app.route('/recycle')
def recycle():
    return render_template('recycle.html')

@app.route('/submit-image', methods=['POST'])
def submit_image():
    # Extract and decode the
[truncated — 2649 more characters]
```

### static/main.js

```javascript
document.getElementById('chatForm').addEventListener('submit', function (e) {
    e.preventDefault();

    // Get user input
    const userInput = document.getElementById('user_input').value;

    // Append the user's message to the chatbox
    const messages = document.getElementById('messages');
    const userMessage = document.createElement('div');
    userMessage.classList.add('message', 'user');
    userMessage.textContent = userInput;
    messages.appendChild(userMessage);

    // Clear the input field
    document.getElementById('user_input').value = '';

    // Send the user's input to the Flask backend
    fetch('/chat', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ message: userInput })
    })
    .then(response => response.json())
    .then(data => {
        // Append chatbot's response to the chatbox
        const botMessage = document.createElement('div');
        botMessage.classList.add('message', 'bot');
        botMessage.textContent = data.response;
        messages.appendChild(botMessage);

        // Scroll chatbox to the bottom
        messages.scrollTop = messages.scrollHeight;

        // Play the Deepgram TTS audio
        const audio = new Audio(data.audio_url);
        audio.play();

        // If the response contains one of the key recommendations, redirect to the corresponding page
        if (data.response.toLowerCase().includes('recycling')) {
            window.location.href = '/recycle';
        } else if (data.response.toLowerCase().includes('electricity')) {
            window.location.href = '/electricity';
        } else if (data.response.toLowerCase().includes('fuel')) {
            window.location.href = '/fuel';
        }
    });
});

```

### test123.py

```python
import pyaudio
p = pyaudio.PyAudio()
print(p.get_device_count())
p.terminate()

```

### test.py

```python
import os
import json
from flask import Flask, render_template
from flask_socketio import SocketIO
from dotenv import load_dotenv
import websockets
import asyncio

# Load environment variables from .env
load_dotenv()

DEEPGRAM_API_KEY = os.getenv('DEEPGRAM_API_KEY')

# Flask app and WebSocket setup
app = Flask(__name__)
socketio = SocketIO(app)

@app.route('/')
def index():
    return render_template('index.html')

async def send_audio_to_deepgram(ws, audio_data):
    async with websockets.connect(
        'wss://api.deepgram.com/v1/listen?encoding=linear16&sample_rate=16000&channels=1',
        extra_headers={'Authorization': f'token {DEEPGRAM_API_KEY}'}
    ) as deepgram_ws:
        await deepgram_ws.send(audio_data)

        async for message in deepgram_ws:
            data = json.loads(message)
            transcript = data['channel']['alternatives'][0]['transcript']
            if transcript:
                print(f'Transcript: {transcript}')
                # Emit the transcript back to the client
                socketio.emit('transcript', {'transcript': transcript})

@socketio.on('audio_chunk')
def handle_audio_chunk(audio_chunk):
    # Start an asyncio task to send audio to Deepgram
    asyncio.run(send_audio_to_deepgram(None, audio_chunk))

if __name__ == '__main__':
    socketio.run(app, debug=True)

```

### templates/reduce_fuel.html

```html
<!DOCTYPE html>
<html>
<head>
    <title>Reduce Fuel Use</title>
</head>
<body>
    <h1>Reduce Fuel Use</h1>
    <p>Here are some suggestions to reduce fuel consumption:</p>
    <ul>
        <li>Carpool when possible.</li>
        <li>Use public transportation.</li>
        <li>Consider walking or cycling for short trips.</li>
    </ul>
</body>
</html>

```

### templates/reduce_electricity.html

```html
<!DOCTYPE html>
<html>
<head>
    <title>Reduce Electricity Consumption</title>
</head>
<body>
    <h1>Reduce Electricity Consumption</h1>
    <p>Here are some tips to reduce your electricity usage:</p>
    <ul>
        <li>Turn off lights when not in use.</li>
        <li>Unplug appliances when done.</li>
        <li>Use energy-efficient appliances.</li>
    </ul>
</body>
</html>

```

### templates/thank_you.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Thank You for Helping the Environment!</title>
</head>
<body>
    <h1>Thank You for Your Contribution!</h1>
    <p>{{ health_message }}</p>

    <p>Your actions not only help the planet but also reduce harmful air pollutants that contribute to serious health conditions like childhood asthma and cancer.</p>
    
    <p>Together, we can make a big difference!</p>
</body>
</html>

```

### templates/index.html

```html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ReduceNow</title>
    <link rel="stylesheet" href="../static/style.css">
</head>
<body>
    <div class="container home-container">
        <div class="logo-container">
            <img src="../static/image/logo.png" alt="ReduceNow Logo" class="logo">
            <p class="typography">Research Based Emission-Reducer Recommender</p>
            <a href="{{ url_for('start') }}">
                <button class="startbutton">Start</button>
            </a>
        </div>
    </div>
 
</body>
</html>

```

### static/style.css

```css
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
body {
    font-family: "Inter", sans-serif;
    background-color: #f4f4f4;
    margin: 0;
    padding: 20px;
    text-align: center;
}

#chatbox {
    width: 400px;
    margin: 0 auto;
    background-color: white;
    border: 1px solid #ccc;
    padding: 10px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
}

#messages {
    height: 300px;
    overflow-y: scroll;
    border-bottom: 1px solid #ccc;
    padding-bottom: 10px;
}

.message {
    margin: 5px 0;
}

.user {
    text-align: right;
    color: blue;
}

.bot {
    text-align: left;
    color: green;
}

form {
    display: flex;
    justify-content: space-between;
    padding-top: 10px;
}

input[type="text"] {
    width: 80%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

button {
    padding: 10px 15px;
    border: none;
    background-color: #28a745;
    color: white;
    border-radius: 5px;
    cursor: pointer;
}

.startbutton {
    margin-top: 20px;
    padding: 10px 20px;
    background-color: #10B27E;
    color: white;
    border: none;
    border-radius: 5px;
    font-size: 25px;
    cursor: pointer;
    transition: background-color 0.3s ease;
    width: 200px;
    margin-left: 35px;
    margin-top: -10px;
}

.startbutton:hover {
    background-color: #45a049;
}

.home-container{
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100%;
    background-image: url('../static/image/ReduceNow-3.png');
    background-repeat: no-repeat;
    background-size: cover;
    margin: 0;
    justify-content: left;
}

.logo-container {
    text-align: left;
    display: flex;
    justify-content: left;
    flex-direction: column;
    margin-left: 120px;
}

.typography {
    margin-top: -150px;
    margin-left: 36px;
    font-size: 36px;
}
.logo {
    width: 748px;
    height: 440px;
    flex-shrink: 0;
}



```

[3 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]