├── screenshot.png ├── .gitignore ├── README.md ├── example.jsonl ├── LICENSE └── main.py /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anchen1011/chatgpt-finetune-ui/HEAD/screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *wandb 2 | *submit 3 | *slurm 4 | 5 | __pycache__/ 6 | .DS_Store 7 | .ipynb_checkpoints/ 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chatgpt-finetune-ui 2 | Simple python WebUI for fine-tuning gpt-3.5-turbo 3 | 4 | 5 | ![screenshot](screenshot.png) 6 | 7 | ## Installation 8 | ``` 9 | pip install openai 10 | pip install streamlit 11 | ``` 12 | 13 | ## Usage 14 | ``` 15 | streamlit run main.py --server.port 8001 --server.address 0.0.0.0 16 | ``` 17 | 18 | ## Experimental Demo 19 | [http://system2.space:8001](http://system2.space:8001) 20 | -------------------------------------------------------------------------------- /example.jsonl: -------------------------------------------------------------------------------- 1 | {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}]} 2 | {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]} 3 | {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters."}]} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Baian Chen (Andrew) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import string 3 | import os 4 | import json 5 | import re 6 | import webbrowser 7 | import openai 8 | import pandas as pd 9 | 10 | st.set_page_config(page_title="ChatGPT Finetuning WebUI", page_icon=":smiley:", layout="wide") 11 | 12 | with st.sidebar: 13 | api_key = st.text_input('Enter your API key:', '') 14 | 15 | # If api_key is entered, read the contents and process the data 16 | if api_key.startswith('sk-'): 17 | openai.api_key = api_key 18 | st.title("ChatGPT Finetuning WebUI") 19 | 20 | st.subheader("Files") 21 | files = openai.File.list() 22 | st.table(pd.DataFrame(sorted(files.data, key=lambda k: -k['created_at']))) 23 | 24 | st.subheader("Jobs") 25 | jobs = openai.FineTuningJob.list() 26 | st.table(pd.DataFrame(sorted(jobs.data, key=lambda k: -k['created_at']))) 27 | 28 | st.subheader("Finetuned Models") 29 | models = openai.Model.list() 30 | st.table(pd.DataFrame([d for d in models.data if d["id"].startswith("ft")])) 31 | 32 | st.subheader("Debug Info") 33 | response_display = st.empty() 34 | 35 | with st.sidebar: 36 | file = st.file_uploader("Upload a file", accept_multiple_files=False) 37 | 38 | file_ids = [d["id"] for d in sorted(files.data, key=lambda k: -k['created_at'])] 39 | file_id = st.selectbox("Select a file", file_ids) 40 | 41 | job_ids = [d["id"] for d in sorted(jobs.data, key=lambda k: -k['created_at'])] 42 | job_id = st.selectbox("Select a job", job_ids) 43 | 44 | n_epochs = st.number_input("Number of Epochs", min_value=1, max_value=100, value=3) 45 | 46 | if file: 47 | uploaded_file = openai.File.create(file=file, purpose='fine-tune', user_provided_filename=file.name) 48 | response_display.write(uploaded_file) 49 | 50 | if st.button("Delete File") and file_id: 51 | deleted_file = openai.File.delete(file_id) 52 | response_display.write(deleted_file) 53 | 54 | if st.button("Create Fine-Tuning Job") and file_id: 55 | job = openai.FineTuningJob.create(training_file=file_id, model='gpt-3.5-turbo', hyperparameters={"n_epochs":n_epochs, }) 56 | response_display.write(job) 57 | 58 | if st.button("Get Fine-Tuning Job Detail") and job_id: 59 | job = openai.FineTuningJob.retrieve(job_id) 60 | response_display.write(job) 61 | 62 | if st.button("List Job Events") and job_id: 63 | events = openai.FineTuningJob.list_events(id=job_id, limit=10) 64 | for event in events.data: 65 | response_display.write(event) 66 | 67 | if st.button("Cancel Job") and job_id: 68 | cancelled_job = openai.FineTuningJob.cancel(job_id) 69 | response_display.write(cancelled_job) 70 | --------------------------------------------------------------------------------