VashuTheGreat commited on
Commit
1f725d8
·
0 Parent(s):

Clean commit without images

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +70 -0
  2. .env.example +15 -0
  3. .gitattributes +35 -0
  4. .gitignore +208 -0
  5. .python-version +1 -0
  6. Dockerfile +17 -0
  7. LICENSE +21 -0
  8. README.md +134 -0
  9. api/Blog/models/models.py +3 -0
  10. api/Blog/routes/blog_router.py +123 -0
  11. api/Blog/routes/page_route_blog.py +16 -0
  12. api/MultiRag/routes/chat_route.py +44 -0
  13. api/MultiRag/routes/pages_route.py +31 -0
  14. api/MultiRag/routes/uploader_route.py +73 -0
  15. api/Web/routes/page_route_web.py +16 -0
  16. api/Web/routes/web_talk_routes.py +13 -0
  17. api/main.py +55 -0
  18. configs/rag_config.yaml +0 -0
  19. constants/__init__.py +1 -0
  20. exception/__init__.py +35 -0
  21. graph.png +0 -0
  22. logger/__init__.py +65 -0
  23. main.py +25 -0
  24. notebook/README.md +3 -0
  25. notebook/agent.ipynb +0 -0
  26. notebook/image_placeHolder.ipynb +376 -0
  27. notebook/rag.ipynb +379 -0
  28. notebook/understanding_self_attention.md +120 -0
  29. notebook/understanding_self_attention_in_deep_learning.md +105 -0
  30. notebook/web.ipynb +255 -0
  31. pyproject.toml +28 -0
  32. requirements.txt +1 -0
  33. results/Attention is All You Need Paper Explained.md +53 -0
  34. results/Introduction to Machine Learning.md +75 -0
  35. setup_folder.py +71 -0
  36. src/Blog/components/image_generation.py +16 -0
  37. src/Blog/components/taivily_search.py +35 -0
  38. src/Blog/constants/__init__.py +2 -0
  39. src/Blog/graph/Compile_graph.py +74 -0
  40. src/Blog/graph/graphs/reducer_subgraph.py +22 -0
  41. src/Blog/graph/nodes/fanout_node.py +23 -0
  42. src/Blog/graph/nodes/orchaster_node.py +40 -0
  43. src/Blog/graph/nodes/reducer_node.py +36 -0
  44. src/Blog/graph/nodes/reducer_sub_node.py +66 -0
  45. src/Blog/graph/nodes/router_node.py +102 -0
  46. src/Blog/graph/nodes/search_node.py +61 -0
  47. src/Blog/graph/nodes/worker_node.py +65 -0
  48. src/Blog/llm/__init__.py +13 -0
  49. src/Blog/models/Evidence_model.py +13 -0
  50. src/Blog/models/ImageSpec_model.py +20 -0
.dockerignore ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Usually these files are written by a python script from a template
2
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
3
+ # Byte-compiled / optimized / DLL files
4
+ # C extensions
5
+ # Distribution / packaging
6
+ # Django stuff:
7
+ # Installer logs
8
+ # Project specific ignores
9
+ # PyBuilder
10
+ # PyInstaller
11
+ # Sphinx documentation
12
+ # Translations
13
+ # Unit test / coverage reports
14
+ *$py.class
15
+ *,cover
16
+ *.csv
17
+ *.egg
18
+ *.egg-info/
19
+ *.log
20
+ *.manifest
21
+ *.mo
22
+ *.pkl
23
+ *.pot
24
+ *.py[cod]
25
+ *.pyc
26
+ *.so
27
+ *.spec
28
+ .Python
29
+ .cache
30
+ .coverage
31
+ .coverage.*
32
+ .dockerignore
33
+ .eggs/
34
+ .env
35
+ .git
36
+ .gitignore
37
+ .idea/
38
+ .installed.cfg
39
+ .python-version
40
+ .tox/
41
+ .venv
42
+ .vscode/
43
+ __pycache__/
44
+ artifact/
45
+ artifacts/
46
+ build/
47
+ coverage.xml
48
+ develop-eggs/
49
+ dist/
50
+ docs/_build/
51
+ downloads/
52
+ eggs/
53
+ env/
54
+ housepricepredictor.egg-info/
55
+ htmlcov/
56
+ lib/
57
+ lib64/
58
+ logs/
59
+ mlruns/
60
+ myenv/
61
+ nosetests.xml
62
+ notebook/
63
+ parts/
64
+ pip-delete-this-directory.txt
65
+ pip-log.txt
66
+ sdist/
67
+ target/
68
+ uv.lock
69
+ var/
70
+ venv/
.env.example ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GROQ_API_KEY=
2
+ AWS_ACCESS_KEY_ID=
3
+ AWS_SECRET_ACCESS_KEY=
4
+ AWS_DEFAULT_REGION=
5
+ HUGGINGFACEHUB_ACCESS_TOKEN=
6
+ PORT=
7
+
8
+
9
+
10
+
11
+ TAVILY_API_KEY=
12
+ Gemini_API_Key=
13
+ HF_TOKEN=
14
+
15
+ APP_API_KEY=
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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__/
208
+ images/
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.12
Dockerfile ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Copy dependency files first (better caching)
6
+ COPY requirements.txt pyproject.toml ./
7
+
8
+ # Install dependencies
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # Copy rest of the application
12
+ COPY . .
13
+
14
+ EXPOSE 7860
15
+
16
+ # Run FastAPI app
17
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vansh Sharma
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
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>
api/Blog/models/models.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from pydantic import BaseModel
2
+ class BlogDeleteRequest(BaseModel):
3
+ data: dict
api/Blog/routes/blog_router.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import os
3
+ import sys
4
+ import logging
5
+ import zipfile
6
+ import io
7
+ from fastapi import HTTPException, WebSocket, WebSocketDisconnect
8
+ from fastapi.responses import StreamingResponse
9
+ from fastapi.staticfiles import StaticFiles
10
+ from api.Blog.models.models import BlogDeleteRequest
11
+ import fastapi
12
+ import uvicorn as uv
13
+
14
+ PROJECT_ROOT = os.getcwd()
15
+ if PROJECT_ROOT not in sys.path:
16
+ sys.path.append(PROJECT_ROOT)
17
+
18
+ from logger import *
19
+ from src.Blog.graph.Compile_graph import run
20
+ from src.Blog.utils.blog_utils import delete_blog_content
21
+
22
+ router=fastapi.APIRouter()
23
+ os.makedirs("images", exist_ok=True)
24
+ os.makedirs("results", exist_ok=True)
25
+
26
+ # Mount static files
27
+ router.mount("/images", StaticFiles(directory="images"), name="images")
28
+ router.mount("/results", StaticFiles(directory="results"), name="results")
29
+
30
+
31
+
32
+
33
+
34
+ @router.get("/blogs")
35
+ async def list_blogs():
36
+ results_dir = "results"
37
+ if not os.path.exists(results_dir):
38
+ return []
39
+ blogs = [f[:-3] for f in os.listdir(results_dir) if f.endswith(".md") and f != "README.md"]
40
+ return blogs
41
+
42
+ @router.get("/blog/{title}")
43
+ async def get_blog(title: str):
44
+ file_path = os.path.join("results", f"{title}.md")
45
+ if not os.path.exists(file_path):
46
+ raise HTTPException(status_code=404, detail="Blog not found")
47
+ with open(file_path, "r", encoding="utf-8") as f:
48
+ content = f.read()
49
+ return {"title": title, "content": content}
50
+
51
+ from fastapi.encoders import jsonable_encoder
52
+
53
+ @router.websocket("/ws/generate_blog")
54
+ async def generate_blog_ws(websocket: WebSocket):
55
+ await websocket.accept()
56
+ try:
57
+ data = await websocket.receive_json()
58
+ topic = data.get("topic")
59
+ if not topic:
60
+ await websocket.send_json({"error": "Topic is required"})
61
+ await websocket.close()
62
+ return
63
+
64
+ logging.info(f"WebSocket: Starting blog generation for topic: {topic}")
65
+
66
+ async for step in run(topic):
67
+ serializable_step = jsonable_encoder(step)
68
+ await websocket.send_json(serializable_step)
69
+
70
+ await websocket.send_json({"status": "completed"})
71
+ except WebSocketDisconnect:
72
+ logging.info("WebSocket disconnected")
73
+ except Exception as e:
74
+ logging.error(f"WebSocket error: {str(e)}")
75
+ await websocket.send_json({"error": str(e)})
76
+ finally:
77
+ try:
78
+ await websocket.close()
79
+ except:
80
+ pass
81
+
82
+ @router.delete("/delete_blog")
83
+ async def delete_blog(request: BlogDeleteRequest):
84
+ success = delete_blog_content(request.data)
85
+ if success:
86
+ return {"message": "Blog and associated images deleted successfully"}
87
+ else:
88
+ raise HTTPException(status_code=404, detail="Blog not found or could not be deleted")
89
+
90
+ @router.get("/download_blog/{title}")
91
+ async def download_blog(title: str):
92
+ md_path = os.path.join("results", f"{title}.md")
93
+ if not os.path.exists(md_path):
94
+ raise HTTPException(status_code=404, detail="Blog not found")
95
+
96
+ with open(md_path, "r", encoding="utf-8") as f:
97
+ content = f.read()
98
+
99
+ # Find images
100
+ image_pattern = r"!\[.*?\]\(\.\./images/(.*?)\)"
101
+ image_filenames = re.findall(image_pattern, content)
102
+
103
+ # Create zip in memory
104
+ zip_buffer = io.BytesIO()
105
+ with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
106
+ # Add markdown file
107
+ zip_file.writestr(f"{title}.md", content)
108
+
109
+ # Add images
110
+ for img_name in image_filenames:
111
+ img_path = os.path.join("images", img_name)
112
+ if os.path.exists(img_path):
113
+ zip_file.write(img_path, os.path.join("images", img_name))
114
+
115
+ zip_buffer.seek(0)
116
+ return StreamingResponse(
117
+ zip_buffer,
118
+ media_type="application/x-zip-compressed",
119
+ headers={"Content-Disposition": f"attachment; filename={title}.zip"}
120
+ )
121
+
122
+ if __name__ == "__main__":
123
+ uv.run("app:app", host="0.0.0.0", port=8000, reload=False)
api/Blog/routes/page_route_blog.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import fastapi
3
+ from fastapi.templating import Jinja2Templates
4
+ from fastapi import Request
5
+
6
+ router = fastapi.APIRouter()
7
+ templates = Jinja2Templates(directory="templates")
8
+
9
+ _APP_USER_ID = os.getenv("APP_API_KEY", "")
10
+
11
+ @router.get("/blog")
12
+ async def blog_root(request: Request):
13
+ return templates.TemplateResponse(
14
+ name="blog.html",
15
+ context={"request": request, "app_user_id": _APP_USER_ID}
16
+ )
api/MultiRag/routes/chat_route.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
33
+
34
+ @router.post("/chat")
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"}
api/MultiRag/routes/pages_route.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import fastapi
3
+ from fastapi import Request
4
+ from fastapi.templating import Jinja2Templates
5
+
6
+ router = fastapi.APIRouter()
7
+ 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
+ )
api/MultiRag/routes/uploader_route.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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"}
api/Web/routes/page_route_web.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import fastapi
3
+ from fastapi import Request
4
+ from fastapi.templating import Jinja2Templates
5
+
6
+ router = fastapi.APIRouter()
7
+ templates = Jinja2Templates(directory="templates")
8
+
9
+ _APP_USER_ID = os.getenv("APP_API_KEY", "")
10
+
11
+ @router.get("/web")
12
+ async def web_page(request: Request):
13
+ return templates.TemplateResponse(
14
+ name="web.html",
15
+ context={"request": request, "app_user_id": _APP_USER_ID}
16
+ )
api/Web/routes/web_talk_routes.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fastapi
2
+ from src.Web.graph.builder import graph
3
+ router=fastapi.APIRouter()
4
+
5
+ @router.post("/web_summerizer")
6
+ async def web_sum(url:str):
7
+
8
+ res=await graph.ainvoke({
9
+ "url":url
10
+ })
11
+ print(res)
12
+
13
+ return {"data": res.get("llm_response", "Error generating response")}
api/main.py ADDED
@@ -0,0 +1,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
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")
10
+ async def check_user_id(request: Request, call_next):
11
+ # Skip middleware for static files and page routes to allow initial connection
12
+ public_routes = [
13
+ "/",
14
+ "/chat",
15
+ "/web",
16
+ "/blog",
17
+ "/docs",
18
+ "/redoc",
19
+ "/openapi.json",
20
+ "/favicon.ico",
21
+ ]
22
+ if request.url.path.startswith("/static") or request.url.path.startswith("/blog/images") or request.url.path in public_routes:
23
+ return await call_next(request)
24
+
25
+ user_id = request.headers.get("user_id") or request.query_params.get("user_id")
26
+
27
+ if not user_id:
28
+ return JSONResponse(
29
+ status_code=401,
30
+ content={"message": "user_id header missing"}
31
+ )
32
+
33
+ response = await call_next(request)
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
+
configs/rag_config.yaml ADDED
File without changes
constants/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ LOGS_DIR="logs"
exception/__init__.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
graph.png ADDED
logger/__init__.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from logging.handlers import RotatingFileHandler
4
+ from datetime import datetime
5
+ from constants import LOGS_DIR
6
+
7
+ # Log File Configuration
8
+ LOG_FILE = f"{datetime.now().strftime('%m_%d_%Y_%H_%M_%S')}.log"
9
+ MAX_FOLDER_SIZE = 2 * 1024 * 1024 # 2MB
10
+ MAX_LOG_SIZE = 5 * 1024 * 1024 # This is still needed for RotatingFileHandler if a single run exceeds 5MB
11
+
12
+ log_file_path = os.path.join(LOGS_DIR, LOG_FILE)
13
+
14
+ def cleanup_logs():
15
+ """Removes oldest log files if the total folder size exceeds MAX_FOLDER_SIZE."""
16
+ if not os.path.exists(LOGS_DIR):
17
+ return
18
+
19
+ files = [os.path.join(LOGS_DIR, f) for f in os.listdir(LOGS_DIR) if f.endswith(".log")]
20
+ files.sort(key=os.path.getmtime) # Sort by modification time (oldest first)
21
+
22
+ total_size = sum(os.path.getsize(f) for f in files)
23
+
24
+ while total_size > MAX_FOLDER_SIZE and files:
25
+ oldest_file = files.pop(0)
26
+ file_size = os.path.getsize(oldest_file)
27
+ try:
28
+ os.remove(oldest_file)
29
+ total_size -= file_size
30
+ logging.info(f"Deleted old log file: {oldest_file}")
31
+ except Exception as e:
32
+ logging.error(f"Error deleting old log file {oldest_file}: {e}")
33
+ break
34
+
35
+ def configure_logger():
36
+ # Ensure logs directory exists
37
+ os.makedirs(LOGS_DIR, exist_ok=True)
38
+
39
+ # Run cleanup before creating new log
40
+ cleanup_logs()
41
+
42
+ logger = logging.getLogger()
43
+ logger.setLevel(logging.DEBUG)
44
+
45
+ formatter = logging.Formatter("[ %(asctime)s ] %(name)s - %(levelname)s - %(message)s")
46
+
47
+ # File Handler
48
+ file_handler = RotatingFileHandler(log_file_path, maxBytes=MAX_LOG_SIZE, backupCount=3)
49
+ file_handler.setFormatter(formatter)
50
+ file_handler.setLevel(logging.DEBUG)
51
+
52
+ # Console Handler
53
+ console_handler = logging.StreamHandler()
54
+ console_handler.setFormatter(formatter)
55
+ console_handler.setLevel(logging.INFO)
56
+
57
+ # Avoid duplicate handlers if the logger is re-initialized
58
+ logger.handlers.clear()
59
+
60
+ logger.addHandler(file_handler)
61
+ logger.addHandler(console_handler)
62
+
63
+ # Automatically configure on import
64
+ configure_logger()
65
+ logging.info(f"Logger initialized. Logging to {log_file_path}")
main.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ load_dotenv() # ← must be FIRST so os.getenv works in all imported modules
3
+
4
+ import uvicorn as uv
5
+ from api.main import app
6
+ from logger import *
7
+ from fastapi.staticfiles import StaticFiles
8
+ from src.MultiRag.constants import DATA_FOLDER_PATH, DB_FOLDER_PATH
9
+ import os
10
+ app.mount("/static", StaticFiles(directory="static"), name="static")
11
+ os.makedirs("images", exist_ok=True)
12
+ app.mount("/blog/images", StaticFiles(directory="images"), name="blog_images")
13
+ # app.mount("/images", StaticFiles(directory="images"), name="blog_images")
14
+
15
+ os.makedirs(DATA_FOLDER_PATH, exist_ok=True)
16
+ os.makedirs(DB_FOLDER_PATH, exist_ok=True)
17
+
18
+ if __name__ == "__main__":
19
+ uv.run(
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
+ )
notebook/README.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # Notebooks
2
+
3
+ Here goes the notebooks used for research and development.
notebook/agent.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
notebook/image_placeHolder.ipynb ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 6,
6
+ "id": "0b9ffe5f",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "from pydantic import BaseModel,Field\n",
11
+ "from typing import Literal,List\n"
12
+ ]
13
+ },
14
+ {
15
+ "cell_type": "code",
16
+ "execution_count": 4,
17
+ "id": "cd7bb64d",
18
+ "metadata": {},
19
+ "outputs": [
20
+ {
21
+ "data": {
22
+ "text/plain": [
23
+ "True"
24
+ ]
25
+ },
26
+ "execution_count": 4,
27
+ "metadata": {},
28
+ "output_type": "execute_result"
29
+ }
30
+ ],
31
+ "source": [
32
+ "from dotenv import load_dotenv\n",
33
+ "load_dotenv()"
34
+ ]
35
+ },
36
+ {
37
+ "cell_type": "code",
38
+ "execution_count": 7,
39
+ "id": "dd8207ef",
40
+ "metadata": {},
41
+ "outputs": [],
42
+ "source": [
43
+ "class ImageSpec(BaseModel):\n",
44
+ " placeholder:str=Field(...,description=\"e.g. [[IMAGE_1]]\")\n",
45
+ " filename:str=Field(...,description=\"Save under images/, e.g. qkv_flow.png\")\n",
46
+ " prompt:str=Field(...,description=\"Prompt to send to the image model\")\n",
47
+ " size:Literal[\"1024x1024\",\"1024x1536\",\"1536x1024\"]=\"1025x1024\"\n",
48
+ " quality: Literal[\"low\", \"medium\", \"high\"] = \"medium\"\n",
49
+ "\n",
50
+ "\n",
51
+ "class GlobalImagePlan(BaseModel):\n",
52
+ " md_with_placeholders:str\n",
53
+ " images:List[ImageSpec]=Field(default_factory=list)"
54
+ ]
55
+ },
56
+ {
57
+ "cell_type": "code",
58
+ "execution_count": 8,
59
+ "id": "63f25031",
60
+ "metadata": {},
61
+ "outputs": [],
62
+ "source": [
63
+ "from langchain_aws import ChatBedrockConverse\n"
64
+ ]
65
+ },
66
+ {
67
+ "cell_type": "code",
68
+ "execution_count": 9,
69
+ "id": "255a2613",
70
+ "metadata": {},
71
+ "outputs": [],
72
+ "source": [
73
+ "LLM_MODEL_ID = \"us.meta.llama3-3-70b-instruct-v1:0\"\n",
74
+ "LLM_REGION = \"us-east-1\"\n",
75
+ "llm = ChatBedrockConverse(\n",
76
+ " model_id=LLM_MODEL_ID,\n",
77
+ " region_name=LLM_REGION\n",
78
+ ")"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": 11,
84
+ "id": "849c528a",
85
+ "metadata": {},
86
+ "outputs": [],
87
+ "source": [
88
+ "placehonder=\"\"\"You are an expert technical blog image planning assistant.\n",
89
+ "\n",
90
+ "Your job is to analyze a Markdown blog post and generate a structured image plan.\n",
91
+ "\n",
92
+ "You MUST return output strictly matching the Pydantic model `GlobalImagePlan`.\n",
93
+ "\n",
94
+ "-----------------------------------------\n",
95
+ "YOUR TASK\n",
96
+ "-----------------------------------------\n",
97
+ "\n",
98
+ "You will receive a Markdown blog as input.\n",
99
+ "\n",
100
+ "You must:\n",
101
+ "\n",
102
+ "1. Keep the Markdown EXACTLY the same.\n",
103
+ "2. DO NOT rewrite, summarize, improve, or modify any text.\n",
104
+ "3. DO NOT remove or change any formatting.\n",
105
+ "4. Only insert image placeholders where images would improve clarity.\n",
106
+ "\n",
107
+ "-----------------------------------------\n",
108
+ "WHERE TO INSERT IMAGES\n",
109
+ "-----------------------------------------\n",
110
+ "\n",
111
+ "Insert placeholders only:\n",
112
+ "- After major section headings (## or ###)\n",
113
+ "- After complex explanations\n",
114
+ "- After architecture descriptions\n",
115
+ "- After workflows\n",
116
+ "- After comparisons\n",
117
+ "- Where diagrams would help understanding\n",
118
+ "- Where visual examples would add clarity\n",
119
+ "\n",
120
+ "DO NOT:\n",
121
+ "- Add images randomly\n",
122
+ "- Add too many images\n",
123
+ "- Break code blocks\n",
124
+ "- Insert placeholders inside code blocks\n",
125
+ "- Modify existing content\n",
126
+ "\n",
127
+ "-----------------------------------------\n",
128
+ "PLACEHOLDER FORMAT\n",
129
+ "-----------------------------------------\n",
130
+ "\n",
131
+ "Use this exact format:\n",
132
+ "\n",
133
+ "[[IMAGE_1]]\n",
134
+ "[[IMAGE_2]]\n",
135
+ "[[IMAGE_3]]\n",
136
+ "\n",
137
+ "Number them sequentially.\n",
138
+ "\n",
139
+ "-----------------------------------------\n",
140
+ "IMAGE SPEC RULES\n",
141
+ "-----------------------------------------\n",
142
+ "\n",
143
+ "For each placeholder generate an ImageSpec with:\n",
144
+ "\n",
145
+ "- placeholder: exact placeholder string (e.g. [[IMAGE_1]])\n",
146
+ "- filename: save under images/ directory (example: images/attention_flow.png)\n",
147
+ "- prompt: highly detailed image generation prompt describing what the image should show\n",
148
+ "- size: choose one of:\n",
149
+ " - 1024x1024 (for square diagrams)\n",
150
+ " - 1536x1024 (for wide architecture diagrams)\n",
151
+ " - 1024x1536 (for vertical infographics)\n",
152
+ "- quality: \"medium\" unless diagram is complex → use \"high\"\n",
153
+ "\n",
154
+ "The prompt must:\n",
155
+ "- Be descriptive\n",
156
+ "- Mention diagram style\n",
157
+ "- Mention labels\n",
158
+ "- Mention arrows and flow\n",
159
+ "- Mention clean white background\n",
160
+ "- Mention professional technical illustration style\n",
161
+ "\n",
162
+ "-----------------------------------------\n",
163
+ "IMPORTANT OUTPUT RULES\n",
164
+ "-----------------------------------------\n",
165
+ "\n",
166
+ "You MUST return ONLY a valid GlobalImagePlan JSON object.\n",
167
+ "\n",
168
+ "Do NOT include:\n",
169
+ "- Explanations\n",
170
+ "- Extra text\n",
171
+ "- Markdown fences\n",
172
+ "- Comments\n",
173
+ "- Any text before or after the JSON\n",
174
+ "\n",
175
+ "-----------------------------------------\n",
176
+ "OUTPUT FORMAT\n",
177
+ "-----------------------------------------\n",
178
+ "\n",
179
+ "{\n",
180
+ " \"md_with_placeholders\": \"...full markdown with inserted placeholders...\",\n",
181
+ " \"images\": [\n",
182
+ " {\n",
183
+ " \"placeholder\": \"[[IMAGE_1]]\",\n",
184
+ " \"filename\": \"images/example.png\",\n",
185
+ " \"prompt\": \"Detailed image generation prompt...\",\n",
186
+ " \"size\": \"1536x1024\",\n",
187
+ " \"quality\": \"medium\"\n",
188
+ " }\n",
189
+ " ]\n",
190
+ "}\"\"\""
191
+ ]
192
+ },
193
+ {
194
+ "cell_type": "code",
195
+ "execution_count": 14,
196
+ "id": "332e03d8",
197
+ "metadata": {},
198
+ "outputs": [],
199
+ "source": [
200
+ "from langchain.messages import SystemMessage,HumanMessage"
201
+ ]
202
+ },
203
+ {
204
+ "cell_type": "code",
205
+ "execution_count": 16,
206
+ "id": "1a7a4167",
207
+ "metadata": {},
208
+ "outputs": [],
209
+ "source": [
210
+ "markdown=\"\"\"\n",
211
+ "# State of Multimodal LLMs in 2026\n",
212
+ "\n",
213
+ "## Introduction to Multimodal LLMs\n",
214
+ "Recent developments in multimodal LLMs have shown significant progress, with models now capable of processing and generating multiple forms of data, such as text, images, and audio [Not found in provided sources]. \n",
215
+ "* Multimodal LLMs have been applied to various tasks, including visual question answering, image captioning, and text-to-image synthesis.\n",
216
+ "* The impact of multimodal LLMs can be seen in industries like healthcare, education, and entertainment, where they are used for applications such as medical image analysis, interactive learning systems, and content creation [Not found in provided sources].\n",
217
+ "* Despite the advancements, key challenges in multimodal LLM research remain, including the need for large-scale datasets, improved model architectures, and better evaluation metrics [Not found in provided sources].\n",
218
+ "\n",
219
+ "## Recent Advances in Multimodal LLMs\n",
220
+ "Recent breakthroughs in multimodal LLM architecture have led to significant improvements in the field. \n",
221
+ "* Multimodal transformers, which combine visual and textual features, have shown promising results in tasks such as visual question answering and image-text retrieval [Not found in provided sources].\n",
222
+ "* The use of multimodal attention mechanisms has also been explored, allowing models to focus on specific parts of the input data [Not found in provided sources].\n",
223
+ "\n",
224
+ "Multimodal LLMs play a crucial role in both computer vision and natural language processing. \n",
225
+ "They can be used to analyze and understand visual data, such as images and videos, and generate text-based descriptions or summaries.\n",
226
+ "In natural language processing, multimodal LLMs can be used to improve language understanding and generation tasks, such as machine translation and text summarization.\n",
227
+ "\n",
228
+ "The potential applications of multimodal LLMs in healthcare are vast. \n",
229
+ "They can be used to analyze medical images, such as X-rays and MRIs, and generate text-based diagnoses or recommendations.\n",
230
+ "Additionally, multimodal LLMs can be used to develop personalized treatment plans and improve patient outcomes [Not found in provided sources].\n",
231
+ "Overall, the latest advancements in multimodal LLMs have the potential to revolutionize various fields, including healthcare, and improve the way we interact with and understand visual and textual data.\n",
232
+ "\n",
233
+ "## Challenges and Limitations\n",
234
+ "The development of multimodal LLMs has made significant progress, but there are still several challenges and limitations that need to be addressed. \n",
235
+ "* The limitations of current multimodal LLM models include their inability to fully understand the nuances of human communication, such as sarcasm, idioms, and figurative language [Not found in provided sources].\n",
236
+ "* Training and deploying multimodal LLMs pose significant challenges, including the need for large amounts of diverse and high-quality training data, as well as the requirement for significant computational resources [Not found in provided sources].\n",
237
+ "* Further research is needed to improve the performance and robustness of multimodal LLMs, particularly in areas such as common sense reasoning, emotional intelligence, and adaptability to new contexts and domains [Not found in provided sources]. \n",
238
+ "Overall, addressing these challenges and limitations will be crucial to unlocking the full potential of multimodal LLMs and achieving more effective and engaging human-computer interactions.\n",
239
+ "\n",
240
+ "## Future Directions\n",
241
+ "The future of multimodal LLMs holds great promise, with potential applications in areas such as [virtual assistants](Not found in provided sources) and [human-computer interaction](Not found in provided sources). \n",
242
+ "* Multimodal LLMs may be used to improve accessibility and user experience in various domains.\n",
243
+ "* The role of multimodal LLMs in shaping the future of AI is significant, as they can enable more natural and intuitive interactions between humans and machines.\n",
244
+ "* Continued research in multimodal LLMs is crucial to overcome current limitations and unlock their full potential, driving innovation and progress in the field of AI [Not found in provided sources].\n",
245
+ "\n",
246
+ "\"\"\""
247
+ ]
248
+ },
249
+ {
250
+ "cell_type": "code",
251
+ "execution_count": 18,
252
+ "id": "796739f7",
253
+ "metadata": {},
254
+ "outputs": [
255
+ {
256
+ "data": {
257
+ "text/plain": [
258
+ "GlobalImagePlan(md_with_placeholders='# State of Multimodal LLMs in 2026\\n## Introduction to Multimodal LLMs\\nRecent developments in multimodal LLMs have shown significant progress, with models now capable of processing and generating multiple forms of data, such as text, images, and audio [Not found in provided sources]. \\n* Multimodal LLMs have been applied to various tasks, including visual question answering, image captioning, and text-to-image synthesis.\\n* The impact of multimodal LLMs can be seen in industries like healthcare, education, and entertainment, where they are used for applications such as medical image analysis, interactive learning systems, and content creation [Not found in provided sources].\\n* Despite the advancements, key challenges in multimodal LLM research remain, including the need for large-scale datasets, improved model architectures, and better evaluation metrics [Not found in provided sources].\\n[[IMAGE_1]]\\n## Recent Advances in Multimodal LLMs\\nRecent breakthroughs in multimodal LLM architecture have led to significant improvements in the field. \\n* Multimodal transformers, which combine visual and textual features, have shown promising results in tasks such as visual question answering and image-text retrieval [Not found in provided sources].\\n* The use of multimodal attention mechanisms has also been explored, allowing models to focus on specific parts of the input data [Not found in provided sources].\\n[[IMAGE_2]]\\nMultimodal LLMs play a crucial role in both computer vision and natural language processing. \\nThey can be used to analyze and understand visual data, such as images and videos, and generate text-based descriptions or summaries.\\nIn natural language processing, multimodal LLMs can be used to improve language understanding and generation tasks, such as machine translation and text summarization.\\n[[IMAGE_3]]\\nThe potential applications of multimodal LLMs in healthcare are vast. \\nThey can be used to analyze medical images, such as X-rays and MRIs, and generate text-based diagnoses or recommendations.\\nAdditionally, multimodal LLMs can be used to develop personalized treatment plans and improve patient outcomes [Not found in provided sources].\\nOverall, the latest advancements in multimodal LLMs have the potential to revolutionize various fields, including healthcare, and improve the way we interact with and understand visual and textual data.\\n[[IMAGE_4]]\\n## Challenges and Limitations\\nThe development of multimodal LLMs has made significant progress, but there are still several challenges and limitations that need to be addressed. \\n* The limitations of current multimodal LLM models include their inability to fully understand the nuances of human communication, such as sarcasm, idioms, and figurative language [Not found in provided sources].\\n* Training and deploying multimodal LLMs pose significant challenges, including the need for large amounts of diverse and high-quality training data, as well as the requirement for significant computational resources [Not found in provided sources].\\n* Further research is needed to improve the performance and robustness of multimodal LLMs, particularly in areas such as common sense reasoning, emotional intelligence, and adaptability to new contexts and domains [Not found in provided sources]. \\nOverall, addressing these challenges and limitations will be crucial to unlocking the full potential of multimodal LLMs and achieving more effective and engaging human-computer interactions.\\n[[IMAGE_5]]\\n## Future Directions\\nThe future of multimodal LLMs holds great promise, with potential applications in areas such as [virtual assistants](Not found in provided sources) and [human-computer interaction](Not found in provided sources). \\n* Multimodal LLMs may be used to improve accessibility and user experience in various domains.\\n* The role of multimodal LLMs in shaping the future of AI is significant, as they can enable more natural and intuitive interactions between humans and machines.\\n* Continued research in multimodal LLMs is crucial to overcome current limitations and unlock their full potential, driving innovation and progress in the field of AI [Not found in provided sources].\\n[[IMAGE_6]]', images=[ImageSpec(placeholder='[[IMAGE_1]]', filename='images/multimodal_llm_architecture.png', prompt='A diagram showing the architecture of a multimodal LLM, with visual and textual features combined, and labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1536x1024', quality='medium'), ImageSpec(placeholder='[[IMAGE_2]]', filename='images/multimodal_transformers.png', prompt='An illustration of multimodal transformers, with visual and textual features combined, and labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1024x1024', quality='medium'), ImageSpec(placeholder='[[IMAGE_3]]', filename='images/multimodal_llm_applications.png', prompt='A diagram showing the various applications of multimodal LLMs, including computer vision and natural language processing, with labels and arrows indicating the relationships between the different applications, on a clean white background, in a professional technical illustration style', size='1024x1536', quality='medium'), ImageSpec(placeholder='[[IMAGE_4]]', filename='images/multimodal_llm_healthcare.png', prompt='An illustration of the potential applications of multimodal LLMs in healthcare, including medical image analysis and personalized treatment plans, with labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1536x1024', quality='medium'), ImageSpec(placeholder='[[IMAGE_5]]', filename='images/multimodal_llm_challenges.png', prompt='A diagram showing the challenges and limitations of multimodal LLMs, including the need for large-scale datasets and improved model architectures, with labels and arrows indicating the relationships between the different challenges, on a clean white background, in a professional technical illustration style', size='1024x1024', quality='medium'), ImageSpec(placeholder='[[IMAGE_6]]', filename='images/multimodal_llm_future.png', prompt='An illustration of the future directions of multimodal LLMs, including potential applications in virtual assistants and human-computer interaction, with labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1024x1536', quality='medium')])"
259
+ ]
260
+ },
261
+ "execution_count": 18,
262
+ "metadata": {},
263
+ "output_type": "execute_result"
264
+ }
265
+ ],
266
+ "source": [
267
+ "output=llm.with_structured_output(GlobalImagePlan)\\\n",
268
+ ".invoke(\n",
269
+ " [\n",
270
+ " SystemMessage(content=placehonder),\n",
271
+ " HumanMessage(content=markdown)\n",
272
+ " ]\n",
273
+ ")\n",
274
+ "\n",
275
+ "output"
276
+ ]
277
+ },
278
+ {
279
+ "cell_type": "code",
280
+ "execution_count": 20,
281
+ "id": "0e44ffd5",
282
+ "metadata": {},
283
+ "outputs": [
284
+ {
285
+ "data": {
286
+ "text/plain": [
287
+ "'# State of Multimodal LLMs in 2026\\n## Introduction to Multimodal LLMs\\nRecent developments in multimodal LLMs have shown significant progress, with models now capable of processing and generating multiple forms of data, such as text, images, and audio [Not found in provided sources]. \\n* Multimodal LLMs have been applied to various tasks, including visual question answering, image captioning, and text-to-image synthesis.\\n* The impact of multimodal LLMs can be seen in industries like healthcare, education, and entertainment, where they are used for applications such as medical image analysis, interactive learning systems, and content creation [Not found in provided sources].\\n* Despite the advancements, key challenges in multimodal LLM research remain, including the need for large-scale datasets, improved model architectures, and better evaluation metrics [Not found in provided sources].\\n[[IMAGE_1]]\\n## Recent Advances in Multimodal LLMs\\nRecent breakthroughs in multimodal LLM architecture have led to significant improvements in the field. \\n* Multimodal transformers, which combine visual and textual features, have shown promising results in tasks such as visual question answering and image-text retrieval [Not found in provided sources].\\n* The use of multimodal attention mechanisms has also been explored, allowing models to focus on specific parts of the input data [Not found in provided sources].\\n[[IMAGE_2]]\\nMultimodal LLMs play a crucial role in both computer vision and natural language processing. \\nThey can be used to analyze and understand visual data, such as images and videos, and generate text-based descriptions or summaries.\\nIn natural language processing, multimodal LLMs can be used to improve language understanding and generation tasks, such as machine translation and text summarization.\\n[[IMAGE_3]]\\nThe potential applications of multimodal LLMs in healthcare are vast. \\nThey can be used to analyze medical images, such as X-rays and MRIs, and generate text-based diagnoses or recommendations.\\nAdditionally, multimodal LLMs can be used to develop personalized treatment plans and improve patient outcomes [Not found in provided sources].\\nOverall, the latest advancements in multimodal LLMs have the potential to revolutionize various fields, including healthcare, and improve the way we interact with and understand visual and textual data.\\n[[IMAGE_4]]\\n## Challenges and Limitations\\nThe development of multimodal LLMs has made significant progress, but there are still several challenges and limitations that need to be addressed. \\n* The limitations of current multimodal LLM models include their inability to fully understand the nuances of human communication, such as sarcasm, idioms, and figurative language [Not found in provided sources].\\n* Training and deploying multimodal LLMs pose significant challenges, including the need for large amounts of diverse and high-quality training data, as well as the requirement for significant computational resources [Not found in provided sources].\\n* Further research is needed to improve the performance and robustness of multimodal LLMs, particularly in areas such as common sense reasoning, emotional intelligence, and adaptability to new contexts and domains [Not found in provided sources]. \\nOverall, addressing these challenges and limitations will be crucial to unlocking the full potential of multimodal LLMs and achieving more effective and engaging human-computer interactions.\\n[[IMAGE_5]]\\n## Future Directions\\nThe future of multimodal LLMs holds great promise, with potential applications in areas such as [virtual assistants](Not found in provided sources) and [human-computer interaction](Not found in provided sources). \\n* Multimodal LLMs may be used to improve accessibility and user experience in various domains.\\n* The role of multimodal LLMs in shaping the future of AI is significant, as they can enable more natural and intuitive interactions between humans and machines.\\n* Continued research in multimodal LLMs is crucial to overcome current limitations and unlock their full potential, driving innovation and progress in the field of AI [Not found in provided sources].\\n[[IMAGE_6]]'"
288
+ ]
289
+ },
290
+ "execution_count": 20,
291
+ "metadata": {},
292
+ "output_type": "execute_result"
293
+ }
294
+ ],
295
+ "source": [
296
+ "output.md_with_placeholders"
297
+ ]
298
+ },
299
+ {
300
+ "cell_type": "code",
301
+ "execution_count": 21,
302
+ "id": "00892f27",
303
+ "metadata": {},
304
+ "outputs": [
305
+ {
306
+ "data": {
307
+ "text/plain": [
308
+ "[ImageSpec(placeholder='[[IMAGE_1]]', filename='images/multimodal_llm_architecture.png', prompt='A diagram showing the architecture of a multimodal LLM, with visual and textual features combined, and labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1536x1024', quality='medium'),\n",
309
+ " ImageSpec(placeholder='[[IMAGE_2]]', filename='images/multimodal_transformers.png', prompt='An illustration of multimodal transformers, with visual and textual features combined, and labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1024x1024', quality='medium'),\n",
310
+ " ImageSpec(placeholder='[[IMAGE_3]]', filename='images/multimodal_llm_applications.png', prompt='A diagram showing the various applications of multimodal LLMs, including computer vision and natural language processing, with labels and arrows indicating the relationships between the different applications, on a clean white background, in a professional technical illustration style', size='1024x1536', quality='medium'),\n",
311
+ " ImageSpec(placeholder='[[IMAGE_4]]', filename='images/multimodal_llm_healthcare.png', prompt='An illustration of the potential applications of multimodal LLMs in healthcare, including medical image analysis and personalized treatment plans, with labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1536x1024', quality='medium'),\n",
312
+ " ImageSpec(placeholder='[[IMAGE_5]]', filename='images/multimodal_llm_challenges.png', prompt='A diagram showing the challenges and limitations of multimodal LLMs, including the need for large-scale datasets and improved model architectures, with labels and arrows indicating the relationships between the different challenges, on a clean white background, in a professional technical illustration style', size='1024x1024', quality='medium'),\n",
313
+ " ImageSpec(placeholder='[[IMAGE_6]]', filename='images/multimodal_llm_future.png', prompt='An illustration of the future directions of multimodal LLMs, including potential applications in virtual assistants and human-computer interaction, with labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style', size='1024x1536', quality='medium')]"
314
+ ]
315
+ },
316
+ "execution_count": 21,
317
+ "metadata": {},
318
+ "output_type": "execute_result"
319
+ }
320
+ ],
321
+ "source": [
322
+ "output.images"
323
+ ]
324
+ },
325
+ {
326
+ "cell_type": "code",
327
+ "execution_count": 23,
328
+ "id": "0b4e77e2",
329
+ "metadata": {},
330
+ "outputs": [
331
+ {
332
+ "data": {
333
+ "text/plain": [
334
+ "'A diagram showing the architecture of a multimodal LLM, with visual and textual features combined, and labels and arrows indicating the flow of data, on a clean white background, in a professional technical illustration style'"
335
+ ]
336
+ },
337
+ "execution_count": 23,
338
+ "metadata": {},
339
+ "output_type": "execute_result"
340
+ }
341
+ ],
342
+ "source": [
343
+ "output.images[0].prompt"
344
+ ]
345
+ },
346
+ {
347
+ "cell_type": "code",
348
+ "execution_count": null,
349
+ "id": "8666fa58",
350
+ "metadata": {},
351
+ "outputs": [],
352
+ "source": []
353
+ }
354
+ ],
355
+ "metadata": {
356
+ "kernelspec": {
357
+ "display_name": "bloggig-Agent (3.12.12)",
358
+ "language": "python",
359
+ "name": "python3"
360
+ },
361
+ "language_info": {
362
+ "codemirror_mode": {
363
+ "name": "ipython",
364
+ "version": 3
365
+ },
366
+ "file_extension": ".py",
367
+ "mimetype": "text/x-python",
368
+ "name": "python",
369
+ "nbconvert_exporter": "python",
370
+ "pygments_lexer": "ipython3",
371
+ "version": "3.12.12"
372
+ }
373
+ },
374
+ "nbformat": 4,
375
+ "nbformat_minor": 5
376
+ }
notebook/rag.ipynb ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 2,
6
+ "id": "9304576f",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "data": {
11
+ "text/plain": [
12
+ "True"
13
+ ]
14
+ },
15
+ "execution_count": 2,
16
+ "metadata": {},
17
+ "output_type": "execute_result"
18
+ }
19
+ ],
20
+ "source": [
21
+ "import os\n",
22
+ "from dotenv import load_dotenv\n",
23
+ "load_dotenv()"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": 3,
29
+ "id": "bbaf9dea",
30
+ "metadata": {},
31
+ "outputs": [],
32
+ "source": [
33
+ "from langchain_aws import ChatBedrockConverse\n",
34
+ "LLM_MODEL_ID = \"us.meta.llama3-3-70b-instruct-v1:0\"\n",
35
+ "LLM_REGION = \"us-east-1\"\n",
36
+ "\n",
37
+ "import logging\n",
38
+ "llm = ChatBedrockConverse(\n",
39
+ " model_id=LLM_MODEL_ID,\n",
40
+ " region_name=LLM_REGION\n",
41
+ ")\n",
42
+ "logging.info(f\"LLM initialized with model_id={LLM_MODEL_ID}, region_name={LLM_REGION}\")"
43
+ ]
44
+ },
45
+ {
46
+ "cell_type": "markdown",
47
+ "id": "751de1c5",
48
+ "metadata": {},
49
+ "source": [
50
+ "# Data Ingestion"
51
+ ]
52
+ },
53
+ {
54
+ "cell_type": "code",
55
+ "execution_count": 13,
56
+ "id": "6dba7a05",
57
+ "metadata": {},
58
+ "outputs": [],
59
+ "source": [
60
+ "from langchain_community.document_loaders import TextLoader,DirectoryLoader\n",
61
+ "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
62
+ "\n",
63
+ "from langchain_chroma import Chroma\n",
64
+ "\n",
65
+ "from langchain_ollama.embeddings import OllamaEmbeddings"
66
+ ]
67
+ },
68
+ {
69
+ "cell_type": "code",
70
+ "execution_count": 7,
71
+ "id": "68a36c6c",
72
+ "metadata": {},
73
+ "outputs": [],
74
+ "source": [
75
+ "def load_documents(docs_path=\"docs\"):\n",
76
+ " \"\"\"Load all text files from the docs directory\"\"\"\n",
77
+ " print(f\"Loading documents from {docs_path}...\")\n",
78
+ " \n",
79
+ " # Check if docs directory exists\n",
80
+ " if not os.path.exists(docs_path):\n",
81
+ " raise FileNotFoundError(f\"The directory {docs_path} does not exist. Please create it and add your company files.\")\n",
82
+ " \n",
83
+ " # Load all .txt files from the docs directory\n",
84
+ " loader = DirectoryLoader(\n",
85
+ " path=docs_path,\n",
86
+ " glob=\"*.txt\",\n",
87
+ " loader_cls=TextLoader\n",
88
+ " )\n",
89
+ " \n",
90
+ " documents = loader.load()\n",
91
+ " \n",
92
+ " if len(documents) == 0:\n",
93
+ " raise FileNotFoundError(f\"No .txt files found in {docs_path}. Please add your company documents.\")\n",
94
+ " \n",
95
+ " \n",
96
+ " for i, doc in enumerate(documents[:2]): # Show first 2 documents\n",
97
+ " print(f\"\\nDocument {i+1}:\")\n",
98
+ " print(f\" Source: {doc.metadata['source']}\")\n",
99
+ " print(f\" Content length: {len(doc.page_content)} characters\")\n",
100
+ " print(f\" Content preview: {doc.page_content[:100]}...\")\n",
101
+ " print(f\" metadata: {doc.metadata}\")\n",
102
+ "\n",
103
+ " return documents"
104
+ ]
105
+ },
106
+ {
107
+ "cell_type": "code",
108
+ "execution_count": null,
109
+ "id": "d4b05f9c",
110
+ "metadata": {},
111
+ "outputs": [],
112
+ "source": [
113
+ "def split_documents(documents, chunk_size=1000, chunk_overlap=0):\n",
114
+ " \"\"\"Split documents into smaller chunks with overlap\"\"\"\n",
115
+ " print(\"Splitting documents into chunks...\")\n",
116
+ " \n",
117
+ " text_splitter = RecursiveCharacterTextSplitter(\n",
118
+ " chunk_size=chunk_size, \n",
119
+ " chunk_overlap=chunk_overlap\n",
120
+ " )\n",
121
+ " \n",
122
+ " chunks = text_splitter.split_documents(documents)\n",
123
+ " \n",
124
+ " if chunks:\n",
125
+ " \n",
126
+ " for i, chunk in enumerate(chunks[:5]):\n",
127
+ " print(f\"\\n--- Chunk {i+1} ---\")\n",
128
+ " print(f\"Source: {chunk.metadata['source']}\")\n",
129
+ " print(f\"Length: {len(chunk.page_content)} characters\")\n",
130
+ " print(f\"Content:\")\n",
131
+ " print(chunk.page_content)\n",
132
+ " print(\"-\" * 50)\n",
133
+ " \n",
134
+ " if len(chunks) > 5:\n",
135
+ " print(f\"\\n... and {len(chunks) - 5} more chunks\")\n",
136
+ " \n",
137
+ " return chunks"
138
+ ]
139
+ },
140
+ {
141
+ "cell_type": "code",
142
+ "execution_count": 14,
143
+ "id": "e9d2c201",
144
+ "metadata": {},
145
+ "outputs": [],
146
+ "source": [
147
+ "def create_vector_store(chunks, persist_directory=\"db/chroma_db\"):\n",
148
+ " \"\"\"Create and persist ChromaDB vector store\"\"\"\n",
149
+ " print(\"Creating embeddings and storing in ChromaDB...\")\n",
150
+ " \n",
151
+ " embedding_model = OllamaEmbeddings(model=\"gemma2:2b\")\n",
152
+ " \n",
153
+ " # Create ChromaDB vector store\n",
154
+ " print(\"--- Creating vector store ---\")\n",
155
+ " vectorstore = Chroma.from_documents(\n",
156
+ " documents=chunks,\n",
157
+ " embedding=embedding_model,\n",
158
+ " persist_directory=persist_directory, \n",
159
+ " collection_metadata={\"hnsw:space\": \"cosine\"}\n",
160
+ " )\n",
161
+ " print(\"--- Finished creating vector store ---\")\n",
162
+ " \n",
163
+ " print(f\"Vector store created and saved to {persist_directory}\")\n",
164
+ " return vectorstore"
165
+ ]
166
+ },
167
+ {
168
+ "cell_type": "code",
169
+ "execution_count": 16,
170
+ "id": "28dd89fe",
171
+ "metadata": {},
172
+ "outputs": [],
173
+ "source": [
174
+ "def main():\n",
175
+ " \"\"\"Main ingestion pipeline\"\"\"\n",
176
+ " print(\"=== RAG Document Ingestion Pipeline ===\\n\")\n",
177
+ " \n",
178
+ " # Define paths\n",
179
+ " docs_path = \"data\"\n",
180
+ " persistent_directory = \"db/chroma_db\"\n",
181
+ " \n",
182
+ " # Check if vector store already exists\n",
183
+ " if os.path.exists(persistent_directory):\n",
184
+ " print(\"✅ Vector store already exists. No need to re-process documents.\")\n",
185
+ " \n",
186
+ " embedding_model = OllamaEmbeddings(model=\"gemma2:2b\")\n",
187
+ " vectorstore = Chroma(\n",
188
+ " persist_directory=persistent_directory,\n",
189
+ " embedding_function=embedding_model, \n",
190
+ " collection_metadata={\"hnsw:space\": \"cosine\"}\n",
191
+ " )\n",
192
+ " print(f\"Loaded existing vector store with {vectorstore._collection.count()} documents\")\n",
193
+ " return vectorstore\n",
194
+ " \n",
195
+ " print(\"Persistent directory does not exist. Initializing vector store...\\n\")\n",
196
+ " \n",
197
+ " # Step 1: Load documents\n",
198
+ " documents = load_documents(docs_path) \n",
199
+ "\n",
200
+ " # Step 2: Split into chunks\n",
201
+ " chunks = split_documents(documents)\n",
202
+ " \n",
203
+ " # # Step 3: Create vector store\n",
204
+ " vectorstore = create_vector_store(chunks, persistent_directory)\n",
205
+ " \n",
206
+ " print(\"\\n✅ Ingestion complete! Your documents are now ready for RAG queries.\")\n",
207
+ " return vectorstore"
208
+ ]
209
+ },
210
+ {
211
+ "cell_type": "code",
212
+ "execution_count": 17,
213
+ "id": "0bbabc0a",
214
+ "metadata": {},
215
+ "outputs": [
216
+ {
217
+ "name": "stdout",
218
+ "output_type": "stream",
219
+ "text": [
220
+ "=== RAG Document Ingestion Pipeline ===\n",
221
+ "\n",
222
+ "Persistent directory does not exist. Initializing vector store...\n",
223
+ "\n",
224
+ "Loading documents from data...\n"
225
+ ]
226
+ },
227
+ {
228
+ "ename": "FileNotFoundError",
229
+ "evalue": "The directory data does not exist. Please create it and add your company files.",
230
+ "output_type": "error",
231
+ "traceback": [
232
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
233
+ "\u001b[31mFileNotFoundError\u001b[39m Traceback (most recent call last)",
234
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[17]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m vectordb=\u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m vectordb\n",
235
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[16]\u001b[39m\u001b[32m, line 25\u001b[39m, in \u001b[36mmain\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m 22\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33m\"\u001b[39m\u001b[33mPersistent directory does not exist. Initializing vector store...\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m\"\u001b[39m)\n\u001b[32m 24\u001b[39m \u001b[38;5;66;03m# Step 1: Load documents\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m25\u001b[39m documents = \u001b[43mload_documents\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdocs_path\u001b[49m\u001b[43m)\u001b[49m \n\u001b[32m 27\u001b[39m \u001b[38;5;66;03m# Step 2: Split into chunks\u001b[39;00m\n\u001b[32m 28\u001b[39m chunks = split_documents(documents)\n",
236
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[7]\u001b[39m\u001b[32m, line 7\u001b[39m, in \u001b[36mload_documents\u001b[39m\u001b[34m(docs_path)\u001b[39m\n\u001b[32m 5\u001b[39m \u001b[38;5;66;03m# Check if docs directory exists\u001b[39;00m\n\u001b[32m 6\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m os.path.exists(docs_path):\n\u001b[32m----> \u001b[39m\u001b[32m7\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mFileNotFoundError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mThe directory \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdocs_path\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m does not exist. Please create it and add your company files.\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 9\u001b[39m \u001b[38;5;66;03m# Load all .txt files from the docs directory\u001b[39;00m\n\u001b[32m 10\u001b[39m loader = DirectoryLoader(\n\u001b[32m 11\u001b[39m path=docs_path,\n\u001b[32m 12\u001b[39m glob=\u001b[33m\"\u001b[39m\u001b[33m*.txt\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 13\u001b[39m loader_cls=TextLoader\n\u001b[32m 14\u001b[39m )\n",
237
+ "\u001b[31mFileNotFoundError\u001b[39m: The directory data does not exist. Please create it and add your company files."
238
+ ]
239
+ }
240
+ ],
241
+ "source": [
242
+ "vectordb=main()\n",
243
+ "vectordb"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "execution_count": 18,
249
+ "id": "cb14033a",
250
+ "metadata": {},
251
+ "outputs": [
252
+ {
253
+ "ename": "NameError",
254
+ "evalue": "name 'embedding_model' is not defined",
255
+ "output_type": "error",
256
+ "traceback": [
257
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
258
+ "\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
259
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 11\u001b[39m\n\u001b[32m 4\u001b[39m load_dotenv()\n\u001b[32m 6\u001b[39m persistent_directory = \u001b[33m\"\u001b[39m\u001b[33mdb/chroma_db\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 9\u001b[39m db = Chroma(\n\u001b[32m 10\u001b[39m persist_directory=persistent_directory,\n\u001b[32m---> \u001b[39m\u001b[32m11\u001b[39m embedding_function=\u001b[43membedding_model\u001b[49m,\n\u001b[32m 12\u001b[39m collection_metadata={\u001b[33m\"\u001b[39m\u001b[33mhnsw:space\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mcosine\u001b[39m\u001b[33m\"\u001b[39m} \n\u001b[32m 13\u001b[39m )\n\u001b[32m 15\u001b[39m \u001b[38;5;66;03m# Search for relevant documents\u001b[39;00m\n\u001b[32m 16\u001b[39m query = \u001b[33m\"\u001b[39m\u001b[33mHow much did Microsoft pay to acquire GitHub?\u001b[39m\u001b[33m\"\u001b[39m\n",
260
+ "\u001b[31mNameError\u001b[39m: name 'embedding_model' is not defined"
261
+ ]
262
+ }
263
+ ],
264
+ "source": [
265
+ "from langchain_chroma import Chroma\n",
266
+ "from dotenv import load_dotenv\n",
267
+ "\n",
268
+ "load_dotenv()\n",
269
+ "\n",
270
+ "persistent_directory = \"db/chroma_db\"\n",
271
+ "\n",
272
+ "\n",
273
+ "db = Chroma(\n",
274
+ " persist_directory=persistent_directory,\n",
275
+ " embedding_function=embedding_model,\n",
276
+ " collection_metadata={\"hnsw:space\": \"cosine\"} \n",
277
+ ")\n",
278
+ "\n",
279
+ "# Search for relevant documents\n",
280
+ "query = \"How much did Microsoft pay to acquire GitHub?\"\n",
281
+ "\n",
282
+ "retriever = db.as_retriever(search_kwargs={\"k\": 5})\n",
283
+ "\n",
284
+ "# retriever = db.as_retriever(\n",
285
+ "# search_type=\"similarity_score_threshold\",\n",
286
+ "# search_kwargs={\n",
287
+ "# \"k\": 5,\n",
288
+ "# \"score_threshold\": 0.3 # Only return chunks with cosine similarity ≥ 0.3\n",
289
+ "# }\n",
290
+ "# )\n",
291
+ "\n",
292
+ "relevant_docs = retriever.invoke(query)\n",
293
+ "\n",
294
+ "print(f\"User Query: {query}\")\n",
295
+ "# Display results\n",
296
+ "print(\"--- Context ---\")\n",
297
+ "for i, doc in enumerate(relevant_docs, 1):\n",
298
+ " print(f\"Document {i}:\\n{doc.page_content}\\n\")\n",
299
+ "\n",
300
+ "\n",
301
+ "# Synthetic Questions: \n",
302
+ "\n",
303
+ "# 1. \"What was NVIDIA's first graphics accelerator called?\"\n",
304
+ "# 2. \"Which company did NVIDIA acquire to enter the mobile processor market?\"\n",
305
+ "# 3. \"What was Microsoft's first hardware product release?\"\n",
306
+ "# 4. \"How much did Microsoft pay to acquire GitHub?\"\n",
307
+ "# 5. \"In what year did Tesla begin production of the Roadster?\"\n",
308
+ "# 6. \"Who succeeded Ze'ev Drori as CEO in October 2008?\"\n",
309
+ "# 7. \"What was the name of the autonomous spaceport drone ship that achieved the first successful sea landing?\"\n",
310
+ "# 8. \"What was the original name of Microsoft before it became Microsoft?\""
311
+ ]
312
+ },
313
+ {
314
+ "cell_type": "code",
315
+ "execution_count": 2,
316
+ "id": "9b97a0c6",
317
+ "metadata": {},
318
+ "outputs": [
319
+ {
320
+ "ename": "ImportError",
321
+ "evalue": "cannot import name 'TransfoXLModel' from 'transformers' (c:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\transformers\\__init__.py)",
322
+ "output_type": "error",
323
+ "traceback": [
324
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
325
+ "\u001b[31mImportError\u001b[39m Traceback (most recent call last)",
326
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01msummarizer\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Summarizer\n\u001b[32m 3\u001b[39m document = \u001b[33m\"\"\"\u001b[39m\n\u001b[32m 4\u001b[39m \u001b[33mDeep learning is a subset of machine learning that uses neural networks.\u001b[39m\n\u001b[32m 5\u001b[39m \u001b[33mThese networks consist of multiple layers that can learn complex patterns.\u001b[39m\n\u001b[32m 6\u001b[39m \u001b[33mConvolutional neural networks are widely used in image recognition tasks.\u001b[39m\n\u001b[32m 7\u001b[39m \u001b[33m\"\"\"\u001b[39m\n\u001b[32m 9\u001b[39m model = Summarizer()\n",
327
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\summarizer\\__init__.py:1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01msummarizer\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mbert\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Summarizer, TransformerSummarizer\n\u001b[32m 3\u001b[39m __all__ = [\u001b[33m\"\u001b[39m\u001b[33mSummarizer\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mTransformerSummarizer\u001b[39m\u001b[33m\"\u001b[39m]\n",
328
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\summarizer\\bert.py:4\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mfunctools\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m partial\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mtyping\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m List, Optional, Union\n\u001b[32m----> \u001b[39m\u001b[32m4\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mtransformers\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m (AlbertModel, AlbertTokenizer, BartModel, BigBirdModel, BigBirdTokenizer,\n\u001b[32m 5\u001b[39m BartTokenizer, BertModel, BertTokenizer,\n\u001b[32m 6\u001b[39m CamembertModel, CamembertTokenizer, CTRLModel,\n\u001b[32m 7\u001b[39m CTRLTokenizer, DistilBertModel, DistilBertTokenizer,\n\u001b[32m 8\u001b[39m GPT2Model, GPT2Tokenizer, LongformerModel,\n\u001b[32m 9\u001b[39m LongformerTokenizer, OpenAIGPTModel,\n\u001b[32m 10\u001b[39m OpenAIGPTTokenizer, PreTrainedModel,\n\u001b[32m 11\u001b[39m PreTrainedTokenizer, RobertaModel, RobertaTokenizer,\n\u001b[32m 12\u001b[39m TransfoXLModel, TransfoXLTokenizer, XLMModel,\n\u001b[32m 13\u001b[39m XLMTokenizer, XLNetModel, XLNetTokenizer)\n\u001b[32m 15\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01msummarizer\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01msummary_processor\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m SummaryProcessor\n\u001b[32m 16\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01msummarizer\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mtext_processors\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01msentence_handler\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m SentenceHandler\n",
329
+ "\u001b[31mImportError\u001b[39m: cannot import name 'TransfoXLModel' from 'transformers' (c:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\transformers\\__init__.py)"
330
+ ]
331
+ }
332
+ ],
333
+ "source": [
334
+ "from summarizer import Summarizer\n",
335
+ "\n",
336
+ "document = \"\"\"\n",
337
+ "Deep learning is a subset of machine learning that uses neural networks.\n",
338
+ "These networks consist of multiple layers that can learn complex patterns.\n",
339
+ "Convolutional neural networks are widely used in image recognition tasks.\n",
340
+ "\"\"\"\n",
341
+ "\n",
342
+ "model = Summarizer()\n",
343
+ "\n",
344
+ "summary = model(document, ratio=0.3)\n",
345
+ "\n",
346
+ "print(summary)"
347
+ ]
348
+ },
349
+ {
350
+ "cell_type": "code",
351
+ "execution_count": null,
352
+ "id": "b538f506",
353
+ "metadata": {},
354
+ "outputs": [],
355
+ "source": []
356
+ }
357
+ ],
358
+ "metadata": {
359
+ "kernelspec": {
360
+ "display_name": "AIAgents (3.12.12)",
361
+ "language": "python",
362
+ "name": "python3"
363
+ },
364
+ "language_info": {
365
+ "codemirror_mode": {
366
+ "name": "ipython",
367
+ "version": 3
368
+ },
369
+ "file_extension": ".py",
370
+ "mimetype": "text/x-python",
371
+ "name": "python",
372
+ "nbconvert_exporter": "python",
373
+ "pygments_lexer": "ipython3",
374
+ "version": "3.12.12"
375
+ }
376
+ },
377
+ "nbformat": 4,
378
+ "nbformat_minor": 5
379
+ }
notebook/understanding_self_attention.md ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Understanding Self Attention
2
+
3
+ ### Introduction to Self Attention
4
+ Self-attention, also known as intra-attention, is a mechanism used in deep learning models to allow the model to attend to different parts of the input data and weigh their importance. It's a key component of the Transformer architecture, introduced in 2017, which revolutionized the field of natural language processing (NLP). Self-attention enables the model to capture long-range dependencies and contextual relationships in the input data, making it particularly useful for sequence-to-sequence tasks such as machine translation, text summarization, and chatbots. The importance of self-attention lies in its ability to handle variable-length input sequences, parallelize computation, and improve model performance by focusing on the most relevant parts of the input data. In this blog, we'll delve deeper into the concept of self-attention, its types, and its applications in deep learning.
5
+
6
+ ### How Self Attention Works
7
+ Self-attention is a mechanism that allows a model to attend to different parts of the input sequence simultaneously and weigh their importance. It's a key component of the Transformer architecture, introduced in the paper "Attention is All You Need" by Vaswani et al.
8
+
9
+ The self-attention mechanism takes in a set of input vectors, typically the output of an encoder or a previous layer, and computes a weighted sum of these vectors based on their similarity. The weights are learned during training and reflect the relative importance of each input vector.
10
+
11
+ The mathematical formulation of self-attention can be broken down into three main steps:
12
+
13
+ 1. **Query, Key, and Value Vectors**: The input vectors are first transformed into three different vectors: Query (Q), Key (K), and Value (V). These vectors are obtained by applying linear transformations to the input vectors.
14
+ 2. **Attention Scores**: The attention scores are computed by taking the dot product of the Query and Key vectors and applying a scaling factor. The attention scores represent the similarity between the input vectors.
15
+ 3. **Weighted Sum**: The attention scores are then used to compute a weighted sum of the Value vectors. The weighted sum is the final output of the self-attention mechanism.
16
+
17
+ The self-attention mechanism can be formulated mathematically as follows:
18
+
19
+ `Attention(Q, K, V) = softmax(Q * K^T / sqrt(d)) * V`
20
+
21
+ where `Q`, `K`, and `V` are the Query, Key, and Value vectors, respectively, `d` is the dimensionality of the input vectors, and `softmax` is the softmax activation function.
22
+
23
+ The self-attention mechanism has several benefits, including:
24
+
25
+ * **Parallelization**: Self-attention can be parallelized more easily than recurrent neural networks (RNNs), making it more efficient for long-range dependencies.
26
+ * **Flexibility**: Self-attention can handle variable-length input sequences and can be used for both encoding and decoding tasks.
27
+ * **Interpretability**: The attention scores can provide insights into which parts of the input sequence are most relevant for a particular task.
28
+
29
+ ### Types of Self Attention
30
+ There are several types of self-attention mechanisms that have been proposed in the literature, each with its own strengths and weaknesses. The two main categories of self-attention are local self-attention and global self-attention.
31
+
32
+ #### Local Self Attention
33
+ Local self-attention, also known as local attention or window-based attention, focuses on a fixed-size window of the input sequence. This type of attention is useful when the relationships between nearby elements in the sequence are more important than the relationships between distant elements. Local self-attention is often used in tasks such as language modeling and machine translation.
34
+
35
+ #### Global Self Attention
36
+ Global self-attention, on the other hand, considers the entire input sequence when computing the attention weights. This type of attention is useful when the relationships between all elements in the sequence are important, regardless of their distance. Global self-attention is often used in tasks such as question answering and text classification.
37
+
38
+ #### Other Types of Self Attention
39
+ In addition to local and global self-attention, there are other variants of self-attention that have been proposed, including:
40
+ * **Hierarchical self-attention**: This type of attention uses a hierarchical representation of the input sequence, where the attention weights are computed at multiple levels of granularity.
41
+ * **Graph-based self-attention**: This type of attention is used for graph-structured data, where the attention weights are computed based on the graph structure.
42
+ * **Multi-head self-attention**: This type of attention uses multiple attention heads to capture different types of relationships between the elements in the input sequence.
43
+
44
+ ### Applications of Self Attention
45
+ Self-attention has numerous applications across various fields, including natural language processing, computer vision, and more. Some of the key applications of self-attention are:
46
+ * **Natural Language Processing (NLP)**: Self-attention is widely used in NLP tasks such as language translation, question answering, and text summarization. It helps in understanding the context and relationships between different words in a sentence.
47
+ * **Computer Vision**: Self-attention is used in computer vision tasks such as image classification, object detection, and image generation. It helps in understanding the relationships between different parts of an image.
48
+ * **Speech Recognition**: Self-attention is used in speech recognition tasks to improve the accuracy of speech-to-text models.
49
+ * **Recommendation Systems**: Self-attention is used in recommendation systems to understand the relationships between different items and recommend relevant items to users.
50
+ * **Time Series Forecasting**: Self-attention is used in time series forecasting to understand the relationships between different time steps and predict future values.
51
+ The use of self-attention has led to state-of-the-art results in many of these applications, and its potential continues to be explored in other fields.
52
+
53
+ ### Implementing Self Attention
54
+ Implementing self-attention in a deep learning model involves several key steps. Here's a step-by-step guide to help you get started:
55
+ #### Step 1: Define the Self-Attention Mechanism
56
+ The self-attention mechanism is based on the Query-Key-Value (QKV) framework. You need to define the QKV matrices and calculate the attention weights using the following formula:
57
+ $$Attention(Q, K, V) = softmax(\frac{Q \cdot K^T}{\sqrt{d_k}}) \cdot V$$
58
+ where $d_k$ is the dimensionality of the key vector.
59
+
60
+ #### Step 2: Choose the Attention Type
61
+ There are two main types of self-attention: scaled dot-product attention and multi-head attention. Scaled dot-product attention is a basic form of self-attention, while multi-head attention allows the model to jointly attend to information from different representation subspaces.
62
+
63
+ #### Step 3: Implement the Self-Attention Layer
64
+ You can implement the self-attention layer using popular deep learning frameworks such as PyTorch or TensorFlow. The self-attention layer takes in the input sequence and outputs a weighted sum of the input elements.
65
+
66
+ #### Step 4: Integrate the Self-Attention Layer into the Model
67
+ Once you have implemented the self-attention layer, you can integrate it into your deep learning model. This typically involves adding the self-attention layer to the model architecture and adjusting the model's parameters accordingly.
68
+
69
+ #### Step 5: Train the Model
70
+ After integrating the self-attention layer, you need to train the model using a suitable optimizer and loss function. The self-attention mechanism can be trained end-to-end with the rest of the model.
71
+
72
+ #### Example Code
73
+ Here's an example code snippet in PyTorch that demonstrates how to implement a basic self-attention layer:
74
+ ```python
75
+ import torch
76
+ import torch.nn as nn
77
+ import torch.nn.functional as F
78
+
79
+ class SelfAttention(nn.Module):
80
+ def __init__(self, embed_dim, num_heads):
81
+ super(SelfAttention, self).__init__()
82
+ self.embed_dim = embed_dim
83
+ self.num_heads = num_heads
84
+ self.query_linear = nn.Linear(embed_dim, embed_dim)
85
+ self.key_linear = nn.Linear(embed_dim, embed_dim)
86
+ self.value_linear = nn.Linear(embed_dim, embed_dim)
87
+ self.dropout = nn.Dropout(0.1)
88
+
89
+ def forward(self, x):
90
+ # Calculate Q, K, V
91
+ Q = self.query_linear(x)
92
+ K = self.key_linear(x)
93
+ V = self.value_linear(x)
94
+
95
+ # Calculate attention weights
96
+ attention_weights = torch.matmul(Q, K.T) / math.sqrt(self.embed_dim)
97
+ attention_weights = F.softmax(attention_weights, dim=-1)
98
+
99
+ # Calculate output
100
+ output = torch.matmul(attention_weights, V)
101
+ output = self.dropout(output)
102
+ return output
103
+ ```
104
+ Note that this is a simplified example, and you may need to modify the code to suit your specific use case.
105
+
106
+ ### Advantages and Limitations of Self Attention
107
+ The self-attention mechanism has several advantages that make it a powerful tool in deep learning models. Some of the key benefits include:
108
+ * **Parallelization**: Self-attention allows for parallelization of sequential data, making it much faster than traditional recurrent neural networks (RNNs) for long sequences.
109
+ * **Flexibility**: Self-attention can handle variable-length input sequences and can be used for both short-term and long-term dependencies.
110
+ * **Interpretability**: The attention weights provide a way to visualize and understand which parts of the input sequence are most relevant for a particular task.
111
+
112
+ However, self-attention also has some limitations:
113
+ * **Computational Cost**: Self-attention has a high computational cost, especially for long sequences, due to the need to compute attention weights for every pair of elements.
114
+ * **Memory Requirements**: Self-attention requires a significant amount of memory to store the attention weights and the input sequence.
115
+ * **Difficulty in Handling Local Dependencies**: Self-attention can struggle to capture local dependencies, such as those found in images or text with strong spatial relationships.
116
+
117
+ Despite these limitations, self-attention has the potential for future directions, including:
118
+ * **Improving Efficiency**: Researchers are exploring ways to improve the efficiency of self-attention, such as using sparse attention or hierarchical attention.
119
+ * **Combining with Other Mechanisms**: Self-attention can be combined with other mechanisms, such as convolutional neural networks (CNNs) or RNNs, to create more powerful models.
120
+ * **Applying to New Domains**: Self-attention can be applied to new domains, such as computer vision or speech recognition, to improve performance and efficiency.
notebook/understanding_self_attention_in_deep_learning.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Understanding Self Attention in Deep Learning
2
+
3
+ ## Introduction to Self Attention
4
+ Self attention is a fundamental concept in deep learning, enabling models to weigh the importance of different input elements relative to each other. It plays a crucial role in deep learning models, particularly in natural language processing and computer vision tasks, by allowing the model to focus on specific parts of the input data.
5
+
6
+ The traditional attention mechanisms have a limitation - they rely on a fixed-length context, which can be restrictive for sequences with varying lengths. This fixed-length context can lead to information loss or inefficient processing, especially when dealing with long sequences.
7
+
8
+ To address this, self attention mechanisms are used, which can be implemented using the following minimal code snippet:
9
+ ```python
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.nn.functional as F
13
+
14
+ class SelfAttention(nn.Module):
15
+ def __init__(self, embed_dim):
16
+ super(SelfAttention, self).__init__()
17
+ self.query_linear = nn.Linear(embed_dim, embed_dim)
18
+ self.key_linear = nn.Linear(embed_dim, embed_dim)
19
+ self.value_linear = nn.Linear(embed_dim, embed_dim)
20
+
21
+ def forward(self, x):
22
+ query = self.query_linear(x)
23
+ key = self.key_linear(x)
24
+ value = self.value_linear(x)
25
+ attention_scores = torch.matmul(query, key.T) / math.sqrt(key.size(-1))
26
+ attention_weights = F.softmax(attention_scores, dim=-1)
27
+ output = torch.matmul(attention_weights, value)
28
+ return output
29
+ ```
30
+ This code snippet demonstrates a basic self attention implementation, highlighting its importance in deep learning models.
31
+
32
+ ## Implementing Self Attention
33
+ To implement self attention, it's essential to understand the underlying mathematical formulation. The self attention mechanism is based on the concept of attention, which allows the model to focus on specific parts of the input data.
34
+
35
+ * The mathematical formulation of self attention involves computing the attention weights based on the query, key, and value vectors. This is typically done using the following equation: `Attention(Q, K, V) = softmax(Q * K^T / sqrt(d)) * V`, where `Q`, `K`, and `V` are the query, key, and value vectors, respectively, and `d` is the dimensionality of the input data.
36
+
37
+ The query-key-value attention mechanism is a core component of self attention. In this mechanism, the query vector represents the context in which the attention is being applied, the key vector represents the input data, and the value vector represents the importance of each input element.
38
+
39
+ ```python
40
+ import torch
41
+ import torch.nn as nn
42
+ import torch.nn.functional as F
43
+
44
+ class SelfAttention(nn.Module):
45
+ def __init__(self, embed_dim):
46
+ super(SelfAttention, self).__init__()
47
+ self.query_linear = nn.Linear(embed_dim, embed_dim)
48
+ self.key_linear = nn.Linear(embed_dim, embed_dim)
49
+ self.value_linear = nn.Linear(embed_dim, embed_dim)
50
+
51
+ def forward(self, x):
52
+ Q = self.query_linear(x)
53
+ K = self.key_linear(x)
54
+ V = self.value_linear(x)
55
+ attention_weights = F.softmax(torch.matmul(Q, K.T) / math.sqrt(x.size(-1)), dim=-1)
56
+ return torch.matmul(attention_weights, V)
57
+ ```
58
+ This code example demonstrates how to implement self attention in PyTorch, a popular deep learning framework. By using this implementation, developers can easily integrate self attention into their own models.
59
+
60
+ ## Applications of Self Attention
61
+ Self attention has numerous applications in various fields.
62
+ In natural language processing tasks, self attention is used to weigh the importance of different words in a sentence, allowing models to capture long-range dependencies and context.
63
+
64
+ * Example in computer vision: self attention can be applied to image classification models to focus on specific regions of the image, as shown in this PyTorch code snippet:
65
+ ```python
66
+ import torch
67
+ import torch.nn as nn
68
+
69
+ class SelfAttention(nn.Module):
70
+ def __init__(self, embed_dim):
71
+ super(SelfAttention, self).__init__()
72
+ self.query_linear = nn.Linear(embed_dim, embed_dim)
73
+ self.key_linear = nn.Linear(embed_dim, embed_dim)
74
+ self.value_linear = nn.Linear(embed_dim, embed_dim)
75
+
76
+ def forward(self, x):
77
+ query = self.query_linear(x)
78
+ key = self.key_linear(x)
79
+ value = self.value_linear(x)
80
+ attention_weights = torch.matmul(query, key.T) / math.sqrt(x.size(-1))
81
+ output = torch.matmul(attention_weights, value)
82
+ return output
83
+ ```
84
+ Self attention can also be used in recommender systems to model user-item interactions, allowing for more accurate personalized recommendations by considering the relationships between different items.
85
+
86
+ ## Common Mistakes in Self Attention
87
+ When working with self attention models, several common pitfalls can hinder performance and lead to suboptimal results.
88
+
89
+ * Overfitting is a significant problem in self attention models, where the model becomes too specialized to the training data and fails to generalize well to new, unseen data. This can be mitigated by using techniques such as dropout and early stopping, which help to prevent the model from becoming too complex.
90
+
91
+ Proper initialization and regularization are also crucial when using self attention. Initialization with random weights can lead to slow convergence or getting stuck in local minima, while regularization techniques like L1 and L2 regularization can help to prevent overfitting by adding a penalty term to the loss function.
92
+
93
+ To debug self attention models, follow these steps:
94
+ * Check the input data for any inconsistencies or missing values
95
+ * Verify that the model is correctly implemented, with attention weights being properly computed and applied
96
+ * Monitor the model's performance on a validation set during training, and adjust hyperparameters as needed to prevent overfitting.
97
+ By being aware of these common mistakes and taking steps to avoid them, developers can build more effective and reliable self attention models.
98
+
99
+ ## Best Practices for Self Attention
100
+ To ensure effective use of self attention in your projects, follow this checklist for production readiness:
101
+ * Validate input data quality
102
+ * Test model performance on diverse datasets
103
+ * Monitor training time and memory usage
104
+ Monitoring performance metrics, such as accuracy and loss, is crucial for identifying potential issues.
105
+ For further learning and improvement, refer to the Transformer library documentation and research papers on self attention mechanisms.
notebook/web.ipynb ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "3d9158b7",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "name": "stderr",
11
+ "output_type": "stream",
12
+ "text": [
13
+ "c:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
14
+ " from .autonotebook import tqdm as notebook_tqdm\n"
15
+ ]
16
+ }
17
+ ],
18
+ "source": [
19
+ "from langchain_aws import ChatBedrockConverse\n",
20
+ "LLM_MODEL_ID = \"us.meta.llama3-3-70b-instruct-v1:0\"\n",
21
+ "LLM_REGION = \"us-east-1\"\n",
22
+ "\n",
23
+ "import logging\n",
24
+ "llm = ChatBedrockConverse(\n",
25
+ " model_id=LLM_MODEL_ID,\n",
26
+ " region_name=LLM_REGION\n",
27
+ ")\n",
28
+ "logging.info(f\"LLM initialized with model_id={LLM_MODEL_ID}, region_name={LLM_REGION}\")"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": 4,
34
+ "id": "cad5e68d",
35
+ "metadata": {},
36
+ "outputs": [
37
+ {
38
+ "name": "stderr",
39
+ "output_type": "stream",
40
+ "text": [
41
+ "WARNING:langchain_community.utils.user_agent:USER_AGENT environment variable not set, consider setting it to identify your requests.\n"
42
+ ]
43
+ }
44
+ ],
45
+ "source": [
46
+ "from langchain_community.document_loaders import WebBaseLoader"
47
+ ]
48
+ },
49
+ {
50
+ "cell_type": "code",
51
+ "execution_count": 5,
52
+ "id": "2a289acb",
53
+ "metadata": {},
54
+ "outputs": [],
55
+ "source": [
56
+ "loader=WebBaseLoader(\"https://docs.langchain.com/oss/python/integrations/document_loaders/web_base\")"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "code",
61
+ "execution_count": 10,
62
+ "id": "d1fcbd5f",
63
+ "metadata": {},
64
+ "outputs": [
65
+ {
66
+ "data": {
67
+ "text/plain": [
68
+ "[Document(metadata={'source': 'https://docs.langchain.com/oss/python/integrations/document_loaders/web_base', 'title': 'WebBaseLoader integration - Docs by LangChain', 'description': 'Integrate with the WebBaseLoader document loader using LangChain Python.', 'language': 'en'}, page_content='WebBaseLoader integration - Docs by LangChainSkip to main contentDocs by LangChain home pageOpen sourceSearch...⌘KAsk AIGitHubTry LangSmithTry LangSmithSearch...NavigationWebBaseLoader integrationDeep AgentsLangChainLangGraphIntegrationsLearnReferenceContributePythonLangChain integrationsAll providersPopular ProvidersOpenAIAnthropicGoogleAWSHugging FaceMicrosoftOllamaGroqNVIDIAIntegrations by componentChat modelsTools and toolkitsMiddlewareRetrieversText splittersEmbedding modelsVector storesDocument loadersKey-value storesOn this pageOverviewIntegration detailsLoader featuresSetupCredentialsInstallationInitializationInitialization with multiple pagesLoadLoad multiple urls concurrentlyLoading a xml file, or using a different BeautifulSoup parserLazy loadAsyncUsing proxiesAPI referenceWebBaseLoader integrationCopy pageIntegrate with the WebBaseLoader document loader using LangChain Python.Copy pageThis covers how to use WebBaseLoader to load all text from HTML webpages into a document format that we can use downstream. For more custom logic for loading webpages look at some child class examples such as IMSDbLoader, AZLyricsLoader, and CollegeConfidentialLoader.\\nIf you don’t want to worry about website crawling, bypassing JS-blocking sites, and data cleaning, consider using FireCrawlLoader or the faster option SpiderLoader.\\n\\u200bOverview\\n\\u200bIntegration details\\n\\nTODO: Fill in table features.\\nTODO: Remove JS support link if not relevant, otherwise ensure link is correct.\\nTODO: Make sure API reference links are correct.\\n\\nClassPackageLocalSerializableJS supportWebBaseLoaderlangchain-community✅❌❌\\n\\u200bLoader features\\nSourceDocument Lazy LoadingNative Async SupportWebBaseLoader✅✅\\n\\u200bSetup\\n\\u200bCredentials\\nWebBaseLoader does not require any credentials.\\n\\u200bInstallation\\nTo use the WebBaseLoader you first need to install the langchain-community python package.\\nCopypip install -qU langchain-community beautifulsoup4\\n\\n\\u200bInitialization\\nNow we can instantiate our model object and load documents:\\nCopyfrom langchain_community.document_loaders import WebBaseLoader\\n\\nloader = WebBaseLoader(\"https://www.example.com/\")\\n\\nTo bypass SSL verification errors during fetching, you can set the “verify” option:\\nloader.requests_kwargs = {\\'verify\\':False}\\n\\u200bInitialization with multiple pages\\nYou can also pass in a list of pages to load from.\\nCopyloader_multiple_pages = WebBaseLoader(\\n [\"https://www.example.com/\", \"https://google.com\"]\\n)\\n\\n\\u200bLoad\\nCopydocs = loader.load()\\n\\ndocs[0]\\n\\nCopyDocument(metadata={\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}, page_content=\\'\\\\n\\\\n\\\\nExample Domain\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\nExample Domain\\\\nThis domain is for use in illustrative examples in documents. You may use this\\\\n domain in literature without prior coordination or asking for permission.\\\\nMore information...\\\\n\\\\n\\\\n\\\\n\\')\\n\\nCopyprint(docs[0].metadata)\\n\\nCopy{\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}\\n\\n\\u200bLoad multiple urls concurrently\\nYou can speed up the scraping process by scraping and parsing multiple urls concurrently.\\nThere are reasonable limits to concurrent requests, defaulting to 2 per second. If you aren’t concerned about being a good citizen, or you control the server you are scraping and don’t care about load, you can change the requests_per_second parameter to increase the max concurrent requests. Note, while this will speed up the scraping process, but may cause the server to block you. Be careful!\\nCopypip install -qU nest_asyncio\\n\\n# fixes a bug with asyncio and jupyter\\nimport nest_asyncio\\n\\nnest_asyncio.apply()\\n\\nCopyloader = WebBaseLoader([\"https://www.example.com/\", \"https://google.com\"])\\nloader.requests_per_second = 1\\ndocs = loader.aload()\\ndocs\\n\\nCopyFetching pages: 100%|###########################################################################| 2/2 [00:00<00:00, 8.28it/s]\\n\\nCopy[Document(metadata={\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}, page_content=\\'\\\\n\\\\n\\\\nExample Domain\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\nExample Domain\\\\nThis domain is for use in illustrative examples in documents. You may use this\\\\n domain in literature without prior coordination or asking for permission.\\\\nMore information...\\\\n\\\\n\\\\n\\\\n\\'),\\n Document(metadata={\\'source\\': \\'https://google.com\\', \\'title\\': \\'Google\\', \\'description\\': \"Search the world\\'s information, including webpages, images, videos and more. Google has many special features to help you find exactly what you\\'re looking for.\", \\'language\\': \\'en\\'}, page_content=\\'GoogleSearch Images Maps Play YouTube News Gmail Drive More »Web History | Settings | Sign in\\\\xa0Advanced search5 ways Gemini can help during the HolidaysAdvertisingBusiness SolutionsAbout Google© 2024 - Privacy - Terms \\')]\\n\\n\\u200bLoading a xml file, or using a different BeautifulSoup parser\\nYou can also look at SitemapLoader for an example of how to load a sitemap file, which is an example of using this feature.\\nCopyloader = WebBaseLoader(\\n \"https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\"\\n)\\nloader.default_parser = \"xml\"\\ndocs = loader.load()\\ndocs\\n\\nCopy[Document(metadata={\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}, page_content=\\'\\\\n\\\\n10\\\\nEnergy\\\\n3\\\\n2018-01-01\\\\n2018-01-01\\\\nfalse\\\\nUniform test method for the measurement of energy efficiency of commercial packaged boilers.\\\\n§ 431.86\\\\nSection § 431.86\\\\n\\\\nEnergy\\\\nDEPARTMENT OF ENERGY\\\\nENERGY CONSERVATION\\\\nENERGY EFFICIENCY PROGRAM FOR CERTAIN COMMERCIAL AND INDUSTRIAL EQUIPMENT\\\\nCommercial Packaged Boilers\\\\nTest Procedures\\\\n\\\\n\\\\n\\\\n\\\\n§\\\\u2009431.86\\\\nUniform test method for the measurement of energy efficiency of commercial packaged boilers.\\\\n(a) Scope. This section provides test procedures, pursuant to the Energy Policy and Conservation Act (EPCA), as amended, which must be followed for measuring the combustion efficiency and/or thermal efficiency of a gas- or oil-fired commercial packaged boiler.\\\\n(b) Testing and Calculations. Determine the thermal efficiency or combustion efficiency of commercial packaged boilers by conducting the appropriate test procedure(s) indicated in Table 1 of this section.\\\\n\\\\nTable 1—Test Requirements for Commercial Packaged Boiler Equipment Classes\\\\n\\\\nEquipment category\\\\nSubcategory\\\\nCertified rated inputBtu/h\\\\n\\\\nStandards efficiency metric(§\\\\u2009431.87)\\\\n\\\\nTest procedure(corresponding to\\\\nstandards efficiency\\\\nmetric required\\\\nby §\\\\u2009431.87)\\\\n\\\\n\\\\n\\\\nHot Water\\\\nGas-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nHot Water\\\\nGas-fired\\\\n>2,500,000\\\\nCombustion Efficiency\\\\nAppendix A, Section 3.\\\\n\\\\n\\\\nHot Water\\\\nOil-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nHot Water\\\\nOil-fired\\\\n>2,500,000\\\\nCombustion Efficiency\\\\nAppendix A, Section 3.\\\\n\\\\n\\\\nSteam\\\\nGas-fired (all*)\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nSteam\\\\nGas-fired (all*)\\\\n>2,500,000 and ≤5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\n\\\\u2003\\\\n\\\\n>5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.OR\\\\nAppendix A, Section 3 with Section 2.4.3.2.\\\\n\\\\n\\\\n\\\\nSteam\\\\nOil-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nSteam\\\\nOil-fired\\\\n>2,500,000 and ≤5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\n\\\\u2003\\\\n\\\\n>5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.OR\\\\nAppendix A, Section 3. with Section 2.4.3.2.\\\\n\\\\n\\\\n\\\\n*\\\\u2009Equipment classes for commercial packaged boilers as of July 22, 2009 (74 FR 36355) distinguish between gas-fired natural draft and all other gas-fired (except natural draft).\\\\n\\\\n(c) Field Tests. The field test provisions of appendix A may be used only to test a unit of commercial packaged boiler with rated input greater than 5,000,000 Btu/h.\\\\n[81 FR 89305, Dec. 9, 2016]\\\\n\\\\n\\\\nEnergy Efficiency Standards\\\\n\\\\n\\')]\\n\\n\\u200bLazy load\\nYou can use lazy loading to only load one page at a time in order to minimize memory requirements.\\nCopypages = []\\nfor doc in loader.lazy_load():\\n pages.append(doc)\\n\\nprint(pages[0].page_content[:100])\\nprint(pages[0].metadata)\\n\\nCopy10\\nEnergy\\n3\\n2018-01-01\\n2018-01-01\\nfalse\\nUniform test method for the measurement of energy efficien\\n{\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}\\n\\n\\u200bAsync\\nCopypages = []\\nasync for doc in loader.alazy_load():\\n pages.append(doc)\\n\\nprint(pages[0].page_content[:100])\\nprint(pages[0].metadata)\\n\\nCopyFetching pages: 100%|###########################################################################| 1/1 [00:00<00:00, 10.51it/s]\\n\\nCopy10\\nEnergy\\n3\\n2018-01-01\\n2018-01-01\\nfalse\\nUniform test method for the measurement of energy efficien\\n{\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}\\n\\n\\u200bUsing proxies\\nSometimes you might need to use proxies to get around IP blocks. You can pass in a dictionary of proxies to the loader (and requests underneath) to use them.\\nCopyloader = WebBaseLoader(\\n \"https://www.walmart.com/search?q=parrots\",\\n proxies={\\n \"http\": \"http://{username}:{password}:@proxy.service.com:6666/\",\\n \"https\": \"https://{username}:{password}:@proxy.service.com:6666/\",\\n },\\n)\\ndocs = loader.load()\\n\\n\\n\\u200bAPI reference\\nFor detailed documentation of all WebBaseLoader features and configurations head to the API reference: python.langchain.com/api_reference/community/document_loaders/langchain_community.document_loaders.web_base.WebBaseLoader.html\\n\\nEdit this page on GitHub or file an issue.Connect these docs to Claude, VSCode, and more via MCP for real-time answers.Was this page helpful?YesNo⌘IDocs by LangChain home pagegithubxlinkedinyoutubeResourcesForumChangelogLangChain AcademyTrust CenterCompanyHomeAboutCareersBloggithubxlinkedinyoutube\\n')]"
69
+ ]
70
+ },
71
+ "execution_count": 10,
72
+ "metadata": {},
73
+ "output_type": "execute_result"
74
+ }
75
+ ],
76
+ "source": [
77
+ "docs=loader.load()\n",
78
+ "docs"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": 13,
84
+ "id": "0ee58d3a",
85
+ "metadata": {},
86
+ "outputs": [
87
+ {
88
+ "data": {
89
+ "text/plain": [
90
+ "'WebBaseLoader integration - Docs by LangChainSkip to main contentDocs by LangChain home pageOpen sourceSearch...⌘KAsk AIGitHubTry LangSmithTry LangSmithSearch...NavigationWebBaseLoader integrationDeep AgentsLangChainLangGraphIntegrationsLearnReferenceContributePythonLangChain integrationsAll providersPopular ProvidersOpenAIAnthropicGoogleAWSHugging FaceMicrosoftOllamaGroqNVIDIAIntegrations by componentChat modelsTools and toolkitsMiddlewareRetrieversText splittersEmbedding modelsVector storesDocument loadersKey-value storesOn this pageOverviewIntegration detailsLoader featuresSetupCredentialsInstallationInitializationInitialization with multiple pagesLoadLoad multiple urls concurrentlyLoading a xml file, or using a different BeautifulSoup parserLazy loadAsyncUsing proxiesAPI referenceWebBaseLoader integrationCopy pageIntegrate with the WebBaseLoader document loader using LangChain Python.Copy pageThis covers how to use WebBaseLoader to load all text from HTML webpages into a document format that we can use downstream. For more custom logic for loading webpages look at some child class examples such as IMSDbLoader, AZLyricsLoader, and CollegeConfidentialLoader.\\nIf you don’t want to worry about website crawling, bypassing JS-blocking sites, and data cleaning, consider using FireCrawlLoader or the faster option SpiderLoader.\\n\\u200bOverview\\n\\u200bIntegration details\\n\\nTODO: Fill in table features.\\nTODO: Remove JS support link if not relevant, otherwise ensure link is correct.\\nTODO: Make sure API reference links are correct.\\n\\nClassPackageLocalSerializableJS supportWebBaseLoaderlangchain-community✅❌❌\\n\\u200bLoader features\\nSourceDocument Lazy LoadingNative Async SupportWebBaseLoader✅✅\\n\\u200bSetup\\n\\u200bCredentials\\nWebBaseLoader does not require any credentials.\\n\\u200bInstallation\\nTo use the WebBaseLoader you first need to install the langchain-community python package.\\nCopypip install -qU langchain-community beautifulsoup4\\n\\n\\u200bInitialization\\nNow we can instantiate our model object and load documents:\\nCopyfrom langchain_community.document_loaders import WebBaseLoader\\n\\nloader = WebBaseLoader(\"https://www.example.com/\")\\n\\nTo bypass SSL verification errors during fetching, you can set the “verify” option:\\nloader.requests_kwargs = {\\'verify\\':False}\\n\\u200bInitialization with multiple pages\\nYou can also pass in a list of pages to load from.\\nCopyloader_multiple_pages = WebBaseLoader(\\n [\"https://www.example.com/\", \"https://google.com\"]\\n)\\n\\n\\u200bLoad\\nCopydocs = loader.load()\\n\\ndocs[0]\\n\\nCopyDocument(metadata={\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}, page_content=\\'\\\\n\\\\n\\\\nExample Domain\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\nExample Domain\\\\nThis domain is for use in illustrative examples in documents. You may use this\\\\n domain in literature without prior coordination or asking for permission.\\\\nMore information...\\\\n\\\\n\\\\n\\\\n\\')\\n\\nCopyprint(docs[0].metadata)\\n\\nCopy{\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}\\n\\n\\u200bLoad multiple urls concurrently\\nYou can speed up the scraping process by scraping and parsing multiple urls concurrently.\\nThere are reasonable limits to concurrent requests, defaulting to 2 per second. If you aren’t concerned about being a good citizen, or you control the server you are scraping and don’t care about load, you can change the requests_per_second parameter to increase the max concurrent requests. Note, while this will speed up the scraping process, but may cause the server to block you. Be careful!\\nCopypip install -qU nest_asyncio\\n\\n# fixes a bug with asyncio and jupyter\\nimport nest_asyncio\\n\\nnest_asyncio.apply()\\n\\nCopyloader = WebBaseLoader([\"https://www.example.com/\", \"https://google.com\"])\\nloader.requests_per_second = 1\\ndocs = loader.aload()\\ndocs\\n\\nCopyFetching pages: 100%|###########################################################################| 2/2 [00:00<00:00, 8.28it/s]\\n\\nCopy[Document(metadata={\\'source\\': \\'https://www.example.com/\\', \\'title\\': \\'Example Domain\\', \\'language\\': \\'No language found.\\'}, page_content=\\'\\\\n\\\\n\\\\nExample Domain\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\nExample Domain\\\\nThis domain is for use in illustrative examples in documents. You may use this\\\\n domain in literature without prior coordination or asking for permission.\\\\nMore information...\\\\n\\\\n\\\\n\\\\n\\'),\\n Document(metadata={\\'source\\': \\'https://google.com\\', \\'title\\': \\'Google\\', \\'description\\': \"Search the world\\'s information, including webpages, images, videos and more. Google has many special features to help you find exactly what you\\'re looking for.\", \\'language\\': \\'en\\'}, page_content=\\'GoogleSearch Images Maps Play YouTube News Gmail Drive More »Web History | Settings | Sign in\\\\xa0Advanced search5 ways Gemini can help during the HolidaysAdvertisingBusiness SolutionsAbout Google© 2024 - Privacy - Terms \\')]\\n\\n\\u200bLoading a xml file, or using a different BeautifulSoup parser\\nYou can also look at SitemapLoader for an example of how to load a sitemap file, which is an example of using this feature.\\nCopyloader = WebBaseLoader(\\n \"https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\"\\n)\\nloader.default_parser = \"xml\"\\ndocs = loader.load()\\ndocs\\n\\nCopy[Document(metadata={\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}, page_content=\\'\\\\n\\\\n10\\\\nEnergy\\\\n3\\\\n2018-01-01\\\\n2018-01-01\\\\nfalse\\\\nUniform test method for the measurement of energy efficiency of commercial packaged boilers.\\\\n§ 431.86\\\\nSection § 431.86\\\\n\\\\nEnergy\\\\nDEPARTMENT OF ENERGY\\\\nENERGY CONSERVATION\\\\nENERGY EFFICIENCY PROGRAM FOR CERTAIN COMMERCIAL AND INDUSTRIAL EQUIPMENT\\\\nCommercial Packaged Boilers\\\\nTest Procedures\\\\n\\\\n\\\\n\\\\n\\\\n§\\\\u2009431.86\\\\nUniform test method for the measurement of energy efficiency of commercial packaged boilers.\\\\n(a) Scope. This section provides test procedures, pursuant to the Energy Policy and Conservation Act (EPCA), as amended, which must be followed for measuring the combustion efficiency and/or thermal efficiency of a gas- or oil-fired commercial packaged boiler.\\\\n(b) Testing and Calculations. Determine the thermal efficiency or combustion efficiency of commercial packaged boilers by conducting the appropriate test procedure(s) indicated in Table 1 of this section.\\\\n\\\\nTable 1—Test Requirements for Commercial Packaged Boiler Equipment Classes\\\\n\\\\nEquipment category\\\\nSubcategory\\\\nCertified rated inputBtu/h\\\\n\\\\nStandards efficiency metric(§\\\\u2009431.87)\\\\n\\\\nTest procedure(corresponding to\\\\nstandards efficiency\\\\nmetric required\\\\nby §\\\\u2009431.87)\\\\n\\\\n\\\\n\\\\nHot Water\\\\nGas-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nHot Water\\\\nGas-fired\\\\n>2,500,000\\\\nCombustion Efficiency\\\\nAppendix A, Section 3.\\\\n\\\\n\\\\nHot Water\\\\nOil-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nHot Water\\\\nOil-fired\\\\n>2,500,000\\\\nCombustion Efficiency\\\\nAppendix A, Section 3.\\\\n\\\\n\\\\nSteam\\\\nGas-fired (all*)\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nSteam\\\\nGas-fired (all*)\\\\n>2,500,000 and ≤5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\n\\\\u2003\\\\n\\\\n>5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.OR\\\\nAppendix A, Section 3 with Section 2.4.3.2.\\\\n\\\\n\\\\n\\\\nSteam\\\\nOil-fired\\\\n≥300,000 and ≤2,500,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\nSteam\\\\nOil-fired\\\\n>2,500,000 and ≤5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.\\\\n\\\\n\\\\n\\\\u2003\\\\n\\\\n>5,000,000\\\\nThermal Efficiency\\\\nAppendix A, Section 2.OR\\\\nAppendix A, Section 3. with Section 2.4.3.2.\\\\n\\\\n\\\\n\\\\n*\\\\u2009Equipment classes for commercial packaged boilers as of July 22, 2009 (74 FR 36355) distinguish between gas-fired natural draft and all other gas-fired (except natural draft).\\\\n\\\\n(c) Field Tests. The field test provisions of appendix A may be used only to test a unit of commercial packaged boiler with rated input greater than 5,000,000 Btu/h.\\\\n[81 FR 89305, Dec. 9, 2016]\\\\n\\\\n\\\\nEnergy Efficiency Standards\\\\n\\\\n\\')]\\n\\n\\u200bLazy load\\nYou can use lazy loading to only load one page at a time in order to minimize memory requirements.\\nCopypages = []\\nfor doc in loader.lazy_load():\\n pages.append(doc)\\n\\nprint(pages[0].page_content[:100])\\nprint(pages[0].metadata)\\n\\nCopy10\\nEnergy\\n3\\n2018-01-01\\n2018-01-01\\nfalse\\nUniform test method for the measurement of energy efficien\\n{\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}\\n\\n\\u200bAsync\\nCopypages = []\\nasync for doc in loader.alazy_load():\\n pages.append(doc)\\n\\nprint(pages[0].page_content[:100])\\nprint(pages[0].metadata)\\n\\nCopyFetching pages: 100%|###########################################################################| 1/1 [00:00<00:00, 10.51it/s]\\n\\nCopy10\\nEnergy\\n3\\n2018-01-01\\n2018-01-01\\nfalse\\nUniform test method for the measurement of energy efficien\\n{\\'source\\': \\'https://www.govinfo.gov/content/pkg/CFR-2018-title10-vol3/xml/CFR-2018-title10-vol3-sec431-86.xml\\'}\\n\\n\\u200bUsing proxies\\nSometimes you might need to use proxies to get around IP blocks. You can pass in a dictionary of proxies to the loader (and requests underneath) to use them.\\nCopyloader = WebBaseLoader(\\n \"https://www.walmart.com/search?q=parrots\",\\n proxies={\\n \"http\": \"http://{username}:{password}:@proxy.service.com:6666/\",\\n \"https\": \"https://{username}:{password}:@proxy.service.com:6666/\",\\n },\\n)\\ndocs = loader.load()\\n\\n\\n\\u200bAPI reference\\nFor detailed documentation of all WebBaseLoader features and configurations head to the API reference: python.langchain.com/api_reference/community/document_loaders/langchain_community.document_loaders.web_base.WebBaseLoader.html\\n\\nEdit this page on GitHub or file an issue.Connect these docs to Claude, VSCode, and more via MCP for real-time answers.Was this page helpful?YesNo⌘IDocs by LangChain home pagegithubxlinkedinyoutubeResourcesForumChangelogLangChain AcademyTrust CenterCompanyHomeAboutCareersBloggithubxlinkedinyoutube\\n'"
91
+ ]
92
+ },
93
+ "execution_count": 13,
94
+ "metadata": {},
95
+ "output_type": "execute_result"
96
+ }
97
+ ],
98
+ "source": [
99
+ "docs[0].page_content"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "code",
104
+ "execution_count": 14,
105
+ "id": "775a77b9",
106
+ "metadata": {},
107
+ "outputs": [
108
+ {
109
+ "data": {
110
+ "text/plain": [
111
+ "1"
112
+ ]
113
+ },
114
+ "execution_count": 14,
115
+ "metadata": {},
116
+ "output_type": "execute_result"
117
+ }
118
+ ],
119
+ "source": [
120
+ "len(docs)"
121
+ ]
122
+ },
123
+ {
124
+ "cell_type": "code",
125
+ "execution_count": 16,
126
+ "id": "47202522",
127
+ "metadata": {},
128
+ "outputs": [
129
+ {
130
+ "data": {
131
+ "text/plain": [
132
+ "992"
133
+ ]
134
+ },
135
+ "execution_count": 16,
136
+ "metadata": {},
137
+ "output_type": "execute_result"
138
+ }
139
+ ],
140
+ "source": [
141
+ "len(docs[0].page_content.split())"
142
+ ]
143
+ },
144
+ {
145
+ "cell_type": "code",
146
+ "execution_count": 2,
147
+ "id": "46f0d682",
148
+ "metadata": {},
149
+ "outputs": [],
150
+ "source": [
151
+ "from langchain_community.document_loaders import YoutubeLoader"
152
+ ]
153
+ },
154
+ {
155
+ "cell_type": "code",
156
+ "execution_count": 3,
157
+ "id": "c0cb3d1f",
158
+ "metadata": {},
159
+ "outputs": [],
160
+ "source": [
161
+ "loader = YoutubeLoader.from_youtube_url(\n",
162
+ " \"https://www.youtube.com/watch?v=QsYGlZkevEg\", add_video_info=False\n",
163
+ ")"
164
+ ]
165
+ },
166
+ {
167
+ "cell_type": "code",
168
+ "execution_count": 5,
169
+ "id": "496ebb6d",
170
+ "metadata": {},
171
+ "outputs": [
172
+ {
173
+ "data": {
174
+ "text/plain": [
175
+ "[Document(metadata={'source': 'QsYGlZkevEg'}, page_content='LADIES AND GENTLEMEN, PEDRO PASCAL! [ CHEERS AND APPLAUSE ] >> THANK YOU, THANK YOU. THANK YOU VERY MUCH. I\\'M SO EXCITED TO BE HERE. THANK YOU. I SPENT THE LAST YEAR SHOOTING A SHOW CALLED \"THE LAST OF US\" ON HBO. FOR SOME HBO SHOES, YOU GET TO SHOOT IN A FIVE STAR ITALIAN RESORT SURROUNDED BY BEAUTIFUL PEOPLE, BUT I SAID, NO, THAT\\'S TOO EASY. I WANT TO SHOOT IN A FREEZING CANADIAN FOREST WHILE BEING CHASED AROUND BY A GUY WHOSE HEAD LOOKS LIKE A GENITAL WART. IT IS AN HONOR BEING A PART OF THESE HUGE FRANCHISEs LIKE \"GAME OF THRONES\" AND \"STAR WARS,\" BUT I\\'M STILL GETTING USED TO PEOPLE RECOGNIZING ME. THE OTHER DAY, A GUY STOPPED ME ON THE STREET AND SAYS, MY SON LOVES \"THE MANDALORIAN\" AND THE NEXT THING I KNOW, I\\'M FACE TIMING WITH A 6-YEAR-OLD WHO HAS NO IDEA WHO I AM BECAUSE MY CHARACTER WEARS A MASK THE ENTIRE SHOW. THE GUY IS LIKE, DO THE MANDO VOICE, BUT IT\\'S LIKE A BEDROOM VOICE. WITHOUT THE MASK, IT JUST SOUNDS PORNY. PEOPLE WALKING BY ON THE STREET SEE ME WHISPERING TO A 6-YEAR-OLD KID. I CAN BRING YOU IN WARM, OR I CAN BRING YOU IN COLD. EVEN THOUGH I CAME TO THE U.S. WHEN I WAS LITTLE, I WAS BORN IN CHILE, AND I HAVE 34 FIRST COUSINS WHO ARE STILL THERE. THEY\\'RE VERY PROUD OF ME. I KNOW THEY\\'RE PROUD BECAUSE THEY GIVE MY PHONE NUMBER TO EVERY PERSON THEY MEET, WHICH MEANS EVERY DAY, SOMEONE IN SANTIAGO WILL TEXT ME STUFF LIKE, CAN YOU COME TO MY WEDDING, OR CAN YOU SING MY PRIEST HAPPY BIRTHDAY, OR IS BABY YODA MEAN IN REAL LIFE. SO I HAVE TO BE LIKE NO, NO, AND HIS NAME IS GROGU. BUT MY COUSINS WEREN\\'T ALWAYS SO PROUD. EARLY IN MY CAREER, I PLAYED SMALL PARTS IN EVERY CRIME SHOW. I EVEN PLAYED TWO DIFFERENT CHARACTERS ON \"LAW AND ORDER.\" TITO CABASSA WHO LOOKED LIKE THIS. AND ONE YEAR LATER, I PLAYED REGGIE LUCKMAN WHO LOOKS LIKE THIS. AND THAT, MY FRIENDS, IS CALLED RANGE. BUT IT IS AMAZING TO BE HERE, LIKE I SAID. I WAS BORN IN CHILE, AND NINE MONTHS LATER, MY PARENTS FLED AND BROUGHT ME AND MY SISTER TO THE U.S. THEY WERE SO BRAVE, AND WITHOUT THEM, I WOULDN\\'T BE HERE IN THIS WONDERFUL COUNTRY, AND I CERTAINLY WOULDN\\'T BE STANDING HERE WITH YOU ALL TONIGHT. SO TO ALL MY FAMILY WATCHING IN CHILE, I WANT TO SAY [ SPEAKING NON-ENGLISH ] WHICH MEANS, I LOVE YOU, I MISS YOU, AND STOP GIVING OUT MY PHONE NUMBER. WE\\'VE GOT AN AMAZING SHOW FOR YOU TONIGHT. COLDPLAY IS HERE, SO STICK')]"
176
+ ]
177
+ },
178
+ "execution_count": 5,
179
+ "metadata": {},
180
+ "output_type": "execute_result"
181
+ }
182
+ ],
183
+ "source": [
184
+ "loader.load()"
185
+ ]
186
+ },
187
+ {
188
+ "cell_type": "code",
189
+ "execution_count": 8,
190
+ "id": "3c4920b7",
191
+ "metadata": {},
192
+ "outputs": [
193
+ {
194
+ "ename": "HTTPError",
195
+ "evalue": "HTTP Error 400: Bad Request",
196
+ "output_type": "error",
197
+ "traceback": [
198
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
199
+ "\u001b[31mHTTPError\u001b[39m Traceback (most recent call last)",
200
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 4\u001b[39m\n\u001b[32m 1\u001b[39m loader = YoutubeLoader.from_youtube_url(\n\u001b[32m 2\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mhttps://www.youtube.com/watch?v=QsYGlZkevEg\u001b[39m\u001b[33m\"\u001b[39m, add_video_info=\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m 3\u001b[39m )\n\u001b[32m----> \u001b[39m\u001b[32m4\u001b[39m \u001b[43mloader\u001b[49m\u001b[43m.\u001b[49m\u001b[43mload\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
201
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\langchain_community\\document_loaders\\youtube.py:258\u001b[39m, in \u001b[36mYoutubeLoader.load\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 250\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mImportError\u001b[39;00m(\n\u001b[32m 251\u001b[39m \u001b[33m'\u001b[39m\u001b[33mCould not import \u001b[39m\u001b[33m\"\u001b[39m\u001b[33myoutube_transcript_api\u001b[39m\u001b[33m\"\u001b[39m\u001b[33m Python package. \u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m 252\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mPlease install it with `pip install youtube-transcript-api`.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 253\u001b[39m )\n\u001b[32m 255\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m.add_video_info:\n\u001b[32m 256\u001b[39m \u001b[38;5;66;03m# Get more video meta info\u001b[39;00m\n\u001b[32m 257\u001b[39m \u001b[38;5;66;03m# Such as title, description, thumbnail url, publish_date\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m258\u001b[39m video_info = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_get_video_info\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 259\u001b[39m \u001b[38;5;28mself\u001b[39m._metadata.update(video_info)\n\u001b[32m 261\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n",
202
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\langchain_community\\document_loaders\\youtube.py:336\u001b[39m, in \u001b[36mYoutubeLoader._get_video_info\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 330\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mImportError\u001b[39;00m(\n\u001b[32m 331\u001b[39m \u001b[33m'\u001b[39m\u001b[33mCould not import \u001b[39m\u001b[33m\"\u001b[39m\u001b[33mpytube\u001b[39m\u001b[33m\"\u001b[39m\u001b[33m Python package. \u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m 332\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mPlease install it with `pip install pytube`.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 333\u001b[39m )\n\u001b[32m 334\u001b[39m yt = YouTube(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mhttps://www.youtube.com/watch?v=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m.video_id\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m\"\u001b[39m)\n\u001b[32m 335\u001b[39m video_info = {\n\u001b[32m--> \u001b[39m\u001b[32m336\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mtitle\u001b[39m\u001b[33m\"\u001b[39m: \u001b[43myt\u001b[49m\u001b[43m.\u001b[49m\u001b[43mtitle\u001b[49m \u001b[38;5;129;01mor\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mUnknown\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 337\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mdescription\u001b[39m\u001b[33m\"\u001b[39m: yt.description \u001b[38;5;129;01mor\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mUnknown\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 338\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mview_count\u001b[39m\u001b[33m\"\u001b[39m: yt.views \u001b[38;5;129;01mor\u001b[39;00m \u001b[32m0\u001b[39m,\n\u001b[32m 339\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mthumbnail_url\u001b[39m\u001b[33m\"\u001b[39m: yt.thumbnail_url \u001b[38;5;129;01mor\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mUnknown\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 340\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mpublish_date\u001b[39m\u001b[33m\"\u001b[39m: yt.publish_date.strftime(\u001b[33m\"\u001b[39m\u001b[33m%\u001b[39m\u001b[33mY-\u001b[39m\u001b[33m%\u001b[39m\u001b[33mm-\u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[33m \u001b[39m\u001b[33m%\u001b[39m\u001b[33mH:\u001b[39m\u001b[33m%\u001b[39m\u001b[33mM:\u001b[39m\u001b[33m%\u001b[39m\u001b[33mS\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 341\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m yt.publish_date\n\u001b[32m 342\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mUnknown\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 343\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mlength\u001b[39m\u001b[33m\"\u001b[39m: yt.length \u001b[38;5;129;01mor\u001b[39;00m \u001b[32m0\u001b[39m,\n\u001b[32m 344\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mauthor\u001b[39m\u001b[33m\"\u001b[39m: yt.author \u001b[38;5;129;01mor\u001b[39;00m \u001b[33m\"\u001b[39m\u001b[33mUnknown\u001b[39m\u001b[33m\"\u001b[39m,\n\u001b[32m 345\u001b[39m }\n\u001b[32m 346\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m video_info\n",
203
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\pytube\\__main__.py:341\u001b[39m, in \u001b[36mYouTube.title\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 338\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._title\n\u001b[32m 340\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m341\u001b[39m \u001b[38;5;28mself\u001b[39m._title = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mvid_info\u001b[49m[\u001b[33m'\u001b[39m\u001b[33mvideoDetails\u001b[39m\u001b[33m'\u001b[39m][\u001b[33m'\u001b[39m\u001b[33mtitle\u001b[39m\u001b[33m'\u001b[39m]\n\u001b[32m 342\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[32m 343\u001b[39m \u001b[38;5;66;03m# Check_availability will raise the correct exception in most cases\u001b[39;00m\n\u001b[32m 344\u001b[39m \u001b[38;5;66;03m# if it doesn't, ask for a report.\u001b[39;00m\n\u001b[32m 345\u001b[39m \u001b[38;5;28mself\u001b[39m.check_availability()\n",
204
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\pytube\\__main__.py:246\u001b[39m, in \u001b[36mYouTube.vid_info\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 242\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._vid_info\n\u001b[32m 244\u001b[39m innertube = InnerTube(use_oauth=\u001b[38;5;28mself\u001b[39m.use_oauth, allow_cache=\u001b[38;5;28mself\u001b[39m.allow_oauth_cache)\n\u001b[32m--> \u001b[39m\u001b[32m246\u001b[39m innertube_response = \u001b[43minnertube\u001b[49m\u001b[43m.\u001b[49m\u001b[43mplayer\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mvideo_id\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 247\u001b[39m \u001b[38;5;28mself\u001b[39m._vid_info = innertube_response\n\u001b[32m 248\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._vid_info\n",
205
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\pytube\\innertube.py:448\u001b[39m, in \u001b[36mInnerTube.player\u001b[39m\u001b[34m(self, video_id)\u001b[39m\n\u001b[32m 444\u001b[39m query = {\n\u001b[32m 445\u001b[39m \u001b[33m'\u001b[39m\u001b[33mvideoId\u001b[39m\u001b[33m'\u001b[39m: video_id,\n\u001b[32m 446\u001b[39m }\n\u001b[32m 447\u001b[39m query.update(\u001b[38;5;28mself\u001b[39m.base_params)\n\u001b[32m--> \u001b[39m\u001b[32m448\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_call_api\u001b[49m\u001b[43m(\u001b[49m\u001b[43mendpoint\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mquery\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mbase_data\u001b[49m\u001b[43m)\u001b[49m\n",
206
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\pytube\\innertube.py:390\u001b[39m, in \u001b[36mInnerTube._call_api\u001b[39m\u001b[34m(self, endpoint, query, data)\u001b[39m\n\u001b[32m 386\u001b[39m headers[\u001b[33m'\u001b[39m\u001b[33mAuthorization\u001b[39m\u001b[33m'\u001b[39m] = \u001b[33mf\u001b[39m\u001b[33m'\u001b[39m\u001b[33mBearer \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m.access_token\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m'\u001b[39m\n\u001b[32m 388\u001b[39m headers.update(\u001b[38;5;28mself\u001b[39m.header)\n\u001b[32m--> \u001b[39m\u001b[32m390\u001b[39m response = \u001b[43mrequest\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_execute_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 391\u001b[39m \u001b[43m \u001b[49m\u001b[43mendpoint_url\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 392\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mPOST\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m 393\u001b[39m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[43m=\u001b[49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m 394\u001b[39m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m=\u001b[49m\u001b[43mdata\u001b[49m\n\u001b[32m 395\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 396\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m json.loads(response.read())\n",
207
+ "\u001b[36mFile \u001b[39m\u001b[32mc:\\Users\\vansh\\Projects\\AIAgents\\.venv\\Lib\\site-packages\\pytube\\request.py:37\u001b[39m, in \u001b[36m_execute_request\u001b[39m\u001b[34m(url, method, headers, data, timeout)\u001b[39m\n\u001b[32m 35\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 36\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mInvalid URL\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m---> \u001b[39m\u001b[32m37\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43murlopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m=\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n",
208
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:215\u001b[39m, in \u001b[36murlopen\u001b[39m\u001b[34m(url, data, timeout, cafile, capath, cadefault, context)\u001b[39m\n\u001b[32m 213\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 214\u001b[39m opener = _opener\n\u001b[32m--> \u001b[39m\u001b[32m215\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mopener\u001b[49m\u001b[43m.\u001b[49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n",
209
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:521\u001b[39m, in \u001b[36mOpenerDirector.open\u001b[39m\u001b[34m(self, fullurl, data, timeout)\u001b[39m\n\u001b[32m 519\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m processor \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m.process_response.get(protocol, []):\n\u001b[32m 520\u001b[39m meth = \u001b[38;5;28mgetattr\u001b[39m(processor, meth_name)\n\u001b[32m--> \u001b[39m\u001b[32m521\u001b[39m response = \u001b[43mmeth\u001b[49m\u001b[43m(\u001b[49m\u001b[43mreq\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresponse\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 523\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m response\n",
210
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:630\u001b[39m, in \u001b[36mHTTPErrorProcessor.http_response\u001b[39m\u001b[34m(self, request, response)\u001b[39m\n\u001b[32m 627\u001b[39m \u001b[38;5;66;03m# According to RFC 2616, \"2xx\" code indicates that the client's\u001b[39;00m\n\u001b[32m 628\u001b[39m \u001b[38;5;66;03m# request was successfully received, understood, and accepted.\u001b[39;00m\n\u001b[32m 629\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[32m200\u001b[39m <= code < \u001b[32m300\u001b[39m):\n\u001b[32m--> \u001b[39m\u001b[32m630\u001b[39m response = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mparent\u001b[49m\u001b[43m.\u001b[49m\u001b[43merror\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 631\u001b[39m \u001b[43m \u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mhttp\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresponse\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmsg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhdrs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 633\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m response\n",
211
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:559\u001b[39m, in \u001b[36mOpenerDirector.error\u001b[39m\u001b[34m(self, proto, *args)\u001b[39m\n\u001b[32m 557\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m http_err:\n\u001b[32m 558\u001b[39m args = (\u001b[38;5;28mdict\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mdefault\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mhttp_error_default\u001b[39m\u001b[33m'\u001b[39m) + orig_args\n\u001b[32m--> \u001b[39m\u001b[32m559\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_call_chain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n",
212
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:492\u001b[39m, in \u001b[36mOpenerDirector._call_chain\u001b[39m\u001b[34m(self, chain, kind, meth_name, *args)\u001b[39m\n\u001b[32m 490\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m handler \u001b[38;5;129;01min\u001b[39;00m handlers:\n\u001b[32m 491\u001b[39m func = \u001b[38;5;28mgetattr\u001b[39m(handler, meth_name)\n\u001b[32m--> \u001b[39m\u001b[32m492\u001b[39m result = \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43margs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 493\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m result \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 494\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m result\n",
213
+ "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Roaming\\uv\\python\\cpython-3.12.12-windows-x86_64-none\\Lib\\urllib\\request.py:639\u001b[39m, in \u001b[36mHTTPDefaultErrorHandler.http_error_default\u001b[39m\u001b[34m(self, req, fp, code, msg, hdrs)\u001b[39m\n\u001b[32m 638\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mhttp_error_default\u001b[39m(\u001b[38;5;28mself\u001b[39m, req, fp, code, msg, hdrs):\n\u001b[32m--> \u001b[39m\u001b[32m639\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m HTTPError(req.full_url, code, msg, hdrs, fp)\n",
214
+ "\u001b[31mHTTPError\u001b[39m: HTTP Error 400: Bad Request"
215
+ ]
216
+ }
217
+ ],
218
+ "source": [
219
+ "loader = YoutubeLoader.from_youtube_url(\n",
220
+ " \"https://www.youtube.com/watch?v=QsYGlZkevEg\", add_video_info=True\n",
221
+ ")\n",
222
+ "loader.load()"
223
+ ]
224
+ },
225
+ {
226
+ "cell_type": "code",
227
+ "execution_count": null,
228
+ "id": "7c635f42",
229
+ "metadata": {},
230
+ "outputs": [],
231
+ "source": []
232
+ }
233
+ ],
234
+ "metadata": {
235
+ "kernelspec": {
236
+ "display_name": ".venv",
237
+ "language": "python",
238
+ "name": "python3"
239
+ },
240
+ "language_info": {
241
+ "codemirror_mode": {
242
+ "name": "ipython",
243
+ "version": 3
244
+ },
245
+ "file_extension": ".py",
246
+ "mimetype": "text/x-python",
247
+ "name": "python",
248
+ "nbconvert_exporter": "python",
249
+ "pygments_lexer": "ipython3",
250
+ "version": "3.12.12"
251
+ }
252
+ },
253
+ "nbformat": 4,
254
+ "nbformat_minor": 5
255
+ }
pyproject.toml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "aiagents"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ 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",
13
+ "langchain>=1.2.10",
14
+ "langchain-aws>=1.3.1",
15
+ "langchain-chroma>=1.1.0",
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
+ ]
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ -e .
results/Attention is All You Need Paper Explained.md ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Attention is All You Need Paper Explained
2
+ ## Introduction to Attention is All You Need
3
+ The concept of attention in deep learning refers to the ability of a model to focus on specific parts of the input data that are relevant for the task at hand.
4
+ * Introduce the concept of attention in deep learning: Attention allows models to selectively concentrate on certain inputs or features, improving performance and efficiency.
5
+ * Explain the limitations of traditional sequence-to-sequence models: Traditional sequence-to-sequence models rely on recurrent neural networks (RNNs) or long short-term memory (LSTM) networks, which can be limited by their sequential processing and fixed-length context.
6
+ * Highlight the key contributions of the Attention is All You Need paper: The Attention is All You Need paper introduced a novel architecture that relies entirely on self-attention mechanisms, eliminating the need for RNNs and LSTMs, and achieving state-of-the-art results in machine translation tasks.
7
+ ![attention mechanism](../images/attention_mechanism.png)
8
+ ## The Transformer Model Architecture
9
+ The Transformer model, introduced in the "Attention is All You Need" paper, revolutionized the field of natural language processing. At its core, the Transformer model consists of an encoder-decoder structure.
10
+ * The encoder takes in a sequence of tokens, such as words or characters, and generates a continuous representation of the input sequence.
11
+ * The decoder then uses this representation to generate the output sequence, one token at a time.
12
+
13
+ Self-attention mechanisms play a crucial role in the Transformer model, allowing it to weigh the importance of different tokens in the input sequence relative to each other. This is particularly useful for tasks such as machine translation, where the context of a word can greatly affect its translation.
14
+
15
+ The Transformer model also relies on positional encoding to preserve the order of the input sequence. Since the self-attention mechanism is permutation-invariant, the model would not be able to distinguish between different token orders without some form of positional information.
16
+ Positional encoding adds a fixed vector to each token's representation, based on its position in the sequence, allowing the model to capture sequential relationships between tokens.
17
+ This combination of self-attention and positional encoding enables the Transformer model to effectively process sequential data, making it a powerful tool for a wide range of NLP tasks.
18
+ ![transformer architecture](../images/transformer_architecture.png)
19
+ ## Applying the Transformer Model to Real-World Examples
20
+ The Transformer model, introduced in the "Attention is All You Need" paper, has been widely adopted in various NLP tasks. To apply this model to real-world examples, it's essential to understand its implementation and applications.
21
+ * A minimal code sketch of a Transformer model implementation can be represented as follows:
22
+ ```python
23
+ import torch
24
+ import torch.nn as nn
25
+ import torch.optim as optim
26
+
27
+ class TransformerModel(nn.Module):
28
+ def __init__(self):
29
+ super(TransformerModel, self).__init__()
30
+ self.encoder = nn.TransformerEncoderLayer(d_model=512, nhead=8)
31
+ self.decoder = nn.TransformerDecoderLayer(d_model=512, nhead=8)
32
+
33
+ def forward(self, src, tgt):
34
+ encoder_output = self.encoder(src)
35
+ decoder_output = self.decoder(tgt, encoder_output)
36
+ return decoder_output
37
+ ```
38
+ * The Transformer model has been highly effective in machine translation tasks, allowing for parallelization of the decoding process and improving overall translation quality.
39
+ * The Transformer model can also be applied to other NLP tasks, such as text classification, sentiment analysis, and question answering, by modifying the model architecture and training objectives to suit the specific task requirements.
40
+ ![transformer application](../images/transformer_application.png)
41
+ ## Common Mistakes and Challenges
42
+ When implementing the Transformer model, several common pitfalls can hinder its performance.
43
+ * Proper hyperparameter tuning is crucial, as it directly affects the model's ability to learn and generalize.
44
+ * Training large Transformer models can be challenging due to their complexity and computational requirements, often leading to issues like overfitting or slow training times.
45
+ * Careful evaluation metrics are necessary to accurately assess the model's performance, as misleading metrics can lead to suboptimal results or incorrect conclusions about the model's effectiveness.
46
+ By being aware of these potential issues, developers can take steps to mitigate them and ensure successful implementation of the Transformer model.
47
+ ![common mistakes](../images/common_mistakes.png)
48
+ ## Conclusion
49
+ The Attention is All You Need paper made significant contributions to the field of NLP, introducing a novel architecture that relies entirely on self-attention mechanisms.
50
+ * The main contributions of the paper include the proposal of a transformer model that replaces traditional recurrent neural network (RNN) and convolutional neural network (CNN) architectures.
51
+ * The paper's impact on NLP has been substantial, enabling state-of-the-art results in various tasks such as machine translation and text generation.
52
+ * Future directions for research and application include exploring the use of attention mechanisms in other areas of NLP, such as question answering and text summarization, and applying the transformer model to other domains like computer vision.
53
+ ![conclusion](../images/conclusion.png)
results/Introduction to Machine Learning.md ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Introduction to Machine Learning
2
+
3
+ ![machine learning overview](../images/machine_learning_overview.png)
4
+
5
+ ## What is Machine Learning?
6
+ Machine learning is a subset of artificial intelligence that involves training algorithms to learn from data and make predictions or decisions without being explicitly programmed.
7
+ * Define machine learning: It is a field of study that focuses on the use of algorithms and statistical models to enable machines to perform a specific task.
8
+ * Explain types of machine learning: There are several types, including supervised, unsupervised, and reinforcement learning, each with its own strengths and weaknesses.
9
+ * Provide examples of machine learning applications: Examples include image recognition, natural language processing, and predictive analytics, which are used in various industries such as healthcare, finance, and transportation.
10
+ Machine learning has numerous applications and is a key driver of innovation in many fields, with its performance and edge cases being crucial considerations for developers.
11
+
12
+ ![ml workflow diagram](../images/ml_workflow_diagram.png)
13
+
14
+ ## Machine Learning Workflow
15
+ The machine learning workflow is a series of steps that help developers build and deploy effective machine learning models. To start a machine learning project, several key steps are involved:
16
+ * Data collection: This is the initial step where data relevant to the problem is gathered. The quality and quantity of the data collected have a significant impact on the performance of the model.
17
+ * Data preprocessing: After collecting the data, it needs to be cleaned and preprocessed to ensure it is in a suitable format for the model. This step involves handling missing values, removing duplicates, and scaling the data.
18
+ * Model selection: With the preprocessed data, the next step is to choose a suitable machine learning algorithm. The choice of model depends on the type of problem, the size of the dataset, and the desired outcome.
19
+ * Model training: Once the model is selected, it is trained using the preprocessed data. The goal of this step is to find the optimal parameters that result in the best performance.
20
+ * Model evaluation: After training the model, its performance is evaluated using various metrics such as accuracy, precision, and recall. This step helps to identify the strengths and weaknesses of the model and provides insights for further improvement.
21
+ Considering edge cases and performance considerations, developers should be aware of potential issues that may arise during these steps, such as overfitting or underfitting, and take necessary measures to address them. By following these basic steps and being mindful of potential pitfalls, developers can build effective machine learning models that deliver reliable results.
22
+
23
+ ![ml common mistakes](../images/ml_common_mistakes.png)
24
+
25
+ ## Common Mistakes in Machine Learning
26
+ When working on machine learning projects, it's essential to be aware of common mistakes that can hinder performance and accuracy. These mistakes can be easily avoided with a good understanding of the underlying concepts.
27
+ * Overfitting occurs when a model is too complex and learns the training data too well, resulting in poor performance on new, unseen data.
28
+ * Underfitting happens when a model is too simple and fails to capture the underlying patterns in the training data, leading to subpar performance.
29
+ * Data leakage is another common issue, where information from the test data is inadvertently used during training, causing the model to perform unrealistically well on the test set, but poorly on real-world data.
30
+ By recognizing these potential pitfalls, developers can take steps to mitigate them and develop more robust and accurate machine learning models.
31
+
32
+ ![ml model example](../images/ml_model_example.png)
33
+
34
+ ## Machine Learning Example
35
+ To implement a simple machine learning model, several key steps must be followed. The process begins with selecting a suitable dataset.
36
+ * Choose a dataset: This is a crucial step as the quality and relevance of the data will directly impact the performance of the model. A dataset should be chosen based on the problem you are trying to solve, and it should be large enough to train the model effectively.
37
+
38
+ Once the dataset is chosen, the next step is to select a suitable model.
39
+ * Select a model: There are various machine learning models available, including linear regression, decision trees, and neural networks. The choice of model depends on the type of problem you are trying to solve and the characteristics of your dataset.
40
+
41
+ After selecting the model, the next step is to train it.
42
+ * Train the model: Training a model involves feeding it with the chosen dataset and adjusting its parameters to minimize the error between predicted and actual outputs. This can be done using various algorithms, such as gradient descent.
43
+
44
+ Finally, the trained model needs to be evaluated to determine its performance.
45
+ * Evaluate the model: Evaluation involves testing the model on a separate dataset to determine its accuracy and reliability. This can be done using metrics such as mean squared error or accuracy score.
46
+
47
+ Here's a minimal code sketch in Python to illustrate the process:
48
+ ```python
49
+ from sklearn import datasets
50
+ from sklearn.model_selection import train_test_split
51
+ from sklearn.linear_model import LinearRegression
52
+ from sklearn.metrics import mean_squared_error
53
+
54
+ # Load the dataset
55
+ dataset = datasets.load_diabetes()
56
+
57
+ # Split the dataset into training and testing sets
58
+ X_train, X_test, y_train, y_test = train_test_split(dataset.data, dataset.target, test_size=0.2, random_state=42)
59
+
60
+ # Create and train a linear regression model
61
+ model = LinearRegression()
62
+ model.fit(X_train, y_train)
63
+
64
+ # Make predictions and evaluate the model
65
+ y_pred = model.predict(X_test)
66
+ mse = mean_squared_error(y_test, y_pred)
67
+ print(f"Mean squared error: {mse}")
68
+ ```
69
+ This code sketch demonstrates how to choose a dataset, select a model, train the model, and evaluate its performance. It also highlights the importance of considering edge cases and performance considerations when implementing machine learning models.
70
+
71
+ ## Conclusion
72
+ In this introduction to machine learning, key points include understanding the basics of machine learning and its applications.
73
+ * Summarize key points: Machine learning is a subset of artificial intelligence that involves training algorithms to make predictions or decisions based on data.
74
+ * Provide resources for further learning: For developers looking to dive deeper, online courses and tutorials are available to explore machine learning concepts and implementation.
75
+ Machine learning has various applications, and its performance considerations are crucial for optimal results.
setup_folder.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ PROJECT_NAME = "."
4
+
5
+ folders = [
6
+ "src/ingestion",
7
+ "src/chunking",
8
+ "src/embeddings",
9
+ "src/vectorstore",
10
+ "src/retrievers",
11
+ "src/chains",
12
+ "src/prompts",
13
+ "src/llm",
14
+ "src/evaluation",
15
+ "src/utils",
16
+ "src/config",
17
+
18
+ "api",
19
+ "data/raw",
20
+ "data/processed",
21
+ "vector_db",
22
+ "experiments",
23
+ "monitoring",
24
+ "notebooks",
25
+ "tests",
26
+
27
+ "deployment",
28
+ "configs"
29
+ ]
30
+
31
+ files = {
32
+ "src/ingestion/ingest_pipeline.py": "",
33
+ "src/chunking/text_chunker.py": "",
34
+ "src/embeddings/embedding_model.py": "",
35
+ "src/vectorstore/vector_db.py": "",
36
+ "src/retrievers/retriever.py": "",
37
+ "src/chains/rag_chain.py": "",
38
+ "src/prompts/prompt_templates.py": "",
39
+ "src/llm/llm_loader.py": "",
40
+ "src/evaluation/rag_metrics.py": "",
41
+ "src/utils/helpers.py": "",
42
+ "src/config/settings.py": "",
43
+
44
+ "api/routes.py": "",
45
+ "api/main.py": "",
46
+
47
+ "deployment/Dockerfile": "",
48
+ "deployment/docker-compose.yml": "",
49
+
50
+ "configs/rag_config.yaml": "",
51
+
52
+ ".env": "",
53
+ "requirements.txt": "",
54
+ "README.md": ""
55
+ }
56
+
57
+ # Create project root
58
+ os.makedirs(PROJECT_NAME, exist_ok=True)
59
+
60
+ # Create folders
61
+ for folder in folders:
62
+ path = os.path.join(PROJECT_NAME, folder)
63
+ os.makedirs(path, exist_ok=True)
64
+
65
+ # Create files
66
+ for file_path, content in files.items():
67
+ full_path = os.path.join(PROJECT_NAME, file_path)
68
+ with open(full_path, "w") as f:
69
+ f.write(content)
70
+
71
+ print(f"✅ RAG LLMOps project '{PROJECT_NAME}' created successfully!")
src/Blog/components/image_generation.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from huggingface_hub import InferenceClient
3
+
4
+ class ImageGeneration:
5
+ def __init__(self):
6
+ self.client = InferenceClient(
7
+ provider="nscale",
8
+ api_key=os.environ["HF_TOKEN"],
9
+ )
10
+
11
+ async def generateImage(self,prompt:str):
12
+ image = self.client.text_to_image(
13
+ prompt,
14
+ model="stabilityai/stable-diffusion-xl-base-1.0",
15
+ )
16
+ return image
src/Blog/components/taivily_search.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ from typing import List
4
+ from langchain_community.tools.tavily_search import TavilySearchResults
5
+ from exception import MyException
6
+ from utils.asyncHandler import asyncHandler
7
+
8
+
9
+ class Taivily_search:
10
+ def __init__(self):
11
+ pass
12
+
13
+ @asyncHandler
14
+ async def _tavily_search(self, query: str, max_results: int = 5) -> List[dict]:
15
+ logging.info(f"Using Tavily to search for: {query}")
16
+ try:
17
+ tool = TavilySearchResults(max_results=max_results)
18
+ results = await tool.ainvoke({"query": query})
19
+
20
+ normalized: List[dict] = []
21
+ for r in results or []:
22
+ normalized.append(
23
+ {
24
+ "title": r.get("title") or "",
25
+ "url": r.get("url") or "",
26
+ "snippet": r.get("content") or r.get("snippet") or "",
27
+ "published_at": r.get("published_date") or r.get("published_at"),
28
+ "source": r.get("source"),
29
+ }
30
+ )
31
+ logging.debug(f"Tavily search returned {len(normalized)} results")
32
+ return normalized
33
+ except Exception as e:
34
+ logging.error(f"Error in Tavily_search: {str(e)}")
35
+ raise MyException(e, sys)
src/Blog/constants/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import os
2
+ FOLDER_PATH_TO_SAVE_MD="results"
src/Blog/graph/Compile_graph.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import asyncio
3
+ from dotenv import load_dotenv
4
+ from langgraph.graph import StateGraph,START,END
5
+ from src.Blog.models.State_model import State
6
+ from src.Blog.graph.nodes.router_node import router_node,route_next
7
+ from src.Blog.graph.nodes.reducer_node import reducer_node
8
+ from src.Blog.graph.nodes.search_node import research_node
9
+ from src.Blog.graph.nodes.orchaster_node import orchestrator_node
10
+ from src.Blog.graph.nodes.worker_node import worker_node
11
+ from src.Blog.graph.nodes.fanout_node import fanout
12
+ load_dotenv()
13
+
14
+ g = StateGraph(State)
15
+ g.add_node("router", router_node)
16
+ g.add_node("research", research_node)
17
+ g.add_node("orchestrator", orchestrator_node)
18
+ g.add_node("worker", worker_node)
19
+ g.add_node("reducer", reducer_node)
20
+
21
+ g.add_edge(START, "router")
22
+ g.add_conditional_edges("router", route_next, {"research": "research", "orchestrator": "orchestrator"})
23
+ g.add_edge("research", "orchestrator")
24
+
25
+ g.add_conditional_edges("orchestrator", fanout, ["worker"])
26
+ g.add_edge("worker", "reducer")
27
+ g.add_edge("reducer", END)
28
+
29
+ app = g.compile()
30
+
31
+
32
+ png_data = app.get_graph().draw_mermaid_png()
33
+ with open("graph.png", "wb") as f:
34
+ f.write(png_data)
35
+ async def run(topic: str):
36
+ logging.info(f"Starting blog generation for topic: {topic}")
37
+ try:
38
+ # out = await app.ainvoke(
39
+ # {
40
+ # "topic": topic,
41
+ # "mode": "",
42
+ # "needs_research": False,
43
+ # "queries": [],
44
+ # "evidence": [],
45
+ # "plan": None,
46
+ # "sections": [],
47
+ # "final": "",
48
+ # }
49
+ # )
50
+ async for step in app.astream(
51
+ {
52
+ "topic": topic,
53
+ "mode": "",
54
+ "needs_research": False,
55
+ "queries": [],
56
+ "evidence": [],
57
+ "plan": None,
58
+ "sections": [],
59
+ "final": "",
60
+ },
61
+ stream_mode="values" # important
62
+ ):
63
+ # print("Current Step:", step)
64
+ yield step
65
+ logging.info("Blog generation completed successfully")
66
+ return
67
+ except Exception as e:
68
+ logging.error(f"Error during graph execution: {str(e)}")
69
+ raise
70
+
71
+ if __name__ == "__main__":
72
+ from logger import *
73
+ out=asyncio.run(run("State of Multimodal LLMs in 2026"))
74
+ print(out)
src/Blog/graph/graphs/reducer_subgraph.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from langgraph.graph import StateGraph,START,END
3
+ from src.Blog.models.ImageSpec_model import State
4
+ from src.Blog.graph.nodes.reducer_sub_node import reducer_sub_image,reducer_sub_llm,merge_images_and_md
5
+ app=StateGraph(State)
6
+
7
+
8
+ app.add_node("reducer_sub_llm",reducer_sub_llm)
9
+ app.add_node("reducer_sub_image",reducer_sub_image)
10
+ app.add_node("merge_images_and_md",merge_images_and_md)
11
+
12
+ app.add_edge(START,"reducer_sub_llm")
13
+ app.add_edge("reducer_sub_llm","reducer_sub_image")
14
+ app.add_edge("reducer_sub_image","merge_images_and_md")
15
+ app.add_edge("merge_images_and_md",END)
16
+
17
+
18
+
19
+
20
+ app=app.compile()
21
+ logging.info("Reducer subgraph compiled successfully")
22
+
src/Blog/graph/nodes/fanout_node.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from src.Blog.models.State_model import State
3
+ from langgraph.types import Send
4
+
5
+
6
+ def fanout(state: State):
7
+ logging.info("Entering fanout")
8
+ tasks = state["plan"].tasks
9
+ logging.debug(f"Fanning out {len(tasks)} tasks")
10
+
11
+ return [
12
+ Send(
13
+ "worker",
14
+ {
15
+ "task": task.model_dump(),
16
+ "topic": state["topic"],
17
+ "mode": state["mode"],
18
+ "plan": state["plan"].model_dump(),
19
+ "evidence": [e.model_dump() for e in state.get("evidence", [])],
20
+ },
21
+ )
22
+ for task in tasks
23
+ ]
src/Blog/graph/nodes/orchaster_node.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ from src.Blog.models.State_model import State
4
+ from src.Blog.llm import llm
5
+ from exception import MyException
6
+ from src.Blog.models.Plan_model import Plan
7
+ from src.Blog.prompts import ORCH_SYSTEM
8
+ from langchain_core.messages import SystemMessage, HumanMessage
9
+ from utils.asyncHandler import asyncHandler
10
+
11
+
12
+ @asyncHandler
13
+ async def orchestrator_node(state: State) -> dict:
14
+ logging.info("Entering orchestrator_node")
15
+ try:
16
+ planner = llm.with_structured_output(Plan)
17
+
18
+ evidence = state.get("evidence", [])
19
+ mode = state.get("mode", "closed_book")
20
+ logging.debug(f"Mode: {mode}, Evidence count: {len(evidence)}")
21
+
22
+ plan = await planner.ainvoke(
23
+ [
24
+ SystemMessage(content=ORCH_SYSTEM),
25
+ HumanMessage(
26
+ content=(
27
+ f"Topic: {state['topic']}\n"
28
+ f"Mode: {mode}\n\n"
29
+ f"Evidence (ONLY use for fresh claims; may be empty):\n"
30
+ f"{[e.model_dump() for e in evidence][:16]}"
31
+ )
32
+ ),
33
+ ]
34
+ )
35
+
36
+ logging.info(f"Orchestrator plan created: {plan.blog_title} with {len(plan.tasks)} tasks.")
37
+ return {"plan": plan}
38
+ except Exception as e:
39
+ logging.error(f"Error in orchestrator_node: {str(e)}")
40
+ raise MyException(e, sys)
src/Blog/graph/nodes/reducer_node.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ from pathlib import Path
4
+ from src.Blog.models.State_model import State
5
+ from exception import MyException
6
+ from utils.asyncHandler import asyncHandler
7
+ from src.Blog.constants import FOLDER_PATH_TO_SAVE_MD
8
+ import os
9
+ from src.Blog.graph.graphs.reducer_subgraph import app
10
+ @asyncHandler
11
+ async def reducer_node(state: State) -> dict:
12
+ logging.info("Entering reducer_node")
13
+ try:
14
+ plan = state["plan"]
15
+
16
+ ordered_sections = [md for _, md in sorted(state["sections"], key=lambda x: x[0])]
17
+ body = "\n\n".join(ordered_sections).strip()
18
+ final_md = f"# {plan.blog_title}\n\n{body}\n"
19
+
20
+ filename = f"{plan.blog_title}.md"
21
+ logging.debug(f"Writing final blog to {filename}")
22
+
23
+ logging.info("Starting image generation and merging via subgraph")
24
+ red_f_ob=await app.ainvoke({"prompt_markdown":final_md})
25
+ final_md=red_f_ob["final_md"]
26
+
27
+ logging.debug(f"Final MD size after merging: {len(final_md)} characters")
28
+ os.makedirs(FOLDER_PATH_TO_SAVE_MD,exist_ok=True)
29
+ file_path=os.path.join(FOLDER_PATH_TO_SAVE_MD,filename)
30
+ Path(file_path).write_text(final_md, encoding="utf-8")
31
+
32
+ logging.info(f"Reducer node completed successfully, blog saved to {file_path}")
33
+ return {"final": final_md}
34
+ except Exception as e:
35
+ logging.error(f"Error in reducer_node: {str(e)}")
36
+ raise MyException(e, sys)
src/Blog/graph/nodes/reducer_sub_node.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from src.Blog.models.ImageSpec_model import State, GlobalImagePlan
4
+ from utils.asyncHandler import asyncHandler
5
+ from langchain.messages import SystemMessage, HumanMessage
6
+ from src.Blog.prompts import IMAGE_PLACEHOLDER_GENERATION
7
+ from exception import MyException
8
+ import sys
9
+ from src.Blog.components.image_generation import ImageGeneration
10
+ from src.Blog.llm import image_planner_llm
11
+
12
+
13
+ @asyncHandler
14
+ async def reducer_sub_llm(state: State) -> State:
15
+ logging.info("Calling Claude Haiku for image placeholder planning (structured output)")
16
+ output = await image_planner_llm.with_structured_output(GlobalImagePlan).ainvoke(
17
+ [
18
+ SystemMessage(content=IMAGE_PLACEHOLDER_GENERATION),
19
+ HumanMessage(content=state["prompt_markdown"]),
20
+ ]
21
+ )
22
+ if not output:
23
+ logging.error("LLM failed to return a valid image placeholder plan (output is None)")
24
+ raise MyException("Failed to generate image placeholder plan from LLM", sys)
25
+
26
+ state["output"] = output
27
+ logging.info("Successfully generated image placeholder plan")
28
+ return state
29
+
30
+
31
+ @asyncHandler
32
+ async def reducer_sub_image(state: State) -> State:
33
+ output = state['output']
34
+ image_generator = ImageGeneration()
35
+ if not output:
36
+ raise MyException("output from reducer_sub not found", sys)
37
+
38
+ os.makedirs("images", exist_ok=True)
39
+
40
+ logging.info(f"Starting image generation for {len(output.images)} images")
41
+ for image_con in output.images:
42
+ logging.debug(f"Generating image: {image_con.filename} with prompt: {image_con.prompt[:50]}...")
43
+ image = await image_generator.generateImage(prompt=image_con.prompt)
44
+ image.save(image_con.filename)
45
+ logging.info("All images generated successfully")
46
+ return state
47
+
48
+
49
+ @asyncHandler
50
+ async def merge_images_and_md(state: State) -> State:
51
+ output = state["output"]
52
+ md = output.md_with_placeholders
53
+
54
+ logging.info(f"Merging {len(output.images)} images into Markdown")
55
+ for im in output.images:
56
+ alt_text = (
57
+ im.filename.split("/")[-1]
58
+ .replace(".png", "")
59
+ .replace("_", " ")
60
+ )
61
+ md_image_tag = f"![{alt_text}](../{im.filename})"
62
+ md = md.replace(im.placeholder, md_image_tag)
63
+
64
+ state["final_md"] = md
65
+ logging.info("Markdown merging completed")
66
+ return state
src/Blog/graph/nodes/router_node.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ import json
4
+ import re
5
+ from src.Blog.models.RouterDecision_model import RouterDecision
6
+ from langchain_core.messages import SystemMessage, HumanMessage
7
+ from src.Blog.models.State_model import State
8
+ from src.Blog.llm import llm
9
+ from src.Blog.prompts import ROUTER_SYSTEM
10
+ from exception import MyException
11
+ from utils.asyncHandler import asyncHandler
12
+
13
+
14
+ @asyncHandler
15
+ async def router_node(state: State):
16
+ logging.info("Entering router_node")
17
+ topic = state['topic']
18
+ logging.debug(f"Topic: {topic}")
19
+
20
+ try:
21
+ try:
22
+ runnable = llm.with_structured_output(RouterDecision)
23
+ decision = await runnable.ainvoke(
24
+ [
25
+ SystemMessage(content=ROUTER_SYSTEM),
26
+ HumanMessage(content=f"Topic: {topic}")
27
+ ]
28
+ )
29
+ if decision:
30
+ logging.info(f"Router decision (structured): needs_research={decision.needs_research}, mode={decision.mode}")
31
+ return {
32
+ "needs_research": decision.needs_research,
33
+ "mode": decision.mode,
34
+ "queries": decision.queries,
35
+ }
36
+ except Exception as e:
37
+ logging.warning(f"Structured output failed: {str(e)}. Attempting manual parse.")
38
+
39
+ raw_response = await llm.ainvoke(
40
+ [
41
+ SystemMessage(content=ROUTER_SYSTEM + "\n\nCRITICAL: You MUST return a valid JSON object. Do not include any text before or after the JSON."),
42
+ HumanMessage(content=f"Topic: {topic}")
43
+ ]
44
+ )
45
+ content = raw_response.content
46
+ logging.debug(f"Raw LLM content for fallback: {content}")
47
+
48
+ json_str = ""
49
+ markdown_match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL)
50
+ if markdown_match:
51
+ json_str = markdown_match.group(1)
52
+ else:
53
+ start = content.find('{')
54
+ end = content.rfind('}')
55
+ if start != -1 and end != -1:
56
+ json_str = content[start:end+1]
57
+
58
+ if json_str:
59
+ try:
60
+ data = json.loads(json_str)
61
+ except json.JSONDecodeError:
62
+ # Progressive truncation fallback
63
+ success = False
64
+ temp_str = json_str
65
+ while '}' in temp_str:
66
+ try:
67
+ data = json.loads(temp_str)
68
+ success = True
69
+ break
70
+ except json.JSONDecodeError:
71
+ last_brace = temp_str.rfind('}')
72
+ if last_brace == -1: break
73
+ temp_str = temp_str[:last_brace]
74
+
75
+ if not success:
76
+ raise ValueError("Failed to parse JSON even after structural truncation")
77
+
78
+ needs_res = str(data.get("needs_research", "")).lower() in ["true", "1", "yes"]
79
+
80
+ decision = RouterDecision(
81
+ needs_research=needs_res,
82
+ mode=data.get("mode", "open_book"),
83
+ queries=data.get("queries", [])
84
+ )
85
+ logging.info(f"Router decision (manual): needs_research={decision.needs_research}, mode={decision.mode}")
86
+ return {
87
+ "needs_research": decision.needs_research,
88
+ "mode": decision.mode,
89
+ "queries": decision.queries,
90
+ }
91
+
92
+ logging.error("Failed to extract JSON from LLM response")
93
+ raise ValueError("LLM failed to return a valid RouterDecision. Please check prompts or model output.")
94
+
95
+ except Exception as e:
96
+ logging.error(f"Error in router_node: {str(e)}")
97
+ raise
98
+
99
+ def route_next(state: State) -> str:
100
+ needs_research = state.get("needs_research", False)
101
+ logging.info(f"Routing next based on research need: {needs_research}")
102
+ return "research" if needs_research else "orchestrator"
src/Blog/graph/nodes/search_node.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ import asyncio
4
+ import json
5
+ import re
6
+ from typing import List
7
+ from src.Blog.models.State_model import State
8
+ from src.Blog.components.taivily_search import Taivily_search
9
+ from exception import MyException
10
+ from src.Blog.llm import llm
11
+ from langchain_core.messages import SystemMessage, HumanMessage
12
+ from src.Blog.prompts import RESEARCH_SYSTEM
13
+ from src.Blog.models.Evidence_model import EvidencePack, EvidenceItem
14
+ from utils.asyncHandler import asyncHandler
15
+
16
+
17
+ @asyncHandler
18
+ async def research_node(state: State) -> dict:
19
+ logging.info("Entering research_node")
20
+ try:
21
+ taivily_search = Taivily_search()
22
+ queries = state.get("queries", []) or []
23
+ logging.debug(f"Queries for research: {queries}")
24
+ max_results = 6
25
+
26
+ raw_results: List[dict] = []
27
+
28
+ for q in queries:
29
+ logging.debug(f"Queuing tavily search for query: {q}")
30
+ raw_results.extend(await taivily_search._tavily_search(q, max_results=max_results))
31
+
32
+ if not raw_results:
33
+ logging.warning("No raw results found during research")
34
+
35
+ return {"evidence": []}
36
+
37
+
38
+
39
+ logging.info(f"Extracted {len(raw_results)} raw results. Processing with LLM for EvidencePack.")
40
+
41
+ try:
42
+ extractor = llm.with_structured_output(EvidencePack)
43
+ pack = await extractor.ainvoke(
44
+ [
45
+ SystemMessage(content=RESEARCH_SYSTEM),
46
+ HumanMessage(content=f"Raw results:\n{raw_results}"),
47
+ ]
48
+ )
49
+ if pack:
50
+ logging.info(f"EvidencePack extracted (structured). Evidence count: {len(pack.evidence)}")
51
+ dedup={}
52
+ for e in pack.evidence:
53
+ dedup[e.url]=e
54
+ return {"evidence": list(dedup.values())}
55
+ except Exception as e:
56
+ logging.warning(f"Structured output failed in research_node: {str(e)}. Attempting manual parse.")
57
+
58
+
59
+ except Exception as e:
60
+ logging.error(f"Error in research_node: {str(e)}")
61
+ raise MyException(e, sys)
src/Blog/graph/nodes/worker_node.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import sys
3
+ from src.Blog.models.Task_models import Task
4
+ from src.Blog.models.Plan_model import Plan
5
+ from src.Blog.models.Evidence_model import EvidenceItem
6
+ from src.Blog.llm import llm
7
+ from langchain_core.messages import SystemMessage, HumanMessage
8
+ from src.Blog.prompts import WORKER_SYSTEM
9
+ from exception import MyException
10
+ from utils.asyncHandler import asyncHandler
11
+
12
+
13
+ @asyncHandler
14
+ async def worker_node(payload: dict) -> dict:
15
+ logging.info("Entering worker_node")
16
+ try:
17
+ task = Task(**payload["task"])
18
+ plan = Plan(**payload["plan"])
19
+ evidence = [EvidenceItem(**e) for e in payload.get("evidence", [])]
20
+ topic = payload["topic"]
21
+ mode = payload.get("mode", "closed_book")
22
+
23
+ logging.debug(f"Task: {task.title}, Mode: {mode}")
24
+
25
+ bullets_text = "\n- " + "\n- ".join(task.bullets)
26
+
27
+ evidence_text = ""
28
+ if evidence:
29
+ evidence_text = "\n".join(
30
+ f"- {e.title} | {e.url} | {e.published_at or 'date:unknown'}".strip()
31
+ for e in evidence[:20]
32
+ )
33
+
34
+ response = await llm.ainvoke(
35
+ [
36
+ SystemMessage(content=WORKER_SYSTEM),
37
+ HumanMessage(
38
+ content=(
39
+ f"Blog title: {plan.blog_title}\n"
40
+ f"Audience: {plan.audience}\n"
41
+ f"Tone: {plan.tone}\n"
42
+ f"Blog kind: {plan.blog_kind}\n"
43
+ f"Constraints: {plan.constraints}\n"
44
+ f"Topic: {topic}\n"
45
+ f"Mode: {mode}\n\n"
46
+ f"Section title: {task.title}\n"
47
+ f"Goal: {task.goal}\n"
48
+ f"Target words: {task.target_words}\n"
49
+ f"Tags: {task.tags}\n"
50
+ f"requires_research: {task.requires_research}\n"
51
+ f"requires_citations: {task.requires_citations}\n"
52
+ f"requires_code: {task.requires_code}\n"
53
+ f"Bullets:{bullets_text}\n\n"
54
+ f"Evidence (ONLY use these URLs when citing):\n{evidence_text}\n"
55
+ )
56
+ ),
57
+ ]
58
+ )
59
+ section_md = response.content.strip()
60
+
61
+ logging.info(f"Worker node completed task: {task.title}")
62
+ return {"sections": [(task.id, section_md)]}
63
+ except Exception as e:
64
+ logging.error(f"Error in worker_node: {str(e)}")
65
+ raise MyException(e, sys)
src/Blog/llm/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_aws import ChatBedrockConverse
2
+ LLM_MODEL_ID = "us.meta.llama3-3-70b-instruct-v1:0"
3
+ LLM_REGION = "us-east-1"
4
+ llm = ChatBedrockConverse(
5
+ model_id=LLM_MODEL_ID,
6
+ region_name=LLM_REGION
7
+ )
8
+
9
+
10
+ image_planner_llm = ChatBedrockConverse(
11
+ model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0",
12
+ region_name="us-east-1",
13
+ )
src/Blog/models/Evidence_model.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional,List,Literal
2
+ from pydantic import BaseModel,Field
3
+ class EvidenceItem(BaseModel):
4
+ title: str
5
+ url: str
6
+ published_at: Optional[str] = None # keep if Tavily provides; DO NOT rely on it
7
+ snippet: Optional[str] = None
8
+ source: Optional[str] = None
9
+
10
+
11
+
12
+ class EvidencePack(BaseModel):
13
+ evidence: List[EvidenceItem] = Field(default_factory=list)
src/Blog/models/ImageSpec_model.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel,Field
2
+ from typing import List,Literal,TypedDict
3
+ class ImageSpec(BaseModel):
4
+ placeholder:str=Field(...,description="e.g. [[IMAGE_1]]")
5
+ filename:str=Field(...,description="Save under images/, e.g. qkv_flow.png")
6
+ prompt:str=Field(...,description="Prompt to send to the image model")
7
+ size:Literal["1024x1024","1024x1536","1536x1024"]="1025x1024"
8
+ quality: Literal["low", "medium", "high"] = "medium"
9
+
10
+
11
+ class GlobalImagePlan(BaseModel):
12
+ md_with_placeholders:str
13
+ images:List[ImageSpec]=Field(default_factory=list)
14
+
15
+
16
+
17
+ class State(TypedDict):
18
+ prompt_markdown:str
19
+ final_md:str
20
+ output: GlobalImagePlan