A Complete Step-by-Step Guide to Building a GenAI Career Assistant with LangGraph and LangChain

We will explore how to build a Generative AI Learning Agent using LangGraph, LangChain, and Groq. The goal is to create a structured workflow that classifies user queries and provides intelligent responses using different AI models.

LangGraph is designed for stateful, multi-step workflows in AI applications. It extends LangChain by providing:

  • State Management: Tracks conversation context across steps.
  • Conditional Routing: Dynamically directs queries based on real-time decisions.
  • Cyclic Workflows: Supports loops (e.g., for iterative Q&A).

Key Features of the GenAI Career Assistant

🚀 Learning & Content Creation

  • Provides personalized learning paths in Generative AI, covering essential topics and skills.
  • Assists in crafting tutorials, blogs, and posts based on user interests and queries.

💡R Q∓A Support

  • Offers on-demand Q&A sessions for real-time guidance on concepts and coding challenges.

📄 Resume Building & Review

  • Delivers one-on-one resume consultations with expert guidance.
  • Creates personalized, market-optimized resumes aligned with current industry trends.

🎯 Interview Preparation

  • Conducts Q&A sessions on common and technical interview questions.
  • Simulates real interview scenarios with mock interview sessions.
None

Agents in This System

None

1. Overview of Key Components

The system consists of:

  • State Management: Uses TypedDict to track conversation state.
  • LangGraph Workflow: Manages decision-making and routing.
  • AI Agent Functions: Handles different user queries (learning, resume, interview, job search).
  • File Management: Saves responses in markdown files.
  • Interactive CLI: Allows users to input queries and get responses.

2. Detailed Code Breakdown

2.1 Imports and Initial Setup

from typing import Dict, TypedDict
from langgraph.graph import StateGraph, END, START
from langchain_core.prompts import ChatPromptTemplate
from langchain_groq import ChatGroq
from dotenv import load_dotenv
import os
from datetime import datetime
  • TypedDict: Defines structured state for the workflow.
  • StateGraph: Manages workflow states and transitions.
  • ChatGroq: Uses Groq's fast LLM API (Llama3-70b).
  • dotenv: Loads environment variables (API keys).

2.2 LLM Initialization

llm = ChatGroq(
    model="llama3-70b-8192",
    verbose=True,
    temperature=0.5,
    groq_api_key=os.environ["GROQ_API_KEY"]
)
  • Uses Groq's Llama3–70b for fast responses.
  • temperature=0.5: Balances creativity and accuracy.

2.3 State Definition

class State(TypedDict):
    query: str          # User's input query
    category: str       # Determined category (learning, resume, etc.)
    response: str       # Generated response or file path
  • Tracks the conversation state across workflow steps.

2.4 Helper Functions

def save_file(data, filename):
    """Saves responses in markdown files with timestamps."""
    folder_name = "Agent_output"
    os.makedirs(folder_name, exist_ok=True)
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
    filename = f"{filename}_{timestamp}.md"
    file_path = os.path.join(folder_name, filename)
    with open(file_path, "w", encoding="utf-8") as file:
        file.write(data)
    return file_path
  • Stores AI responses in organized markdown files
def trim_conversation(prompt):
    """Keeps only the latest messages to avoid exceeding token limits."""
    return trim_messages(prompt, max_tokens=10, strategy="last")
  • Prevents excessive memory usage in long conversations.

2.5 Categorization & Routing

def categorize(state: State):
    """Classifies user queries into categories using keywords."""
    query = state['query']
    if 'learn' in query.lower():
        return {"category": "handle_learning_resource"}
    elif 'resume' in query.lower():
        return {"category": "handle_resume_making"}
    elif 'interview' in query.lower():
        return {"category": "handle_interview_preparation"}
    elif 'job' in query.lower():
        return {"category": "job_search"}
    else:
        return {"category": "handle_learning_resource"}
  • Uses keyword matching to classify queries.

route_query()

def route_query(state: State):
    """Directs queries to the appropriate handler."""
    return state['category']
  • Routes based on the category from categorize().

2.6 Agent Handlers

handle_learning_resource()

def handle_learning_resource(state: State):
    """Generates learning materials using Groq LLM."""
    prompt = ChatPromptTemplate.from_messages([
        SystemMessage(content="You are an AI learning expert."),
        HumanMessage(content=state['query'])
    ])
    agent = LearningResourceAgent(prompt)
    response_path = agent.TutorialAgent(state['query'])
    return {"response": response_path, "category": "Learning Resource"}
  • Uses LearningResourceAgent to generate tutorials.

handle_resume_making()

def handle_resume_making(state: State):
    """Saves resume-related queries to a file."""
    path = save_file(f"Resume Request: {state['query']}", 'Resume_Request')
    return {"response": path, "category": "Resume Making"}

Placeholder for resume-building logic.

2.7 LearningResourceAgent Class

class LearningResourceAgent:
    def __init__(self, prompt):
        self.model = ChatGroq(model="llama3-70b-8192")
        self.prompt = prompt
        self.tools = [DuckDuckGoSearchResults()]  # Web search for real-time data
def TutorialAgent(self, user_input):
        """Generates tutorials using LLM and tools."""
        agent = create_tool_calling_agent(self.model, self.tools, self.prompt)
        agent_executor = AgentExecutor(agent=agent, tools=self.tools)
        response = agent_executor.invoke({"input": user_input})
        path = save_file(response['output'], 'Tutorial')
        return path
    def QueryBot(self, user_input):
        """Interactive Q&A loop."""
        while True:
            response = self.model.invoke(self.prompt)
            if user_input.lower() == "exit":
                break
            # Continues conversation until 'exit'
  • Uses DuckDuckGo Search for real-time data.
  • Supports interactive Q&A sessions.

2.8 LangGraph Workflow Setup

workflow = StateGraph(State)
# Add nodes
workflow.add_node("categorize", categorize)
workflow.add_node("handle_learning_resource", handle_learning_resource)
workflow.add_node("handle_resume_making", handle_resume_making)
# Define transitions
workflow.add_edge(START, "categorize")
workflow.add_conditional_edges(
    "categorize",
    route_query,
    {
        "handle_learning_resource": "handle_learning_resource",
        "handle_resume_making": "handle_resume_making",
    }
)
workflow.add_edge("handle_learning_resource", END)
workflow.add_edge("handle_resume_making", END)
app = workflow.compile()  # Final executable workflow
  • StateGraph defines the workflow structure.
  • Conditional edges route queries dynamically.

2.9 Main Execution

def main():
    """CLI interface for user interaction."""
    while True:
        query = input("Enter your query (or 'exit'): ")
        if query.lower() == 'exit':
            break
        results = app.invoke({"query": query})
        print(f"Category: {results['category']}, Response: {results['response']}")
  • Runs an interactive loop for user queries.