frkhan commited on
Commit
2b78b1a
Β·
1 Parent(s): ec72ec6

Developed the complete RAG system.

Browse files

Necessary docker deployment files are added.

Files changed (6) hide show
  1. Dockerfile +21 -0
  2. app.py +0 -0
  3. app/app.py +133 -0
  4. app/config.py +20 -0
  5. docker-compose.yml +17 -0
  6. requirements.txt +3 -1
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use official Python base image
2
+ FROM python:3.10-slim-bookworm
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Upgrade system packages to patch vulnerabilities
8
+ RUN apt-get update && apt-get upgrade -y && apt-get clean
9
+
10
+ # Copy requirements and install dependencies
11
+ COPY requirements.txt .
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ # Copy app code
15
+ COPY . .
16
+
17
+ # Expose Gradio default port
18
+ EXPOSE 7860
19
+
20
+ # Run the app
21
+ CMD ["python", "app.py"]
app.py DELETED
File without changes
app/app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
3
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
4
+ import fitz # PyMuPDF
5
+ from langchain.docstore.document import Document
6
+ from langchain.vectorstores import Chroma
7
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
8
+ from langchain.chat_models import init_chat_model
9
+ import os
10
+ from config import GOOGLE_API_KEY, NVIDIA_API_KEY, CHROMA_DIR
11
+
12
+
13
+
14
+ def setup_nvidia_embedding_model():
15
+
16
+ os.environ["NVIDIA_API_KEY"] = NVIDIA_API_KEY
17
+ nvidia_embedding_model = "nvidia/nv-embed-v1"
18
+ embedding_model = NVIDIAEmbeddings(model=nvidia_embedding_model)
19
+
20
+ return embedding_model
21
+
22
+ def setup_google_gemini_embedding_model():
23
+ os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY
24
+ gemini_embedding_model = "models/gemini-embedding-001"
25
+ embedding_model = GoogleGenerativeAIEmbeddings(model=gemini_embedding_model)
26
+
27
+ return embedding_model
28
+
29
+ vectorstore = None
30
+
31
+ def answer_with_llm(query, retrieved_docs, model_name, model_provider):
32
+ if not retrieved_docs:
33
+ return "No relevant information found to answer your question."
34
+
35
+ context = "\n\n".join(doc.page_content for doc in retrieved_docs)
36
+
37
+ prompt = f"""
38
+ You are an expert assistant. Use the following context to answer the user's question.
39
+ If you do not find or know the answer, do not hallucinate, do not try to generate fake answers.
40
+ If no Context is given, simply state "No relevant information found to answer your question."
41
+
42
+ Context:
43
+ {context}
44
+
45
+ Question:
46
+ {query}
47
+
48
+ Answer:
49
+
50
+ """
51
+
52
+ llm = init_chat_model(model_name, model_provider=model_provider)
53
+ response = llm.invoke(prompt)
54
+ return response.content
55
+
56
+
57
+ def read_pdf(file):
58
+ doc = fitz.open(stream=file, filetype="pdf")
59
+ text = "\n".join([page.get_text() for page in doc])
60
+ return text
61
+
62
+
63
+ def process_pdf(file):
64
+ global vectorstore
65
+
66
+ if not file:
67
+ return "Error: No file uploaded."
68
+
69
+ text = read_pdf(file)
70
+ splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
71
+ chunks = splitter.split_text(text)
72
+ docs = [Document(page_content=chunk) for chunk in chunks]
73
+
74
+ #Create Chroma DB
75
+ embedding_model = setup_nvidia_embedding_model()
76
+ # embedding_model = setup_google_gemini_embedding_model()
77
+
78
+ vectorstore = Chroma.from_documents(documents=docs, embedding=embedding_model, persist_directory=CHROMA_DIR )
79
+ # vectorstore.persist()
80
+
81
+ return f"PDF processed and stored with {len(docs)} chunks."
82
+
83
+
84
+ def search_query(query):
85
+ if not vectorstore:
86
+ error_message = "Error: No vectorstore found. Please upload and process a PDF first."
87
+ return error_message, error_message
88
+
89
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
90
+ results = retriever.get_relevant_documents(query)
91
+ # results = retriever.similarity_search(query, k=2)
92
+
93
+ # return "\n\n-------------\n\n".join(doc.page_content for doc in results)
94
+
95
+ semantic_search_response = "\n\n-------------\n\n".join(doc.page_content for doc in results)
96
+
97
+ # model_name = "gemini-2.5-pro"
98
+ # model_provider = "google_genai"
99
+
100
+ model_name = "bytedance/seed-oss-36b-instruct"
101
+ model_provider = "nvidia"
102
+
103
+ llm_answer = answer_with_llm(query, results, model_name=model_name, model_provider=model_provider)
104
+ return semantic_search_response, llm_answer
105
+
106
+ #Gradio UI
107
+ with gr.Blocks() as demo:
108
+ gr.Markdown("# 🧠 Semantic Search App (Langchain + ChromaDb + NVidia LLM API)")
109
+
110
+ with gr.Row():
111
+ pdf_input = gr.File(label="Upload PDF (max 5mb)", type="binary", file_types=[".pdf"])
112
+ process_btn = gr.Button("Process PDF")
113
+
114
+ status = gr.Textbox(label="Status")
115
+
116
+ with gr.Row():
117
+ query_input = gr.Textbox(label="Enter your query")
118
+ search_btn = gr.Button("Semantic Search")
119
+
120
+ with gr.Row():
121
+ semantic_search_response = gr.Textbox(label="Semantic Search Response", lines=10, show_copy_button=True)
122
+ llm_response = gr.Textbox(label="LLM Response", lines=10, show_copy_button=True)
123
+
124
+ process_btn.click(fn=process_pdf, inputs=pdf_input, outputs=status)
125
+ search_btn.click(fn=search_query, inputs=query_input, outputs=(semantic_search_response, llm_response))
126
+
127
+
128
+ demo.launch(server_name="0.0.0.0")
129
+
130
+
131
+
132
+
133
+
app/config.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+
4
+ #Load .env only if running locally
5
+ env_path = os.path.join(os.path.dirname(__file__), '..', '.env')
6
+
7
+ if os.path.exists(env_path):
8
+ load_dotenv(dotenv_path=env_path)
9
+
10
+
11
+ # Access Secrets
12
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
13
+ NVIDIA_API_KEY = os.getenv("NVIDIA_API_KEY")
14
+ CHROMA_DIR = os.getenv("CHROMA_DIR", "./chroma_db")
15
+
16
+ if not GOOGLE_API_KEY:
17
+ print("⚠️ Warning: GOOGLE_API_KEY is not set. Gemini LLM API may fail.")
18
+
19
+ if not NVIDIA_API_KEY:
20
+ print("⚠️ Warning: NVIDIA_API_KEY is not set. NVIDIA LLM API may fail.")
docker-compose.yml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ semantic-search-app:
5
+ build:
6
+ context: .
7
+ dockerfile: Dockerfile
8
+ container_name: semantic-search-app
9
+ ports:
10
+ - "1200:7860"
11
+ volumes:
12
+ - ./app:/app:rw # Live code updates via bind mount
13
+ - ./chroma_db:/app/chroma_db # Persist Chroma DB
14
+ environment:
15
+ - NVIDIA_API_KEY=${NVIDIA_API_KEY} # Optional: if using .env
16
+ restart: unless-stopped
17
+ command: python -m app
requirements.txt CHANGED
@@ -1,6 +1,8 @@
1
  gradio
2
  langchain
 
3
  chromadb
4
  PyMuPDF
5
  langchain-google-genai
6
- langchain-nvidia-ai-endpoints
 
 
1
  gradio
2
  langchain
3
+ langchain-community
4
  chromadb
5
  PyMuPDF
6
  langchain-google-genai
7
+ langchain-nvidia-ai-endpoints
8
+ dotenv