Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from openai import OpenAI
|
3 |
+
from io import BytesIO
|
4 |
+
from PIL import Image
|
5 |
+
import base64
|
6 |
+
|
7 |
+
st.set_page_config(page_title='GPT-4 Vision', page_icon='👁️')
|
8 |
+
|
9 |
+
if 'initialized' not in st.session_state:
|
10 |
+
st.session_state['history'] = [{'role': 'system', 'content': ''}]
|
11 |
+
st.session_state['cost'] = 0.0
|
12 |
+
st.session_state['initialized'] = True
|
13 |
+
|
14 |
+
st.markdown('# GPT-4 Vision Client')
|
15 |
+
api_key = st.text_input('OpenAI API Key', '', type='password')
|
16 |
+
|
17 |
+
# display cost
|
18 |
+
if st.session_state['cost'] > 0:
|
19 |
+
st.info('Session Cost: ${:f}'.format(st.session_state['cost']), icon='💰')
|
20 |
+
|
21 |
+
# make tabs
|
22 |
+
chatTab, settingsTab = st.tabs(['Chat', 'Settings'])
|
23 |
+
|
24 |
+
# set openai settings
|
25 |
+
with settingsTab:
|
26 |
+
image_detail = st.selectbox('Image Detail', ['low', 'high'])
|
27 |
+
temperature = st.slider('Temperature', 0.0, 2.0, 0.7)
|
28 |
+
max_tokens = st.slider('Max Token Output', 100, 1000, 300)
|
29 |
+
|
30 |
+
with chatTab:
|
31 |
+
# optional system message
|
32 |
+
with st.expander('System Message'):
|
33 |
+
st.session_state['history'][0]['content'] = st.text_area('sys message',
|
34 |
+
st.session_state['history'][0]['content'],
|
35 |
+
label_visibility='collapsed')
|
36 |
+
|
37 |
+
# display chat
|
38 |
+
for msg in st.session_state['history'][1:]:
|
39 |
+
if msg['role'] == 'user':
|
40 |
+
for i in msg['content']:
|
41 |
+
if i['type'] == 'text':
|
42 |
+
st.markdown(f"<span style='color: #c4c4c4'>You: {i['text']}</span>", unsafe_allow_html=True)
|
43 |
+
else:
|
44 |
+
with st.expander('Attached Image'):
|
45 |
+
img = Image.open(BytesIO(base64.b64decode(i['image_url']['url'][23:])))
|
46 |
+
st.image(img)
|
47 |
+
else:
|
48 |
+
msg_content = ''.join([' ' + char if char == '\n' else char for char in msg['content']]) # fixes display issue
|
49 |
+
st.markdown('Assistant: ' + msg_content)
|
50 |
+
|
51 |
+
# get user inputs
|
52 |
+
text_input = st.text_input('Prompt', '')
|
53 |
+
img_input = st.file_uploader('Images', accept_multiple_files=True)
|
54 |
+
|
55 |
+
# set up button layout
|
56 |
+
st.markdown(
|
57 |
+
"""
|
58 |
+
<style>
|
59 |
+
[data-testid="column"]
|
60 |
+
{
|
61 |
+
width: calc(33.3333% - 1rem) !important;
|
62 |
+
flex: 1 1 calc(33.3333% - 1rem) !important;
|
63 |
+
min-width: calc(33% - 1rem) !important;
|
64 |
+
}
|
65 |
+
div[data-testid="column"]:nth-of-type(2)
|
66 |
+
{
|
67 |
+
text-align: right;
|
68 |
+
}
|
69 |
+
</style>
|
70 |
+
""", unsafe_allow_html=True
|
71 |
+
)
|
72 |
+
cols = st.columns(2)
|
73 |
+
|
74 |
+
# send api request
|
75 |
+
with cols[0]:
|
76 |
+
if st.button('Send'):
|
77 |
+
if api_key:
|
78 |
+
if text_input or img_input:
|
79 |
+
msg = {'role': 'user', 'content': []}
|
80 |
+
if text_input:
|
81 |
+
msg['content'].append({'type': 'text', 'text': text_input})
|
82 |
+
for img in img_input:
|
83 |
+
encoded_img = base64.b64encode(img.read()).decode('utf-8')
|
84 |
+
msg['content'].append(
|
85 |
+
{
|
86 |
+
'type': 'image_url',
|
87 |
+
'image_url': {
|
88 |
+
'url': f'data:image/jpeg;base64,{encoded_img}',
|
89 |
+
'detail': image_detail
|
90 |
+
}
|
91 |
+
}
|
92 |
+
)
|
93 |
+
st.session_state['history'].append(msg)
|
94 |
+
history = (
|
95 |
+
st.session_state['history']
|
96 |
+
if st.session_state['history'][0]['content']
|
97 |
+
else st.session_state['history'][1:]
|
98 |
+
)
|
99 |
+
client = OpenAI(api_key=api_key)
|
100 |
+
response = client.chat.completions.create(
|
101 |
+
model='gpt-4-vision-preview',
|
102 |
+
temperature=temperature,
|
103 |
+
max_tokens=max_tokens,
|
104 |
+
messages=history
|
105 |
+
)
|
106 |
+
st.session_state['history'].append(
|
107 |
+
{'role': 'assistant', 'content': response.choices[0].message.content}
|
108 |
+
)
|
109 |
+
st.session_state['cost'] += response.usage.prompt_tokens * 0.01 / 1000
|
110 |
+
st.session_state['cost'] += response.usage.completion_tokens * 0.03 / 1000
|
111 |
+
st.rerun()
|
112 |
+
else:
|
113 |
+
st.warning('You can\'t just send nothing!')
|
114 |
+
else:
|
115 |
+
st.warning('API Key required')
|
116 |
+
|
117 |
+
# clear chat history
|
118 |
+
with cols[1]:
|
119 |
+
if st.button('Clear'):
|
120 |
+
st.session_state['history'] = [st.session_state['history'][0]]
|
121 |
+
st.rerun()
|