CoolFace
Apppublic

MifosBot/Mobile-Wallet

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py190 linesDownload Raw Back to root
1from dotenv import load_dotenv2import os3load_dotenv()4 5OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")6 7from langchain_text_splitters import RecursiveCharacterTextSplitter8from langchain_text_splitters import Language9from langchain_openai import OpenAIEmbeddings10from langchain_community.vectorstores import Chroma11from langchain_openai import ChatOpenAI12from langchain.chains import RetrievalQA13import chromadb14import gradio as gr15import tqdm16 17def read_file(file_path):18    with open(file_path, "r", encoding="utf-8") as file:19        return file.read()20 21def infer_module_name(file_path):22    path_parts = file_path.split(os.sep)23    if "src" in path_parts:24        src_index = path_parts.index("src")25        return "/".join(path_parts[src_index+1:-1])26    return "root"27 28def process_files(root_dir, file_extension, language=None):29    if language:30        splitter = RecursiveCharacterTextSplitter.from_language(31            language=language, chunk_size=3000, chunk_overlap=10032        )33    else:34        splitter = RecursiveCharacterTextSplitter(35            chunk_size=3000, chunk_overlap=10036        )37    38    all_docs = []39 40    for root, _, files in os.walk(root_dir):41        for file in files:42            if file.endswith(file_extension):43                file_path = os.path.join(root, file)44                file_name = os.path.basename(file_path)45                folder_path = root46                module_name = infer_module_name(file_path)47                content = read_file(file_path)48                content = f"file name: {file_name}\n path: {folder_path}\n {content}"49 50                docs = splitter.create_documents(51                    [content],52                    metadatas=[{53                        'source': file_name, 54                        'type': file_extension[1:],55                        'module': module_name,  56                        'folder_path': folder_path  57                    }]58                )59                all_docs.extend(docs)60 61    return all_docs62 63def process_all_files(root_directory):64    ts_docs = process_files(root_directory, '.ts', Language.TS)65    html_docs = process_files(root_directory, '.html', Language.HTML)66    txt_docs = process_files(root_directory, '.txt')67    md_docs = process_files(root_directory, '.md')68    js_docs = process_files(root_directory, '.js', Language.JS)69    kt_docs = process_files(root_directory, '.kt', Language.KOTLIN)70 71    all_docs = ts_docs + html_docs + txt_docs + md_docs + js_docs + kt_docs72    return all_docs73 74def initialize_or_load_database():75    model_name = 'text-embedding-3-large'76    embeddings = OpenAIEmbeddings(77        model=model_name,78        openai_api_key=os.environ.get('OPENAI_API_KEY')79    )80 81    chroma_client = chromadb.PersistentClient(path="./mobile_wallet_vector_storage")82    collection_name = "all_files"83 84    if os.path.exists("collection_storage.txt"):85        with open("collection_storage.txt", "r") as f:86            collection_storage_name, collection_storage_id = f.read().splitlines()87        print("Loading existing vector database...")88        docsearch = Chroma(89            client=chroma_client,90            collection_name=collection_name,91            embedding_function=embeddings92        )93    else:94        print("Creating new vector database...")95        root_directory = "mobile-wallet"    96        all_documents = process_all_files(root_directory)97        print(f"Total number of chunks across all files: {len(all_documents)}")98        print("Total number of files: ", len(set([doc.metadata['source'] for doc in all_documents])))99 100        docsearch = Chroma.from_documents(101            documents=all_documents,102            embedding=embeddings,103            collection_name=collection_name,104            client=chroma_client105        )106 107        collection_storage_name = chroma_client.list_collections()[0].name108        collection_storage_id = chroma_client.list_collections()[0].id109        # print("name: ", collection_storage_name)110        # print("id: ", collection_storage_id)111        112        with open("collection_storage.txt", "w") as f:113            f.write(f"{collection_storage_name}\n{collection_storage_id}")114 115    return docsearch116 117docsearch = initialize_or_load_database()118 119llm = ChatOpenAI(120    openai_api_key=os.environ.get('OPENAI_API_KEY'),121    model_name='gpt-4o-mini',122    temperature=0.3123)124 125qa = RetrievalQA.from_chain_type(126    llm=llm,127    chain_type="stuff",  128    retriever=docsearch.as_retriever(),129    return_source_documents=True130)131 132def get_top_20_embeddings(query):133    docs_and_scores = docsearch.similarity_search_with_score(query, k=20) 134    return docs_and_scores135 136 137def get_parent_document_embeddings(query, num_docs=5):138 139    docs_and_scores = docsearch.similarity_search_with_score(query, k=num_docs)140    141    parent_docs = {}142    143    for doc, score in docs_and_scores:144        parent_doc_key = doc.metadata['source'] 145        if parent_doc_key not in parent_docs:146            parent_docs[parent_doc_key] = (doc, score)147    148    return list(parent_docs.values())149 150def get_top_5_parent_documents(query):151    return get_parent_document_embeddings(query, num_docs=5)152 153def answer_question_with_parent_docs(question):154    top_5_results = get_top_5_parent_documents(question)155    156    context = "\n".join([doc.page_content for doc, _ in top_5_results])157    print("Context: ", context)158    159    query_data = (160        "You are an expert in project structure and various file types including TypeScript, HTML, Markdown, JS and Kotlin."161        "When answering questions, focus on the file organization, key components of the codebase, and the structure of the project."162        "For general queries,like hi,hello etc provide a brief answer, but for questions about project structure, include module names, file paths, and folder organization."163        "If you're unsure of the answer, suggest referring to the Mifos Slack Channel."164        "\nContext:\n" + context + "\n" + question165    )166 167    response = qa.invoke(query_data)168    169    # top_20_results = get_top_5_parent_documents(question)170    # print("Top 5 matching parent documents:")171    # for i, (doc, score) in enumerate(top_20_results, 1):172    #     print(f"{i}. Document: {doc.page_content[:1000]}...")173    #     print(f"   Metadata: {doc.metadata}")174    #     print(f"   Similarity Score: {score}")175    #     print()176    177    return response['result']178 179 180interface = gr.Interface(181    fn=answer_question_with_parent_docs,  182    inputs=gr.Textbox(label="Ask a question about the files"),183    outputs=gr.Textbox(label="Answer"),184    title="Mifos Mobile-Wallet Chatbot",185    description="Ask questions about Kotlin in Mifos Mobile-Wallet",186)187 188if __name__ == "__main__":189    interface.launch()190