|
import gradio as gr |
|
from openai import OpenAI |
|
import os |
|
import sqlite3 |
|
import base64 |
|
|
|
|
|
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY') |
|
if not OPENAI_API_KEY: |
|
raise ValueError("API key not found. Please set the OPENAI_API_KEY environment variable.") |
|
|
|
client = OpenAI(api_key=OPENAI_API_KEY) |
|
|
|
|
|
conn = sqlite3.connect('faqs.db') |
|
c = conn.cursor() |
|
c.execute('''CREATE TABLE IF NOT EXISTS faq (id INTEGER PRIMARY KEY, question TEXT, answer TEXT)''') |
|
conn.commit() |
|
|
|
global_system_prompt = None |
|
global_model = 'gpt-4o' |
|
|
|
def encode_image(image_path): |
|
with open(image_path, "rb") as image_file: |
|
return base64.b64encode(image_file.read()).decode('utf-8') |
|
|
|
def build_assistant(field, lang, name, model, description, rules): |
|
global global_system_prompt |
|
global global_model |
|
list_faqs = get_faqs() |
|
system_prompt = f'''You are a helpful chatbot that helps customers and answers based on FAQs. |
|
You must answer only in {lang}. |
|
your name is {name}. |
|
''' |
|
global_system_prompt = system_prompt |
|
if len(description) > 0: |
|
global_system_prompt = system_prompt + ' {description}.' |
|
if model != 'gpt-4o': |
|
global_model = model |
|
if len(rules) > 0: |
|
global_system_prompt = system_prompt + f'you must follow these rules: {rules}' |
|
if len(list_faqs) > 0: |
|
global_system_prompt = system_prompt + f'if the customer asks a question first check these list of faqs for the answer. if theres is no answer suggest this phone number to the customer to call 09999999999' |
|
|
|
def add_faq(question, answer): |
|
conn = sqlite3.connect('faqs.db') |
|
c = conn.cursor() |
|
c.execute('INSERT INTO faq (question, answer) VALUES (?, ?)', (question, answer)) |
|
conn.commit() |
|
conn.close() |
|
|
|
def get_faqs(): |
|
faq_list = '' |
|
conn = sqlite3.connect('faqs.db') |
|
c = conn.cursor() |
|
c.execute('SELECT question, answer FROM faq') |
|
faqs = c.fetchall() |
|
if len(faqs) > 0: |
|
faq_list = "\n\n".join([f"Q: {faq[0]}\nA: {faq[1]}" for faq in faqs]) |
|
conn.close() |
|
return faq_list |
|
|
|
def send_message(user_message, chat_history): |
|
chat_history.append((f"User: {user_message}", 'Hi there')) |
|
return "", chat_history |
|
|
|
def convert_history_to_openai_format(history): |
|
""" |
|
Convert chat history to OpenAI format. |
|
|
|
Parameters: |
|
history (list of tuples): The chat history where each tuple consists of (message, sender). |
|
|
|
Returns: |
|
list of dict: The formatted history for OpenAI with "role" as either "user" or "assistant". |
|
""" |
|
global global_system_prompt |
|
if global_system_prompt == None: |
|
global_system_prompt = "You are a helpful assistant." |
|
formatted_history = [{"role": "system", "content": global_system_prompt},] |
|
for user_msg, assistant_msg in history: |
|
if ('.png' in user_msg[0]) or ('.jpg' in user_msg[0]): |
|
encoded_image = encode_image(user_msg[0]) |
|
text = 'help me based on the image' |
|
if user_msg[1] != '': |
|
text = user_msg[1] |
|
content = [{'type':'text', 'text':text},{'type':'image_url','image_url':{'url':f'data:image/jpeg;base64,{encoded_image}'}}] |
|
formatted_history.append({"role": 'user', "content": content}) |
|
else: |
|
formatted_history.append({"role": 'user', "content": user_msg}) |
|
if isinstance(assistant_msg,str): |
|
formatted_history.append({"role": 'assistant', "content": assistant_msg}) |
|
return formatted_history |
|
def add_message(history, message): |
|
if len(message["files"]) > 0: |
|
for x in message["files"]: |
|
history.append(((x,message["text"]), None)) |
|
else: |
|
if message["text"]!='': |
|
history.append((message["text"], None)) |
|
print(history) |
|
return history, gr.MultimodalTextbox(value=None, interactive=False) |
|
def bot(history): |
|
global global_model |
|
response = client.chat.completions.create( |
|
model=global_model, |
|
messages=convert_history_to_openai_format(history) |
|
) |
|
|
|
chatbot_message = response.choices[0].message.content.strip() |
|
history[-1][1] = chatbot_message |
|
return history |
|
|
|
with gr.Blocks() as demo: |
|
|
|
warning_markdown = gr.Markdown(value="", visible=False) |
|
with gr.Row(): |
|
with gr.Column(scale=1, min_width=200): |
|
gr.Markdown("### Assistant settings") |
|
field = gr.Textbox(label="Field", value='AI') |
|
lang = gr.Dropdown(label='Language', choices=['English', 'Persian'], value='English') |
|
name = gr.Textbox(label="Name", value='AIBOT') |
|
model = gr.Dropdown(label="Model", choices=['gpt-4o','gpt-4','gpt-3.5'], value='gpt-4o') |
|
description = gr.Textbox(label="Description", lines=3) |
|
rules = gr.Textbox(label="Rules", lines=3) |
|
build_button = gr.Button("Build") |
|
|
|
|
|
with gr.Column(scale=1, min_width=200): |
|
gr.Markdown("### Add FAQ") |
|
question = gr.Textbox(label="Question", lines=2) |
|
answer = gr.Textbox(label="Answer", lines=3) |
|
add_button = gr.Button("Add") |
|
|
|
|
|
with gr.Column(scale=1, min_width=200): |
|
gr.Markdown("### List of FAQs") |
|
faq_list = gr.Textbox(label="", interactive=False, lines=15, max_lines=15, placeholder="No FAQs available") |
|
refresh_button = gr.Button("Refresh") |
|
|
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Markdown("### Chatbot Playground") |
|
chatbot = gr.Chatbot(label="Chatbot:", bubble_full_width=False,show_copy_button=True,min_width=400, |
|
avatar_images=(os.path.join(os.getcwd(),'user.png'),os.path.join(os.getcwd(),'ai.png'))) |
|
chat_input = gr.MultimodalTextbox(interactive=True, |
|
placeholder="Enter message or upload file...", show_label=False) |
|
|
|
|
|
build_button.click(build_assistant, inputs=[field, lang, |
|
name, model, description, rules], outputs=[]) |
|
add_button.click(add_faq, inputs=[question, answer], outputs=[]) |
|
refresh_button.click(get_faqs, inputs=[], outputs=[faq_list]) |
|
chat_msg = chat_input.submit(add_message, [chatbot, chat_input], [chatbot, chat_input]) |
|
bot_msg = chat_msg.then(bot, chatbot, chatbot, api_name="bot_response") |
|
bot_msg.then(lambda: gr.MultimodalTextbox(interactive=True), None, [chat_input]) |
|
|
|
|
|
|
|
|
|
demo.launch() |
|
|