Gemini Fullstack LangGraph Quickstart

repository·main·Indexed 12 days ago

https://github.com/google-gemini/gemini-fullstack-langgraph-quickstart

A fullstack demonstration of a research-augmented conversational AI featuring a React frontend and a LangGraph-powered backend. The application performs iterative web research using Google Gemini and the Google Search API, utilizing a StateGraph workflow to generate queries, analyze knowledge gaps, and synthesize final answers with citations.

Tokens
8.4K
Snippets
31
Records
34
Agent score
94%

What's inside Gemini Fullstack LangGraph Quickstart

  1. How the LangGraph research agent works

    main

    The backend agent (defined in backend/src/agent/graph.py) performs iterative research using the following lifecycle:

    1. Generate Initial Queries: Uses Gemini to create search terms based on user input.
    2. Web Research: Uses the Google Search API via Gemini to find relevant web pages.
    3. Reflection & Knowledge Gap Analysis: Analyzes results to see if information is sufficient or if gaps exist.
    4. Iterative Refinement: If gaps are found, it generates follow-up queries and repeats the research (up to a configured maximum).
    5. Finalize Answer: Synthesizes findings into a coherent answer with citations from web sources.
  2. Set up Gemini Fullstack LangGraph for local development

    main

    To run the application locally, you need Node.js, npm, and Python 3.11+.

    1. Configure Environment Variables

    Create a .env file in the backend/ directory by copying backend/.env.example. You must provide a Google Gemini API key:

    GEMINI_API_KEY="YOUR_ACTUAL_API_KEY"

    2. Install Dependencies

    Backend:

    cd backend
    pip install .

    Frontend:

    cd frontend
    npm install

    3. Run Development Servers

    You can start both servers simultaneously using make from the project root:

    make dev

    Alternatively, run them separately:

    • Backend: In backend/, run langgraph dev. The API will be at http://127.0.0.1:2024.
    • Frontend: In frontend/, run npm run dev. The UI will be at http://localhost:5173.
    cd backend
    pip install .
    
    cd frontend
    npm install
    
    make dev
  3. Deploy the application using Docker Compose

    main

    For production, the backend requires a Redis instance (for pub-sub streaming) and a Postgres database (for persistence and task queuing).

    1. Build the Image

    From the project root:

    docker build -t gemini-fullstack-langgraph -f Dockerfile .

    2. Run with Docker Compose

    You will need a GEMINI_API_KEY and a LANGSMITH_API_KEY.

    GEMINI_API_KEY=<your_gemini_api_key> LANGSMITH_API_KEY=<your_langsmith_api_key> docker-compose up

    3. Access the App

    • UI: http://localhost:8123/app/
    • API: http://localhost:8123

    Note on apiUrl: If you are not using the docker-compose.yml example or are exposing the server to the public internet, you must manually update the apiUrl in frontend/src/App.tsx.

    • For docker-compose: http://localhost:8123
    • For local development: http://localhost:2024
    docker build -t gemini-fullstack-langgraph -f Dockerfile .
    
    GEMINI_API_KEY=<your_gemini_api_key> LANGSMITH_API_KEY=<your_langsmith_api_key> docker-compose up
  4. Understand the Pro-Search Agent Graph Workflow

    main

    The agent is implemented as a LangGraph StateGraph that automates a research loop. The workflow follows these stages:

    1. generate_query: Uses Gemini 2.0 Flash to transform the user's question into a list of optimized search queries.
    2. continue_to_web_research: A conditional edge that spawns parallel web_research nodes for each generated query using the Send pattern.
    3. web_research: Performs actual web searches using the native Google Search API tool. It retrieves grounding metadata and handles citation insertion.
    4. reflection: Analyzes gathered research to identify knowledge gaps and determines if more research is needed.
    5. evaluate_research: A routing function that decides whether to loop back to web_research (if gaps exist and max_research_loops hasn't been reached) or proceed to finalize_answer.
    6. finalize_answer: Consolidates all research, deduplicates sources, and formats the final research report with proper citations.

    The graph is compiled with the name pro-search-agent.

    from agent.graph import graph
    # The graph can then be invoked with an OverallState and a Configuration
    # result = await graph.ainvoke(initial_state, config=...) 
  5. How the web_research node handles Google Search grounding

    main

    The web_research node uses the google.genai.Client directly rather than the standard LangChain client. This is because the native Google GenAI client provides access to grounding_metadata, which is essential for retrieving the actual URLs and sources used in the search.

    When web_research is called, it:

    1. Invokes the model with the google_search tool enabled.
    2. Extracts grounding_chunks from the response.
    3. Uses resolve_urls to map these chunks to usable URLs.
    4. Uses get_citations and insert_citation_markers to ensure the generated text contains proper references to the sources.
  6. Maintain conversation state and context

    main

    The agent maintains state through a messages list. To continue a conversation or follow up on a previous answer, pass the existing message history along with the new user message to the graph.invoke method. This allows the agent to understand context from previous turns.

    # Continuing a conversation using the previous state
    state = graph.invoke({
        "messages": state["messages"] + [{"role": "user", "content": "How has the most titles? List the top 5"}]
    })
  7. Configure the LangGraph infrastructure with Docker Compose

    main

    The project uses Docker Compose to orchestrate the backend services required for the LangGraph agent. The setup includes a Redis instance for state/caching, a PostgreSQL instance for persistence, and the LangGraph API service itself.

    Key service details:

    • langgraph-redis: Uses redis:6.
    • langgraph-postgres: Uses postgres:16. It maps host port 5433 to container port 5432. Default credentials are postgres/postgres for database postgres.
    • langgraph-api: Maps host port 8123 to container port 8000. It depends on both Redis and Postgres being healthy before starting.
    services:
      langgraph-redis:
        image: docker.io/redis:6
        container_name: langgraph-redis
      langgraph-postgres:
        image: docker.io/postgres:16
        container_name: langgraph-postgres
        ports:
          - "5433:5432"
        environment:
          POSTGRES_DB: postgres
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
      langgraph-api:
        image: gemini-fullstack-langgraph
        container_name: langgraph-api
        ports:
          - "8123:8000"
  8. Configure the Pro-Search Agent via RunnableConfig

    main

    The agent's behavior is controlled through a Configuration object passed via the LangGraph RunnableConfig. This allows users to customize the research process without changing the core logic. Key configuration parameters (accessible via Configuration.from_runnable_config(config)) include:

    • query_generator_model: The model used for initial query generation.
    • reflection_model: The model used to identify knowledge gaps.
    • answer_model: The model used to write the final report.
    • max_research_loops: The maximum number of times the agent will perform the research/reflection cycle.
    • number_of_initial_queries: The number of search queries to generate in the first step.

    Note: The agent requires the GEMINI_API_KEY environment variable to be set.

  9. Set environment variables for the LangGraph API service

    main

    When running the langgraph-api service via Docker Compose, you must provide the following environment variables. These are injected from your host environment into the container:

    • GEMINI_API_KEY: Your Google Gemini API key.
    • LANGSMITH_API_KEY: Your LangSmith API key for tracing.

    The service also uses internal connection strings for the database and cache:

    • REDIS_URI: redis://langgraph-redis:6379
    • POSTGRES_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable
    environment:
      GEMINI_API_KEY: ${GEMINI_API_KEY}
      LANGSMITH_API_KEY: ${LANGSMITH_API_KEY}
      REDIS_URI: redis://langgraph-redis:6379
      POSTGRES_URI: postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable
  10. Display agent responses as Markdown

    main

    The agent's output is stored in the messages list within the state. The most recent response from the agent is located at state["messages"][-1].content. You can use IPython.display.Markdown to render this content formatted as Markdown.

    from IPython.display import Markdown
    
    # Display the last message content as rendered Markdown
    Markdown(state["messages"][-1].content)