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 @@
+
+
+