chatgpt-vision / app.py
dipta007's picture
added option to append message
8469de9
from openai import OpenAI
import streamlit as st
from utils import im_2_b64, calculate_cost, clear_uploader, undo, restart
import pickle
from upload import upload_file, get_file
share_keys = ["messages", "cost"]
client = OpenAI(api_key=st.secrets["OPENAI_KEY"])
st.set_page_config(
page_title="ChatGPT with Vision",
page_icon="πŸ€–",
menu_items={
"About": """
*ChatGPT with Vision* is a chat interface that uses OpenAI's API to generate responses to your prompts.
*---- Developed by **[Shubhashis Roy Dipta](https://roydipta.com)** ----*
"""
}
)
if "messages" not in st.session_state:
st.session_state.messages = []
if "uploader_key" not in st.session_state:
st.session_state["uploader_key"] = 0
if "cost" not in st.session_state:
st.session_state.cost = []
if len(st.session_state.messages) == 0 and "id" in st.query_params:
with st.spinner("Loading chat..."):
id = st.query_params["id"]
data = get_file(id, 'chatgpt-vision-007')
obj = pickle.loads(data)
for k, v in obj.items():
st.session_state[k] = v
def share():
obj = {}
for k in share_keys:
if k in st.session_state:
obj[k] = st.session_state[k]
data = pickle.dumps(obj)
id = upload_file(data, 'chatgpt-vision-007')
url = f"https://umbc-nlp-chatgpt-vision.hf.space/?id={id}"
st.success(f"Share URL: {url}")
with st.sidebar:
st.title(":blue[ChatGPT with Vision]")
password = st.text_input("Password", type="password")
if st.button("Share", use_container_width=True):
share()
cols = st.columns(2)
with cols[0]:
if st.button("Restart", type="primary", use_container_width=True):
restart()
with cols[1]:
if st.button("Undo", use_container_width=True):
undo()
with st.expander("Advanced Configuration"):
st.subheader("Temperature")
temperature = st.slider(label="x", min_value=0.1, max_value=1.0, value=0.2, step=0.1, label_visibility='collapsed')
st.subheader("Max Tokens")
max_tokens = st.slider(label="x", min_value=32, max_value=1024, value=256, step=32, label_visibility='collapsed')
st.subheader("Random Seed")
random_seed = st.number_input("Seed", min_value=0, max_value=1000000, value=42, step=1, label_visibility='collapsed')
with st.expander("Image Input", expanded=True):
images = st.file_uploader(
"Image Upload",
accept_multiple_files=True,
type=["png", "jpg", "jpeg"],
key=st.session_state["uploader_key"],
label_visibility="collapsed",
)
with st.expander(f"Total Cost: ${sum(st.session_state.cost):.10f}"):
if len(st.session_state.cost) > 0:
st.subheader("Cost Breakdown")
for i, c in enumerate(st.session_state.cost):
st.write(f"Message {i+1}: ${c:.10f}")
st.markdown("---")
st.write(f"Total: ${sum(st.session_state.cost):.10f}")
else:
st.write("No cost incurred yet")
append = st.checkbox("Append to previous message", value=False)
for message in st.session_state.messages:
with st.chat_message(message["role"]):
contents = message["content"]
for content in contents:
if content["type"] == "text":
st.markdown(content["text"])
number_of_images = sum(1 for c in contents if c["type"] == "image_url")
if number_of_images > 0:
cols = st.columns(number_of_images)
i = 0
for content in contents:
if content["type"] == "image_url":
with cols[i]:
st.image(content["image_url"]["url"])
i += 1
def push_message(role, content, images=None):
contents = []
contents.append({"type": "text", "text": content})
if images:
for image in images:
image_b64 = im_2_b64(image)
image_url = f"data:image/jpeg;base64,{image_b64.decode('utf-8')}"
obj = {
"type": "image_url",
"image_url": {
"url": image_url,
},
}
contents.append(obj)
message = {"role": role, "content": contents}
st.session_state.messages.append(message)
return message
if prompt := st.chat_input("Type a message", key="chat_input"):
if password != st.secrets["PASSWORD"]:
st.error("Invalid password. Demo is read-only.")
st.stop()
push_message("user", prompt, images)
with st.chat_message("user"):
st.markdown(prompt)
if images:
cols = st.columns(len(images))
for i, image in enumerate(images):
with cols[i]:
st.image(image)
if not append:
with st.chat_message("assistant"):
messages = [
{"role": m["role"], "content": m["content"]}
for m in st.session_state.messages
]
stream = client.chat.completions.create(
model="gpt-4-vision-preview",
messages=messages,
stream=True,
seed=random_seed,
temperature=temperature,
max_tokens=max_tokens,
)
response = st.write_stream(stream)
push_message("assistant", response)
calculate_cost()
clear_uploader()