Jeevant10 commited on
Commit
a4538e5
Β·
1 Parent(s): 4c83c6e

all in one go

Browse files
Files changed (19) hide show
  1. .gitignore +21 -200
  2. Data/machine_learning.txt +15 -0
  3. Data/python_intro.txt +13 -0
  4. Dockerfile +64 -0
  5. LICENSE +1 -1
  6. README.md +1 -0
  7. app.py +130 -0
  8. config/config.yaml +76 -0
  9. main.py +33 -0
  10. params.yaml +43 -0
  11. requirements.txt +29 -0
  12. setup.py +54 -0
  13. src/__init__.py +0 -0
  14. src/data_loader.py +157 -0
  15. src/embedding.py +40 -0
  16. src/search.py +114 -0
  17. src/vectorstore.py +103 -0
  18. temp.py +40 -0
  19. test_updates.py +123 -0
.gitignore CHANGED
@@ -1,207 +1,28 @@
1
- # Byte-compiled / optimized / DLL files
2
- __pycache__/
3
- *.py[codz]
4
- *$py.class
5
-
6
- # C extensions
7
- *.so
8
-
9
- # Distribution / packaging
10
- .Python
11
- build/
12
- develop-eggs/
13
- dist/
14
- downloads/
15
- eggs/
16
- .eggs/
17
- lib/
18
- lib64/
19
- parts/
20
- sdist/
21
- var/
22
- wheels/
23
- share/python-wheels/
24
- *.egg-info/
25
- .installed.cfg
26
- *.egg
27
- MANIFEST
28
-
29
- # PyInstaller
30
- # Usually these files are written by a python script from a template
31
- # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
- *.manifest
33
- *.spec
34
-
35
- # Installer logs
36
- pip-log.txt
37
- pip-delete-this-directory.txt
38
-
39
- # Unit test / coverage reports
40
- htmlcov/
41
- .tox/
42
- .nox/
43
- .coverage
44
- .coverage.*
45
- .cache
46
- nosetests.xml
47
- coverage.xml
48
- *.cover
49
- *.py.cover
50
- .hypothesis/
51
- .pytest_cache/
52
- cover/
53
-
54
- # Translations
55
- *.mo
56
- *.pot
57
-
58
- # Django stuff:
59
- *.log
60
- local_settings.py
61
- db.sqlite3
62
- db.sqlite3-journal
63
-
64
- # Flask stuff:
65
- instance/
66
- .webassets-cache
67
-
68
- # Scrapy stuff:
69
- .scrapy
70
-
71
- # Sphinx documentation
72
- docs/_build/
73
-
74
- # PyBuilder
75
- .pybuilder/
76
- target/
77
-
78
- # Jupyter Notebook
79
- .ipynb_checkpoints
80
-
81
- # IPython
82
- profile_default/
83
- ipython_config.py
84
-
85
- # pyenv
86
- # For a library or package, you might want to ignore these files since the code is
87
- # intended to run in multiple environments; otherwise, check them in:
88
- # .python-version
89
-
90
- # pipenv
91
- # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
- # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
- # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
- # install all needed dependencies.
95
- #Pipfile.lock
96
-
97
- # UV
98
- # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
- # This is especially recommended for binary packages to ensure reproducibility, and is more
100
- # commonly ignored for libraries.
101
- #uv.lock
102
-
103
- # poetry
104
- # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
- # This is especially recommended for binary packages to ensure reproducibility, and is more
106
- # commonly ignored for libraries.
107
- # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
- #poetry.lock
109
- #poetry.toml
110
 
111
- # pdm
112
- # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
- # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
- # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
- #pdm.lock
116
- #pdm.toml
117
- .pdm-python
118
- .pdm-build/
119
 
120
- # pixi
121
- # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
- #pixi.lock
123
- # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
- # in the .venv directory. It is recommended not to include this directory in version control.
125
- .pixi
126
 
127
- # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
- __pypackages__/
129
-
130
- # Celery stuff
131
- celerybeat-schedule
132
- celerybeat.pid
133
-
134
- # SageMath parsed files
135
- *.sage.py
136
-
137
- # Environments
138
  .env
139
- .envrc
140
- .venv
141
- env/
142
- venv/
143
- ENV/
144
- env.bak/
145
- venv.bak/
146
-
147
- # Spyder project settings
148
- .spyderproject
149
- .spyproject
150
-
151
- # Rope project settings
152
- .ropeproject
153
-
154
- # mkdocs documentation
155
- /site
156
-
157
- # mypy
158
- .mypy_cache/
159
- .dmypy.json
160
- dmypy.json
161
-
162
- # Pyre type checker
163
- .pyre/
164
-
165
- # pytype static type analyzer
166
- .pytype/
167
-
168
- # Cython debug symbols
169
- cython_debug/
170
-
171
- # PyCharm
172
- # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
- # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
- # and can be added to the global gitignore or merged into this file. For a more nuclear
175
- # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
- #.idea/
177
-
178
- # Abstra
179
- # Abstra is an AI-powered process automation framework.
180
- # Ignore directories containing user credentials, local state, and settings.
181
- # Learn more at https://abstra.io/docs
182
- .abstra/
183
-
184
- # Visual Studio Code
185
- # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
- # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
- # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
- # you could uncomment the following to ignore the entire vscode folder
189
- # .vscode/
190
-
191
- # Ruff stuff:
192
- .ruff_cache/
193
 
194
- # PyPI configuration file
195
- .pypirc
 
196
 
197
- # Cursor
198
- # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
- # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
- # refer to https://docs.cursor.com/context/ignore-files
201
- .cursorignore
202
- .cursorindexingignore
203
 
204
- # Marimo
205
- marimo/_static/
206
- marimo/_lsp/
207
- __marimo__/
 
1
+ # gitignore template for LangChain products, e.g., LangGraph, LangSmith
2
+ # website: https://www.langchain.com/
3
+ # website: https://www.langchain.com/langgraph
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # LangGraph
6
+ .langgraph_api/
7
+
8
+ vector_store/
 
 
 
 
9
 
 
 
 
 
 
 
10
 
11
+ # ignore .env
 
 
 
 
 
 
 
 
 
 
12
  .env
13
+ __pycache__/
14
+ src/__pycache__/
15
+ # Environment
16
+ .env
17
+ .env.*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # Python cache
20
+ __pycache__/
21
+ *.pyc
22
 
23
+ # Vector DB
24
+ faiss_store/
25
+ vector_store/
 
 
 
26
 
27
+ # LangGraph
28
+ .langgraph_api/
 
 
Data/machine_learning.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Machine Learning Basics
2
+
3
+ Machine learning is a subset of artificial intelligence that enables systems to learn and improve
4
+ from experience without being explicitly programmed. It focuses on developing computer programs
5
+ that can access data and use it to learn for themselves.
6
+
7
+ Types of Machine Learning:
8
+ 1. Supervised Learning: Learning with labeled data
9
+ 2. Unsupervised Learning: Finding patterns in unlabeled data
10
+ 3. Reinforcement Learning: Learning through rewards and penalties
11
+
12
+ Applications include image recognition, speech processing, and recommendation systems
13
+
14
+
15
+
Data/python_intro.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Python Programming Introduction
2
+
3
+ Python is a high-level, interpreted programming language known for its simplicity and readability.
4
+ Created by Guido van Rossum and first released in 1991, Python has become one of the most popular
5
+ programming languages in the world.
6
+
7
+ Key Features:
8
+ - Easy to learn and use
9
+ - Extensive standard library
10
+ - Cross-platform compatibility
11
+ - Strong community support
12
+
13
+ Python is widely used in web development, data science, artificial intelligence, and automation.
Dockerfile ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modern Multi-stage Dockerfile for RAG System
2
+ FROM python:3.11-slim as builder
3
+
4
+ # Set environment variables
5
+ ENV PYTHONDONTWRITEBYTECODE=1 \
6
+ PYTHONUNBUFFERED=1 \
7
+ POETRY_NO_INTERACTION=1 \
8
+ POETRY_VENV_IN_PROJECT=1 \
9
+ POETRY_CACHE_DIR=/tmp/poetry_cache
10
+
11
+ # Install system dependencies
12
+ RUN apt-get update && apt-get install -y --no-install-recommends \
13
+ build-essential \
14
+ curl \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Install Python dependencies
18
+ WORKDIR /app
19
+ COPY requirements.txt .
20
+ RUN pip install --no-cache-dir --upgrade pip && \
21
+ pip install --no-cache-dir -r requirements.txt
22
+
23
+ # Production stage
24
+ FROM python:3.11-slim as production
25
+
26
+ # Set environment variables
27
+ ENV PYTHONDONTWRITEBYTECODE=1 \
28
+ PYTHONUNBUFFERED=1 \
29
+ PYTHONPATH="/app/src:$PYTHONPATH"
30
+
31
+ # Install runtime dependencies only
32
+ RUN apt-get update && apt-get install -y --no-install-recommends \
33
+ curl \
34
+ && rm -rf /var/lib/apt/lists/*
35
+
36
+ # Create non-root user
37
+ RUN groupadd -r appuser && useradd -r -g appuser appuser
38
+
39
+ # Copy Python packages from builder stage
40
+ COPY --from=builder /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.11/site-packages/
41
+ COPY --from=builder /usr/local/bin/ /usr/local/bin/
42
+
43
+ # Set working directory
44
+ WORKDIR /app
45
+
46
+ # Copy application code
47
+ COPY --chown=appuser:appuser . .
48
+
49
+ # Create necessary directories
50
+ RUN mkdir -p /app/faiss_store /app/data /app/logs && \
51
+ chown -R appuser:appuser /app
52
+
53
+ # Switch to non-root user
54
+ USER appuser
55
+
56
+ # Health check
57
+ HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
58
+ CMD curl -f http://localhost:8000/health || exit 1
59
+
60
+ # Expose port
61
+ EXPOSE 8000
62
+
63
+ # Default command
64
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
LICENSE CHANGED
@@ -1,6 +1,6 @@
1
  MIT License
2
 
3
- Copyright (c) 2026 Jeevant
4
 
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
  of this software and associated documentation files (the "Software"), to deal
 
1
  MIT License
2
 
3
+ Copyright (c) 2025 Jeevant
4
 
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
  of this software and associated documentation files (the "Software"), to deal
README.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # Langchain-Model
app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import List, Optional
3
+ from contextlib import asynccontextmanager
4
+
5
+ from fastapi import FastAPI, HTTPException
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from pydantic import BaseModel
8
+ from dotenv import load_dotenv
9
+
10
+ from src.search import RAGSearch, RetrievalResult
11
+
12
+ import uvicorn
13
+
14
+ load_dotenv()
15
+
16
+ # Global variable for RAG system
17
+ rag_search: Optional[RAGSearch] = None
18
+
19
+ @asynccontextmanager
20
+ async def lifespan(app: FastAPI):
21
+ # Startup
22
+ global rag_search
23
+ try:
24
+ persist_dir = os.getenv("PERSIST_DIR", "faiss_store")
25
+ embedding_model = os.getenv("EMBEDDING_MODEL", "all-MiniLM-L6-v2")
26
+ llm_model = os.getenv("LLM_MODEL", "llama-3.1-8b-instant")
27
+
28
+ rag_search = RAGSearch(
29
+ persist_dir=persist_dir,
30
+ embedding_model=embedding_model,
31
+ llm_model=llm_model,
32
+ )
33
+ print("[INFO] RAG system loaded successfully")
34
+ except Exception as e:
35
+ print(f"[ERROR] Failed to load RAG system: {e}")
36
+ raise
37
+
38
+ yield # Application runs here
39
+
40
+ # Shutdown (cleanup if needed)
41
+ print("[INFO] Shutting down RAG system")
42
+
43
+ # -------------------------
44
+ # FastAPI App
45
+ # -------------------------
46
+ app = FastAPI(
47
+ title="RAG Question Answering API",
48
+ description="FAISS + SentenceTransformers + Groq LLM",
49
+ version="2.0.0",
50
+ lifespan=lifespan
51
+ )
52
+
53
+ # CORS for React/Node clients
54
+ cors_origins = os.getenv("CORS_ORIGINS", "*").split(",")
55
+ app.add_middleware(
56
+ CORSMiddleware,
57
+ allow_origins=[o.strip() for o in cors_origins] if cors_origins else ["*"],
58
+ allow_credentials=True,
59
+ allow_methods=["*"],
60
+ allow_headers=["*"],
61
+ )
62
+
63
+ # -------------------------
64
+ # Request / Response Models
65
+ # -------------------------
66
+ class SourceItem(BaseModel):
67
+ index: int
68
+ distance: float
69
+ text: Optional[str] = None
70
+
71
+ class QueryRequest(BaseModel):
72
+ query: str
73
+ top_k: int = 3
74
+
75
+ class QueryResponse(BaseModel):
76
+ query: str
77
+ answer: str
78
+ sources: List[SourceItem]
79
+
80
+
81
+ # -------------------------
82
+ # Routes
83
+ # -------------------------
84
+ @app.get("/")
85
+ def root():
86
+ return {"message": "RAG API is running. Go to /docs"}
87
+
88
+ @app.get("/health")
89
+ def health():
90
+ if not rag_search:
91
+ return {"ready": False}
92
+ meta_count = len(rag_search.vectorstore.metadata) if rag_search.vectorstore else 0
93
+ return {
94
+ "ready": True,
95
+ "persist_dir": rag_search.vectorstore.persist_dir,
96
+ "documents_indexed": meta_count,
97
+ "embedding_model": rag_search.embedding_model,
98
+ "llm_model": rag_search.llm_model,
99
+ }
100
+
101
+ @app.post("/query", response_model=QueryResponse)
102
+ def query_rag(payload: QueryRequest):
103
+ if not rag_search:
104
+ raise HTTPException(status_code=503, detail="RAG system not ready")
105
+
106
+ try:
107
+ # Retrieve and summarize
108
+ sources: List[RetrievalResult] = rag_search.retrieve(payload.query, top_k=payload.top_k)
109
+ answer: str = rag_search.summarize(payload.query, sources)
110
+
111
+ # Map sources for response
112
+ resp_sources = [
113
+ SourceItem(index=s.index, distance=float(s.distance), text=s.text)
114
+ for s in sources
115
+ ]
116
+ return QueryResponse(query=payload.query, answer=answer, sources=resp_sources)
117
+ except Exception as e:
118
+ raise HTTPException(status_code=500, detail=str(e))
119
+
120
+
121
+ # -------------------------
122
+ # Run locally
123
+ # -------------------------
124
+ if __name__ == "__main__":
125
+ uvicorn.run(
126
+ "app:app",
127
+ host="0.0.0.0",
128
+ port=int(os.getenv("PORT", "8000")),
129
+ reload=True
130
+ )
config/config.yaml ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Environment-specific Configuration
2
+ environment: "development"
3
+
4
+ # Database and Storage Settings
5
+ storage:
6
+ faiss_store_path: "faiss_store"
7
+ backup_enabled: true
8
+ backup_frequency: "daily"
9
+
10
+ # Model Configuration
11
+ models:
12
+ embedding:
13
+ provider: "sentence-transformers"
14
+ model_name: "all-MiniLM-L6-v2"
15
+ device: "cpu" # or "cuda" if GPU available
16
+
17
+ llm:
18
+ provider: "groq"
19
+ model_name: "llama-3.1-8b-instant"
20
+ api_key_env: "GROQ_API_KEY"
21
+ parameters:
22
+ temperature: 0.1
23
+ max_tokens: 1000
24
+ top_p: 0.9
25
+
26
+ # Processing Settings
27
+ processing:
28
+ text_splitter:
29
+ type: "recursive_character"
30
+ chunk_size: 1000
31
+ chunk_overlap: 200
32
+ separators: ["\n\n", "\n", " ", ""]
33
+
34
+ batch_processing:
35
+ enabled: true
36
+ batch_size: 100
37
+
38
+ # API Settings
39
+ api:
40
+ server:
41
+ host: "0.0.0.0"
42
+ port: 8000
43
+ workers: 1
44
+ reload: true
45
+
46
+ security:
47
+ cors_enabled: true
48
+ cors_origins: ["*"]
49
+ rate_limiting: false
50
+
51
+ features:
52
+ health_check: true
53
+ metrics: false
54
+ documentation: true
55
+
56
+ # Logging and Monitoring
57
+ logging:
58
+ level: "INFO"
59
+ file_enabled: false
60
+ file_path: "logs/app.log"
61
+ console_enabled: true
62
+
63
+ monitoring:
64
+ metrics_enabled: false
65
+ health_checks: true
66
+
67
+ # Development Settings
68
+ development:
69
+ debug: true
70
+ hot_reload: true
71
+
72
+ # Production Settings (override in production)
73
+ production:
74
+ debug: false
75
+ workers: 4
76
+ logging_level: "WARNING"
main.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Simple CLI test runner for RAG retrieval + summarization.
3
+ Run: python main.py
4
+ """
5
+
6
+ from src.search import RAGSearch
7
+ import os
8
+
9
+ if __name__ == "__main__":
10
+ # Check for GROQ API key
11
+ if not os.getenv("GROQ_API_KEY"):
12
+ print("WARNING: GROQ_API_KEY not found in environment variables.")
13
+ print("Please set it in a .env file or environment variable to use the LLM features.")
14
+ print("You can still test document loading and embeddings without it.")
15
+
16
+ try:
17
+ rag_search = RAGSearch(
18
+ persist_dir="faiss_store",
19
+ embedding_model="all-MiniLM-L6-v2",
20
+ llm_model="llama-3.1-8b-instant"
21
+ )
22
+
23
+ query = "What is Database Management System?"
24
+ answer = rag_search.search_and_summarize(query=query, top_k=3)
25
+ print("Query:", query)
26
+ print("Answer:\n", answer)
27
+
28
+ except Exception as e:
29
+ print(f"Error: {e}")
30
+ print("\nTroubleshooting:")
31
+ print("1. Make sure you have documents in 'Research/data/', 'data/', or 'Data/' directory")
32
+ print("2. Set GROQ_API_KEY in your .env file")
33
+ print("3. Run: pip install -r requirements.txt")
params.yaml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # RAG System Configuration
2
+ rag:
3
+ embedding:
4
+ model: "all-MiniLM-L6-v2"
5
+ chunk_size: 1000
6
+ chunk_overlap: 200
7
+
8
+ vectorstore:
9
+ persist_dir: "faiss_store"
10
+ index_type: "faiss"
11
+
12
+ llm:
13
+ provider: "groq"
14
+ model: "llama-3.1-8b-instant"
15
+ temperature: 0.1
16
+ max_tokens: 1000
17
+
18
+ retrieval:
19
+ top_k: 5
20
+ similarity_threshold: 0.7
21
+
22
+ # API Configuration
23
+ api:
24
+ host: "0.0.0.0"
25
+ port: 8000
26
+ cors_origins: "*"
27
+ reload: true
28
+
29
+ # Data Configuration
30
+ data:
31
+ input_dir: "data"
32
+ supported_formats:
33
+ - "pdf"
34
+ - "txt"
35
+ - "csv"
36
+ - "xlsx"
37
+ - "docx"
38
+ - "json"
39
+
40
+ # Logging Configuration
41
+ logging:
42
+ level: "INFO"
43
+ format: "[%(levelname)s] %(asctime)s - %(name)s - %(message)s"
requirements.txt ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core LangChain packages
2
+ langchain>=0.3.0
3
+ langchain-core>=0.3.0
4
+ langchain-community>=0.3.0
5
+ langchain-text-splitters>=0.3.0
6
+ langchain-groq>=0.2.0
7
+
8
+ # Document processing
9
+ pypdf>=4.0.1
10
+ pymupdf>=1.24.0
11
+
12
+ # Embeddings and vector databases
13
+ sentence-transformers>=3.0.0
14
+ faiss-cpu>=1.8.0
15
+ chromadb>=0.5.0
16
+
17
+ # Search and indexing
18
+ typesense>=0.19.0
19
+
20
+ # Web framework and API
21
+ fastapi>=0.115.0
22
+ uvicorn[standard]>=0.32.0
23
+ pydantic>=2.9.0
24
+
25
+ # Environment and utilities
26
+ python-dotenv>=1.0.0
27
+
28
+ # Build tools (only if needed for development)
29
+ setuptools>=75.0.0
setup.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import setuptools
2
+
3
+ with open("README.md", "r", encoding="utf-8") as f:
4
+ long_description = f.read()
5
+
6
+ __version__ = "2.0.0"
7
+
8
+ REPO_NAME = "Langchain_RAG_System"
9
+ AUTHOR_USER_NAME = "jeevant"
10
+ SRC_REPO = "langchain_rag"
11
+ AUTHOR_EMAIL = "jeevantmudgil10@gmail.com"
12
+
13
+ setuptools.setup(
14
+ name=SRC_REPO,
15
+ version=__version__,
16
+ author=AUTHOR_USER_NAME,
17
+ author_email=AUTHOR_EMAIL,
18
+ description="A modern RAG system using LangChain, FAISS, and Groq LLM",
19
+ long_description=long_description,
20
+ long_description_content_type="text/markdown",
21
+ url=f"https://github.com/{AUTHOR_USER_NAME}/{REPO_NAME}",
22
+ project_urls={
23
+ "Bug Tracker": f"https://github.com/{AUTHOR_USER_NAME}/{REPO_NAME}/issues",
24
+ "Documentation": f"https://github.com/{AUTHOR_USER_NAME}/{REPO_NAME}#readme",
25
+ },
26
+ package_dir={"": "src"},
27
+ packages=setuptools.find_packages(where="src"),
28
+ python_requires=">=3.8",
29
+ install_requires=[
30
+ "langchain>=0.3.0",
31
+ "langchain-core>=0.3.0",
32
+ "langchain-community>=0.3.0",
33
+ "langchain-text-splitters>=0.3.0",
34
+ "langchain-groq>=0.2.0",
35
+ "fastapi>=0.115.0",
36
+ "uvicorn[standard]>=0.32.0",
37
+ "sentence-transformers>=3.0.0",
38
+ "faiss-cpu>=1.8.0",
39
+ "python-dotenv>=1.0.0",
40
+ ],
41
+ classifiers=[
42
+ "Development Status :: 4 - Beta",
43
+ "Intended Audience :: Developers",
44
+ "License :: OSI Approved :: MIT License",
45
+ "Operating System :: OS Independent",
46
+ "Programming Language :: Python :: 3",
47
+ "Programming Language :: Python :: 3.8",
48
+ "Programming Language :: Python :: 3.9",
49
+ "Programming Language :: Python :: 3.10",
50
+ "Programming Language :: Python :: 3.11",
51
+ "Topic :: Software Development :: Libraries :: Python Modules",
52
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
53
+ ],
54
+ )
src/__init__.py ADDED
File without changes
src/data_loader.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ from typing import List, Any
3
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader, CSVLoader
4
+ from langchain_community.document_loaders import Docx2txtLoader
5
+ from langchain_community.document_loaders.excel import UnstructuredExcelLoader
6
+ from langchain_community.document_loaders import JSONLoader
7
+
8
+
9
+ def load_all_documents(data_dir: str) -> List[Any] :
10
+
11
+ data_path = Path(data_dir).resolve()
12
+ print(f"[DEBUG] Data Path : {data_path}")
13
+ document = []
14
+
15
+
16
+ ## Pdf files
17
+
18
+ pdf_files = list(data_path.glob('**/*.pdf'))
19
+ print(f"[DEBUG] Found {len(pdf_files)} PDF files : { [str(f) for f in pdf_files] }")
20
+ for pdf_file in pdf_files:
21
+ print(f"[DEBUG] Loading PDF: {pdf_file}")
22
+ try:
23
+ loader = PyPDFLoader(str(pdf_file))
24
+ loaded = loader.load()
25
+ print(f"[DEBUG] Loaded {len(loaded)} PDF docs from {pdf_file}")
26
+ document.extend(loaded)
27
+ except Exception as e:
28
+ print(f"[ERROR] Failed to load PDF {pdf_file} : {e}")
29
+
30
+
31
+
32
+ ## TXT files
33
+
34
+ txt_files = list(data_path.glob('**/*.txt'))
35
+ print(f'[DEBUG] Founded {len(txt_files)} TXT files: {[str(f) for f in txt_files]} ')
36
+ for txt_file in txt_files:
37
+ print(f"[DEBUG] Loading TXT : {txt_file}")
38
+ try:
39
+ loader = TextLoader(str(txt_file), encoding="utf-8")
40
+ loaded = loader.load()
41
+ print(f"[DEBUG] Loaded {len(loaded)} TXT docs from {txt_file}")
42
+ document.extend(loaded)
43
+ except Exception as e:
44
+ print(f"[ERROR] failed to load TXT {txt_file} : {e}")
45
+
46
+
47
+
48
+ ## CSV files
49
+
50
+
51
+ csv_files = list(data_path.glob('**/*.csv'))
52
+ print(f"[DEBUG] Found {len((csv_files))} CSV files : {[str(f) for f in csv_files]}")
53
+ for csv_file in csv_files:
54
+ print(f"[DEBUG] Loading CSV : {csv_file}")
55
+ try :
56
+ loader = CSVLoader(str(csv_file))
57
+ loaded = loader.load()
58
+ print(f"[DEBUG] Loaded {len(loaded)} CSV docs from {csv_file}")
59
+ document.extend(loaded)
60
+ except Exception as e:
61
+ print(f"[ERROR] failed to load CSV {csv_file} : {e}")
62
+
63
+
64
+
65
+ ## Excel files
66
+
67
+
68
+ xlsx_files = list(data_path.glob('**/*.xlsx'))
69
+ print(f"[DEBUG] Found {len(xlsx_files)} xlsx files : {[str(f) for f in xlsx_files]}")
70
+ for xlsx_file in xlsx_files:
71
+ print(f"[DEBUG] Loading XLSX : {xlsx_file}")
72
+ try :
73
+ loader = UnstructuredExcelLoader(str(xlsx_file))
74
+ loaded = loader.load()
75
+ print(f"[DEBUG] Loaded {(len(loaded))} XLSX docs from {xlsx_file}")
76
+ document.extend(loaded)
77
+ except Exception as e :
78
+ print(f"[ERROR] failed to load Excel {xlsx_file} : {e} ")
79
+
80
+
81
+
82
+ ## Word file
83
+
84
+
85
+ word_files = list(data_path.glob('**/*.docx'))
86
+ print(f"[DEBUG] Found {len(word_files)} word files : {[str(f) for f in word_files]}")
87
+ for word_file in word_files:
88
+ print(f"[DEBUG] Loaded WORD : {word_file}")
89
+ try :
90
+ loader = Docx2txtLoader(str(word_file))
91
+ loaded = loader.load()
92
+ print(f"[DEBUG] Loaded {(len(loaded))} Word docs from {word_file}")
93
+ document.extend(loaded)
94
+ except Exception as e:
95
+ print(f"[ERROR] failed to load Word Document {word_file} : {e}")
96
+
97
+
98
+
99
+
100
+ ## JSON files
101
+
102
+
103
+ json_files = list(data_path.glob('**/*.json'))
104
+ print(f"[DEBUG] Found {(len(json_files))} json files : {[str(f) for f in json_files]}")
105
+ for json_file in json_files:
106
+ print(f"[DEBUG] Loaded JSON : {(str(json_file))}")
107
+ try:
108
+ loader = JSONLoader(
109
+ str(json_file),
110
+ jq_schema=".",
111
+ text_content=False
112
+ )
113
+ loaded = loader.load()
114
+ print(f"[DEBUG] Loaded {(len(loaded))} JSON from {json_file}")
115
+ document.extend(loaded)
116
+ except Exception as e:
117
+ print(f"[ERROR] Failed to load JSON file{json_file} : {e}")
118
+
119
+
120
+ print(f"[DEBUG] Total Loaded Documents : {len(document)}")
121
+ return document
122
+
123
+
124
+ if __name__ == '__main__':
125
+ docs = load_all_documents('Research/data/pdf')
126
+ print(f"Loaded {len(docs)} document.")
127
+ print("Example document:", docs[0] if docs else None)
128
+
129
+
130
+ # def process_all_pdf(pdf_directory):
131
+
132
+ # all_documents = []
133
+ # pdf_dir = Path(pdf_directory)
134
+
135
+ # pdf_files = list(pdf_dir.glob('**/*.pdf'))
136
+
137
+ # print(f"found {len(pdf_files)} PDF files to Process")
138
+
139
+ # for pdf_files in pdf_files:
140
+ # print(f"\npreprocessing : {pdf_files.name}")
141
+ # try:
142
+ # loader = PyPDFLoader(str(pdf_files))
143
+ # documents = loader.load()
144
+
145
+ # for doc in documents:
146
+ # doc.metadata['source_file'] = pdf_files.name
147
+ # doc.metadata['file_type'] = 'pdf'
148
+
149
+ # all_documents.extend(documents)
150
+ # print(f" Loaded {len(documents)} pages")
151
+ # except Exception as e:
152
+ # print(f" Error : {e}")
153
+
154
+ # print(f"\n Total documents loaded : {len(all_documents)}")
155
+ # return all_documents
156
+
157
+ # all_pdf_files = process_all_pdf('./data')
src/embedding.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Any, Optional
2
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
3
+ from sentence_transformers import SentenceTransformer
4
+ import numpy as np
5
+ from src.data_loader import load_all_documents
6
+
7
+ class EmbeddingPipeline:
8
+ def __init__(self, model_name: str = 'all-MiniLM-L6-v2', chunk_size: int = 1000, chunk_overlap: int = 200):
9
+ self.model_name = model_name
10
+ self.chunk_size = chunk_size
11
+ self.chunk_overlap = chunk_overlap
12
+ self.model = SentenceTransformer(model_name)
13
+ print(f"[INFO] Loaded embedding model: {model_name}")
14
+
15
+ def chunk_documents(self, documents: List[Any]) -> List[Any]:
16
+ splitter = RecursiveCharacterTextSplitter(
17
+ chunk_size=self.chunk_size,
18
+ chunk_overlap=self.chunk_overlap,
19
+ length_function=len,
20
+ separators=["\n\n", "\n", " ", ""]
21
+ )
22
+
23
+ chunks = splitter.split_documents(documents)
24
+ print(f"[INFO] Split {len(documents)} documents into {len(chunks)} chunks.")
25
+ return chunks
26
+
27
+ def embed_chunks(self, chunks: List[Any]) -> np.ndarray:
28
+ texts = [chunk.page_content for chunk in chunks]
29
+ print(f"[INFO] Generating embeddings for {len(texts)} chunks...")
30
+ embeddings = self.model.encode(texts, show_progress_bar = True)
31
+ print(f"[INFO] Embeddings shape : {embeddings.shape}")
32
+ return embeddings
33
+
34
+ if __name__ == "__main__":
35
+ docs = load_all_documents('Research/data/pdf')
36
+ emb_pipe = EmbeddingPipeline()
37
+ chunks = emb_pipe.chunk_documents(docs)
38
+ embeddings = emb_pipe.embed_chunks(chunks)
39
+ print(f"[INFO] Example embeddings:", embeddings[0] if len(embeddings) > 0 else None)
40
+
src/search.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dataclasses import dataclass
3
+ from typing import List, Optional
4
+
5
+ from dotenv import load_dotenv
6
+ from langchain_groq import ChatGroq
7
+ from langchain_core.messages import HumanMessage, SystemMessage
8
+
9
+ from src.vectorstore import FaissVectorStore
10
+
11
+ load_dotenv()
12
+
13
+ @dataclass
14
+ class RetrievalResult:
15
+ index: int
16
+ distance: float
17
+ text: Optional[str]
18
+
19
+ class RAGSearch:
20
+ def __init__(
21
+ self,
22
+ persist_dir: str = "faiss_store",
23
+ embedding_model: str = "all-MiniLM-L6-v2",
24
+ llm_model: str = "llama-3.1-8b-instant",
25
+ ):
26
+ # Vector store setup
27
+ self.vectorstore = FaissVectorStore(persist_dir=persist_dir, embedding_model=embedding_model)
28
+
29
+ faiss_path = os.path.join(persist_dir, "faiss.index")
30
+ meta_path = os.path.join(persist_dir, "metadata.pkl")
31
+
32
+ if not (os.path.exists(faiss_path) and os.path.exists(meta_path)):
33
+ # Build from local 'Research/data' directory if index doesn't exist
34
+ from src.data_loader import load_all_documents
35
+ # Try multiple possible data directories
36
+ data_dirs = ["Research/data", "data", "Data"]
37
+ docs = []
38
+
39
+ for data_dir in data_dirs:
40
+ if os.path.exists(data_dir):
41
+ print(f"[INFO] Checking for documents in: {data_dir}")
42
+ docs = load_all_documents(data_dir)
43
+ if docs:
44
+ print(f"[INFO] Found {len(docs)} documents in {data_dir}")
45
+ break
46
+
47
+ if not docs:
48
+ print("[WARNING] No documents found in any data directory. Vector store will be empty.")
49
+ print("[INFO] Please add documents to 'Research/data/', 'data/', or 'Data/' directory.")
50
+ # Create empty index for now
51
+ self.vectorstore.index = None
52
+ self.vectorstore.metadata = []
53
+ else:
54
+ self.vectorstore.build_from_documents(docs)
55
+ else:
56
+ self.vectorstore.load()
57
+
58
+ # LLM setup
59
+ groq_api_key = os.getenv("GROQ_API_KEY")
60
+ if not groq_api_key:
61
+ raise ValueError("GROQ_API_KEY missing in environment")
62
+ self.llm_model = llm_model
63
+ self.embedding_model = embedding_model
64
+ self.llm = ChatGroq(api_key=groq_api_key, model=llm_model, temperature=0.1)
65
+ print(f"[INFO] Groq LLM initialized: {llm_model}")
66
+
67
+ def retrieve(self, query: str, top_k: int = 5) -> List[RetrievalResult]:
68
+ # Check if vector store is empty
69
+ if self.vectorstore.index is None or len(self.vectorstore.metadata) == 0:
70
+ print("[WARNING] Vector store is empty. No documents to search.")
71
+ return []
72
+
73
+ results = self.vectorstore.query(query_text=query, top_k=top_k)
74
+ out: List[RetrievalResult] = []
75
+ for r in results:
76
+ text = r["metadata"]["texts"] if r.get("metadata") and r["metadata"].get("texts") else None
77
+ out.append(RetrievalResult(index=int(r["index"]), distance=float(r["distance"]), text=text))
78
+ return out
79
+
80
+ def summarize(self, query: str, retrieved: List[RetrievalResult]) -> str:
81
+ if not retrieved:
82
+ return "No documents are available in the vector store. Please add some documents to the data directory and restart the application."
83
+
84
+ texts = [r.text for r in retrieved if r.text]
85
+ context = "\n\n".join(texts)
86
+ if not context:
87
+ return "No relevant documents found for your query."
88
+
89
+ # Using proper message formatting for better LLM interaction
90
+ system_message = SystemMessage(content="You are a helpful assistant that summarizes documents based on queries. Provide clear, concise summaries with relevant quotes when appropriate.")
91
+ human_message = HumanMessage(content=f"""
92
+ Based on the following context, answer the query: '{query}'
93
+
94
+ Context:
95
+ {context}
96
+
97
+ Please provide a comprehensive answer based solely on the provided context. If you quote specific information, indicate it clearly.
98
+ """)
99
+
100
+ try:
101
+ response = self.llm.invoke([system_message, human_message])
102
+ return response.content
103
+ except Exception as e:
104
+ return f"Error generating response: {str(e)}. Please check your GROQ_API_KEY is set correctly."
105
+
106
+ def search_and_summarize(self, query: str, top_k: int = 5) -> str:
107
+ retrieved = self.retrieve(query, top_k=top_k)
108
+ return self.summarize(query, retrieved)
109
+
110
+ if __name__ == "__main__":
111
+ rag_search = RAGSearch()
112
+ query = "What is Database Management System?"
113
+ summary = rag_search.search_and_summarize(query, top_k=3)
114
+ print("Summary:", summary)
src/vectorstore.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import faiss
3
+ import numpy as np
4
+ import pickle
5
+ from typing import List, Any
6
+ from sentence_transformers import SentenceTransformer
7
+ from src.embedding import EmbeddingPipeline
8
+
9
+ class FaissVectorStore:
10
+ def __init__(
11
+ self,
12
+ persist_dir: str = "faiss_store",
13
+ embedding_model: str = "all-MiniLM-L6-v2",
14
+ chunk_size: int = 1000,
15
+ chunk_overlap: int = 200,
16
+ ):
17
+ self.persist_dir = persist_dir
18
+ os.makedirs(self.persist_dir, exist_ok=True)
19
+ self.index = None
20
+ self.metadata = []
21
+ self.embedding_model = embedding_model
22
+ self.model = SentenceTransformer(embedding_model)
23
+ self.chunk_size = chunk_size
24
+ self.chunk_overlap = chunk_overlap
25
+ print(f"[INFO] Loaded embedding model: {embedding_model}")
26
+
27
+ def build_from_documents(self, documents: List[Any]):
28
+ print(f"[INFO] Building vector store from {len(documents)} raw document(s)...")
29
+ emb_pipe = EmbeddingPipeline(
30
+ model_name=self.embedding_model,
31
+ chunk_size=self.chunk_size,
32
+ chunk_overlap=self.chunk_overlap,
33
+ )
34
+ chunks = emb_pipe.chunk_documents(documents)
35
+ embeddings = emb_pipe.embed_chunks(chunks)
36
+ metadatas = [{"texts": chunk.page_content} for chunk in chunks]
37
+ self.add_embeddings(np.array(embeddings).astype("float32"), metadatas)
38
+ self.save()
39
+ print(f"[INFO] Vector Store built and saved to {self.persist_dir}")
40
+
41
+ def add_embeddings(self, embeddings: np.ndarray, metadatas: List[Any] = None):
42
+ # Handle empty embeddings case
43
+ if embeddings.size == 0:
44
+ print("[WARNING] No embeddings to add. Vector store remains empty.")
45
+ return
46
+
47
+ dim = embeddings.shape[1]
48
+ if self.index is None:
49
+ self.index = faiss.IndexFlatL2(dim)
50
+ self.index.add(embeddings)
51
+ if metadatas:
52
+ self.metadata.extend(metadatas)
53
+ print(f"[INFO] Added {embeddings.shape[0]} vectors to Faiss Index.")
54
+
55
+ def save(self):
56
+ if self.index is None:
57
+ print("[WARNING] Cannot save: index is empty. Skipping save operation.")
58
+ return
59
+ faiss_path = os.path.join(self.persist_dir, "faiss.index")
60
+ meta_path = os.path.join(self.persist_dir, "metadata.pkl")
61
+ faiss.write_index(self.index, faiss_path)
62
+ with open(meta_path, "wb") as f:
63
+ pickle.dump(self.metadata, f)
64
+ print(f"[INFO] Saved Faiss index and metadata to {self.persist_dir}")
65
+
66
+ def load(self):
67
+ faiss_path = os.path.join(self.persist_dir, "faiss.index")
68
+ meta_path = os.path.join(self.persist_dir, "metadata.pkl")
69
+ if not (os.path.exists(faiss_path) and os.path.exists(meta_path)):
70
+ raise FileNotFoundError(f"Missing index/metadata in {self.persist_dir}. Build the store first.")
71
+ self.index = faiss.read_index(faiss_path)
72
+ with open(meta_path, "rb") as f:
73
+ self.metadata = pickle.load(f)
74
+ print(f"[INFO] Loaded Faiss Index and metadata from {self.persist_dir}")
75
+
76
+ def search(self, query_embeddings: np.ndarray, top_k: int = 5):
77
+ if self.index is None:
78
+ print("[WARNING] Vector store is empty. No results to return.")
79
+ return []
80
+
81
+ D, I = self.index.search(query_embeddings, top_k)
82
+ results = []
83
+ for idx, dist in zip(I[0], D[0]):
84
+ meta = self.metadata[idx] if idx < len(self.metadata) else None
85
+ results.append({"index": int(idx), "distance": float(dist), "metadata": meta})
86
+ return results
87
+
88
+ def query(self, query_text: str, top_k: int = 5):
89
+ if self.index is None:
90
+ print("[WARNING] Vector store is empty. No results to return.")
91
+ return []
92
+
93
+ print(f"[INFO] Querying vector store for: '{query_text}'")
94
+ query_emb = self.model.encode([query_text]).astype("float32")
95
+ return self.search(query_emb, top_k=top_k)
96
+
97
+ if __name__ == "__main__":
98
+ from src.data_loader import load_all_documents
99
+ docs = load_all_documents("data")
100
+ store = FaissVectorStore("faiss_store")
101
+ store.build_from_documents(docs)
102
+ store.load()
103
+ print(store.query("What is Database Management System?", top_k=3))
temp.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import logging
4
+
5
+ logging.basicConfig(level=logging.INFO, format='[%(asctime)s]:(message)s:')
6
+
7
+ project_name = "testSummarizer"
8
+
9
+ list_of_files = [
10
+ ".github/workflows/.gitkeep",
11
+ f"src/data_loader.py",
12
+ f"src/embedding.py",
13
+ f"src/__init__.py",
14
+ f"src/search.py",
15
+ f"src/vectorstore.py",
16
+ "config/config.yaml",
17
+ "params.yaml",
18
+ "app.py",
19
+ "main.py",
20
+ "Dockerfile",
21
+ "setup.py",
22
+ "research/trails.ipynb"
23
+
24
+ ]
25
+
26
+ for filepath in list_of_files:
27
+ filepath = Path(filepath)
28
+ filedir, filename = os.path.split(filepath)
29
+
30
+ if filedir != "":
31
+ os.makedirs(filedir, exist_ok=True)
32
+ logging.info(f"Creating directry:{filepath} for the file {filepath}")
33
+
34
+ if (not os.path.exists(filepath)) or (os.path.getsize(filepath) == 0):
35
+ with open(filepath, 'w') as f:
36
+ pass
37
+ logging.info(f"Creating empty file: {filepath}")
38
+
39
+ else :
40
+ logging.info(f"{filename} is already exists.")
test_updates.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script to verify the updated Langchain RAG system works correctly.
4
+ """
5
+ import sys
6
+ import os
7
+ import traceback
8
+
9
+ def test_imports():
10
+ """Test that all required imports work."""
11
+ print("Testing imports...")
12
+ try:
13
+ # Core imports
14
+ from src.search import RAGSearch, RetrievalResult
15
+ from src.embedding import EmbeddingPipeline
16
+ from src.vectorstore import FaissVectorStore
17
+ from src.data_loader import load_all_documents
18
+
19
+ # External dependencies
20
+ import langchain
21
+ import langchain_core
22
+ import langchain_community
23
+ import langchain_text_splitters
24
+ import sentence_transformers
25
+ import faiss
26
+ import pydantic
27
+ import fastapi
28
+ import uvicorn
29
+
30
+ print("βœ… All imports successful!")
31
+
32
+ # Print versions
33
+ print(f"\nPackage versions:")
34
+ print(f"- LangChain: {langchain.__version__}")
35
+ print(f"- LangChain Core: {langchain_core.__version__}")
36
+ print(f"- Sentence Transformers: {sentence_transformers.__version__}")
37
+ print(f"- Pydantic: {pydantic.__version__}")
38
+ print(f"- FastAPI: {fastapi.__version__}")
39
+
40
+ return True
41
+ except Exception as e:
42
+ print(f"❌ Import failed: {e}")
43
+ traceback.print_exc()
44
+ return False
45
+
46
+ def test_basic_functionality():
47
+ """Test basic functionality without requiring API keys."""
48
+ print("\nTesting basic functionality...")
49
+ try:
50
+ from src.embedding import EmbeddingPipeline
51
+ from src.vectorstore import FaissVectorStore
52
+
53
+ # Test embedding pipeline initialization
54
+ embedding_pipeline = EmbeddingPipeline()
55
+ print("βœ… Embedding pipeline initialized")
56
+
57
+ # Test vector store initialization
58
+ vector_store = FaissVectorStore(persist_dir="test_store", embedding_model="all-MiniLM-L6-v2")
59
+ print("βœ… Vector store initialized")
60
+
61
+ return True
62
+ except Exception as e:
63
+ print(f"❌ Basic functionality test failed: {e}")
64
+ traceback.print_exc()
65
+ return False
66
+
67
+ def test_config_loading():
68
+ """Test configuration file loading."""
69
+ print("\nTesting configuration loading...")
70
+ try:
71
+ import yaml
72
+
73
+ # Test params.yaml
74
+ if os.path.exists("params.yaml"):
75
+ with open("params.yaml", "r") as f:
76
+ params = yaml.safe_load(f)
77
+ print("βœ… params.yaml loaded successfully")
78
+
79
+ # Test config.yaml
80
+ if os.path.exists("config/config.yaml"):
81
+ with open("config/config.yaml", "r") as f:
82
+ config = yaml.safe_load(f)
83
+ print("βœ… config/config.yaml loaded successfully")
84
+
85
+ return True
86
+ except Exception as e:
87
+ print(f"❌ Config loading failed: {e}")
88
+ return False
89
+
90
+ def main():
91
+ """Run all tests."""
92
+ print("=== Updated Langchain RAG System Test ===\n")
93
+
94
+ all_passed = True
95
+
96
+ # Test imports
97
+ if not test_imports():
98
+ all_passed = False
99
+
100
+ # Test basic functionality
101
+ if not test_basic_functionality():
102
+ all_passed = False
103
+
104
+ # Test config loading
105
+ if not test_config_loading():
106
+ all_passed = False
107
+
108
+ print(f"\n{'='*50}")
109
+ if all_passed:
110
+ print("πŸŽ‰ All tests passed! Your project is successfully updated!")
111
+ print("\nNext steps:")
112
+ print("1. Set your GROQ_API_KEY in a .env file")
113
+ print("2. Place your documents in the 'data' directory")
114
+ print("3. Run: python main.py")
115
+ print("4. Or start the API: python app.py")
116
+ else:
117
+ print("❌ Some tests failed. Please check the errors above.")
118
+ return 1
119
+
120
+ return 0
121
+
122
+ if __name__ == "__main__":
123
+ sys.exit(main())