taaha3244 commited on
Commit
c90e83e
1 Parent(s): e71028f

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +93 -107
main.py CHANGED
@@ -7,100 +7,115 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
7
  from langchain import hub
8
  from langchain_community.vectorstores import Qdrant
9
  from qdrant_client import QdrantClient
10
- from langchain_openai import OpenAIEmbeddings
11
- from langchain_openai import ChatOpenAI
12
  from langchain_core.output_parsers import StrOutputParser
13
  from langchain_core.runnables import RunnablePassthrough
14
  from langchain.prompts import PromptTemplate
 
15
 
16
  load_dotenv()
17
 
18
- def summarize_pdf_document(file_path, openai_api_key):
19
- # Load PDF document
20
- loader = PyPDFLoader(file_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  documents = loader.load()
 
22
 
23
- # Split text from documents
24
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=500)
25
- docs = text_splitter.split_documents(documents)
26
-
27
- # Set up OpenAI client
28
- llm = OpenAI(temperature=0, openai_api_key=openai_api_key)
29
-
30
- # Load the summarization chain process
31
- summary_chain = load_summarize_chain(llm=llm, chain_type='map_reduce')
32
-
33
- # Invoke the summarization process
34
- output = summary_chain.run(docs)
35
-
36
- return output
37
-
38
- def embed_document_data(documents):
39
- """Load, process, and embed a PDF file into a vector store.
40
-
41
- Args:
42
- file_path (str): Path to the PDF file to be processed and embedded.
43
- """
44
-
45
-
46
- # Split text from documents into smaller chunks
47
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=400)
48
- texts = text_splitter.split_documents(documents)
49
 
50
- # Set up embeddings model with OpenAI
51
- openai_api_key = os.getenv("OPENAI_API_KEY")
52
- embeddings_model = OpenAIEmbeddings(model='text-embedding-3-small', openai_api_key=openai_api_key)
53
-
54
- # Configure Qdrant client
55
- qdrant_url = os.getenv("QDRANT_URL")
56
- qdrant_api_key = os.getenv("QDRANT_API_KEY")
57
- client = QdrantClient(location=qdrant_url, api_key=qdrant_api_key)
58
-
59
- # Initialize Qdrant storage with the client and embedding model
60
- qdrant = Qdrant(client=client, collection_name="Lex-v1", embeddings=embeddings_model)
61
-
62
- # Add documents to the Qdrant collection
63
- qdrant.add_documents(texts)
64
-
65
-
66
- def retrieve_documents(query: str):
67
- """
68
- Takes a user query as input and returns a response using a Retrieval-Augmented Generation (RAG) flow
69
- incorporating langchain, Qdrant, and OpenAI.
70
 
71
- Args:
72
- query (str): The user's question to be answered.
73
 
74
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  try:
76
- # Setup
77
- qdrant_url = os.getenv('QDRANT_URL')
78
- qdrant_api_key = os.getenv("QDRANT_API_KEY")
79
- openai_api_key=os.getenv('OPENAI_API_KEY')
80
-
81
- embeddings_model = OpenAIEmbeddings(model='text-embedding-3-small', openai_api_key=openai_api_key)
82
- qdrant_client = QdrantClient(url=qdrant_url, api_key=qdrant_api_key)
83
- qdrant = Qdrant(client=qdrant_client, collection_name="Lex-v1",
84
- embeddings=embeddings_model)
85
- retriever = qdrant.as_retriever(search_kwargs={"k": 5})
86
-
87
 
88
- prompt=PromptTemplate(
 
 
 
 
 
 
89
 
90
  template="""
91
  # Your role
92
  You are a brilliant expert at understanding the intent of the questioner and the crux of the question, and providing the most optimal answer from the docs to the questioner's needs from the documents you are given.
93
-
94
-
95
  # Instruction
96
  Your task is to answer the question using the following pieces of retrieved context delimited by XML tags.
97
-
98
  <retrieved context>
99
  Retrieved Context:
100
  {context}
101
  </retrieved context>
102
-
103
-
104
  # Constraint
105
  1. Think deeply and multiple times about the user's question\nUser's question:\n{question}\nYou must understand the intent of their question and provide the most appropriate answer.
106
  - Ask yourself why to understand the context of the question and why the questioner asked it, reflect on it, and provide an appropriate response based on what you understand.
@@ -109,48 +124,19 @@ def retrieve_documents(query: str):
109
  4. When you don't have retrieved context for the question or If you have a retrieved documents, but their content is irrelevant to the question, you should answer 'I can't find the answer to that question in the material I have'.
110
  5. Use five sentences maximum. Keep the answer concise but logical/natural/in-depth.
111
  6. At the end of the response provide metadata provided in the relevant docs , For example:"Metadata: page: 19, source: /content/OCR_RSCA/Analyse docs JVB + mails et convention FOOT INNOVATION.pdf'.Return just the page and source.Provide a list of all the metadata found in the Relevent content formatted as bullets
112
-
113
-
114
-
115
  # Question:
116
  {question}""",
117
  input_variables=["context","question"]
118
  )
119
- llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0,openai_api_key=openai_api_key)
120
-
121
-
122
- def format_docs(docs):
123
- formatted_docs = []
124
- for doc in docs:
125
- # Format the metadata into a string
126
- metadata_str = ', '.join(f"{key}: {value}" for key, value in doc.metadata.items())
127
-
128
- # Combine page content with its metadata
129
- doc_str = f"{doc.page_content}\nMetadata: {metadata_str}"
130
-
131
- # Append to the list of formatted documents
132
- formatted_docs.append(doc_str)
133
-
134
- # Join all formatted documents with double newlines
135
- return "\n\n".join(formatted_docs)
136
-
137
-
138
- rag_chain = (
139
- {"context": retriever | format_docs, "question": RunnablePassthrough()}
140
  | prompt
141
  | llm
142
  | StrOutputParser()
143
- )
 
144
 
145
- result = rag_chain.invoke(query)
146
- return result
147
- except Exception as e:
148
- print(f"Error processing the query: {e}")
149
- return None
150
-
151
  def is_document_embedded(filename):
152
- """Check if a document has already been embedded based on its filename."""
153
- # This function needs to query your backend or check a local database/file.
154
- # For simplicity, here's a placeholder that always returns False.
155
- # Replace this with actual logic.
156
- return False
 
7
  from langchain import hub
8
  from langchain_community.vectorstores import Qdrant
9
  from qdrant_client import QdrantClient
10
+ from langchain_openai import OpenAIEmbeddings, ChatOpenAI
 
11
  from langchain_core.output_parsers import StrOutputParser
12
  from langchain_core.runnables import RunnablePassthrough
13
  from langchain.prompts import PromptTemplate
14
+ from langchain_community.document_loaders import UnstructuredAPIFileLoader
15
 
16
  load_dotenv()
17
 
18
+ def setup_openai_embeddings(api_key):
19
+ """Set up OpenAI embeddings."""
20
+ return OpenAIEmbeddings(model='text-embedding-3-small', openai_api_key=api_key)
21
+
22
+ def setup_qdrant_client(url, api_key):
23
+ """Set up Qdrant client."""
24
+ return QdrantClient(location=url, api_key=api_key)
25
+
26
+ def format_document_metadata(docs):
27
+ """Format metadata for each document."""
28
+ formatted_docs = []
29
+ for doc in docs:
30
+ metadata_str = ', '.join(f"{key}: {value}" for key, value in doc.metadata.items())
31
+ doc_str = f"{doc.page_content}\nMetadata: {metadata_str}"
32
+ formatted_docs.append(doc_str)
33
+ return "\n\n".join(formatted_docs)
34
+
35
+ def openai_llm(model_name: str, api_key: str):
36
+ """Get a configured OpenAI language model."""
37
+ return ChatOpenAI(model_name=model_name, temperature=0, openai_api_key=api_key)
38
+
39
+ def load_documents_OCR(file_path,unstructured_api):
40
+ """This Loads Documents that require OCR via unstructured"""
41
+ loader = UnstructuredAPIFileLoader(
42
+ file_path=file_path,
43
+ api_key=unstructured_api,
44
+ )
45
  documents = loader.load()
46
+ return documents
47
 
48
+ def load_documents(file_path):
49
+ """Loads Docs using Langchain"""
50
+ loader=PyPDFLoader(file_path)
51
+ documents=loader.load()
52
+ return documents
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ def split_documents(documents):
55
+ """Splits documents using Langchain splitter"""
56
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=500)
57
+ split_docs = text_splitter.split_documents(documents)
58
+ return split_docs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
 
60
 
61
+ def load_and_split_documents(file_path):
62
+ """Load and split documents from the specified file path."""
63
+ loader = PyPDFLoader(file_path)
64
+ documents = loader.load()
65
+ if not documents:
66
+ print("No documents loaded from file:", file_path)
67
+ return []
68
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=500)
69
+ split_docs = text_splitter.split_documents(documents)
70
+ if not split_docs:
71
+ print("Document splitting resulted in no output for file:", file_path)
72
+ return split_docs
73
+
74
+ def update_metadata(documents, original_name):
75
+ """Update metadata for each document."""
76
+ updated_documents = []
77
+ for doc in documents:
78
+ doc.metadata['source'] = original_name
79
+ updated_documents.append(doc)
80
+ return updated_documents
81
+
82
+ def setup_summary_chain(api_key, model_name):
83
+ """Set up a summary chain with a specified LLM."""
84
+ llm = openai_llm(model_name=model_name, api_key=api_key)
85
+ return load_summarize_chain(llm=llm, chain_type='map_reduce')
86
+
87
+ def summarize_documents(model_name, documents, api_key):
88
+ """Generate summaries for provided documents."""
89
+ summary_chain = setup_summary_chain(api_key, model_name)
90
+ return summary_chain.run(documents)
91
+
92
+ def embed_documents_into_qdrant(documents, api_key, qdrant_url, qdrant_api_key, collection_name="Lex-v1"):
93
+ """Embed documents into Qdrant."""
94
+ embeddings_model = setup_openai_embeddings(api_key)
95
+ client = setup_qdrant_client(qdrant_url, qdrant_api_key)
96
+ qdrant = Qdrant(client=client, collection_name=collection_name, embeddings=embeddings_model)
97
  try:
98
+ qdrant.add_documents(documents)
99
+ except Exception as e:
100
+ print("Failed to embed documents:", e)
 
 
 
 
 
 
 
 
101
 
102
+ def retrieve_documents(query, api_key, qdrant_url, qdrant_api_key, model_name):
103
+ """Retrieve documents based on the specified query."""
104
+ embeddings_model = setup_openai_embeddings(api_key)
105
+ qdrant_client = setup_qdrant_client(qdrant_url, qdrant_api_key)
106
+ qdrant = Qdrant(client=qdrant_client, collection_name="Lex-v1", embeddings=embeddings_model)
107
+ retriever = qdrant.as_retriever(search_kwargs={"k": 5})
108
+ prompt=PromptTemplate(
109
 
110
  template="""
111
  # Your role
112
  You are a brilliant expert at understanding the intent of the questioner and the crux of the question, and providing the most optimal answer from the docs to the questioner's needs from the documents you are given.
 
 
113
  # Instruction
114
  Your task is to answer the question using the following pieces of retrieved context delimited by XML tags.
 
115
  <retrieved context>
116
  Retrieved Context:
117
  {context}
118
  </retrieved context>
 
 
119
  # Constraint
120
  1. Think deeply and multiple times about the user's question\nUser's question:\n{question}\nYou must understand the intent of their question and provide the most appropriate answer.
121
  - Ask yourself why to understand the context of the question and why the questioner asked it, reflect on it, and provide an appropriate response based on what you understand.
 
124
  4. When you don't have retrieved context for the question or If you have a retrieved documents, but their content is irrelevant to the question, you should answer 'I can't find the answer to that question in the material I have'.
125
  5. Use five sentences maximum. Keep the answer concise but logical/natural/in-depth.
126
  6. At the end of the response provide metadata provided in the relevant docs , For example:"Metadata: page: 19, source: /content/OCR_RSCA/Analyse docs JVB + mails et convention FOOT INNOVATION.pdf'.Return just the page and source.Provide a list of all the metadata found in the Relevent content formatted as bullets
 
 
 
127
  # Question:
128
  {question}""",
129
  input_variables=["context","question"]
130
  )
131
+ llm = openai_llm(model_name=model_name, api_key=api_key)
132
+ rag_chain = (
133
+ {"context": retriever | format_document_metadata, "question": RunnablePassthrough()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  | prompt
135
  | llm
136
  | StrOutputParser()
137
+ )
138
+ return rag_chain.invoke(query)
139
 
 
 
 
 
 
 
140
  def is_document_embedded(filename):
141
+ """Check if a document is already embedded. Actual implementation needed."""
142
+ return False