visual-chatgpt / app.py
decisact's picture
Update
11b2a1a
from typing import List, Tuple, Dict, Generator
from langchain.chat_models import ChatOpenAI
import gradio as gr
import json
import os
import openai
parent = os.path.dirname(__file__)
data_path = os.path.join(parent, 'data.json')
def create_formatted_messages( messages: List[dict]) -> List[Tuple[str, str]]:
'''
create formatted history
=
Create formatted history for gradio chatbot
'''
user_messages = []
formatted_messages = []
assistant_messages = []
for message in messages:
if message['role'] == 'user':
user_messages.append(message['content'])
elif message['role'] == 'assistant':
assistant_messages.append(message['content'])
if user_messages and assistant_messages:
formatted_messages.append(
(''.join(user_messages), ''.join(assistant_messages))
)
user_messages = []
assistant_messages = []
# append any remaining messages
if user_messages:
formatted_messages.append((''.join(user_messages), None))
elif assistant_messages:
formatted_messages.append((None, ''.join(assistant_messages)))
return formatted_messages
class ChatGPT:
def chat(self, message: str, messages: List[Dict[str, str]], message_length:int) \
-> Generator[Tuple[List[Tuple[str, str]], List[Dict[str, str]]], None, None]:
if messages == None:
messages = []
messages.append({'role': 'system', 'content': 'ChatDefense is available to assist you with your legal questions.'})
messages.append({'role': 'user', 'content': message})
# We have no content for the assistant's response yet but we will update this:
messages.append({'role': 'assistant', 'content': ''})
response_message = ''
try:
chat_generator = self.openai.client.create(
messages=messages[-2*int(message_length):],
model=self.openai.model_name,
stream=True,
)
for chunk in chat_generator:
if 'choices' in chunk:
for choice in chunk['choices']:
if 'delta' in choice and 'content' in choice['delta']:
new_token = choice['delta']['content']
# Add the latest token:
response_message += new_token
# Update the assistant's response in our model:
messages[-1]['content'] = response_message
if 'finish_reason' in choice and choice['finish_reason'] == 'stop':
break
formatted_messages = create_formatted_messages(messages)
# TODO database
json.dump(messages, open(data_path, 'w'))
yield '', messages, formatted_messages
except Exception as e:
print(str(e))
def clear(self):
json.dump([], open(data_path, 'w'))
return [], []
def init_agent(self, openai_api_key):
self.openai = ChatOpenAI(openai_api_key=openai_api_key)
return gr.update(visible = True)
chatgpt = ChatGPT()
with gr.Blocks() as iface:
with gr.Row():
openai_api_key_textbox = gr.Textbox(
placeholder='Paste your OpenAI API key here to start ChatGPT(sk-...) and press Enter',
label='OpenAI API key',
type='password',
)
# larger lenght will generate a more accuarte response but exponetially larger token size
message_length = gr.Number(value=5, label='History message length')
data = json.load(open(data_path)) if os.path.exists(data_path) else {}
chatbot = gr.Chatbot(value=create_formatted_messages(data)).style()
with gr.Row(visible=False) as input_raws:
with gr.Column(scale=.9):
txt = gr.Textbox(placeholder='Enter message here', show_label=False).style(container=False)
with gr.Column(scale=.1, min_width=0):
clear = gr.Button(value='Clear')
messages = gr.State(data or [])
txt.submit(chatgpt.chat, [txt, messages, message_length], [txt, messages, chatbot])
clear.click(chatgpt.clear, [], [chatbot, messages])
openai_api_key_textbox.submit(chatgpt.init_agent, [openai_api_key_textbox], [input_raws])
iface.queue().launch()