This repository is my personal learning path for AI engineering. I initially started with the AI Engineering course by Telusko. During the breaks, I followed LangGraph's playlist from the CampusX YouTube playlist.
Notes and code examples exploring AI engineering concepts including LLM integrations, agents, RAG, and more.
AI-Engg/
├── 101/ # Getting started with LLM SDKs
│ ├── openai-sdk.py # OpenAI SDK basics
│ └── gemini-sdk.py # Google Gemini SDK basics
│
├── Old-school-requests/ # Direct API calls using requests library
│ └── openai-req.py # Raw HTTP requests to OpenAI API
│
├── langchain-demo/ # LangChain fundamentals
│ ├── lc-basicQA.py # Basic Q&A with prompt templates
│ ├── lc-without-memory.py
│ └── Multi-turn_chatbot_memory.py # Chatbot with conversation memory
│
├── Tool-calling/ # Function/tool calling with LLMs
│ ├── ddg_tool.py # DuckDuckGo search tool
│ └── custom_tools/ # Building custom tools
│ ├── datetime_tool-V0.py
│ ├── datetime_tool-V1.py
│ └── multi_tool.py
│
├── Agents/ # LLM Agents
│ ├── 00_react_agent.py # ReAct agent with tools
│ └── 01_agent.py
│
├── RAG/ # Retrieval Augmented Generation
│ └── product_recommendation.py # Product recommendations with ChromaDB
│
├── LangGraph/ # Graph-based LLM workflows
│ ├── 01_Basics/ # Graph fundamentals (CampusX playlist)
│ │ ├── 00_graph_without_LLM.py
│ │ ├── 01_joke_simulator.py
│ │ ├── 02_parallel_workflow.py
│ │ ├── 03_batsman.py
│ │ └── 04-07_*.ipynb # Prompt chaining, essay eval, routing, X post gen
│ └── chatbot/ # Streaming chatbot, iterated version by version
│ ├── langgraph_backend.py # StateGraph + InMemorySaver checkpointer
│ ├── langgraph_backend_database_v2.py # + SqliteSaver persistence (current)
│ ├── langgraph_backend_tools.py # + tool calling (search, calculator, stock price)
│ ├── langgraph_backend_async.py # Async graph invocation (ainvoke)
│ ├── main.py # CLI chat loop
│ ├── streamlit_frontend.py # Basic Streamlit UI
│ ├── streamlit_frontend_streaming.py # Streamed token output
│ ├── streamlit_frontend_threading.py # Multi-thread sidebar + auto-naming
│ ├── streamlit_frontend_database_v2.py # + persisted thread titles (current)
│ └── streamlit_frontend_tools.py # + tool-calling UI
│
├── LangSmith/ # Observability & tracing for LLM apps
│ ├── 1_simple_llm_call.py # Minimal traced chain
│ ├── 2_sequential_chain.py # Multi-step chain tracing
│ ├── 3_rag_v1.py → v4.py # RAG pipeline, iterated to fix tracing gaps + avoid PDF re-embedding
│ ├── 4_agent.py # ReAct agent with tracing
│ └── 5_langgraph.py, v2.py # LangGraph workflow tracing (OpenAI → Claude Haiku)
│
└── MCP/ # Model Context Protocol
├── 00_MCP_FS_Client/ # File system MCP client
└── 01_MCP_Server/ # Custom MCP server & client
| Topic | Folder | What's built |
|---|---|---|
| LLM SDK Basics | 101/ |
Direct OpenAI & Gemini API calls |
| Raw HTTP | Old-school-requests/ |
requests lib against OpenAI REST |
| LangChain | langchain-demo/ |
Chains, prompt templates, output parsers |
| Memory | langchain-demo/ |
Stateful multi-turn chatbot with RunnableWithMessageHistory |
| Tool Calling | Tool-calling/ |
DuckDuckGo + custom @tool decorators, manual tool loop |
| Agents | Agents/ |
ReAct pattern with create_react_agent |
| RAG | RAG/ |
ChromaDB + OpenAI embeddings + retrieval chain |
Following the CampusX LangGraph playlist:
| # | Topic | File | Status |
|---|---|---|---|
| 1 | Graph basics, no LLM (BMI/Loan workflow) | LangGraph/01_Basics/00_graph_without_LLM.py |
✅ |
| 2 | Simple LLM workflow | LangGraph/01_Basics/01_joke_simulator.py |
✅ |
| 3 | Prompt chaining | LangGraph/01_Basics/04_prompt_chaining.ipynb |
✅ |
| 4 | Parallel workflow | LangGraph/01_Basics/02_parallel_workflow.py, 03_batsman.py |
✅ |
| 5 | UPSC essay workflow | LangGraph/01_Basics/05_essay_evaluator.ipynb |
✅ |
| 6 | Conditional edges / routing | LangGraph/01_Basics/06_review_handler.ipynb |
✅ |
| 7 | Review reply workflow | LangGraph/01_Basics/06_review_handler.ipynb |
✅ |
| 8 | X post generator | LangGraph/01_Basics/07_X_post_generator.ipynb |
✅ |
| 9 | Basic chatbot in LangGraph | LangGraph/chatbot/langgraph_backend.py, main.py, streamlit_frontend*.py |
✅ |
| 10 | Persistence (checkpointers, thread IDs, DB-backed titles) | LangGraph/chatbot/langgraph_backend_database_v2.py |
✅ |
| 11 | Tools in LangGraph | LangGraph/chatbot/langgraph_backend_tools.py, streamlit_frontend_tools.py |
✅ |
| 12 | MCP | MCP/ |
✅ Done separately |
| 13 | RAG in LangGraph | RAG/ |
✅ Done separately |
| 14 | Async graph execution | LangGraph/chatbot/langgraph_backend_async.py |
✅ Done separately |
| 15 | Human-in-the-Loop (HITL) | — | ❌ |
| 16 | Subgraphs + shared state | — | ❌ |
Remaining order: 15 (HITL) → 16 (subgraphs)
Instrumented the LangChain/LangGraph examples above with LangSmith tracing to see what a chain actually does under the hood — token usage, step timing, and where retries/tool calls happen.
| File | What it covers |
|---|---|
LangSmith/1_simple_llm_call.py |
Minimal traced chain — baseline trace shape |
LangSmith/2_sequential_chain.py |
Tracing across multiple chained steps |
LangSmith/3_rag_v1.py |
First pass: traces only cover retrieval + answering, not PDF load/chunk/embed |
LangSmith/3_rag_v2.py → 3_rag_v4.py |
Iterated to trace every stage with @traceable, then cache the FAISS index so PDFs aren't re-embedded on every run |
LangSmith/4_agent.py |
Tracing a ReAct agent (tool calls, intermediate reasoning steps) |
LangSmith/5_langgraph.py |
Tracing a LangGraph workflow (OpenAI) |
LangSmith/5_langgraph_v2.py |
Same workflow ported to Claude Haiku 4.5 via langchain-anthropic |
The chatbot (LangGraph/chatbot/) also has LangSmith tracing wired in via LANGSMITH_PROJECT env vars set per-frontend (Chatbot, Chatbot_tools), so every run shows up as a trace in the LangSmith UI.
Started with Fine-tuning/huggingfacedemo.ipynb (HuggingFace Hub, dataset loading, streaming).
Next: LoRA/QLoRA fine-tuning on an open model, pushing adapters to Hub, inference with fine-tuned model.
- LLM SDK Basics - Direct usage of OpenAI and Gemini SDKs
- LangChain - Chains, prompts, output parsers, and memory
- Tool Calling - Integrating external tools and functions with LLMs
- Agents - ReAct pattern agents that reason and act
- RAG - Vector stores (ChromaDB), embeddings, and retrieval chains
- LangGraph - State machines, tool calling, async execution, and DB-backed persistence for complex LLM apps
- LangSmith - Tracing/observability for chains, agents, and LangGraph workflows
- MCP - Model Context Protocol for connecting AI to external systems
- Python 3.12+
- uv package manager
# Clone the repository
git clone <repo-url>
cd AI-Engg
# Install dependencies using uv
uv syncCreate a .env file with your API keys:
OPENAI_API_KEY=your_openai_key
GOOGLE_API_KEY=your_google_key
ANTHROPIC_API_KEY=your_claude_key # used by chatbot tools variant & LangSmith Claude examples
# LangSmith tracing (LangSmith/, and the chatbot's tool/database frontends)
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=your_langsmith_key
Each script sets its own LANGSMITH_PROJECT in code, so traces land under a per-example project name in the LangSmith UI rather than needing one set in .env.
# Run any example with uv
uv run python 101/openai-sdk.py
uv run python langchain-demo/lc-basicQA.py
uv run python RAG/product_recommendation.pyThe chatbot lives in LangGraph/chatbot/ and is built iteratively — each frontend/backend pair is a separate versioned file rather than an edit-in-place, so you can see how the design evolved:
# Basic Streamlit UI (single thread, no streaming)
uv run streamlit run LangGraph/chatbot/streamlit_frontend.py
# Streamlit UI with token-by-token streaming
uv run streamlit run LangGraph/chatbot/streamlit_frontend_streaming.py
# Streamlit UI with multi-thread sidebar + auto-naming + persistence
uv run streamlit run LangGraph/chatbot/streamlit_frontend_threading.py
# Current: SqliteSaver checkpointer + a `threads` table for persisted titles
uv run streamlit run LangGraph/chatbot/streamlit_frontend_database_v2.py
# + tool calling (DuckDuckGo search, calculator, stock price lookup) on Claude Haiku 4.5
uv run streamlit run LangGraph/chatbot/streamlit_frontend_tools.pylanggraph_backend_async.py is a standalone script (not a Streamlit app) demonstrating ainvoke/async nodes in a LangGraph graph:
uv run python LangGraph/chatbot/langgraph_backend_async.pyuv run python LangSmith/1_simple_llm_call.py
uv run python LangSmith/5_langgraph_v2.pyEach run appears as a trace in the LangSmith UI under the project name set in the script (e.g. rag_v1, Chatbot_tools).
Key libraries used in this project:
openai- OpenAI Python SDKgoogle-genai- Google Gemini SDKlangchain/langchain-openai- LangChain frameworklangchain-anthropic- Claude models (chatbot tools variant, LangSmith Claude examples)langgraph/langgraph-checkpoint-sqlite- Graph-based LLM workflows + SQLite-backed persistencelangchain-chroma/faiss-cpu- Vector store integrations (ChromaDB, FAISS)langsmith- Tracing/observability for chains, agents, and graphsfastmcp/langchain-mcp-adapters- Model Context Protocolddgs- DuckDuckGo search