GLITCH-08 commited on
Commit
62369fb
·
verified ·
1 Parent(s): a5757c9

Upload 14 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ chroma/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text
37
+ data/uber-10-k-2023.pdf filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from database import main as populate_db
3
+ from query import query_rag
4
+ from langchain.schema.document import Document
5
+
6
+
7
+ # Set the page configuration for Streamlit
8
+ st.set_page_config(page_title='Content Engine')
9
+
10
+ # Function to load and populate the database
11
+ def load_and_populate_database():
12
+ st.header("Database Population")
13
+ st.write("Use this section to populate the database.")
14
+ if st.button("Populate Database"):
15
+ populate_db()
16
+
17
+ st.markdown("<hr style='border: 1px dashed #e0e0e0;'>", unsafe_allow_html=True)
18
+
19
+
20
+ # Function to display the scrolling chat box
21
+ def display_chat_box():
22
+ st.header("Chat Box")
23
+ st.write("Enter your questions below and get responses generated from the context.")
24
+
25
+ # Setup for holding old messages
26
+ if 'messages' not in st.session_state:
27
+ st.session_state.messages = []
28
+
29
+ # Display all the history in a scrollable chat box
30
+ with st.container():
31
+ for message in st.session_state.messages:
32
+ st.chat_message(message['role']).markdown(message['content'])
33
+
34
+ # Input field for user query
35
+ user_query = st.chat_input("Your Query:", key="query_input")
36
+
37
+ if user_query:
38
+ # Display user prompt
39
+ st.chat_message('user').markdown(user_query)
40
+
41
+ # Store the user prompt in state
42
+ st.session_state.messages.append({'role': 'user', 'content': user_query})
43
+
44
+ # Buffering message while waiting for response
45
+ with st.spinner('Waiting for response...'):
46
+ # Query processing
47
+ response_text = query_rag(user_query)
48
+
49
+ # Show the LLM response
50
+ st.chat_message('assistant').markdown(response_text)
51
+
52
+ # Store the LLM response
53
+ st.session_state.messages.append({'role': 'assistant', 'content': response_text})
54
+
55
+ # Main function to run the Streamlit app
56
+ def main():
57
+ # Title and description
58
+ st.markdown("<h1 style='font-size: 60px; text-align: center;'>🧠Content Engine🤖</h1>", unsafe_allow_html=True)
59
+ # st.markdown("<hr style='border: 1px dashed #e0e0e0; '>", unsafe_allow_html=True)
60
+ # st.write("This system analyzes and compares multiple PDF documents, specifically identifying and highlighting their differences. The system will utilize Retrieval Augmented Generation (RAG) techniques to effectively retrieve, assess, and generate insights from the documents.")
61
+ st.markdown("<hr style='border: 1px dashed #e0e0e0;'>", unsafe_allow_html=True)
62
+
63
+ # To load and populate the database
64
+ # load_and_populate_database()
65
+
66
+ # Display chat box
67
+ display_chat_box()
68
+
69
+
70
+
71
+ if __name__ == "__main__":
72
+ main()
chroma/360ffad6-f56e-46e1-8b3c-e88a73c8a70d/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2cfeb32effd3397c9d0aae0a629aa165a2dffe3321940cf0abc5e07b9c5b3466
3
+ size 6424000
chroma/360ffad6-f56e-46e1-8b3c-e88a73c8a70d/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b56eb1d0439027f400d145f9eff65f500b8c5d1afb597348ce4bc35443d3bd60
3
+ size 100
chroma/360ffad6-f56e-46e1-8b3c-e88a73c8a70d/index_metadata.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:827b4e3f7d764e876cfb1337993477583d5f230f7748ef0352e04963f97f8265
3
+ size 102041
chroma/360ffad6-f56e-46e1-8b3c-e88a73c8a70d/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5d44dbe88b0e3a2b082ab89d9f9f05498dd3633b19061c8a82c774f2d80a8041
3
+ size 8000
chroma/360ffad6-f56e-46e1-8b3c-e88a73c8a70d/link_lists.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:561ae3ffa1abbf2695cb93002ce011c1bf0eca135b6521c77ff6c4782b2ea122
3
+ size 17044
chroma/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:334e569b55a158a70f6b2c1c410c2326719a1f8808215ccc4f21a38fa9cd7cea
3
+ size 19922944
data/goog-10-k-2023 (1).pdf ADDED
The diff for this file is too large to render. See raw diff
 
data/tsla-20231231-gen.pdf ADDED
Binary file (985 kB). View file
 
data/uber-10-k-2023.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9fc1d0c5f2e2095798c99de2d892a9e785b9ed8329090c0c376e39a22e71ad06
3
+ size 1835051
database.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import os
3
+ import shutil
4
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
5
+ from langchain.schema.document import Document
6
+ from embedding_function import get_embedding
7
+ from langchain_community.document_loaders import PyPDFDirectoryLoader
8
+ from langchain_community.vectorstores import Chroma
9
+
10
+ # Define paths for the Chroma database and the data directory
11
+ CHROMA_PATH = "chroma"
12
+ DATA_PATH = "data"
13
+
14
+ def main():
15
+ # Set up command-line argument parsing
16
+ parser = argparse.ArgumentParser()
17
+ parser.add_argument("--reset", action="store_true", help="Reset the database.")
18
+ args = parser.parse_args()
19
+
20
+ # Clear the database if the reset flag is set
21
+ if args.reset:
22
+ print("✨ Clearing Database")
23
+ clear_database()
24
+
25
+ # Load documents, split them into chunks, and add them to Chroma
26
+ documents = load_documents()
27
+ chunks = split_documents(documents)
28
+ add_to_chroma(chunks)
29
+
30
+ def load_documents():
31
+ # Load PDF documents from the specified directory
32
+ document_loader = PyPDFDirectoryLoader(DATA_PATH)
33
+ return document_loader.load()
34
+
35
+ def split_documents(documents: list[Document]):
36
+ # Split documents into smaller chunks using a character-based splitter
37
+ text_splitter = RecursiveCharacterTextSplitter(
38
+ chunk_size=800,
39
+ chunk_overlap=80,
40
+ length_function=len,
41
+ is_separator_regex=False,
42
+ )
43
+ return text_splitter.split_documents(documents)
44
+
45
+ def add_to_chroma(chunks: list[Document]):
46
+ # Initialize the Chroma vector store with the embedding function
47
+ db = Chroma(
48
+ persist_directory=CHROMA_PATH, embedding_function=get_embedding()
49
+ )
50
+
51
+ # Calculate unique IDs for each chunk
52
+ chunks_with_ids = calculate_chunk_ids(chunks)
53
+
54
+ # Get the existing documents from the database
55
+ existing_items = db.get(include=[]) # IDs are always included by default
56
+ existing_ids = set(existing_items["ids"])
57
+ print(f"Number of existing documents in DB: {len(existing_ids)}")
58
+
59
+ # Add only new chunks that don't exist in the database
60
+ new_chunks = []
61
+ for chunk in chunks_with_ids:
62
+ if chunk.metadata["id"] not in existing_ids:
63
+ new_chunks.append(chunk)
64
+
65
+ # Add new documents to the database and persist the changes
66
+ if len(new_chunks):
67
+ print(f"----->>> Adding new documents: {len(new_chunks)}")
68
+ new_chunk_ids = [chunk.metadata["id"] for chunk in new_chunks]
69
+ db.add_documents(new_chunks, ids=new_chunk_ids)
70
+ db.persist()
71
+ else:
72
+ print("----->>> No new documents to add")
73
+
74
+ def calculate_chunk_ids(chunks):
75
+ # Create unique IDs for each chunk based on the source, page, and chunk index
76
+ last_page_id = None
77
+ current_chunk_index = 0
78
+
79
+ for chunk in chunks:
80
+ source = chunk.metadata.get("source")
81
+ page = chunk.metadata.get("page")
82
+ current_page_id = f"{source}:{page}"
83
+
84
+ # Increment the chunk index if it's the same page
85
+ if current_page_id == last_page_id:
86
+ current_chunk_index += 1
87
+ else:
88
+ current_chunk_index = 0
89
+
90
+ # Assign a unique ID to each chunk
91
+ chunk_id = f"{current_page_id}:{current_chunk_index}"
92
+ last_page_id = current_page_id
93
+ chunk.metadata["id"] = chunk_id
94
+
95
+ return chunks
96
+
97
+ def clear_database():
98
+ # Remove the Chroma directory to clear the database
99
+ if os.path.exists(CHROMA_PATH):
100
+ shutil.rmtree(CHROMA_PATH)
101
+
102
+ if __name__ == "__main__":
103
+ main()
embedding_function.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from langchain_community.embeddings.ollama import OllamaEmbeddings
2
+
3
+ def get_embedding():
4
+ # Initialize embeddings with the specified model
5
+ embeddings = OllamaEmbeddings(model="nomic-embed-text")
6
+ return embeddings # Return the embedding function
query.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from langchain.vectorstores.chroma import Chroma
3
+ from langchain.prompts import ChatPromptTemplate
4
+ from langchain_community.llms.ollama import Ollama
5
+
6
+ from embedding_function import get_embedding
7
+
8
+ # Path to the Chroma database
9
+ CHROMA_PATH = "chroma"
10
+
11
+ # Template for the prompt to be used by the LLM
12
+ PROMPT_TEMPLATE = """
13
+ Answer the question based only on the following context:
14
+
15
+ {context}
16
+
17
+ ---
18
+
19
+ Answer the question based on the above context: {question}
20
+ """
21
+
22
+ def main():
23
+ # Create a command-line interface to accept the query text
24
+ parser = argparse.ArgumentParser()
25
+ parser.add_argument("query_text", type=str, help="The query text.")
26
+ args = parser.parse_args()
27
+ query_text = args.query_text
28
+ query_rag(query_text)
29
+
30
+ def query_rag(query_text: str):
31
+ # Initialize the embedding function
32
+ embedding_function = get_embedding()
33
+
34
+ # Load the Chroma vector store with the embedding function
35
+ db = Chroma(persist_directory=CHROMA_PATH, embedding_function=embedding_function)
36
+
37
+ # Perform a similarity search on the database with the query text
38
+ results = db.similarity_search_with_score(query_text, k=5)
39
+
40
+ # Combine the search results into a single context string
41
+ context_text = "\n\n---\n\n".join([doc.page_content for doc, _score in results])
42
+
43
+ # Format the prompt using the context and the query
44
+ prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
45
+ prompt = prompt_template.format(context=context_text, question=query_text)
46
+ print(prompt)
47
+
48
+ # Initialize the model and generate a response
49
+ model = Ollama(model="mistral")
50
+ response_text = model.invoke(prompt)
51
+
52
+ # Extract source IDs from the search results
53
+ sources = [doc.metadata.get("id", None) for doc, _score in results]
54
+
55
+ # Format and print the response with the sources
56
+ formatted_response = f"Response: {response_text}\nSources: {sources}"
57
+ print(formatted_response)
58
+ return response_text
59
+
60
+ if __name__ == "__main__":
61
+ main()
requirements.txt ADDED
Binary file (150 Bytes). View file