CoolFace
Apppublic

kimosabe777/OpenAI-FineTuning-NLP

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py256 linesDownload Raw Back to root
1import pandas as pd2import json3import re4import openai5from dotenv import load_dotenv6import os7import streamlit as st8import time9import logging10 11 12def createValidationData():13    # Load the dataset14    csvfile = "./datasets/test_dataset.csv"15    df = pd.read_csv(csvfile)16    df = df.dropna()    ## Added this line so that the dataframe does not contain any null values, otherwise it will throw an error in OpenAI fine-tuning17    df_valid = createTrainData(df)18    df_valid["Mood"] = df["Mood"].apply(map_mood)19    return df_valid20    21def loadData(data_file):22    # Load the dataset23    df = pd.read_csv(data_file)24    df = df.dropna()    ## Added this line so that the dataframe does not contain any null values, otherwise it will throw an error in OpenAI fine-tuning25    df_train = createTrainData(df)26    df_train["Mood"] = df["Mood"].apply(map_mood)27    return df_train28    29def createTrainData(df):30    # Create the training data31    df_neu = df[df['Mood']== 0]32    df_pos = df[df['Mood']== 1]33    df_neg = df[df['Mood']== 2]34    35    ## This sampling is based on the distribution of the dataset, required to do this for OpenAI fine-tuning36    df_sample_neu = df_neu.sample(frac=0.01)37    df_sample_pos = df_pos.sample(frac=0.01)38    df_sample_neg = df_neg.sample(frac=0.01)39    40    ## Logging to check the sample sizes are balanced between classes, this can be commented out later on41    logging.error(f"Sample Neutral {df_sample_neu.shape}")42    logging.error(f"Sample Positive {df_sample_pos.shape}")43    logging.error(f"Sample Negative {df_sample_neg.shape}")44    45    ## Combine the samples46    df_sample_sets = pd.concat([df_sample_neu, df_sample_pos, df_sample_neg])47    return df_sample_sets48 49 50def map_mood(senti_score):51    if senti_score == 1:52        return "Positive"53    elif senti_score == 2:54        return "Negative"55    else:56        return "Neutral"57 58 59## Coverting DF to JSON format60def dfToJSON(df, JSONfile):61    # Convert the DataFrame to the required format62    fine_tune_data = df[['translated_text', 'Mood']].rename(columns={'translated_text': 'prompt', 'Mood': 'completion'})63 64    # Save the dataset to a JSONL file65    #with open('fine_tune_data.jsonl', 'w') as f:66    with open(JSONfile, 'w') as f:67        for i, row in fine_tune_data.iterrows():68            json.dump({"prompt": row['prompt'], "completion": row['completion']}, f)69            f.write('\n')70 71    #fine_tune_data.head()72 73## Fine Tune OpenAI74def fineTune_OpenAI(client, JSONfile):75    # * Upload the training JSON data file for fine tuning76    # * Check the status of the upload job process 77    # * Run the fine tuning based on our training data78    # * Check the status of the fine tuning job process79 80    ## Upload the training data JON file to OpenAI (we have limit it to 200 for now see the "nrows" when the CSV data is loaded)81    response = client.files.create(file=open(JSONfile, 'rb'),82                                purpose='fine-tune')83   84    return response.id, response.status85 86def createJob_OpenAI(client, responseID, valid_respID):87    ## Creata a job to fine-tune the model. It might take a while depending on the size of the file that is being processed88    ## So, ideally we only use a small subset of training data89    finetune_response = client.fine_tuning.jobs.create(90        training_file=responseID,91        validation_file=valid_respID,92        model="davinci-002"93    )94    return finetune_response.id95 96def checkJob_OpenAI(client, responseID):97    ## Print the results/status information of the fine-tune job after submission98    #print(f"Fine tuning Job ID          : {finetune_response.id}")99    #print(finetune_response)100    #for key, value in finetune_response:101    #    print(f"{key} : {value}")102 103    ## Print the current results/status information of the fine-tuning job, make sure it is finished/successful104    ## before running the model, otherwise it will fail105    #client.fine_tuning.jobs.list(limit=1)106    jobStatus = client.fine_tuning.jobs.retrieve(responseID)107    #for key, value in jobStatus:108    #    print(f"{key} : {value}")109    110    ## Once the fine tuning is successful, we will get/used the "fine_tuned_model" from JobStatus object,111    ## otherwise, it will return "None"112    fineTunedModel = jobStatus.fine_tuned_model113    status = jobStatus.status114    return fineTunedModel, status115 116def listJobEvents(client, responseID):117    ## To list all the events for the fine-tuning job ##118    response = client.fine_tuning.jobs.list_events(responseID, limit=5)119    events = response.data120    events.reverse()121 122    #for event in events:123    #    print(event.message)124    return events125 126def getlastModel(client):127    # List 10 fine-tuning jobs128    response = client.fine_tuning.jobs.list(limit=1)129    #response130    for i in enumerate(response):131        #print(f"Job ID: {i[1].id}, Fine tuned Model: {i[1].fine_tuned_model}, Status: {i[1].status}")132        ft_jobid = i[1].id133        ft_model = i[1].fine_tuned_model134        ft_status = i[1].status135        break136    return ft_model, ft_status137    138 139def AnalyzeSentiment(client, model, tweet):140    response = client.completions.create(141        model=model,142        prompt=tweet,143        max_tokens=1144        #temperature=0,145        #top_p=1,146        #frequency_penalty=0,147        #presence_penalty=0,148        #stop=["\n"]149    )150    return response151 152 153def uiTweets():154    user_tweet = st.text_input("Tweet: ")155    return user_tweet156 157 158def testTweet(client, fineTunedModel, tweet):159    TestResponse = AnalyzeSentiment(client, fineTunedModel, tweet)160 161    #print(TestResponse.choices[0].text)162    st.write(TestResponse.choices[0].text)163    164 165def main():166    # Set up logging configuration167    logging.basicConfig(filename='tweetLLM_errors.log', level=logging.ERROR, 168                    format='%(asctime)s:%(levelname)s:%(message)s')169    170    ## Load your API key from an environment variable or a configuration file171    load_dotenv()172    openai.api_key = os.getenv("OPENAI_API_KEY", "<your OpenAI API key if not set as env var>")173    client = openai.OpenAI(api_key=openai.api_key)174         175    st.header("NLP with OpenAI : :panda_face:")176     177    user_tweet = st.text_input("Enter Tweet to analyze: ")178    #print(user_tweet)179    #st.write(user_tweet)180    181    button_label = "Evaluate sentiment"182    train_new = 0183    job_status = ""184    opt_rad1 = st.radio("Option", ["Train and fine-tune new model", "Use last Fine-tuned model"], captions = ["Train and fine-tune new model in OpenAI", "Use last Fine-tuned model from OpenAI"])185    if opt_rad1 == "Train and fine-tune new model":186        button_label = "Train new model"187        uploaded_file = st.file_uploader("Choose a file")188        train_new = 1189    else:190        ft_model, ft_status = getlastModel(client)191        job_status = ft_status192        ft_msg = f"Last trained model was *{ft_model}* with status of *{ft_status}*"193        st.write(ft_msg)194   195    196    if st.button(button_label):    197        msg_placeholder = st.empty()198        msg_list = []199        if train_new:    ## Train new model   200            if uploaded_file:     ## This will allow you to upload the datasets to be used to train new model201                dataset = loadData(uploaded_file)202                dataset_v = createValidationData()203                finetune_JSON = "fine_tune_data.jsonl"204                validation_JSON = "validation_data.jsonl"205                dfToJSON(dataset, finetune_JSON)206                dfToJSON(dataset_v, validation_JSON)207                responseID, responseStatus = fineTune_OpenAI(client, finetune_JSON)         ## This line for the training data208                valid_respID, valid_respStatus = fineTune_OpenAI(client, validation_JSON)   ## This line for the validation data209                msg_list.append(f"Response ID: {responseID}, Status : {responseStatus}")210                msg_list.append(f"Response ID: {valid_respID}, Status : {valid_respStatus}")211                msg_placeholder.text_area("Processing", "\n".join(msg_list), height=200)212                responseID = createJob_OpenAI(client, responseID, valid_respID)213                214                with st.spinner("Fine tuning new model in OpenAI..."):215                    while True:216                        fineTunedModel, job_status = checkJob_OpenAI(client, responseID)217                        ##fineTunedModel = "Test tune Model"218                        #msg2 = f"Fine Tune Model : {fineTunedModel} - {type(fineTunedModel)}"219                        msg_list.append(f"Fine Tune Model : {fineTunedModel} - {type(fineTunedModel)}")220                        msg_list.append(f"Job Status : {job_status}")221                        msg_placeholder.text_area("Processing", "\n".join(msg_list), height=200)222                        if job_status == "failed":223                            break224                        else:225                            if fineTunedModel is not None:226                                break227                            else:228                                time.sleep(20)229                                events = listJobEvents(client, responseID)230                                #events = ["Processing...1", "Processing...2", "Processing...3", "Processing...4"]231                                for event in events:232                                    msg_list.append(event.message)233                                    msg_placeholder.text_area("Processing", "\n".join(msg_list), height=200)234                                continue235            else:236                msg_list.append("Training failed! Please upload a file to train new model and try again")237                msg_placeholder.text_area("", "\n".join(msg_list), height=200)238        else:   ## Use the last good model239            st.write(user_tweet)240            if ft_model is not None:241                fineTunedModel = ft_model242        243        if job_status == "failed":244            st.write("Fine-tuning failed. Check your data and please try again.")245        else:246            if job_status == "succeeded":247                TestResponse = AnalyzeSentiment(client, fineTunedModel, user_tweet)248                #TestResponse = "Test response"249                st.write(TestResponse)250                sentiResults = TestResponse.choices[0].text 251                st.write(sentiResults)252    253  254 255if __name__ == "__main__":256    main()