Zubaish commited on
Commit
b713a11
·
0 Parent(s):

Initial backend-only RAG (no PDFs)

Browse files
Files changed (10) hide show
  1. .gitattributes +35 -0
  2. .gitignore +18 -0
  3. Dockerfile +23 -0
  4. README.md +11 -0
  5. app.py +20 -0
  6. config.py +9 -0
  7. guardrails.py +2 -0
  8. ingest.py +17 -0
  9. rag.py +49 -0
  10. requirements.txt +14 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz 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
.gitignore ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+
5
+ # Chroma DB
6
+ chroma_db/
7
+ data/
8
+
9
+ # Environment
10
+ .env
11
+
12
+ # Frontend (DO NOT COMMIT)
13
+ frontend/node_modules/
14
+ frontend/dist/
15
+ frontend/.vite/
16
+
17
+ kb_docs/
18
+ *.pdf
Dockerfile ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # Set working directory
4
+ WORKDIR /app
5
+
6
+ # Install system dependencies
7
+ RUN apt-get update && apt-get install -y \
8
+ git \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Install Python dependencies
12
+ COPY requirements.txt .
13
+ RUN pip install --no-cache-dir -r requirements.txt
14
+
15
+ # Copy application code
16
+ COPY app.py rag.py ingest.py guardrails.py config.py ./
17
+ COPY kb_docs ./kb_docs
18
+
19
+ # Hugging Face Spaces expects port 7860
20
+ EXPOSE 7860
21
+
22
+ # Start FastAPI
23
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: HubRAG
3
+ emoji: 📊
4
+ colorFrom: green
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ short_description: Ask anything about Gandhi ji.
9
+ ---
10
+
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from pydantic import BaseModel
3
+
4
+ from rag import ask_rag_with_status
5
+
6
+ app = FastAPI(title="HubRAG API")
7
+
8
+ class Question(BaseModel):
9
+ question: str
10
+
11
+ @app.get("/")
12
+ def root():
13
+ return {
14
+ "status": "ok",
15
+ "message": "RAG API is running"
16
+ }
17
+
18
+ @app.post("/chat")
19
+ def chat(req: Question):
20
+ return ask_rag_with_status(req.question)
config.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
4
+
5
+ if not HUGGINGFACEHUB_API_TOKEN:
6
+ raise RuntimeError(
7
+ "HUGGINGFACEHUB_API_TOKEN is not set. "
8
+ "Set it as an environment variable or HF Space Secret."
9
+ )
guardrails.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ def validate_question(question: str) -> bool:
2
+ return bool(question and question.strip())
ingest.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
2
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
3
+
4
+ def load_and_split_docs(path="kb_docs"):
5
+ loader = DirectoryLoader(
6
+ path,
7
+ glob="**/*.pdf",
8
+ loader_cls=PyPDFLoader
9
+ )
10
+ docs = loader.load()
11
+
12
+ splitter = RecursiveCharacterTextSplitter(
13
+ chunk_size=800,
14
+ chunk_overlap=100
15
+ )
16
+
17
+ return splitter.split_documents(docs)
rag.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_huggingface import HuggingFaceEmbeddings, ChatHuggingFace
2
+ from langchain_chroma import Chroma
3
+ from langchain.schema import SystemMessage, HumanMessage
4
+
5
+ from ingest import load_and_split_docs
6
+
7
+ print("⏳ Indexing documents...")
8
+
9
+ embeddings = HuggingFaceEmbeddings(
10
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
11
+ )
12
+
13
+ documents = load_and_split_docs()
14
+
15
+ vectorstore = Chroma.from_documents(
16
+ documents,
17
+ embedding=embeddings
18
+ )
19
+
20
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
21
+
22
+ llm = ChatHuggingFace(
23
+ repo_id="microsoft/Phi-4-mini-instruct",
24
+ temperature=0.2
25
+ )
26
+
27
+ print("✅ Indexing complete.")
28
+
29
+ def ask_rag_with_status(question: str):
30
+ status = [
31
+ "🔍 Retrieving relevant documents...",
32
+ "🧠 Building context...",
33
+ "💭 Thinking..."
34
+ ]
35
+
36
+ docs = retriever.get_relevant_documents(question)
37
+ context = "\n\n".join(d.page_content for d in docs)
38
+
39
+ messages = [
40
+ SystemMessage(content="You are a helpful assistant. Answer using the context."),
41
+ HumanMessage(content=f"Context:\n{context}\n\nQuestion: {question}")
42
+ ]
43
+
44
+ response = llm.invoke(messages)
45
+
46
+ return {
47
+ "status": status,
48
+ "answer": response.content
49
+ }
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pydantic
4
+ python-dotenv
5
+
6
+ langchain
7
+ langchain-community
8
+ langchain-core
9
+ langchain-huggingface
10
+
11
+ chromadb
12
+ sentence-transformers
13
+ pypdf
14
+ huggingface_hub