CoolFace
Apppublic

hoson/qGen

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py278 linesDownload Raw Back to root
1# -*- coding: utf-8 -*-2"""3Created on Thu Jul 25 11:57:10 20244 5*** json.xxxs where 's' means String datatype6API Ref:  https://docs.llamaindex.ai/en/stable/api_reference/7Question generation:  https://docs.llamaindex.ai/en/stable/examples/finetuning/llm_judge/correctness/finetune_llm_judge_single_grading_correctness/8 9pip install llama-index10pip install llama-index-llms-azure-openai11pip install ipywidgets12pip install opencc #for CN-CN (e.g traditional<->simplified) translation13 14@author: hoson15"""16import os17import random18import json19from llama_index.core import SimpleDirectoryReader20from llama_index.core.evaluation import DatasetGenerator21from llama_index.llms.azure_openai import AzureOpenAI as LmaIdxAzOpenAI #pip install llama-index-llms-azure-openai22import gradio as gr23# import myLanChLib as lc24 25FOR_HUG_FACE= True; SHARE_H=FOR_HUG_FACE26 27DEBUG_L1=True28if DEBUG_L1: index=0 # for print() index of the randomly picked Question 29GRADIO_ENABLE = True #True  #False to Disable Gradio UI, Debugging30ADD_REF = True # False31 32NUM_PER_CK =5; NO_OF_QUESTIONS=500 #can't work for 1000, 800, 500 when per chunck is 25 (6Aug2024)33entry_1st_global=True34 35LMA_IDX_QUESTION_GEN_PROMPT = ( #string as a prompt for llamaindex36    "You are a Teacher/ Professor. Your task is to setup " #default prompt by llamIdx37    "a quiz/examination. Using the provided context, formulate " #default prompt by llamIdx38    "a single question that captures an important fact from the " #default prompt by llamIdx39    # "do not ask like What is the title of the document or the size for a document" #add by me on 25Jul202440    "context. Restrict the question to the context information provided." #default prompt by llamIdx41    )42# LMA_IDX_QUESTION_GEN_PROMPT = (43#     "你是一名教師/教授。你的任務是設定"44#     "測驗/考試。使用提供的上下文,製定"45#     "一個從中捕捉到重要事實的問題"46#     "上下文。將問題限制在提供的上下文資訊範圍內."47#     )48 49LLM = LmaIdxAzOpenAI( #Azure OpenAI module from llamaindex50    engine='gpt4o-mini', #'g4o', #"GPT-4Omni", # =deployment_name in Langchain Azure51    api_version="2024-05-01-preview",52    model='gpt-4o-mini', #'gpt-4o', # = Model name in Azure53    azure_endpoint="https://4davatar.openai.azure.com/",54    api_key=os.getenv("4davatar1_KEY"),55    temperature=0.0,56    )57 58remove_list=[', as outlined in the provided context',59             'as outlined in the provided context',60             61             ', as mentioned in the provided document',62             'as mentioned in the provided document',63             64             ', as mentioned in the context',65             'as mentioned in the context',66             67             ', as mentioned in the provided context',68             'as mentioned in the provided context',69             70             ', as mentioned in the report',71             'as mentioned in the report',72             73             ' as mentioned in the reference material',74             'mentioned in the reference material'75 76             ', as presented in the document',77             'presented in the document',78             79             ', as described in the document'80             'as described in the document'81             82             'that is referenced in the document',83             ', as referenced in the document'84            85            'in the provided context',86            'according to the provided context',87            'as outlined',88            ', as suggested',89            ', as mentioned',90             ]91 92def remove_sentences(content:str, sentences_list:list):93    """94    Remove a sentence from a big paragraph.95 96    Parameters97    ----------98    content : str99        DESCRIPTION.100    sentences_list : list101        List of all sentences to be removed.102 103    Returns104    -------105    content : str106        The modified comtent107 108    """109    for sent in sentences_list:110        content=content.replace(sent, '')111    return content112 113def dict2str_json(dictionary:dict): #'s' means String114    str_json = json.dumps(dictionary, indent=2) # convert a Python object into formatted Json string.115    return str_json116 117def str_json2file(str_json:str, filename):118    with open(filename, "w") as f: #save119        json.dump(str_json, f) #, indent=4) # writing/dumping formatted JSON to a file/socket.120        print(f"Saved in {filename}.")121    return122 123def translate(text:str, mode='no'):124    assert mode in ('no', 'e2zh', 'zh2e'), 'Error: Invalid mode'125    match mode:126        # case 'e2zh': text = lc.a4o_en2cn_traditional(text)127        # case 'zh2e': text = lc.lc.a4o_cn_traditional2en(text)128        case 'no': pass129        130    return text131 132def gen_question_ans(prompt:str, mode='no'):133    """134    Generate questions and answers from the documents in the folder 'data'.135    136    Parameters137    ----------138    prompt : str139        The prompt instructe an LLM to generate question from the corpus in the folder 'data'140    mode : string, optional141       The default is 'no'.142 143    Returns144    -------145    dicts_list: list of Dict146 147    """148    assert mode in ('no', 'e2zh', 'zh2e'), 'Error: Invalid mode'149# generate questions against chunks    150    print("Loading documents from folder....")151    documents = SimpleDirectoryReader("data").load_data() #folder 'data' in current directory152    dataset_generator = DatasetGenerator.from_documents( # instantiate a DatasetGenerator153        documents,154        question_gen_query=prompt,155        llm=LLM,156        num_questions_per_chunk=NUM_PER_CK #25, #5, #25,157        )158    print("Starting to generate question......, wait for 5-15min")159    # ==============generate questions against chunks==============================160    import nest_asyncio; nest_asyncio.apply() #avoid nested asyn Runtime error,  https://pypi.org/project/nest-asyncio/161    qrd = dataset_generator.generate_dataset_from_nodes(num=NO_OF_QUESTIONS)#350) #num=actual no of questions to gen162    # don't need nest_asyncio if use .agenerate_dataset_from_nodes163    # # qrd = dataset_generator.agenerate_dataset_from_nodes(num=50)#350) #num=actual no of questions to gen164    # =============================================================================165    queries=qrd.queries #Questions166    responses=qrd.responses #Model Answers167    168    print("Generating Q&A Dict for mind miner.")169    dicts_list = []170    for question, answer in zip(queries.values(), responses.values() ):171        match mode: #'no', 'e2zh', 'zh2e'172            case 'e2zh':173                question=translate(question, 'e2zh')174                answer=translate(answer, 'e2zh') 175            case 'zh2e':176                question=translate(question, 'zh2e')177                answer=translate(answer, 'zh2e')178            case 'no':179                pass180              181        dicts_list.append({ # start with '{' is a Dict by default, https://medium.com/@ahmedbilalumer3/fine-tuning-llama-factory-phi-1-3-1-5b-mimicking-researchers-writing-style-1802260ae2b3182            "instruction": question,183            "input": "", #Llamafactory require this.184            "output": answer185            })186 187    return dicts_list #in Llamafactory required format188 189def load_Qans_dict(filename:str, mode):190    tmp=os.listdir() #get all file names in the current directory.191    file_exist=filename in tmp #check file exist or else192    193    choice='no'194    if not FOR_HUG_FACE: choice=input("Create new queston database, 'yes'? or press Enter to skip: ")195    196    if not file_exist or choice=='yes':197        print(f"Generating new question database '{filename}', wait for minutes.......")198        obj_dict=gen_question_ans(LMA_IDX_QUESTION_GEN_PROMPT, mode)199        str_json=dict2str_json(obj_dict)200        str_json2file(str_json, filename) #save to file201        print(f"Save generated {filename} into current folder.")202    else:203        print(f"Loading an existing {filename} in current directory.")204        with open(filename, "r") as f:205            str_json = json.load(f) # load Json formatted string from file206            obj_dict = json.loads(str_json) # load from Json formatted string to Python Object207 208    return obj_dict209 210# def groq_chat(question:str, history):211#     response=lc.groq_chat_complete(question)212#     return response213 214def chatbot_simulator(question:str, history):215    global entry_1st_global, length_global216    if DEBUG_L1: global index217    """218    ....219    ----------220    question : string 221        DESCRIPTION. User prompt question222    history : string223        DESCRIPTION. A list of list representing the conversations up until that point. 224        Each inner list consists of two str representing a pair: [user input, bot response].225    Returns226    -------227    response : string228        DESCRIPTION. The texts show to the User229    """230    idx=random.randint(0, length_global-1) #included both end points. https://www.w3schools.com/python/ref_random_randint.asp231    if DEBUG_L1: index=idx; print(f"index={idx}") #print to Console not GRADIO GUI232    if entry_1st_global==True: #first entry to this function233        response="Hello, have a nice day !\n" + QA_DICT[idx]['instruction']234        entry_1st_global=not(entry_1st_global)235    else: # other than first entry as above236        response=QA_DICT[idx]['instruction']237    238    # if DEBUG_L1: pass #print(f"History is:{str(history)}")239    240    response =remove_sentences(response, remove_list)241    output = f"{response} \n Ref Ans is: {QA_DICT[idx]['output']}" if ADD_REF else  f"{response}"242    return output243 244if __name__ == "__main__":245    QA_DICT=load_Qans_dict("Qans.json", 'no') #'no', 'e2zh', 'zh2e'246    length_global=len(QA_DICT)247 248    if GRADIO_ENABLE:249        gr.ChatInterface( #https://www.gradio.app/guides/creating-a-chatbot-fast250        chatbot_simulator, ####1) Replace this function to return chatbot searched texts251        chatbot=gr.Chatbot(height=300),252    253        ####2) Put the Apps' on-screen texts here(green text as show below).254        title="Master Mind",255        description="           Learning, Exam and Career !",256        # examples=['What is a contract?', 'What is CIC?'], 257        textbox=gr.Textbox(placeholder=f"Press SUBMIT to get a question from ({NO_OF_QUESTIONS} Qs).", container=False, scale=7),258    259        ####3) Other settings260        theme="soft",261        undo_btn="Delete Previous", #change the text on the button262        clear_btn="Clear", #change the text on the button263        cache_examples=False, #True,264        # multimodal=True,265        retry_btn=None,266        fill_height=True,267        ).launch(share=SHARE_H) #False) #True)268    # Complicated Bot: https://www.gradio.app/guides/creating-a-custom-chatbot-with-blocks269    270 271""" Reference:272JSON stands for JavaScript Object Notation. It means that a script (executable) file which is made of text273in a programming language, is used to store and transfer the data. Great uTube: https://www.youtube.com/watch?v=iiADhChRriM274Python supports JSON through a built-in package called JSON.275 276Text in JSON is done through quoted-string which contains a value in key-value mapping within { }. 277It is similar to the dictionary in Python.278"""