VashuTheGreat2 commited on
Commit
5551822
·
verified ·
1 Parent(s): 1f725d8

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +13 -0
  2. .gitignore +9 -1
  3. .vscode/settings.json +4 -0
  4. README.md +90 -85
  5. api/MultiRag/controllers/loadUserContent_component.py +21 -0
  6. api/MultiRag/models/__init__.py +0 -0
  7. api/MultiRag/routes/analyse_url.py +18 -0
  8. api/MultiRag/routes/chat_route.py +30 -20
  9. api/MultiRag/routes/delete_thread_route.py +29 -0
  10. api/MultiRag/routes/get_all_thread_route.py +16 -0
  11. api/MultiRag/routes/get_available_file_fomates_route.py +10 -0
  12. api/MultiRag/routes/load_conversation_route.py +17 -0
  13. api/MultiRag/routes/pages_route.py +13 -13
  14. api/MultiRag/routes/uploader_route.py +96 -46
  15. api/constants/__init__.py +8 -0
  16. api/main.py +13 -13
  17. docs copy/AI_Intro.pdf +0 -0
  18. docs copy/google.docx +3 -0
  19. docs copy/growing_ai_tools.txt +1 -0
  20. docs copy/lena.png +3 -0
  21. docs/AI_Intro.pdf +0 -0
  22. docs/Optical_Recognition.png +0 -0
  23. docs/google.docx +3 -0
  24. docs/growing_ai_tools.txt +1 -0
  25. docs/lena.png +3 -0
  26. exception/__init__.py +3 -23
  27. graph.png +0 -0
  28. images/attention_mechanism.png +3 -0
  29. images/common_mistakes.png +3 -0
  30. images/conclusion.png +3 -0
  31. images/machine_learning_overview.png +3 -0
  32. images/ml_common_mistakes.png +3 -0
  33. images/ml_model_example.png +3 -0
  34. images/ml_workflow_diagram.png +3 -0
  35. images/transformer_application.png +3 -0
  36. images/transformer_architecture.png +3 -0
  37. logs/05_02_2026_19_15_40.log.1 +0 -0
  38. logs/05_02_2026_19_15_40.log.2 +0 -0
  39. main.py +1 -1
  40. notebook/blip_image_captioning_large.ipynb +0 -0
  41. pyproject.toml +10 -0
  42. src/MultiRag/components/__init__.py +0 -0
  43. src/MultiRag/components/content_embedder.py +58 -0
  44. src/MultiRag/components/run_graph.py +20 -0
  45. src/MultiRag/constants/__init__.py +16 -1
  46. src/MultiRag/entity/artifact_entity.py +6 -0
  47. src/MultiRag/entity/config_entity.py +9 -0
  48. src/MultiRag/graph/builder.py +137 -21
  49. src/MultiRag/graph/worker/builder.py +62 -0
  50. src/MultiRag/llm/llm_loader.py +8 -3
.gitattributes CHANGED
@@ -33,3 +33,16 @@ 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
+ docs/google.docx filter=lfs diff=lfs merge=lfs -text
37
+ docs/lena.png filter=lfs diff=lfs merge=lfs -text
38
+ docs[[:space:]]copy/google.docx filter=lfs diff=lfs merge=lfs -text
39
+ docs[[:space:]]copy/lena.png filter=lfs diff=lfs merge=lfs -text
40
+ images/attention_mechanism.png filter=lfs diff=lfs merge=lfs -text
41
+ images/common_mistakes.png filter=lfs diff=lfs merge=lfs -text
42
+ images/conclusion.png filter=lfs diff=lfs merge=lfs -text
43
+ images/machine_learning_overview.png filter=lfs diff=lfs merge=lfs -text
44
+ images/ml_common_mistakes.png filter=lfs diff=lfs merge=lfs -text
45
+ images/ml_model_example.png filter=lfs diff=lfs merge=lfs -text
46
+ images/ml_workflow_diagram.png filter=lfs diff=lfs merge=lfs -text
47
+ images/transformer_application.png filter=lfs diff=lfs merge=lfs -text
48
+ images/transformer_architecture.png filter=lfs diff=lfs merge=lfs -text
.gitignore CHANGED
@@ -205,4 +205,12 @@ cython_debug/
205
  marimo/_static/
206
  marimo/_lsp/
207
  __marimo__/
208
- images/
 
 
 
 
 
 
 
 
 
205
  marimo/_static/
206
  marimo/_lsp/
207
  __marimo__/
208
+
209
+
210
+
211
+ db/
212
+ api/public/
213
+
214
+ scratch/
215
+ docs/
216
+
.vscode/settings.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "python-envs.defaultEnvManager": "ms-python.python:venv",
3
+ "python-envs.defaultPackageManager": "ms-python.python:pip"
4
+ }
README.md CHANGED
@@ -1,134 +1,139 @@
1
-
2
-
3
  ---
4
- title: Multi-Rag AI
5
- emoji: 🐠
6
  colorFrom: blue
7
  colorTo: green
8
  sdk: docker
9
- app_file: Dockerfile
10
- app_port: 7860
11
  pinned: false
 
12
  ---
13
 
14
 
15
  <div align="center">
16
- <h1>🤖 AIAgents Platform</h1>
17
- <p><strong>Intelligent AI Agents Powered by LangGraph, LangChain, and FastAPI</strong></p>
 
 
 
 
 
18
  </div>
19
 
20
- <br />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- Welcome to **AIAgents**, a full-stack, state-of-the-art framework for building and deploying extremely scalable, multi-agent AI ecosystems! Featuring powerful autonomous agents for complex Web Research, Blog Generation, Document RAG functionality, and interactive multi-turn chatting!
 
 
 
 
 
23
 
24
  ---
25
 
26
- ## 🚀 Features
27
 
28
- - **✍️ Bloggig (Blog Agent)**: Powerful autonomous agent that researches, writes, and generates high-quality blog posts complete with AI-generated visuals.
29
- - **🌐 Web Research Agent**: Automatically browse, scrape, and synthesize live internet data straight from any URL (including YouTube videos!) directly within the web interface.
30
- - **📚 Multi-turn RAG Chat**: Chat with arbitrary text or PDF documents using deep LangGraph memory, powerful sentence transformers for vector retrieval, and advanced orchestration logic.
31
- - **🎨 Stunning UI**: Beautiful, fully-responsive, custom Dark Mode interface crafted natively with Jinja2 Templating, vanilla HTML/CSS/JS, and glassmorphism UI elements.
32
- - ** Supercharged Backend**: High-performance asynchronous API crafted using FastAPI.
33
- - **🛠️ Extensible AI Architecture**: Built on top of the robust **LangChain** and **LangGraph** Python ecosystem to allow autonomous scaling of multi-agent workflows.
 
 
 
 
 
34
 
35
  ## 🛠️ Tech Stack
36
 
37
- - **Backend**: Python 3.12+, FastAPI, Uvicorn
38
- - **AI Frameworks**: LangChain, LangGraph, Sentence-Transformers, HuggingFace
39
- - **LLMs**: AWS Bedrock (Claude 3.5 Sonnet, Claude 3 Haiku, Llama 3), OpenAI (GPT-4o)
40
- - **Vector Database**: FAISS (Facebook AI Similarity Search)
41
- - **Frontend**: Jinja2 Templates, Vanilla JS, CSS3, DOM manipulation
42
- - **Development Tooling**: `uv` (Fast Python Package Manager)
 
43
 
44
  ---
45
 
46
- ## ⚙️ Quickstart
47
 
48
  ### Prerequisites
49
-
50
- - Ensure you have **Python >= 3.12** installed on your system.
51
- - Make sure you are using [uv](https://github.com/astral-sh/uv) to manage project dependencies!
52
 
53
  ### 1. Installation
54
-
55
- 1. **Clone the repository**:
56
  ```bash
57
- git clone https://github.com/VashuTheGreat/AiAgents.git
58
- cd AiAgents
59
- ```
60
 
61
- 2. **Set up the virtual environment & install dependencies** using `uv`:
62
- ```bash
63
  uv sync
64
  ```
65
 
66
- ### 2. Environment Variables
67
-
68
- Create a `.env` file in the root of the project and place your necessary API keys inside.
69
-
70
  ```env
71
- # General
72
- APP_API_KEY="your_custom_auth_key"
 
 
73
 
74
- # AWS Bedrock (For Blog Agent)
75
- AWS_ACCESS_KEY_ID="your_key"
76
- AWS_SECRET_ACCESS_KEY="your_secret"
77
- AWS_REGION_NAME="us-east-1"
78
-
79
- # OpenAI
80
- OPENAI_API_KEY="sk-..."
81
  ```
82
 
83
- ### 3. Run the Server
84
-
85
- Simply launch the FastAPI application:
86
  ```bash
87
- uv run .\main.py
 
88
  ```
89
- This will start the development server. Navigate to `http://127.0.0.1:8000/` to see the AIAgents Hub!
90
-
91
- ---
92
-
93
- ## 🎨 Walkthrough of the Application
94
-
95
- ### 🏠 Home Page (`/`)
96
- An elegant gateway into the available AI agent interfaces.
97
-
98
- ### ✍️ Blog Agent (`/blog`)
99
- The flagship feature. Enter a topic, and Bloggig will autonomously research the subject, plan its structure, write the content in Markdown, and generate relevant images. It features a real-time "pipeline console" to track the agent's progress.
100
-
101
- ### 🌐 Web Summarizer (`/web`)
102
- Paste any URL or YouTube Link to extract and summarize content using our custom LangGraph architecture.
103
-
104
- ### 💬 Chat MultiGraph (`/chat`)
105
- Engage with your locally uploaded documents via RAG (Retrieval-Augmented Generation) with intelligent memory buffers.
106
 
107
  ---
108
 
109
  ## 📂 Project Structure
110
 
111
  ```bash
112
- AiAgents/
113
- ├─ api/
114
- ├─ Blog/ # Bloggig-specific routers and models
115
- ─ MultiRag/ # Document RAG routers
116
- Web/ # Web Summarizer routers
117
- ├─ src/
118
- ├─ Blog/ # Bloggig Agent logic (Graph, Nodes, Prompts)
119
- ├─ MultiRag/ # RAG Agent logic (Retrievers, Vectorstores, etc.)
120
- Web/ # Web Agent logic (Loaders, Graph)
121
- images/ # Generated blog visualizations
122
- ├─ results/ # Saved blog markdown outputs
123
- ├─ static/ # CSS, JS, and local frontend assets
124
- templates/ # Jinja2 HTML templates
125
- ├─ data/ # Raw document storage for RAG
126
- ├─ db/ # Local FAISS vector database storage
127
- └─ pyproject.toml # Project dependencies (uv)
128
  ```
129
 
130
  ---
131
 
132
  <div align="center">
133
- <p>Crafted with ❤️ for professional creators.</p>
134
  </div>
 
 
 
1
  ---
2
+ title: Multi-Rag
3
+ emoji: 🎓
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
7
+ app_file: main.py
 
8
  pinned: false
9
+ short_description: This is the Agentic Blog Writing Agent
10
  ---
11
 
12
 
13
  <div align="center">
14
+ <h1>🚀 Multi-RAG AI Pipeline</h1>
15
+ <p><strong>Advanced Multi-Agent RAG Orchestration powered by LangGraph, AWS Bedrock, and FAISS</strong></p>
16
+
17
+ [![Python](https://img.shields.io/badge/Python-3.12+-blue.svg)](https://www.python.org/)
18
+ [![LangGraph](https://img.shields.io/badge/Framework-LangGraph-orange.svg)](https://github.com/langchain-ai/langgraph)
19
+ [![FastAPI](https://img.shields.io/badge/Backend-FastAPI-green.svg)](https://fastapi.tiangolo.com/)
20
+ [![FAISS](https://img.shields.io/badge/VectorDB-FAISS-red.svg)](https://github.com/facebookresearch/faiss)
21
  </div>
22
 
23
+ ---
24
+
25
+ ## 📖 Overview
26
+
27
+ **Multi-RAG AI** is a state-of-the-art, multi-agent RAG (Retrieval-Augmented Generation) pipeline designed for high-performance document intelligence. It leverages **LangGraph** for sophisticated orchestration, allowing an autonomous "Orchestrator" agent to decide which specialized workers (PDF, DOCX, TXT, Images, Web Search) are needed to answer complex user queries.
28
+
29
+ ### Why Multi-RAG?
30
+ - **Intelligent Fan-out**: The orchestrator can trigger multiple workers in parallel to gather information from different sources.
31
+ - **Dynamic Routing**: Automatically detects file types and routes tasks to specialized loaders.
32
+ - **OCR Integration**: Built-in support for image processing and optical character recognition.
33
+ - **Web Search Fallback**: If local documents are insufficient, the agents can autonomously search the live web.
34
+
35
+ ---
36
+
37
+ ## 🏗️ Architecture
38
+
39
+ The system is built as a nested graph structure, providing a clean separation between high-level orchestration and low-level specialized tasks.
40
+
41
+ ### 1. Main Orchestration Graph
42
+ The main graph handles the interaction between the user, the orchestrator, and the final chat response.
43
 
44
+ ![Main Graph Architecture](./graph.png)
45
+
46
+ ### 2. Worker Sub-Graph
47
+ The worker sub-graph is responsible for specialized information retrieval from various file formats.
48
+
49
+ ![Worker Sub-Graph](./worker_sub_graph.png)
50
 
51
  ---
52
 
53
+ ## Key Features
54
 
55
+ - **📂 Multi-Format Support**:
56
+ - **PDF**: Deep document parsing.
57
+ - **DOCX**: Microsoft Word document integration.
58
+ - **TXT**: Plain text analysis.
59
+ - **Images (OCR)**: Extraction of text from PNG/JPG using specialized loaders.
60
+ - **🤖 Autonomous Orchestration**: Uses a Llama-3.3-70B model on **AWS Bedrock** with a manual JSON fallback mechanism for 100% reliable structured output.
61
+ - **🔍 Hybrid Retrieval**: Combines local FAISS vector stores with real-time Google Search integration.
62
+ - **🧠 Persistence & Memory**: Full multi-turn conversation support with LangGraph checkpointers.
63
+ - **⚡ Modern Tech Stack**: Built with `uv` for lightning-fast dependency management and `FastAPI` for a high-performance backend.
64
+
65
+ ---
66
 
67
  ## 🛠️ Tech Stack
68
 
69
+ - **Core**: [Python 3.12](https://www.python.org/)
70
+ - **Orchestration**: [LangGraph](https://github.com/langchain-ai/langgraph) & [LangChain](https://github.com/langchain-ai/langchain)
71
+ - **Large Language Models**: [AWS Bedrock](https://aws.amazon.com/bedrock/) (Llama 3.3 70B)
72
+ - **Vector Storage**: [FAISS](https://github.com/facebookresearch/faiss)
73
+ - **Embeddings**: [HuggingFace](https://huggingface.co/) (all-MiniLM-L6-v2)
74
+ - **Backend API**: [FastAPI](https://fastapi.tiangolo.com/)
75
+ - **Package Management**: [uv](https://github.com/astral-sh/uv)
76
 
77
  ---
78
 
79
+ ## 🚀 Getting Started
80
 
81
  ### Prerequisites
82
+ - Python 3.12+
83
+ - `uv` installed (`pip install uv`)
84
+ - AWS Credentials (for Bedrock access)
85
 
86
  ### 1. Installation
 
 
87
  ```bash
88
+ # Clone the repository
89
+ git clone https://github.com/VashuTheGreat/Multi-Rag.git
90
+ cd Multi-Rag
91
 
92
+ # Install dependencies
 
93
  uv sync
94
  ```
95
 
96
+ ### 2. Environment Setup
97
+ Create a `.env` file in the root directory:
 
 
98
  ```env
99
+ # AWS Bedrock Config
100
+ AWS_ACCESS_KEY_ID=your_access_key
101
+ AWS_SECRET_ACCESS_KEY=your_secret_key
102
+ AWS_REGION_NAME=us-east-1
103
 
104
+ # Tooling (e.g., Search API keys if applicable)
105
+ # ...
 
 
 
 
 
106
  ```
107
 
108
+ ### 3. Run the Application
 
 
109
  ```bash
110
+ # Start the FastAPI server
111
+ uv run main.py
112
  ```
113
+ Navigate to `http://127.0.0.1:8000` to start chatting with your documents!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  ---
116
 
117
  ## 📂 Project Structure
118
 
119
  ```bash
120
+ Multi-Rag/
121
+ ├─ api/ # FastAPI Endpoints & Controllers
122
+ ├─ src/
123
+ MultiRag/
124
+ components/ # Core graph runners & embedders
125
+ ├─ graph/ # LangGraph definitions (Main & Worker)
126
+ ├─ models/ # Pydantic state & output schemas
127
+ ├─ nodes/ # Individual graph node implementations
128
+ prompts/ # LLM system prompts
129
+ │ └ utils/ # Ingestion & document processing utilities
130
+ ├─ static/ # Frontend assets (CSS, JS)
131
+ ├─ templates/ # Jinja2 HTML templates
132
+ db/ # Local FAISS index persistence
 
 
 
133
  ```
134
 
135
  ---
136
 
137
  <div align="center">
138
+ <p>Built with 💖 for the future of Agentic RAG.</p>
139
  </div>
api/MultiRag/controllers/loadUserContent_component.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from utils.asyncHandler import asyncHandler
3
+ from utils.main_utils import load_yaml
4
+ from api.constants import DATA_FOLDER_PATH,USER_CONTENT_FILE_NAME
5
+ from src.MultiRag.models.rag_model import Content
6
+
7
+ @asyncHandler
8
+ async def load_user_content(thread_id):
9
+ user_data = load_yaml(f"{DATA_FOLDER_PATH}/{thread_id}/{USER_CONTENT_FILE_NAME}")
10
+ user_content = []
11
+ if user_data:
12
+ for content in user_data.get("Contents", []):
13
+ user_content.append(
14
+ Content(
15
+ name=content["name"],
16
+ about=content["about"],
17
+ path=content["path"]
18
+ )
19
+ )
20
+
21
+ return user_content
api/MultiRag/models/__init__.py ADDED
File without changes
api/MultiRag/routes/analyse_url.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fastapi
2
+
3
+ import logging
4
+
5
+ router = fastapi.APIRouter()
6
+
7
+
8
+ @router.post("/analyse_url")
9
+ async def analyse_url(thread_id:str,url: str):
10
+ try:
11
+
12
+ if not url:
13
+ return {"data": "URL missing in headers"}
14
+ res = await run_agent(thread_id, url)
15
+ return {"data": res}
16
+ except Exception as e:
17
+ logging.error(f"Chat endpoint error: {e}")
18
+ return {"data": "Failed to chat"}
api/MultiRag/routes/chat_route.py CHANGED
@@ -1,32 +1,31 @@
1
  from fastapi import APIRouter, Request, Query
2
  import logging
3
  import logging
 
4
  from src.MultiRag.graph.builder import graph
 
 
 
5
 
6
  router = APIRouter()
7
 
8
-
9
- async def run_agent(user_id, userQuery: str):
10
- logging.info("Starting AIAgents application...")
11
- # Sample initial state for testing
12
- config = {"configurable": {"thread_id": user_id}}
13
- initial_state = {
14
- "userQuery": userQuery,
15
- "db_path": f"db/{user_id}",
16
- "docs_path": f"data/{user_id}",
17
- "k": 3
18
- }
19
  try:
20
- response = await graph.ainvoke(initial_state, config=config)
21
- logging.debug(f"Graph response: {response}")
22
- logging.info("Graph invocation successful.")
23
- res = response.get("llm_response", "No response found.")
 
 
 
 
24
  return res
25
  except Exception as e:
26
  logging.error(f"Application failed: {e}")
27
- import traceback
28
- logging.error(traceback.format_exc())
29
- return "Chat failed due to internal error"
30
  finally:
31
  logging.info("AIAgents application finished.")
32
 
@@ -35,10 +34,21 @@ async def run_agent(user_id, userQuery: str):
35
  async def chat(req: Request, message: str = Query(...)):
36
  try:
37
  user_id = req.headers.get("user_id")
 
38
  if not user_id:
39
  return {"data": "User ID missing in headers"}
40
- res = await run_agent(user_id, message)
41
- return {"data": res}
 
 
 
 
 
 
 
 
42
  except Exception as e:
43
  logging.error(f"Chat endpoint error: {e}")
44
  return {"data": "Chat failed"}
 
 
 
1
  from fastapi import APIRouter, Request, Query
2
  import logging
3
  import logging
4
+ from src.MultiRag.pipeline.run_pipeline import RunPipeline
5
  from src.MultiRag.graph.builder import graph
6
+ from src.MultiRag.models.rag_model import Content
7
+ from api.MultiRag.controllers.loadUserContent_component import load_user_content
8
+ from exception import MyException
9
 
10
  router = APIRouter()
11
 
12
+ run_pipeline = RunPipeline()
13
+ async def run_agent(user_id, thread_id, userQuery: str):
14
+ logging.info(f"Starting AIAgents application for thread: {thread_id}")
15
+
 
 
 
 
 
 
 
16
  try:
17
+ temp_user_content = await load_user_content(thread_id)
18
+
19
+
20
+ res = await run_pipeline.initiate(
21
+ thread_id=thread_id,
22
+ query=userQuery,
23
+ userContent=temp_user_content
24
+ )
25
  return res
26
  except Exception as e:
27
  logging.error(f"Application failed: {e}")
28
+ raise MyException("AIAgents application failed") from e
 
 
29
  finally:
30
  logging.info("AIAgents application finished.")
31
 
 
34
  async def chat(req: Request, message: str = Query(...)):
35
  try:
36
  user_id = req.headers.get("user_id")
37
+ thread_id = req.headers.get("thread_id") or user_id
38
  if not user_id:
39
  return {"data": "User ID missing in headers"}
40
+ res = await run_agent(user_id, thread_id, message)
41
+
42
+ # Extract the last message content to send to frontend
43
+ messages = res.get("messages", [])
44
+ if messages:
45
+ last_msg = messages[-1]
46
+ content = last_msg.content if hasattr(last_msg, 'content') else str(last_msg)
47
+ return {"data": content}
48
+
49
+ return {"data": "No response from agent."}
50
  except Exception as e:
51
  logging.error(f"Chat endpoint error: {e}")
52
  return {"data": "Chat failed"}
53
+
54
+
api/MultiRag/routes/delete_thread_route.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fastapi
2
+ import logging
3
+ import os
4
+ import shutil
5
+ from exception import MyException
6
+ from api.constants import DATA_FOLDER_PATH,DB_FOLDER_PATH
7
+ from src.MultiRag.graph.builder import deleteThread
8
+ router = fastapi.APIRouter()
9
+
10
+
11
+ @router.delete("/delete_thread")
12
+ async def delete_thread(thread_id: str):
13
+ try:
14
+ logging.info(f"Attempting to delete thread {thread_id}")
15
+ await deleteThread(thread_id)
16
+
17
+ data_path = f"{DATA_FOLDER_PATH}/{thread_id}"
18
+ db_path = f"{DB_FOLDER_PATH}/{thread_id}"
19
+
20
+ if os.path.exists(data_path):
21
+ shutil.rmtree(data_path)
22
+ if os.path.exists(db_path):
23
+ shutil.rmtree(db_path)
24
+
25
+ logging.info(f"Successfully deleted thread {thread_id}")
26
+ return {"message": f"Thread {thread_id} has been deleted."}
27
+ except Exception as e:
28
+ logging.error(f"Failed to delete thread {thread_id}: {str(e)}")
29
+ raise MyException("Failed to delete thread") from e
api/MultiRag/routes/get_all_thread_route.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from src.MultiRag.graph.builder import retrieve_all_threads
2
+ import fastapi
3
+ import logging
4
+
5
+ router = fastapi.APIRouter()
6
+
7
+ @router.get("/get_all_thread")
8
+ async def get_all_thread():
9
+ try:
10
+ logging.info("Received request to get all threads")
11
+ threads = await retrieve_all_threads()
12
+ logging.info(f"Retrieved all threads successfully {threads}")
13
+ return {"threads": threads}
14
+ except Exception as e:
15
+ logging.error(f"Error retrieving threads: {e}")
16
+ return {"message": "Failed to retrieve threads"}
api/MultiRag/routes/get_available_file_fomates_route.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ import fastapi
4
+ from api.constants import AVAILABLE_ANALYSIS
5
+ router = fastapi.APIRouter()
6
+
7
+
8
+ @router.get("/")
9
+ async def get_available_file_fomates():
10
+ return {"message": "Available file formats: pdf, txt, docx, image","data":AVAILABLE_ANALYSIS}
api/MultiRag/routes/load_conversation_route.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fastapi
2
+ from src.MultiRag.graph.builder import load_conversation
3
+ import logging
4
+
5
+ router = fastapi.APIRouter()
6
+
7
+ @router.get("/load_conversation")
8
+ async def get_conversation(thread_id: str):
9
+ try:
10
+ logging.info(f"Loading conversation for thread_id: {thread_id}")
11
+ messages = await load_conversation(thread_id)
12
+ logging.info(f"Conversation loaded successfully for thread_id: {thread_id}")
13
+ return {"messages": messages}
14
+ except Exception as e:
15
+ logging.error(f"Error loading conversation for thread_id: {thread_id}: {e}")
16
+ return {"message": "Failed to load conversation"}
17
+
api/MultiRag/routes/pages_route.py CHANGED
@@ -8,24 +8,24 @@ templates = Jinja2Templates(directory="templates")
8
 
9
  _APP_USER_ID = os.getenv("APP_API_KEY", "")
10
 
11
- @router.get("/")
12
- async def read_root(request: Request):
13
- return templates.TemplateResponse(
14
- name="home.html",
15
- context={"request": request, "app_user_id": _APP_USER_ID}
16
- )
17
 
18
 
19
- @router.get("/chat")
20
  async def chat_model(request: Request):
21
  return templates.TemplateResponse(
22
  name="chat.html",
23
  context={"request": request, "app_user_id": _APP_USER_ID}
24
  )
25
 
26
- @router.get("/web")
27
- async def web_page(request: Request):
28
- return templates.TemplateResponse(
29
- name="web.html",
30
- context={"request": request, "app_user_id": _APP_USER_ID}
31
- )
 
8
 
9
  _APP_USER_ID = os.getenv("APP_API_KEY", "")
10
 
11
+ # @router.get("/")
12
+ # async def read_root(request: Request):
13
+ # return templates.TemplateResponse(
14
+ # name="home.html",
15
+ # context={"request": request, "app_user_id": _APP_USER_ID}
16
+ # )
17
 
18
 
19
+ @router.get("/")
20
  async def chat_model(request: Request):
21
  return templates.TemplateResponse(
22
  name="chat.html",
23
  context={"request": request, "app_user_id": _APP_USER_ID}
24
  )
25
 
26
+ # @router.get("/web")
27
+ # async def web_page(request: Request):
28
+ # return templates.TemplateResponse(
29
+ # name="web.html",
30
+ # context={"request": request, "app_user_id": _APP_USER_ID}
31
+ # )
api/MultiRag/routes/uploader_route.py CHANGED
@@ -1,73 +1,123 @@
1
  import fastapi
2
  from fastapi import UploadFile, Request, BackgroundTasks
3
  import os
4
- import shutil
5
- import asyncio
6
  import logging
7
- from src.MultiRag.constants import CONTENT_PERSISTENT_TIME, DATA_FOLDER_PATH, DB_FOLDER_PATH
8
  from src.MultiRag.graph.builder import deleteThread
9
  from utils.asyncHandler import asyncHandler
10
- from src.MultiRag.nodes.retreiver_check_node import clear_cached_retriever
11
- router = fastapi.APIRouter()
12
-
13
-
14
- @asyncHandler
15
- async def delete_folder_after_time(user_id):
 
16
 
17
- await asyncio.sleep(CONTENT_PERSISTENT_TIME)
18
-
19
- folder_path = f"{DATA_FOLDER_PATH}/{user_id}"
20
- db_path = f"{DB_FOLDER_PATH}/{user_id}"
21
 
22
- # Step 1: null refs, gc.collect(), clear_system_cache() — in that order
23
- clear_cached_retriever(db_path)
24
- await deleteThread(user_id)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- # Step 2: give Windows 3s to fully release OS-level file locks after GC
27
- await asyncio.sleep(3)
28
 
29
- if os.path.exists(folder_path):
30
- shutil.rmtree(folder_path)
31
- logging.info(f"Folder deleted: {folder_path}")
32
 
33
- if os.path.exists(db_path):
34
- for attempt in range(6):
35
- try:
36
- shutil.rmtree(db_path)
37
- logging.info(f"DB deleted: {db_path}")
38
- return
39
- except PermissionError as e:
40
- logging.warning(f"DB delete attempt {attempt+1} failed: {e}")
41
- await asyncio.sleep(3)
42
 
43
- logging.error(f"Failed to delete DB after all retries: {db_path}")
 
 
 
44
 
 
 
45
 
 
 
 
 
46
 
47
-
48
 
 
 
 
49
 
50
- @router.post("/post_content")
51
- async def post_content(
52
- req: Request,
53
- file: UploadFile,
54
- background_tasks: BackgroundTasks
55
- ):
56
  try:
57
  user_id = req.headers.get("user_id")
 
 
 
58
 
59
- folder = f"{DATA_FOLDER_PATH}/{user_id}"
60
  os.makedirs(folder, exist_ok=True)
61
 
62
- file_path = f"{folder}/{file.filename}"
 
 
 
 
 
 
 
 
 
63
 
64
- with open(file_path, "wb") as f:
65
- f.write(await file.read())
 
 
66
 
67
- # start background delete timer
68
- background_tasks.add_task(delete_folder_after_time, user_id)
69
 
70
- return {"message": "File uploaded successfully"}
 
 
 
 
 
71
 
72
  except Exception as e:
73
- return {"message": "File upload failed"}
 
 
1
  import fastapi
2
  from fastapi import UploadFile, Request, BackgroundTasks
3
  import os
 
 
4
  import logging
 
5
  from src.MultiRag.graph.builder import deleteThread
6
  from utils.asyncHandler import asyncHandler
7
+ from utils.main_utils import write_yaml, load_yaml
8
+ from src.MultiRag.models.rag_model import Content
9
+ from src.MultiRag.components.content_embedder import ContentEmbedder
10
+ from src.MultiRag.entity.config_entity import ContentEmbedderConfig
11
+ from api.constants import DATA_FOLDER_PATH, USER_CONTENT_FILE_NAME
12
+ from src.MultiRag.graph.builder import graph
13
+ from langchain_core.messages import HumanMessage
14
 
15
+ router = fastapi.APIRouter()
 
 
 
16
 
17
+ async def generate_retreivers(thread_id: str):
18
+ yaml_path = f"{DATA_FOLDER_PATH}/{thread_id}/{USER_CONTENT_FILE_NAME}"
19
+ yaml_content = load_yaml(yaml_path)
20
+
21
+ if not yaml_content or 'Contents' not in yaml_content:
22
+ logging.warning(f"No contents found in {yaml_path}")
23
+ return
24
+
25
+ for content_dict in yaml_content['Contents']:
26
+ name = content_dict.get("name")
27
+ path = content_dict.get("path")
28
+
29
+ logging.info(f"Processing content: {name}")
30
+
31
+ content_embedder_config = ContentEmbedderConfig(
32
+ file_path=path,
33
+ vector_store_path=f"db/{thread_id}/{name}",
34
+ )
35
+ component = ContentEmbedder(content_embedder_config=content_embedder_config)
36
+ retreiver = await component.embed_content()
37
+ logging.info(f"Generated retreiver for {name}: {retreiver}")
38
+
39
+ @router.post("/")
40
+ async def post_content(
41
+ req: Request,
42
+ file: UploadFile
43
+ ):
44
+ try:
45
+ user_id = req.headers.get("user_id")
46
+ thread_id = req.headers.get("thread_id") or user_id
47
+ if not user_id:
48
+ return {"message": "User ID missing in headers"}
49
 
50
+ folder = f"{DATA_FOLDER_PATH}/{thread_id}"
51
+ os.makedirs(folder, exist_ok=True)
52
 
53
+ saved_file_path = f"{folder}/{file.filename}"
54
+ with open(saved_file_path, "wb") as f:
55
+ f.write(await file.read())
56
 
57
+ yaml_path = f"{folder}/{USER_CONTENT_FILE_NAME}"
58
+
59
+ content_entry = {
60
+ "name": file.filename,
61
+ "about": file.filename,
62
+ "path": saved_file_path
63
+ }
 
 
64
 
65
+ # Append to YAML
66
+ write_yaml(yaml_path, {"Contents": [content_entry]}, mode="a")
67
+
68
+ logging.info(f"File uploaded and entry added to YAML: {file.filename}")
69
 
70
+ # Trigger retriever generation
71
+ await generate_retreivers(thread_id)
72
 
73
+ # Notify the AI about the upload in the thread history
74
+ config = {"configurable": {"thread_id": thread_id}}
75
+ notification = HumanMessage(content=f"[SYSTEM NOTIFICATION]: User has uploaded a new file: {file.filename}. Please keep this in mind for future queries.")
76
+ await graph.aupdate_state(config, {"messages": [notification]})
77
 
78
+ return {"message": "File uploaded successfully"}
79
 
80
+ except Exception as e:
81
+ logging.error(f"File upload failed: {e}")
82
+ return {"message": f"File upload failed: {str(e)}"}
83
 
84
+ @router.post("/upload_url")
85
+ async def upload_url(req: Request, url: str):
 
 
 
 
86
  try:
87
  user_id = req.headers.get("user_id")
88
+ thread_id = req.headers.get("thread_id") or user_id
89
+ if not user_id:
90
+ return {"message": "User ID missing in headers"}
91
 
92
+ folder = f"{DATA_FOLDER_PATH}/{thread_id}"
93
  os.makedirs(folder, exist_ok=True)
94
 
95
+ yaml_path = f"{folder}/{USER_CONTENT_FILE_NAME}"
96
+
97
+ # Use a truncated URL for the name
98
+ display_name = (url[:50] + '...') if len(url) > 50 else url
99
+
100
+ content_entry = {
101
+ "name": display_name,
102
+ "about": url,
103
+ "path": url
104
+ }
105
 
106
+ # Append to YAML
107
+ write_yaml(yaml_path, {"Contents": [content_entry]}, mode="a")
108
+
109
+ logging.info(f"URL entry added to YAML: {url}")
110
 
111
+ # Trigger retriever generation (if the embedder supports URLs)
112
+ await generate_retreivers(thread_id)
113
 
114
+ # Notify the AI about the URL upload
115
+ config = {"configurable": {"thread_id": thread_id}}
116
+ notification = HumanMessage(content=f"[SYSTEM NOTIFICATION]: User has uploaded a new URL: {url}. Please keep this in mind for future queries.")
117
+ await graph.aupdate_state(config, {"messages": [notification]})
118
+
119
+ return {"message": "URL uploaded successfully"}
120
 
121
  except Exception as e:
122
+ logging.error(f"URL upload failed: {e}")
123
+ return {"message": f"URL upload failed: {str(e)}"}
api/constants/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ DATA_FOLDER_PATH="api/public"
2
+ CONTENT_PERSISTENT_TIME=5
3
+ DB_FOLDER_PATH="db"
4
+
5
+ AVAILABLE_ANALYSIS=['pdf','txt','docs','docx','png','url']
6
+
7
+ USER_CONTENT_FILE_NAME="USER_CONTENT.yml"
8
+
api/main.py CHANGED
@@ -1,9 +1,6 @@
1
  from fastapi import FastAPI, Request
2
  from fastapi.responses import JSONResponse
3
- from api.MultiRag.routes import chat_route, uploader_route, pages_route
4
- from api.Web.routes import web_talk_routes
5
- from api.Blog.routes import page_route_blog,blog_router
6
- from api.Web.routes import page_route_web
7
  app = FastAPI()
8
 
9
  @app.middleware("http")
@@ -34,22 +31,25 @@ async def check_user_id(request: Request, call_next):
34
  return response
35
 
36
  app.include_router(pages_route.router)
37
- app.include_router(prefix="/chat", router=chat_route.router)
38
- app.include_router(prefix="/uploader", router=uploader_route.router)
 
 
 
 
39
 
40
 
41
 
42
 
 
 
 
43
 
44
- # -------------------- Web -------------------------------
45
- app.include_router(page_route_web.router)
46
- app.include_router(prefix="/web",router=web_talk_routes.router)
47
 
48
 
49
 
50
 
51
-
52
- # ------------ Blog --------------------
53
- app.include_router(page_route_blog.router)
54
- app.include_router(prefix="/blog",router=blog_router.router)
55
 
 
1
  from fastapi import FastAPI, Request
2
  from fastapi.responses import JSONResponse
3
+ from api.MultiRag.routes import chat_route, uploader_route, pages_route,get_all_thread_route,load_conversation_route,get_available_file_fomates_route, delete_thread_route
 
 
 
4
  app = FastAPI()
5
 
6
  @app.middleware("http")
 
31
  return response
32
 
33
  app.include_router(pages_route.router)
34
+ app.include_router(prefix="/api/v1/chat", router=chat_route.router)
35
+ app.include_router(prefix="/api/v1/uploader", router=uploader_route.router)
36
+ app.include_router(prefix="/api/v1/thread", router=get_all_thread_route.router)
37
+ app.include_router(prefix="/api/v1/thread", router=delete_thread_route.router)
38
+ app.include_router(prefix="/api/v1/conversation", router=load_conversation_route.router)
39
+ app.include_router(prefix="/api/v1/file_formats", router=get_available_file_fomates_route.router)
40
 
41
 
42
 
43
 
44
+ # # -------------------- Web -------------------------------
45
+ # app.include_router(page_route_web.router)
46
+ # app.include_router(prefix="/web",router=web_talk_routes.router)
47
 
 
 
 
48
 
49
 
50
 
51
 
52
+ # # ------------ Blog --------------------
53
+ # app.include_router(page_route_blog.router)
54
+ # app.include_router(prefix="/blog",router=blog_router.router)
 
55
 
docs copy/AI_Intro.pdf ADDED
Binary file (41.5 kB). View file
 
docs copy/google.docx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7eee211e7bc83917dde195f15c5458d6877dce8ba9fe080479c26a58e8da4c6a
3
+ size 3020407
docs copy/growing_ai_tools.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ THE LATEST GROWING AI MODELS (2024-2025)LARGE LANGUAGE MODELS (LLMs) & MULTIMODALGemini 1.5 Pro (Google): Known for its massive context window (up to 2 million tokens), allowing it to process entire libraries or long videos in one go.GPT-4o (OpenAI): An "omni" model designed for seamless real-time interaction across text, audio, and vision.Claude 3.5 Sonnet (Anthropic): Widely praised for its human-like reasoning, coding abilities, and "Artifacts" UI feature.Llama 3.1 (Meta): The leading open-source model series, providing high performance for developers to build private AI applications.DeepSeek-V3: An emerging powerhouse from China gaining traction for its efficiency and strong performance in logic and coding.VIDEO GENERATION MODELS (THE NEW FRONTIER)Sora (OpenAI): A world-simulating model that creates highly realistic 60-second videos.Veo (Google): Google's latest high-definition video generation model with cinematic control.Kling / Luma Dream Machine: Rapidly growing tools accessible to the public for generating high-quality AI video from text prompts.Runway Gen-3 Alpha: A professional-grade video model used by filmmakers and creators for precise motion control.IMAGE & CREATIVE MODELSMidjourney v6: Continues to lead in artistic quality and photorealism.Flux.1 (Black Forest Labs): A new open-weights model that has quickly become a favorite for its incredible detail and ability to render text inside images.DALL-E 3: Integrated into ChatGPT and Bing, focused on strict adherence to complex user prompts.SPECIALIZED & RESEARCH MODELSAlphaFold 3 (Google DeepMind): A revolutionary model for biology that predicts the structure and interactions of all life’s molecules.Grok-2 (xAI): Elon Musk’s AI model integrated into X (Twitter), designed for real-time information access and "edgy" personality.Trends to Watch:Small Language Models (SLMs): Models like Phi-3 or Gemma designed to run locally on phones and laptops.Agentic AI: Models designed not just to talk, but to use tools and complete multi-step tasks autonomously.
docs copy/lena.png ADDED

Git LFS Details

  • SHA256: ab1bac958e9772b0460c7dbf1100499bb83564e3ae8a03c9d08fbffeff4b33cd
  • Pointer size: 131 Bytes
  • Size of remote file: 198 kB
docs/AI_Intro.pdf ADDED
Binary file (41.5 kB). View file
 
docs/Optical_Recognition.png ADDED
docs/google.docx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7eee211e7bc83917dde195f15c5458d6877dce8ba9fe080479c26a58e8da4c6a
3
+ size 3020407
docs/growing_ai_tools.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ THE LATEST GROWING AI MODELS (2024-2025)LARGE LANGUAGE MODELS (LLMs) & MULTIMODALGemini 1.5 Pro (Google): Known for its massive context window (up to 2 million tokens), allowing it to process entire libraries or long videos in one go.GPT-4o (OpenAI): An "omni" model designed for seamless real-time interaction across text, audio, and vision.Claude 3.5 Sonnet (Anthropic): Widely praised for its human-like reasoning, coding abilities, and "Artifacts" UI feature.Llama 3.1 (Meta): The leading open-source model series, providing high performance for developers to build private AI applications.DeepSeek-V3: An emerging powerhouse from China gaining traction for its efficiency and strong performance in logic and coding.VIDEO GENERATION MODELS (THE NEW FRONTIER)Sora (OpenAI): A world-simulating model that creates highly realistic 60-second videos.Veo (Google): Google's latest high-definition video generation model with cinematic control.Kling / Luma Dream Machine: Rapidly growing tools accessible to the public for generating high-quality AI video from text prompts.Runway Gen-3 Alpha: A professional-grade video model used by filmmakers and creators for precise motion control.IMAGE & CREATIVE MODELSMidjourney v6: Continues to lead in artistic quality and photorealism.Flux.1 (Black Forest Labs): A new open-weights model that has quickly become a favorite for its incredible detail and ability to render text inside images.DALL-E 3: Integrated into ChatGPT and Bing, focused on strict adherence to complex user prompts.SPECIALIZED & RESEARCH MODELSAlphaFold 3 (Google DeepMind): A revolutionary model for biology that predicts the structure and interactions of all life’s molecules.Grok-2 (xAI): Elon Musk’s AI model integrated into X (Twitter), designed for real-time information access and "edgy" personality.Trends to Watch:Small Language Models (SLMs): Models like Phi-3 or Gemma designed to run locally on phones and laptops.Agentic AI: Models designed not just to talk, but to use tools and complete multi-step tasks autonomously.
docs/lena.png ADDED

Git LFS Details

  • SHA256: ab1bac958e9772b0460c7dbf1100499bb83564e3ae8a03c9d08fbffeff4b33cd
  • Pointer size: 131 Bytes
  • Size of remote file: 198 kB
exception/__init__.py CHANGED
@@ -1,35 +1,15 @@
1
  import sys
2
  import logging
3
 
4
- def error_message_detail(error:Exception,error_detail:sys)->str:
5
- _, _, exc_tb = error_detail.exc_info()
6
 
7
- # Walk the traceback to find the actual source of the error
8
- while exc_tb.tb_next is not None:
9
- exc_tb = exc_tb.tb_next
10
-
11
- # Get the file name where the exception occurred
12
- file_name = exc_tb.tb_frame.f_code.co_filename
13
-
14
- # Create a formatted error message string with file name, line number, and the actual error
15
- line_number = exc_tb.tb_lineno
16
- error_message = f"Error occurred in python script: [{file_name}] at line number [{line_number}]: {str(error)}"
17
-
18
- # Log the error for better tracking
19
- logging.error(error_message)
20
-
21
- return error_message
22
 
23
  class MyException(Exception):
24
- def __init__(self, error_message: str, error_detail: sys):
25
- # Call the base class constructor with the error message
26
  super().__init__(error_message)
27
 
28
- # Format the detailed error message using the error_message_detail function
29
- self.error_message = error_message_detail(error_message, error_detail)
30
-
31
  def __str__(self) -> str:
32
  """
33
  Returns the string representation of the error message.
34
  """
35
- return self.error_message
 
1
  import sys
2
  import logging
3
 
 
 
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  class MyException(Exception):
7
+ def __init__(self, error_message: str, error_detail: sys = None):
 
8
  super().__init__(error_message)
9
 
10
+ logging.exception(error_message)
 
 
11
  def __str__(self) -> str:
12
  """
13
  Returns the string representation of the error message.
14
  """
15
+ return self.args[0]
graph.png CHANGED
images/attention_mechanism.png ADDED

Git LFS Details

  • SHA256: 17dad1a48eebfa9ff975930cbee97d17ea1605ff8b2c7850c259e367718879f0
  • Pointer size: 132 Bytes
  • Size of remote file: 1.43 MB
images/common_mistakes.png ADDED

Git LFS Details

  • SHA256: 3457c2c085370f4c71d6f67b7597adf3b241a0af85feb2ccfff8d2cce94b5186
  • Pointer size: 132 Bytes
  • Size of remote file: 1.18 MB
images/conclusion.png ADDED

Git LFS Details

  • SHA256: 788c08ba04245231c0bddda32939b559430c0de2e0d343ce2620bb48f12cca5f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.33 MB
images/machine_learning_overview.png ADDED

Git LFS Details

  • SHA256: a00be7f008d70564c217d6f7ba655dadba24ed7eade1744606217890e392519e
  • Pointer size: 132 Bytes
  • Size of remote file: 1.33 MB
images/ml_common_mistakes.png ADDED

Git LFS Details

  • SHA256: 97e3f209373da00a8ed39e6a2087805abaee38ba3eacc90dd51ded063e7ac323
  • Pointer size: 131 Bytes
  • Size of remote file: 983 kB
images/ml_model_example.png ADDED

Git LFS Details

  • SHA256: 95f7f2cac211035a03ce26aec3b5048aacd71ea55cf67ecbe6d33c07d3270b22
  • Pointer size: 132 Bytes
  • Size of remote file: 1.2 MB
images/ml_workflow_diagram.png ADDED

Git LFS Details

  • SHA256: 975698aa25cb0e6982db6e35888093b74a4f066955c89382baa8eac9de7e287d
  • Pointer size: 131 Bytes
  • Size of remote file: 992 kB
images/transformer_application.png ADDED

Git LFS Details

  • SHA256: 6b340d8e5438de2ced43c98751d93f1d9f9f575238f192e50507b9c225daa25f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.34 MB
images/transformer_architecture.png ADDED

Git LFS Details

  • SHA256: 6001351eee461b54b71d89811090d2d8724843580676fa9afaca01ddf037466f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.42 MB
logs/05_02_2026_19_15_40.log.1 ADDED
The diff for this file is too large to render. See raw diff
 
logs/05_02_2026_19_15_40.log.2 ADDED
The diff for this file is too large to render. See raw diff
 
main.py CHANGED
@@ -20,6 +20,6 @@ if __name__ == "__main__":
20
  "main:app",
21
  host="0.0.0.0",
22
  port=7860,
23
- reload=False,
24
  reload_excludes=["db/*", "data/*", "logs/*", "vector_db/*", ".venv/*"],
25
  )
 
20
  "main:app",
21
  host="0.0.0.0",
22
  port=7860,
23
+ reload=True,
24
  reload_excludes=["db/*", "data/*", "logs/*", "vector_db/*", ".venv/*"],
25
  )
notebook/blip_image_captioning_large.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
pyproject.toml CHANGED
@@ -6,7 +6,9 @@ readme = "README.md"
6
  requires-python = ">=3.12"
7
  dependencies = [
8
  "bert-extractive-summarizer>=0.10.1",
 
9
  "dotenv>=0.9.9",
 
10
  "faiss-cpu>=1.13.2",
11
  "fastapi>=0.135.1",
12
  "keybert>=0.9.0",
@@ -16,13 +18,21 @@ dependencies = [
16
  "langchain-community>=0.4.1",
17
  "langchain-core>=1.2.17",
18
  "langchain-google-genai>=4.2.1",
 
19
  "langchain-huggingface>=1.2.1",
20
  "langchain-ollama>=1.0.1",
 
21
  "langgraph>=1.0.10",
 
 
 
22
  "pillow>=12.1.1",
 
23
  "python-multipart>=0.0.22",
24
  "sentence-transformers>=5.2.3",
25
  "transformers>=5.3.0",
26
  "unstructured>=0.21.5",
 
 
27
  "youtube-transcript-api>=1.2.4",
28
  ]
 
6
  requires-python = ">=3.12"
7
  dependencies = [
8
  "bert-extractive-summarizer>=0.10.1",
9
+ "docx2txt>=0.9",
10
  "dotenv>=0.9.9",
11
+ "easyocr>=1.7.2",
12
  "faiss-cpu>=1.13.2",
13
  "fastapi>=0.135.1",
14
  "keybert>=0.9.0",
 
18
  "langchain-community>=0.4.1",
19
  "langchain-core>=1.2.17",
20
  "langchain-google-genai>=4.2.1",
21
+ "langchain-groq>=1.1.2",
22
  "langchain-huggingface>=1.2.1",
23
  "langchain-ollama>=1.0.1",
24
+ "langchain-tavily>=0.2.18",
25
  "langgraph>=1.0.10",
26
+ "pdf2image>=1.17.0",
27
+ "pdfminer-six>=20260107",
28
+ "pi-heif>=1.3.0",
29
  "pillow>=12.1.1",
30
+ "pytesseract>=0.3.13",
31
  "python-multipart>=0.0.22",
32
  "sentence-transformers>=5.2.3",
33
  "transformers>=5.3.0",
34
  "unstructured>=0.21.5",
35
+ "unstructured-inference>=1.6.11",
36
+ "unstructured-pytesseract>=0.3.15",
37
  "youtube-transcript-api>=1.2.4",
38
  ]
src/MultiRag/components/__init__.py ADDED
File without changes
src/MultiRag/components/content_embedder.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from utils.asyncHandler import asyncHandler
3
+ from src.MultiRag.entity.config_entity import ContentEmbedderConfig
4
+ from src.MultiRag.utils.ingestion_utils import create_vector_store,create_retreiver
5
+ from src.MultiRag.constants import RETREIVER_DEFAULT_K
6
+ from src.MultiRag.entity.artifact_entity import RetrievalArtifact
7
+ from abc import ABC, abstractmethod
8
+ import logging
9
+
10
+
11
+ class Retreiver(ABC):
12
+ def __init__(self):
13
+ pass
14
+
15
+ @abstractmethod
16
+ async def retreive(self, query: str):
17
+ pass
18
+
19
+ class ContentRetreiver(Retreiver):
20
+ def __init__(self, retriever):
21
+ self.retriever = retriever
22
+
23
+ async def retreive(self, query: str):
24
+ return await self.retriever.ainvoke(query)
25
+ class ContentEmbedder:
26
+ def __init__(self, content_embedder_config: ContentEmbedderConfig):
27
+ self.content_embedder_config = content_embedder_config
28
+
29
+
30
+ @asyncHandler
31
+ async def embed_PDF(self):
32
+ vector_store = await create_vector_store(path=self.content_embedder_config.vector_store_path, docs=self.content_embedder_config.file_path)
33
+ return vector_store
34
+
35
+ @asyncHandler
36
+ async def create_retriever(self,vector_store, k:int = RETREIVER_DEFAULT_K)->RetrievalArtifact:
37
+ retriever = await create_retreiver(vectorstore=vector_store, k=k)
38
+ return retriever
39
+
40
+
41
+
42
+
43
+ @asyncHandler
44
+ async def embed_content(self)->RetrievalArtifact:
45
+ logging.info("Starting content embedding process...")
46
+
47
+ vector_store = await self.embed_PDF()
48
+ if vector_store is None:
49
+ logging.warning("No vector store created. Returning empty artifact.")
50
+ return RetrievalArtifact(retreivar=None)
51
+
52
+ logging.info("PDF embedding completed. Creating retriever...")
53
+ retriever = await self.create_retriever(vector_store=vector_store)
54
+
55
+ content_retriever = ContentRetreiver(retriever=retriever)
56
+ logging.info("Retriever created successfully.")
57
+ return RetrievalArtifact(retreivar=content_retriever)
58
+
src/MultiRag/components/run_graph.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from src.MultiRag.graph.builder import graph
2
+ from utils.asyncHandler import asyncHandler
3
+ from src.MultiRag.models.rag_model import State
4
+
5
+ import logging
6
+
7
+ class RunComponent:
8
+ def __init__(self):
9
+ pass
10
+
11
+
12
+ @asyncHandler
13
+ async def run(self,state:State, thread_id:str):
14
+ logging.info("Entered in the run_component")
15
+ logging.info(f"Running graph with thread_id: {thread_id}")
16
+
17
+ config = {"configurable": {"thread_id": thread_id}}
18
+ res=await graph.ainvoke(state, config)
19
+ logging.info(f"Graph execution completed")
20
+ return res
src/MultiRag/constants/__init__.py CHANGED
@@ -9,7 +9,7 @@ RETREIVER_DEFAULT_K=3
9
  LOGS_DIR="logs"
10
  LLM_MODEL_ID = "us.meta.llama3-3-70b-instruct-v1:0"
11
  LLM_REGION = "us-east-1"
12
-
13
 
14
  TOP_K_KEYWORDS=10
15
 
@@ -19,3 +19,18 @@ DB_FOLDER_PATH="db"
19
 
20
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  LOGS_DIR="logs"
10
  LLM_MODEL_ID = "us.meta.llama3-3-70b-instruct-v1:0"
11
  LLM_REGION = "us-east-1"
12
+ MODEL_NAME="llama-3.3-70b-versatile"
13
 
14
  TOP_K_KEYWORDS=10
15
 
 
19
 
20
 
21
 
22
+ AVAILABLE_ANALYSIS=['pdf','txt','docs','docx','png','url', 'search']
23
+
24
+
25
+
26
+ # ====================== DB =======================
27
+ DB_FOLDER_PATH="db"
28
+
29
+
30
+
31
+ # ====================== Tool ======================
32
+ SEARCH_MAX_RESULT=5
33
+ SEARCH_TOPIC='general'
34
+
35
+
36
+
src/MultiRag/entity/artifact_entity.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class RetrievalArtifact:
6
+ retreivar: object
src/MultiRag/entity/config_entity.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+
3
+
4
+
5
+ @dataclass
6
+ class ContentEmbedderConfig:
7
+ file_path: str
8
+ vector_store_path: str
9
+ file_types: str = "pdf"
src/MultiRag/graph/builder.py CHANGED
@@ -1,43 +1,136 @@
1
  import logging
2
  from langgraph.graph import START, END, StateGraph
3
  from src.MultiRag.models.rag_model import State
4
- from src.MultiRag.nodes.retreiver_check_node import retreiver_check
5
- from src.MultiRag.nodes.queries_generator import query_generator
6
- from src.MultiRag.nodes.chat_node import chat
7
- from src.MultiRag.nodes.content_summerizer import content_summerizer
 
8
  from src.MultiRag.memory import memory
9
- logging.info("Building state graph...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  graph_builder = StateGraph(State)
11
 
12
- # Add nodes
13
- graph_builder.add_node("retreiver_check", retreiver_check)
14
- graph_builder.add_node("content_summerizer", content_summerizer)
15
- graph_builder.add_node("qureis_builder", query_generator)
16
- graph_builder.add_node("chat", chat)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # Add edges
19
- graph_builder.add_edge(START, "retreiver_check")
20
- graph_builder.add_edge("retreiver_check", "content_summerizer")
21
- graph_builder.add_edge("content_summerizer", "qureis_builder")
22
- graph_builder.add_edge("qureis_builder", "chat")
23
- graph_builder.add_edge("chat", END)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  logging.info("Compiling graph...")
26
  graph = graph_builder.compile(checkpointer=memory)
27
 
28
- png_data = graph.get_graph().draw_mermaid_png()
29
- with open("graph.png", "wb") as f:
30
- f.write(png_data)
 
 
 
 
 
31
  logging.info("Graph compiled successfully.")
32
 
33
 
34
 
35
 
36
- ## ----------- Delete Conversion -----------------
37
  async def deleteThread(thread_id: str):
38
  try:
39
  cp = memory
40
- # Check if thread exists first
41
  state = await cp.aget_tuple(config={'configurable': {'thread_id': thread_id}})
42
  if state is None:
43
  logging.info(f"Thread {thread_id} not found, nothing to delete.")
@@ -49,3 +142,26 @@ async def deleteThread(thread_id: str):
49
  except Exception as e:
50
  logging.error(f"Error deleting thread {thread_id}: {e}")
51
  return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import logging
2
  from langgraph.graph import START, END, StateGraph
3
  from src.MultiRag.models.rag_model import State
4
+ from src.MultiRag.nodes.chat_node import chat_node
5
+ from src.MultiRag.graph.worker.builder import graph as worker_sub_graph
6
+ from src.MultiRag.nodes.orchestrator_node import orchestrator_node
7
+ from src.MultiRag.nodes.reducer_node import reducer_node
8
+ from langgraph.prebuilt import ToolNode
9
  from src.MultiRag.memory import memory
10
+ from langgraph.types import Send
11
+ from src.MultiRag.tools.web_search import WebSearch
12
+ from langchain.agents.middleware import ToolCallLimitMiddleware
13
+
14
+
15
+
16
+ tool_limiter = ToolCallLimitMiddleware(
17
+ run_limit=3,
18
+ exit_behavior="continue",
19
+ )
20
+
21
+ def enforce_tool_limit(state: State):
22
+ updates = tool_limiter.after_model(state, runtime=None)
23
+ return updates or {}
24
+
25
+
26
+ def after_tool_limit(state: State):
27
+ if state.get("jump_to") == "end":
28
+ return "chat_node"
29
+
30
+ last_message = state.get("messages", [])[-1]
31
+ if hasattr(last_message, "tool_calls") and last_message.tool_calls:
32
+ return "tools"
33
+
34
+ return "chat_node"
35
+ logging.info("Initializing StateGraph with State model...")
36
  graph_builder = StateGraph(State)
37
 
38
+ def fanout(state: State):
39
+ logging.info("Evaluating fanout condition from orchestrator_node")
40
+
41
+ plan = state.get("plan")
42
+ if not plan:
43
+ logging.warning("No plan found in state, defaulting to chat_node")
44
+ return "chat_node"
45
+
46
+ if not plan.use_worker:
47
+ logging.info("Orchestrator decided to bypass workers and go to chat")
48
+ return "chat_node"
49
+
50
+ tasks = plan.tasks or []
51
+ if not tasks:
52
+ logging.info("No tasks to execute, going to chat_node")
53
+ return "chat_node"
54
+
55
+ logging.info(f"Fanning out {len(tasks)} tasks to workers")
56
+
57
+ return [
58
+ Send(
59
+ "worker",
60
+ {
61
+ "plan_to_retrieve": task.instruction,
62
+ "file_type": task.file_type,
63
+ "file_path": task.file_path,
64
+ "thread_id": state.get("thread_id", "1"),
65
+ "worker_result": [],
66
+ },
67
+ )
68
+ for task in tasks
69
+ ]
70
+
71
+
72
+ def should_continue(state: State):
73
+ last_message=state.get("messages", [])[-1] if state.get("messages") else None
74
+ if last_message.tool_calls:
75
+ return "tool_limit"
76
+ return END
77
+ logging.info("Adding nodes to graph builder: orchestrator_node, chat_node, worker, reducer_node")
78
+ graph_builder.add_node("orchestrator_node", orchestrator_node)
79
+ graph_builder.add_node("chat_node", chat_node)
80
+ graph_builder.add_node("worker", worker_sub_graph)
81
+ graph_builder.add_node("reducer_node", reducer_node)
82
+ graph_builder.add_node("tools", ToolNode([WebSearch().search]))
83
+ graph_builder.add_node("tool_limit", enforce_tool_limit)
84
+
85
+ logging.info("Configuring graph edges and flow...")
86
+ graph_builder.add_edge(START, "orchestrator_node")
87
 
88
+ logging.info("Setting up conditional edges from orchestrator_node using fanout")
89
+ graph_builder.add_conditional_edges(
90
+ "orchestrator_node",
91
+ fanout,
92
+ {
93
+ "worker": "worker",
94
+ "chat_node": "chat_node"
95
+ }
96
+ )
97
+
98
+ logging.info("Connecting worker to reducer_node and then to chat_node")
99
+ graph_builder.add_edge("worker", "reducer_node")
100
+ graph_builder.add_edge("reducer_node", "chat_node")
101
+ graph_builder.add_conditional_edges(
102
+ "chat_node",
103
+ should_continue,
104
+ ["tool_limit", END]
105
+ )
106
+ # graph_builder.add_conditional_edges("chat_node", should_continue, ["tools", END])
107
+ graph_builder.add_conditional_edges(
108
+ "tool_limit",
109
+ after_tool_limit,
110
+ ["tools", "chat_node"]
111
+ )
112
+ graph_builder.add_edge("tools", "chat_node")
113
 
114
  logging.info("Compiling graph...")
115
  graph = graph_builder.compile(checkpointer=memory)
116
 
117
+ try:
118
+ png_data = graph.get_graph(xray=1).draw_mermaid_png()
119
+ with open("graph.png", "wb") as f:
120
+ f.write(png_data)
121
+ logging.info("Graph visualization saved to graph.png")
122
+ except Exception as e:
123
+ logging.warning(f"Could not generate graph visualization: {e}")
124
+
125
  logging.info("Graph compiled successfully.")
126
 
127
 
128
 
129
 
130
+
131
  async def deleteThread(thread_id: str):
132
  try:
133
  cp = memory
 
134
  state = await cp.aget_tuple(config={'configurable': {'thread_id': thread_id}})
135
  if state is None:
136
  logging.info(f"Thread {thread_id} not found, nothing to delete.")
 
142
  except Exception as e:
143
  logging.error(f"Error deleting thread {thread_id}: {e}")
144
  return False
145
+
146
+
147
+
148
+ async def retrieve_all_threads():
149
+ try:
150
+ cp=memory
151
+ all_threads = set()
152
+ for checkpoint in cp.list(None):
153
+ all_threads.add(checkpoint.config["configurable"]["thread_id"])
154
+ return list(all_threads)
155
+ except Exception as e:
156
+ logging.error(f"Error retrieving threads: {e}")
157
+ return []
158
+
159
+
160
+
161
+ async def load_conversation(thread_id):
162
+ try:
163
+ state = graph.get_state(config={'configurable': {'thread_id': thread_id}})
164
+ return state.values.get('messages', [])
165
+ except Exception as e:
166
+ logging.error(f"Error loading conversation: {e}")
167
+ return []
src/MultiRag/graph/worker/builder.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langgraph.graph import StateGraph, START, END
2
+ from src.MultiRag.models.worker_model import State
3
+ from src.MultiRag.nodes.worker import (
4
+ pdf,
5
+ txt,
6
+ docs,
7
+ image,
8
+ url,
9
+ decider,
10
+ search
11
+ )
12
+ from src.MultiRag.constants import AVAILABLE_ANALYSIS
13
+ import logging
14
+
15
+ logging.info("Building worker sub graph")
16
+
17
+ graph = StateGraph(State)
18
+
19
+ graph.add_node("decider", decider.decider_node)
20
+ graph.add_node("pdf", pdf.pdf_node)
21
+ graph.add_node("txt", txt.txt_node)
22
+ graph.add_node("docs", docs.docs_node)
23
+ graph.add_node("url", url.url_node)
24
+ graph.add_node("image", image.image_node)
25
+ graph.add_node("search", search.search_node)
26
+
27
+ def route_fn(state: State):
28
+ logging.info(f"Routing based on file_type: {state.file_type}")
29
+ if state.file_type in AVAILABLE_ANALYSIS:
30
+ return state.file_type
31
+ return "end"
32
+
33
+ graph.add_conditional_edges(
34
+ START,
35
+ route_fn,
36
+ {
37
+ "pdf": "pdf",
38
+ "txt": "txt",
39
+ "docs": "docs",
40
+ "png": "image",
41
+ "url": "url",
42
+ "search": "search",
43
+ "end":END
44
+ }
45
+ )
46
+
47
+ graph.add_edge("pdf", END)
48
+ graph.add_edge("txt", END)
49
+ graph.add_edge("docs", END)
50
+ graph.add_edge("url", END)
51
+ graph.add_edge("image", END)
52
+ graph.add_edge("search", END)
53
+
54
+ graph = graph.compile()
55
+
56
+ try:
57
+ with open("worker_sub_graph.png", "wb") as f:
58
+ f.write(graph.get_graph().draw_mermaid_png())
59
+ logging.info("Graph image saved successfully")
60
+ except Exception as e:
61
+ logging.error(f"Error saving graph: {e}")
62
+ raise Exception(e)
src/MultiRag/llm/llm_loader.py CHANGED
@@ -1,9 +1,14 @@
1
  from langchain_aws import ChatBedrockConverse
2
-
3
- from src.MultiRag.constants import LLM_MODEL_ID,LLM_REGION
4
  import logging
5
  llm = ChatBedrockConverse(
6
  model_id=LLM_MODEL_ID,
7
  region_name=LLM_REGION
8
  )
9
- logging.info(f"LLM initialized with model_id={LLM_MODEL_ID}, region_name={LLM_REGION}")
 
 
 
 
 
 
1
  from langchain_aws import ChatBedrockConverse
2
+ from langchain_groq import ChatGroq
3
+ from src.MultiRag.constants import LLM_MODEL_ID,LLM_REGION,MODEL_NAME
4
  import logging
5
  llm = ChatBedrockConverse(
6
  model_id=LLM_MODEL_ID,
7
  region_name=LLM_REGION
8
  )
9
+
10
+ # llm=ChatGroq(
11
+ # model=MODEL_NAME
12
+ # )
13
+ # logging.info(f"LLM initialized with model_id={LLM_MODEL_ID}, region_name={LLM_REGION}")
14
+ logging.info(f"LLM initialized with model_name:{MODEL_NAME}")