diff --git a/Chatbox/.gitignore b/Chatbox/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/Chatbox/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/Chatbox/README.md b/Chatbox/README.md new file mode 100644 index 0000000..d98d294 --- /dev/null +++ b/Chatbox/README.md @@ -0,0 +1,34 @@ +# Chatbox - ChatEST + +## Report + +Document: [Report](https://docs.google.com/document/d/1lnbVuqS9-5NX0DShnio0EvpFzl4awvf-Qv7MIyTyals/edit?usp=sharing) +Slide: [Presentation Slide](https://studenthcmusedu-my.sharepoint.com/:p:/g/personal/19127525_student_hcmus_edu_vn/ESQW4FMuGzRJrYHTVzh_OFYBLuFvv4eduu2Y04bbH_WbFQ?e=nBZ2Ik) + +## Demo + +Video: [Demo](https://youtu.be/U9o-iFPdteU) + +## Running + +`python3 app.py` +Run on `127.0.0.1:3000` or `localhost:3000` + +## Technology: + +**Framework**: Flask +**Backend**: Python +**Frontend**: HTML, CSS, Bootstrap 5 + +## Member + +- 19127392 - [To Gia Hao](https://github.com/To-Gia-Hao) +- **19127525 - [Nguyen Thanh Quan](https://github.com/QuanBlue)** +- 19127625 - [Lam Chi Van](https://github.com/chivanz128) + +## Reference + +- [OpenAI guide](https://platform.openai.com/docs/guides/completion/introduction) +- [Flask example](https://github.dev/helloflask/flask-examples) +- [How to create advance chatbot - Ebook](https://www.amazon.com/How-Create-Advanced-Chatbot-Introductory-ebook/dp/B0BR4MDDJL) +- [Controlling the length of Completions](https://help.openai.com/en/articles/5072518-controlling-the-length-of-completions) diff --git a/Chatbox/app.py b/Chatbox/app.py new file mode 100644 index 0000000..ea23d16 --- /dev/null +++ b/Chatbox/app.py @@ -0,0 +1,119 @@ +import os + +try: + import openai + from flask import Flask, render_template, request, Markup + from dotenv import load_dotenv, set_key, find_dotenv + from flask_bootstrap import Bootstrap + from form.InputPromptForm import InputPromptForm +except Exception: + # import all package + os.system("pip install -r requirements.txt") + + import openai + from flask import Flask, render_template, request, Markup + from dotenv import load_dotenv, set_key, find_dotenv + from flask_bootstrap import Bootstrap + from form.InputPromptForm import InputPromptForm + +load_dotenv() # take environment variables from .env. + +SECRET_KEY = os.getenv("SECRET_KEY") +PORT = os.getenv("PORT") +API_KEY = os.getenv("API_KEY") +MODEL_ENGINE = os.getenv("MODEL_ENGINE") +MAX_TOKENS = os.getenv("MAX_TOKENS") +TEMPERATURE = os.getenv("TEMPERATURE") +TOP_P = os.getenv("TOP_P") +FREQUENCY_PENALTY = os.getenv("FREQUENCY_PENALTY") +PRESENCE_PENALTY = os.getenv("PRESENCE_PENALTY") + +app = Flask(__name__) + +Bootstrap(app) + +app.config['SECRET_KEY'] = SECRET_KEY + +# Setup api key +API_KEY = os.getenv("API_KEY") +openai.api_key = API_KEY + +# Define a list to store the conversation history +conversation_history = [] + + +def generate_response(history): + # Combine the conversation history into a single string + # Use the last 5 messages as context + prompt = "\n".join(history[-5:]) + + # Call the OpenAI API to generate a response + response = openai.Completion.create( + engine=MODEL_ENGINE, + prompt=prompt, + max_tokens=int(MAX_TOKENS), + temperature=float(TEMPERATURE), + top_p=float(TOP_P), + frequency_penalty=float(FREQUENCY_PENALTY), + presence_penalty=float(PRESENCE_PENALTY), + ) + + # Extract the response + message = response.choices[0].text.lstrip( + "?!").strip().replace("\n", "
").replace("\"", "\'") + + return message + + +@app.route('/', methods=['GET', 'POST']) +def main(): + form = InputPromptForm() + checkAPI = True + response = "" + prompt = "" + error = "" + + if request.method == "POST": + prompt = request.form.get("prompt") + newAPI = request.form.get("newAPI") + + if (prompt and prompt.strip(" ") != ""): + + # get chatbot response + try: + # Add the user's message to the conversation history + conversation_history.append(prompt) + + # Generate a response + response = generate_response(conversation_history) + + # Add the bot's response to the conversation history + conversation_history.append(response) + except Exception as e: + print("Error:", e) + if "Incorrect API key provided" in str(e): + print("key:", os.getenv("API_KEY")) + response = "Incorrect API key provided" + checkAPI = False + else: + error = e + + # checkAPI = False + response = Markup(response) + + print("GPT:", response) + + if (newAPI): + API_KEY = newAPI + openai.api_key = API_KEY + + dotenv_file = find_dotenv() + set_key(dotenv_file, "API_KEY", API_KEY) + + print("newAPI:", newAPI, "END") + + return render_template('index.html', form=form, message=response, checkAPI=checkAPI, error=error) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=PORT, threaded=True, debug=True) diff --git a/Chatbox/form/InputPromptForm.py b/Chatbox/form/InputPromptForm.py new file mode 100644 index 0000000..e1b7266 --- /dev/null +++ b/Chatbox/form/InputPromptForm.py @@ -0,0 +1,8 @@ +from flask_wtf import FlaskForm +from wtforms import (StringField) + + +class InputPromptForm(FlaskForm): + prompt = StringField("Prompt", render_kw={"placeholder": "Prompt"}) + newAPI = StringField("OpenAI API Key", render_kw={ + "placeholder": "OpenAI API Key"}) diff --git a/Chatbox/requirements.txt b/Chatbox/requirements.txt new file mode 100644 index 0000000..b2df2d1 --- /dev/null +++ b/Chatbox/requirements.txt @@ -0,0 +1,8 @@ +aiohttp==3.8.4 +Flask==2.2.3 +Flask-Bootstrap==3.3.7.1 +Flask-WTF==1.1.1 +openai==0.26.5 +WTForm==1.0 +WTForms==3.0.1 + diff --git a/Chatbox/static/assets/logo/ChatGPT_logo.png b/Chatbox/static/assets/logo/ChatGPT_logo.png new file mode 100644 index 0000000..28e8a17 Binary files /dev/null and b/Chatbox/static/assets/logo/ChatGPT_logo.png differ diff --git a/Chatbox/static/assets/logo/User_logo.jpg b/Chatbox/static/assets/logo/User_logo.jpg new file mode 100644 index 0000000..bb5d662 Binary files /dev/null and b/Chatbox/static/assets/logo/User_logo.jpg differ diff --git a/Chatbox/static/assets/logo/User_logo.png b/Chatbox/static/assets/logo/User_logo.png new file mode 100644 index 0000000..f7ed2d6 Binary files /dev/null and b/Chatbox/static/assets/logo/User_logo.png differ diff --git a/Chatbox/static/assets/logo/openai-logo.png b/Chatbox/static/assets/logo/openai-logo.png new file mode 100644 index 0000000..67787b3 Binary files /dev/null and b/Chatbox/static/assets/logo/openai-logo.png differ diff --git a/Chatbox/static/assets/member/avt_LamChiVan.jpg b/Chatbox/static/assets/member/avt_LamChiVan.jpg new file mode 100644 index 0000000..a150954 Binary files /dev/null and b/Chatbox/static/assets/member/avt_LamChiVan.jpg differ diff --git a/Chatbox/static/assets/member/avt_NguyenThanhQuan.jpg b/Chatbox/static/assets/member/avt_NguyenThanhQuan.jpg new file mode 100644 index 0000000..8ac4729 Binary files /dev/null and b/Chatbox/static/assets/member/avt_NguyenThanhQuan.jpg differ diff --git a/Chatbox/static/scrollbar.css b/Chatbox/static/scrollbar.css new file mode 100644 index 0000000..9c54e23 --- /dev/null +++ b/Chatbox/static/scrollbar.css @@ -0,0 +1,15 @@ +/* width */ +::-webkit-scrollbar { + width: 9px; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: rgb(86, 88, 105); + border-radius: 10px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #acacbe; +} diff --git a/Chatbox/static/style.css b/Chatbox/static/style.css new file mode 100644 index 0000000..1a598dd --- /dev/null +++ b/Chatbox/static/style.css @@ -0,0 +1,123 @@ +* { + margin: auto; + padding: auto; +} + +body { + background: #343541; + font-size: 15px; +} + +h2 { + font-size: 40px; +} + +.btn-primary { + background: #6c757d; + border: none; +} + +.btn-primary:hover { + background: #53595f; + font-weight: bold; +} + +.btn-secondary { + background: transparent; + border: none; +} + +.btn-secondary:hover { + background: transparent; + border: none; + font-weight: bold; +} + +.loading-view { + z-index: 100; +} + +.bg-light-dark { + background: #444654 !important; +} + +.bg-dark { + background: #343541 !important; +} + +.modal-content { + background: #343541; + color: white; +} + +.img-thumbnail { + height: 50px; + width: 50px; +} +.content { + color: white; +} + +.chat-gpt-prompt, +.user-prompt { + text-align: justify; +} + +.input-group, +.send-btn, +#prompt, +#prompt:focus, +#newAPI, +#newAPI:focus { + background-color: #40414f; + color: white; + border-width: 0px !important; + outline-width: 0px; +} + +#prompt { + padding: 10px; + width: 100% !important; +} + +#newAPI { + border-radius: 10px; + padding: 10px 15px; + width: 100% !important; +} +.input-group-text, +.send-btn { + padding: 0px; + height: 100% !important; + /* width: 100% !important; */ +} + +.input-group-text, +.send-btn:hover { + background-color: #343541 !important; +} + +.up-icon, +.down-icon { + height: 40px; + width: 40px; + right: 30px; + bottom: 200px; + border: 1px solid white; + border-radius: 50%; + color: white; + background-color: transparent; +} + +.down-icon { + top: 100px; +} + +.msg img, +md-block img { + width: 400px !important; +} + +.pre-footer { + height: 150px !important; +} diff --git a/Chatbox/templates/index.html b/Chatbox/templates/index.html new file mode 100644 index 0000000..dc233a0 --- /dev/null +++ b/Chatbox/templates/index.html @@ -0,0 +1,394 @@ + + + + + + + ChatEST + + + + + + + + + + + + + +
+ +
+
+
+
+ Loading... +
+
+
+
+ + + + + + +
+

ChatEST

+ + +
+ + + + +
+ + + +
+ + + + + +
+
+
+
+
+
{{form.prompt}}
+ +
+ +
+ ChatEST source + Free Research Preview. ChatEST is not for commercial + use. +
+
+ + +
+ +
+ +
+ + +
+
+ +
+
+ + + + + + ] + + + +