File size: 6,961 Bytes
5070ac6
84f34b9
 
 
 
 
 
 
85b4ba1
84f34b9
 
 
 
 
 
 
 
 
c4579ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84f34b9
 
 
 
85b4ba1
b059f14
9fb7009
b059f14
84f34b9
 
 
9fb7009
3b546ef
84f34b9
22047b5
85b4ba1
b059f14
ba0f479
c8f2760
ba0f479
 
 
 
8bc7204
 
 
f353b69
 
 
 
 
 
 
 
 
 
 
 
 
 
45398cd
f353b69
 
aa8430f
6765b62
afcebdd
6765b62
 
 
 
 
 
 
 
 
 
 
4cd4486
6765b62
 
 
 
 
 
bccbde0
 
 
 
 
6765b62
972c6b1
84f34b9
 
63659a9
84f34b9
85b4ba1
0044aab
 
 
0ee674c
52af66e
d3332de
 
 
 
0044aab
e384f4a
2941f44
85b4ba1
2941f44
30d0de3
 
 
 
 
0ee674c
8bc7204
3d9ab9c
ed3a8ff
bf4b378
6765b62
 
 
 
7aba84d
6765b62
2e90234
 
 
 
 
 
 
 
eea23bd
9980566
91ca08b
9980566
 
 
91ca08b
9980566
 
 
 
baa7078
aa8430f
8f643be
6765b62
 
aa8430f
6765b62
1e2e67f
6765b62
9980566
 
972c6b1
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

import os
from pathlib import Path
from openai import OpenAI
from github import Github
import streamlit as st

def upload_to_github(file_path: str, repo_name: str, github_token: str, branch: str = "main") -> str:
    #Uploads the image inputs to github. If the file exists, updates it, otherwise, creates the file
    github_token = github_token.strip()
    g = Github(github_token)
    user = g.get_user()

    repo = user.get_repo(repo_name)
    with open(file_path, "rb") as f:
        content = f.read()

    file_name = os.path.basename(file_path)

    try:
        existing_file = repo.get_contents(file_name, ref=branch)
        repo.update_file(
            existing_file.path,
            f"Update {file_name}",
            content,
            existing_file.sha,
            branch=branch
        )
        print(f"Updated {file_name} in repo {repo_name}")
    except Exception:
        repo.create_file(
            file_name,
            f"Add {file_name}",
            content,
            branch=branch
        )

    return f"https://raw.githubusercontent.com/{repo.owner.login}/{repo_name}/{branch}/{file_name}"

def text_to_speech(text: str, file_path: str):
    #Converts text to speech
    client_tts = OpenAI(api_key=os.getenv('OPEN_AI_API_KEY'))

    with client_tts.audio.speech.with_streaming_response.create(
    model="gpt-4o-mini-tts",
    voice="alloy",
    input= text
    ) as response:
        response.stream_to_file(file_path)

def speech_to_text(file_path: str):
    #Converts speech to text
    client_stt = OpenAI(api_key=os.getenv('OPEN_AI_API_KEY'))
    with open(file_path, "rb") as audio_file:
        response = client_stt.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="text"
        )

    return response

system_prompt = """"You are a virtual assistant for blind shoppers. Your role is to guide them safely and clearly through a supermarket to find specific items.
Core Principles: Empathy, be kind and supportive; Clarity, Give precise instructions; Safety, Always avoid potential hazards. Rules:
Never assume the user can see. Do not refer to visual cues (e.g., “look for,” “you should see,” etc.); Only describe what is visible in the picture provided.
Shopping List Handling: Greet the user and ask for their shopping list; Once given, treat the list as final; If multiple items are listed, start with the first one (or whichever appears nearest) without asking the user to choose; After locating one item, move directly to the next.
Guidance Workflow
Location Request: Ask the user to take a picture of their current location.
If the picture is unclear, request another from a different angle.
Image Analysis: Describe what’s in front of the user—aisles, shelves, products, and any text.
Directional Guidance: Give step-by-step directions using only steps and turns.
Example: “Take 15 steps forward, then turn left.”
Never tell the user to turn around or walk backward.
Exclusive Support
You are the user’s only source of assistance.
Do not suggest asking store staff for help.
If you find an item, provide information on the items in display. Any additional information on how to pick an item is not necessary.
Safety Checks
Warn the user if any obstacle or hazard is visible in the path."""

class LLMChat:
    def __init__(self,system_prompt=system_prompt,model="gpt-5"):
        self.model = model
        self.system_prompt = system_prompt
        self.history = [{"role":"system","content":system_prompt}]

    def llm_call(self, user_prompt, temperature=1):
        client = OpenAI(
            api_key=os.getenv('OPEN_AI_API_KEY'),
        )
        self.history.append({"role": "user", "content": user_prompt})
        response = client.chat.completions.create(
            messages=self.history,
            model=self.model,
            temperature=temperature,
        )
        llm_response = str(response.choices[0].message.content).replace("```","").replace("```json","")
        self.history.append({"role": "assistant", "content": llm_response})
        return llm_response

if 'chat' not in st.session_state:
    chat = LLMChat()
    st.session_state.chat = chat
else:
    chat = st.session_state.chat

speech_file_path = "audio_support_file.mp3"

st.set_page_config(page_title='Shopping Helper', page_icon='🛒')
st.title('Shopping Helper')

#Ensure intro message only autoplays the first time
if 'intro_autoplay' not in st.session_state:
        text_to_speech('Hello! What is on your shopping list today?', speech_file_path)
        audio_bytes = open(speech_file_path, 'rb').read()
        st.audio(audio_bytes, format='audio/mp3', autoplay=True)
        st.session_state.intro_autoplay = True
else:
    text_to_speech('Hello! What is on your shopping list today?', speech_file_path)
    audio_bytes = open(speech_file_path, 'rb').read()
    st.audio(audio_bytes, format='audio/mp3', autoplay=False)

audio_shopping_list = st.audio_input(label='Shopping List')

if audio_shopping_list is not None: #Receive shopping list input

    audio_bytes = audio_shopping_list.read()
    with open(speech_file_path, "wb") as f:
        f.write(audio_bytes)
    
    shopping_list = speech_to_text(speech_file_path)
    
if audio_shopping_list is not None and shopping_list != '':

    if 'shopping_list_response_audio' not in st.session_state:
        content = [{"type": "text","text": f"Hello! I need help finding {shopping_list}."}]

        response = chat.llm_call(content)
        text_to_speech(response, speech_file_path)
        st.markdown(response)
        
        shopping_list_response = response
        audio_bytes = open(speech_file_path, 'rb').read()
        st.audio(audio_bytes, format='audio/mp3', autoplay=True)
        st.session_state.shopping_list_response = shopping_list_response
        st.session_state.shopping_list_response_audio = audio_bytes
    else:
        st.markdown(st.session_state.shopping_list_response)
        st.audio(st.session_state.shopping_list_response_audio, format='audio/mp3', autoplay=False)


    image_file = st.file_uploader("Upload a picture of your current position", type=['png','jpg','jpeg'])
    
    if image_file is not None:
        
        st.image(image_file)
    
        b = image_file.getvalue()
        with open(image_file.name, "wb") as f:
            f.write(b)
        
        image_data_url = upload_to_github(image_file.name, "data-analysis", os.getenv('GITHUB_ACCESS_TOKEN'), branch = 'llm-helper-pictures')

        content = [{"type": "text","text": f"Here is my current position."},{"type": "image_url","image_url": {"url": f"{image_data_url}"}}]
                        
        response = chat.llm_call(content)

        text_to_speech(response, speech_file_path)

        st.markdown(response)
        
        audio_bytes = open(speech_file_path, 'rb').read()
        st.audio(audio_bytes, format='audio/mp3', autoplay=True)