Spaces:
Runtime error
Runtime error
added cost calculator
Browse files
app.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
from openai import OpenAI
|
| 2 |
import streamlit as st
|
| 3 |
-
from utils import im_2_b64
|
| 4 |
import pickle
|
| 5 |
from upload import upload_file, get_file
|
| 6 |
|
|
|
|
|
|
|
| 7 |
|
| 8 |
st.title("ChatGPT with Vision")
|
| 9 |
|
|
@@ -13,12 +15,16 @@ if "messages" not in st.session_state:
|
|
| 13 |
st.session_state.messages = []
|
| 14 |
if "uploader_key" not in st.session_state:
|
| 15 |
st.session_state["uploader_key"] = 0
|
|
|
|
|
|
|
| 16 |
|
| 17 |
if len(st.session_state.messages) == 0 and "id" in st.query_params:
|
| 18 |
with st.spinner("Loading chat..."):
|
| 19 |
id = st.query_params["id"]
|
| 20 |
data = get_file(id, 'chatgpt-vision-007')
|
| 21 |
-
|
|
|
|
|
|
|
| 22 |
|
| 23 |
def clear_uploader():
|
| 24 |
st.session_state["uploader_key"] += 1
|
|
@@ -31,7 +37,11 @@ def undo():
|
|
| 31 |
st.rerun()
|
| 32 |
|
| 33 |
def share():
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
id = upload_file(data, 'chatgpt-vision-007')
|
| 36 |
url = f"https://umbc-nlp-chatgpt-vision.hf.space/?id={id}"
|
| 37 |
st.success(f"Share URL: {url}")
|
|
@@ -66,6 +76,16 @@ with st.sidebar:
|
|
| 66 |
label_visibility="collapsed",
|
| 67 |
)
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
for message in st.session_state.messages:
|
| 71 |
with st.chat_message(message["role"]):
|
|
@@ -131,6 +151,8 @@ if prompt := st.chat_input("Type a message", key="chat_input", disabled=chat_inp
|
|
| 131 |
max_tokens=max_tokens,
|
| 132 |
)
|
| 133 |
response = st.write_stream(stream)
|
|
|
|
| 134 |
push_message("assistant", response)
|
|
|
|
| 135 |
chat_input_disabled = False
|
| 136 |
clear_uploader()
|
|
|
|
| 1 |
from openai import OpenAI
|
| 2 |
import streamlit as st
|
| 3 |
+
from utils import im_2_b64, calculate_cost
|
| 4 |
import pickle
|
| 5 |
from upload import upload_file, get_file
|
| 6 |
|
| 7 |
+
share_keys = ["messages", "cost"]
|
| 8 |
+
|
| 9 |
|
| 10 |
st.title("ChatGPT with Vision")
|
| 11 |
|
|
|
|
| 15 |
st.session_state.messages = []
|
| 16 |
if "uploader_key" not in st.session_state:
|
| 17 |
st.session_state["uploader_key"] = 0
|
| 18 |
+
if "cost" not in st.session_state:
|
| 19 |
+
st.session_state.cost = []
|
| 20 |
|
| 21 |
if len(st.session_state.messages) == 0 and "id" in st.query_params:
|
| 22 |
with st.spinner("Loading chat..."):
|
| 23 |
id = st.query_params["id"]
|
| 24 |
data = get_file(id, 'chatgpt-vision-007')
|
| 25 |
+
obj = pickle.loads(data)
|
| 26 |
+
for k, v in obj.items():
|
| 27 |
+
st.session_state[k] = v
|
| 28 |
|
| 29 |
def clear_uploader():
|
| 30 |
st.session_state["uploader_key"] += 1
|
|
|
|
| 37 |
st.rerun()
|
| 38 |
|
| 39 |
def share():
|
| 40 |
+
obj = {}
|
| 41 |
+
for k in share_keys:
|
| 42 |
+
if k in st.session_state:
|
| 43 |
+
obj[k] = st.session_state[k]
|
| 44 |
+
data = pickle.dumps(obj)
|
| 45 |
id = upload_file(data, 'chatgpt-vision-007')
|
| 46 |
url = f"https://umbc-nlp-chatgpt-vision.hf.space/?id={id}"
|
| 47 |
st.success(f"Share URL: {url}")
|
|
|
|
| 76 |
label_visibility="collapsed",
|
| 77 |
)
|
| 78 |
|
| 79 |
+
with st.expander(f"Total Cost: ${sum(st.session_state.cost):.10f}"):
|
| 80 |
+
if len(st.session_state.cost) > 0:
|
| 81 |
+
st.subheader("Cost Breakdown")
|
| 82 |
+
for i, c in enumerate(st.session_state.cost):
|
| 83 |
+
st.write(f"Message {i+1}: ${c:.10f}")
|
| 84 |
+
st.markdown("---")
|
| 85 |
+
st.write(f"Total: ${sum(st.session_state.cost):.10f}")
|
| 86 |
+
else:
|
| 87 |
+
st.write("No cost incurred yet")
|
| 88 |
+
|
| 89 |
|
| 90 |
for message in st.session_state.messages:
|
| 91 |
with st.chat_message(message["role"]):
|
|
|
|
| 151 |
max_tokens=max_tokens,
|
| 152 |
)
|
| 153 |
response = st.write_stream(stream)
|
| 154 |
+
|
| 155 |
push_message("assistant", response)
|
| 156 |
+
calculate_cost()
|
| 157 |
chat_input_disabled = False
|
| 158 |
clear_uploader()
|
utils.py
CHANGED
|
@@ -1,6 +1,13 @@
|
|
| 1 |
from PIL import Image
|
| 2 |
from io import BytesIO
|
| 3 |
import base64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
|
| 6 |
# Convert Image to Base64
|
|
@@ -13,3 +20,26 @@ def im_2_b64(image):
|
|
| 13 |
img_str = base64.b64encode(buff.getvalue())
|
| 14 |
return img_str
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from PIL import Image
|
| 2 |
from io import BytesIO
|
| 3 |
import base64
|
| 4 |
+
import streamlit as st
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
UNIT_COST = {
|
| 8 |
+
"user": 0.01,
|
| 9 |
+
"assistant": 0.03,
|
| 10 |
+
}
|
| 11 |
|
| 12 |
|
| 13 |
# Convert Image to Base64
|
|
|
|
| 20 |
img_str = base64.b64encode(buff.getvalue())
|
| 21 |
return img_str
|
| 22 |
|
| 23 |
+
|
| 24 |
+
def calculate_cost():
|
| 25 |
+
def get_text_cost(text, unit_cost):
|
| 26 |
+
num_of_words = len(text.split(" "))
|
| 27 |
+
tokens = max(1000.0 * num_of_words / 750.0, 0.0)
|
| 28 |
+
tokens = tokens / 1000.0
|
| 29 |
+
cost = tokens * unit_cost
|
| 30 |
+
return cost
|
| 31 |
+
def get_image_cost(unit_cost=0.01):
|
| 32 |
+
cost = 0.00255 # 512x512 image: https://openai.com/pricing
|
| 33 |
+
return cost
|
| 34 |
+
|
| 35 |
+
messages = st.session_state.messages
|
| 36 |
+
total_cost = 0
|
| 37 |
+
for message in messages:
|
| 38 |
+
role = message["role"]
|
| 39 |
+
for content in message["content"]:
|
| 40 |
+
if content["type"] == "image_url":
|
| 41 |
+
total_cost += get_image_cost(UNIT_COST[role])
|
| 42 |
+
else:
|
| 43 |
+
total_cost += get_text_cost(content["text"], UNIT_COST[role])
|
| 44 |
+
|
| 45 |
+
st.session_state.cost.append(total_cost)
|