Spaces:
Build error
Build error
Add application file
Browse files- .env.example +1 -0
- Dockerfile +17 -0
- app/__init__.py +0 -0
- app/__pycache__/__init__.cpython-310.pyc +0 -0
- app/api/endpoints.py +0 -0
- app/core/config.py +0 -0
- app/core/constants.py +3 -0
- app/main.py +0 -0
- app/services/__pycache__/ingestion.cpython-310.pyc +0 -0
- app/services/ingestion.py +17 -0
- app/services/llm_service.py +36 -0
- app/services/vector_store.py +18 -0
- docker-compose.yml +12 -0
- main.py +11 -0
- requirements.txt +23 -0
- ui/__pycache__/gradio_app.cpython-310.pyc +0 -0
- ui/gradio_app.py +49 -0
.env.example
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
APP_NAME = "ITI-RAG"
|
Dockerfile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
RUN apt-get update && apt-get install -y \
|
| 6 |
+
build-essential \
|
| 7 |
+
libmagic-dev \
|
| 8 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
+
|
| 10 |
+
COPY requirements.txt .
|
| 11 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
+
|
| 13 |
+
COPY . .
|
| 14 |
+
|
| 15 |
+
EXPOSE 8000
|
| 16 |
+
|
| 17 |
+
CMD ["python", "app/main.py"]
|
app/__init__.py
ADDED
|
File without changes
|
app/__pycache__/__init__.cpython-310.pyc
ADDED
|
Binary file (127 Bytes). View file
|
|
|
app/api/endpoints.py
ADDED
|
File without changes
|
app/core/config.py
ADDED
|
File without changes
|
app/core/constants.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
CHUNK_SIZE = 1500
|
| 2 |
+
CHUNK_OVERLAP = 200
|
| 3 |
+
VECTOR_DB_PATH = "data/vector_db"
|
app/main.py
ADDED
|
File without changes
|
app/services/__pycache__/ingestion.cpython-310.pyc
ADDED
|
Binary file (722 Bytes). View file
|
|
|
app/services/ingestion.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_community.document_loaders import PyMuPDFLoader
|
| 2 |
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
| 3 |
+
from app.core.constants import CHUNK_SIZE, CHUNK_OVERLAP
|
| 4 |
+
|
| 5 |
+
def load_and_split_book(file_path):
|
| 6 |
+
loader = PyMuPDFLoader(file_path)
|
| 7 |
+
documents = loader.load()
|
| 8 |
+
|
| 9 |
+
text_splitter = RecursiveCharacterTextSplitter(
|
| 10 |
+
chunk_size=CHUNK_SIZE,
|
| 11 |
+
chunk_overlap=CHUNK_OVERLAP,
|
| 12 |
+
length_function=len
|
| 13 |
+
)
|
| 14 |
+
chunks = text_splitter.split_documents(documents)
|
| 15 |
+
|
| 16 |
+
print(f"Book splited to {len(chunks)}")
|
| 17 |
+
return chunks
|
app/services/llm_service.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 3 |
+
from langchain.prompts import PromptTemplate
|
| 4 |
+
from langchain.chains import RetrievalQA
|
| 5 |
+
from app.services.vector_store import load_vector_store
|
| 6 |
+
|
| 7 |
+
llm = ChatGoogleGenerativeAI(
|
| 8 |
+
model="gemini-1.5-flash",
|
| 9 |
+
google_api_key="YOUR_GEMINI_API_KEY",
|
| 10 |
+
temperature=0
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
def get_book_assistant_chain(mode="Explain"):
|
| 14 |
+
vector_db = load_vector_store()
|
| 15 |
+
retriever = vector_db.as_retriever(search_kwargs={"k": 5})
|
| 16 |
+
|
| 17 |
+
if mode == "Explain":
|
| 18 |
+
template = """You are an expert tutor. Use the provided context to explain the concept simply.
|
| 19 |
+
Context: {context}
|
| 20 |
+
Question: {question}
|
| 21 |
+
Explanation:"""
|
| 22 |
+
else:
|
| 23 |
+
template = """Based on the following text, generate 3 multiple-choice questions with answers.
|
| 24 |
+
Context: {context}
|
| 25 |
+
Question: {question}
|
| 26 |
+
Questions:"""
|
| 27 |
+
|
| 28 |
+
QA_PROMPT = PromptTemplate(template=template, input_variables=["context", "question"])
|
| 29 |
+
|
| 30 |
+
return RetrievalQA.from_chain_type(
|
| 31 |
+
llm=llm,
|
| 32 |
+
chain_type="stuff",
|
| 33 |
+
retriever=retriever,
|
| 34 |
+
return_source_documents=True,
|
| 35 |
+
chain_type_kwargs={"prompt": QA_PROMPT}
|
| 36 |
+
)
|
app/services/vector_store.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_community.embeddings import HuggingFaceEmbeddings
|
| 2 |
+
from langchain_community.vectorstores import FAISS
|
| 3 |
+
from app.core.constants import VECTOR_DB_PATH
|
| 4 |
+
|
| 5 |
+
# ุงุฎุชูุงุฑูุง ูู all-MiniLM-L6-v2 ูุฃูู ุฎููู ุนูู ุฌูุงุฒู Dell G12 [cite: 51]
|
| 6 |
+
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
|
| 7 |
+
|
| 8 |
+
def create_vector_store(chunks):
|
| 9 |
+
# ุชุญููู ุงููุต ูุฃุฑูุงู
ูุชุฎุฒููู [cite: 29, 30]
|
| 10 |
+
vector_db = FAISS.from_documents(chunks, embeddings)
|
| 11 |
+
|
| 12 |
+
# ุญูุธ ุงููุงุนุฏุฉ ู
ุญููุงู (Local Storage)
|
| 13 |
+
vector_db.save_local(VECTOR_DB_PATH)
|
| 14 |
+
return vector_db
|
| 15 |
+
|
| 16 |
+
def load_vector_store():
|
| 17 |
+
# ุชุญู
ูู ุงููุงุนุฏุฉ ุนูุฏ ุงูุญุงุฌุฉ [cite: 32]
|
| 18 |
+
return FAISS.load_local(VECTOR_DB_PATH, embeddings, allow_dangerous_deserialization=True)
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version: '3.8'
|
| 2 |
+
|
| 3 |
+
services:
|
| 4 |
+
smart-assistant:
|
| 5 |
+
build: .
|
| 6 |
+
ports:
|
| 7 |
+
- "8000:8000"
|
| 8 |
+
environment:
|
| 9 |
+
- GROQ_API_KEY=${GROQ_API_KEY}
|
| 10 |
+
volumes:
|
| 11 |
+
- ./data:/app/data
|
| 12 |
+
|
main.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
import uvicorn
|
| 3 |
+
from ui.gradio_app import demo
|
| 4 |
+
import gradio as gr
|
| 5 |
+
|
| 6 |
+
app = FastAPI(title="Smart Contract/Book Assistant API")
|
| 7 |
+
|
| 8 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
| 9 |
+
|
| 10 |
+
if __name__ == "__main__":
|
| 11 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
requirements.txt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Core Web Framework
|
| 2 |
+
fastapi==0.111.0
|
| 3 |
+
uvicorn[standard]==0.30.1
|
| 4 |
+
|
| 5 |
+
# AI & RAG Engine
|
| 6 |
+
langchain>=0.2.0
|
| 7 |
+
langchain-community>=0.2.0
|
| 8 |
+
langchain-google-genai>=1.0.0
|
| 9 |
+
sentence-transformers>=2.7.0
|
| 10 |
+
faiss-cpu>=1.8.0
|
| 11 |
+
|
| 12 |
+
# Document Processing
|
| 13 |
+
pypdf>=4.2.0
|
| 14 |
+
python-docx>=1.1.0
|
| 15 |
+
|
| 16 |
+
# UI & Local Execution
|
| 17 |
+
gradio>=4.36.1
|
| 18 |
+
transformers>=4.41.0
|
| 19 |
+
torch>=2.3.0
|
| 20 |
+
|
| 21 |
+
# Critical Dependencies (To fix the Numpy/Scipy error)
|
| 22 |
+
numpy<2.0.0
|
| 23 |
+
scipy>=1.13.0
|
ui/__pycache__/gradio_app.cpython-310.pyc
ADDED
|
Binary file (2.13 kB). View file
|
|
|
ui/gradio_app.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from app.services.ingestion import load_and_split_book
|
| 3 |
+
from app.services.vector_store import create_vector_store
|
| 4 |
+
from app.services.llm_service import get_book_assistant_chain
|
| 5 |
+
|
| 6 |
+
def handle_upload(file):
|
| 7 |
+
if file is None:
|
| 8 |
+
return "Please upload a file first."
|
| 9 |
+
|
| 10 |
+
chunks = load_and_split_book(file.name)
|
| 11 |
+
|
| 12 |
+
create_vector_store(chunks)
|
| 13 |
+
|
| 14 |
+
return "โ
Document processed successfully! You can now go to the Chat tab."
|
| 15 |
+
|
| 16 |
+
def handle_chat(user_question, mode):
|
| 17 |
+
qa_chain = get_book_assistant_chain(mode=mode)
|
| 18 |
+
|
| 19 |
+
result = qa_chain({"query": user_question})
|
| 20 |
+
|
| 21 |
+
answer = result["result"]
|
| 22 |
+
sources = "\n\n๐ Sources:\n" + "\n".join([doc.metadata.get('source', 'Unknown') for doc in result["source_documents"]])
|
| 23 |
+
|
| 24 |
+
return answer + sources
|
| 25 |
+
|
| 26 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 27 |
+
gr.Markdown("# ๐ Smart Book & Contract Assistant")
|
| 28 |
+
|
| 29 |
+
with gr.Tabs():
|
| 30 |
+
with gr.TabItem("โฌ๏ธ Upload Document"):
|
| 31 |
+
file_input = gr.File(label="Upload PDF or DOCX", file_types=[".pdf", ".docx"])
|
| 32 |
+
upload_btn = gr.Button("Process Document", variant="primary")
|
| 33 |
+
status_output = gr.Textbox(label="Status", interactive=False)
|
| 34 |
+
upload_btn.click(handle_upload, inputs=file_input, outputs=status_output)
|
| 35 |
+
|
| 36 |
+
with gr.TabItem("๐ฌ Explanation & Q&A"):
|
| 37 |
+
mode_radio = gr.Radio(
|
| 38 |
+
choices=["Explain", "Generate Questions"],
|
| 39 |
+
label="Interaction Mode",
|
| 40 |
+
value="Explain"
|
| 41 |
+
)
|
| 42 |
+
chat_input = gr.Textbox(label="Ask a question or request a summary/questions")
|
| 43 |
+
chat_btn = gr.Button("Submit", variant="primary")
|
| 44 |
+
chat_output = gr.Textbox(label="AI Assistant Response", lines=12)
|
| 45 |
+
|
| 46 |
+
chat_btn.click(handle_chat, inputs=[chat_input, mode_radio], outputs=chat_output)
|
| 47 |
+
|
| 48 |
+
if __name__ == "__main__":
|
| 49 |
+
demo.launch()
|