1.0 Overview & Setup

1.1 Project Overview

This notebook creates a "working prototype" of an AI-powered chatbot, the "AI Mentor," for the City of Brampton's HR Proof of Concept.

The goal is to build a RAG (Retrieval-Augmented Generation) model that is:

  • Authoritative: It answers questions only from a pre-approved set of official HR policy documents.
  • Secure: It uses a "Protection by Design" RAG architecture to prevent AI "hallucinations" and ensure data
  • Intelligent: It demonstrates a "proactive" capability, using the "Golden Thread" found in Policy HRM-160 to connect HR self-service (Project #7) with L&D compliance (Project #6).

This notebook will:

  • Configure all necessary API keys and variables.
  • Write all the application files (app.py, requirements.txt, etc.) to the Colab filesystem.
  • Clone the target GitHub repository.
  • Commit and push the new files to the repo, triggering an automatic deployment on Streamlit Community Cloud.

1.2 Preliminary Setup

Before running this notebook, you must complete these five manual setup steps.

  1. GitHub Repository - Create a new, public GitHub repository. This notebook is configured for:

Repo: https://github.com/burnsgregm/BramptonHR

  1. Upload Policy Documents - Inside your GitHub repo, create a folder named docs and upload the 6 source policy PDFs into it:
  • docs/Anti-Racism and Inclusion Policy ANI-140.pdf
  • docs/Employee Code of Conduct Handbook.pdf
  • docs/Employee Code of Conduct HRM-100.pdf
  • docs/Recruiting and Retaining Top Talent HRM-160.pdf
  • docs/Respectful Workplace Policy HRM-150.pdf
  • docs/Salary Administration Policy HRM-210.pdf
  1. Google Gemini API Key
  • Go to Google AI Studio (aistudio.google.com).
  • Create a new API key.
  • In this Colab notebook, click the "Secrets" (🔑) tab on the left.
  • Create a new secret named GEMINI_API_KEY and paste your key as the value.
  1. GitHub Personal Access Token (PAT) - To allow this notebook to push code to your repo, you must create a PAT.
  • Go to your GitHub Settings > Developer settings > Personal access tokens > Tokens (classic).
  • Click "Generate new token".
  • Give it a note (e.g., "Colab Brampton PoC").
  • Set the expiration (e.g., 7 days).
  • Check the repo scope box (this is the only one you need).
  • Generate the token and copy it immediately.
  • In this Colab notebook, go to the "Secrets" (🔑) tab.
  • Create a new secret named GITHUB_TOKEN and paste your token as the value.
  1. Streamlit Community Cloud - This is a one-time setup to connect your repo to the live app.
  • Go to share.streamlit.io and sign in with your GitHub account.
  • Click "New app".
  • Select your repo: burnsgregm/BramptonHR.
  • The "Main file path" will be app.py.
  • Click "Deploy!"

This first deployment might fail (because app.py doesn't exist yet), but that's fine. It has now "linked" the repo. Every time this notebook pushes an update to GitHub, Streamlit Cloud will automatically re-deploy the live app.

1.3 Install Libraries

In [1]:
# --- 1.3 Install Libraries (final, clean Colab version) ---

print("Uninstalling old/conflicting packages...")
!pip uninstall -y langchain langchain-core langchain-community langchain-text-splitters langchain-classic langchain-google-genai

print("\nUpgrading pip tooling...")
!pip install -q -U pip setuptools wheel jedi

print("\nInstalling pinned, compatible versions...")
!pip install -q -U \
  "langchain==0.3.27" \
  "langchain-core==0.3.79" \
  "langchain-community==0.3.27" \
  "langchain-text-splitters==0.3.11" \
  "langchain-google-genai==2.1.5" \
  "faiss-cpu" \
  "pypdf" \
  "beautifulsoup4" \
  "streamlit==1.*"

print("\nInstall complete. Restart the runtime, then run Section 1.4.")
Uninstalling old/conflicting packages...
Found existing installation: langchain 0.3.27
Uninstalling langchain-0.3.27:
  Successfully uninstalled langchain-0.3.27
Found existing installation: langchain-core 0.3.79
Uninstalling langchain-core-0.3.79:
  Successfully uninstalled langchain-core-0.3.79
WARNING: Skipping langchain-community as it is not installed.
Found existing installation: langchain-text-splitters 0.3.11
Uninstalling langchain-text-splitters-0.3.11:
  Successfully uninstalled langchain-text-splitters-0.3.11
WARNING: Skipping langchain-classic as it is not installed.
WARNING: Skipping langchain-google-genai as it is not installed.

Upgrading pip tooling...
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 83.9 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 76.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 88.8 MB/s eta 0:00:00

Installing pinned, compatible versions...
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
google-generativeai 0.8.5 requires google-ai-generativelanguage==0.6.15, but you have google-ai-generativelanguage 0.6.18 which is incompatible.

Install complete. Restart the runtime, then run Section 1.4.

1.4 Import Libaries

In [8]:
# --- 1.4 Import Libraries ---

os.environ["USER_AGENT"] = "burnsgregm-bramptonhr/0.1"

# Core Python & File Management
import os
import textwrap
from getpass import getpass

# Colab-Specific
from google.colab import userdata

# Data Ingestion & Processing
import pypdf
from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

# Vector Store
from langchain_community.vectorstores import FAISS
from langchain_google_genai import GoogleGenerativeAIEmbeddings

# LLM / Chat / RAG Components (new style)
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.retrieval import create_retrieval_chain

print("All libraries imported successfully and ready to roll!")
All libraries imported successfully and ready to roll!

1.5 Global Configurations

In [9]:
# --- 1.5 Global Configurations ---

# --- 1. GitHub Configuration ---
GITHUB_USERNAME = "burnsgregm"
GITHUB_REPO_NAME = "BramptonHR"
GITHUB_TOKEN_NAME = "GITHUB_TOKEN"  # Colab Secret name
GITHUB_EMAIL = "burnsgregm@gmail.com"
GIT_COMMIT_MESSAGE = "Build: Initial PoC build from Colab factory"

# --- 2. Google AI Configuration ---
GEMINI_API_KEY_NAME = "GEMINI_API_KEY"  # Colab Secret name
GEMINI_EMBEDDING_MODEL = "models/text-embedding-004"
GEMINI_LLM_MODEL = "models/gemini-2.5-pro"
# ---

# --- 3. Project File & Path Configuration ---
REPO_PATH = f"/content/{GITHUB_REPO_NAME}"
DOCS_DIR = "docs"
DOCS_PATH_IN_REPO = f"{REPO_PATH}/{DOCS_DIR}"
VECTORSTORE_PATH = "/content/vectorstore"

DOC_FILENAMES = [
    "Anti-Racism and Inclusion Policy ANI-140.pdf",
    "Employee Code of Conduct Handbook.pdf",
    "Employee Code of Conduct HRM-100.pdf",
    "Recruiting and Retaining Top Talent HRM-160.pdf",
    "Respectful Workplace Policy HRM-150.pdf",
    "Salary Administration Policy HRM-210.pdf"
]

GBA_PLUS_URLS = [
    "https://www.brampton.ca/EN/City-Hall/Equity-Office/Pages/Training-and-Education-Progress-Updates.aspx",
    "https://www.canada.ca/en/women-gender-equality/gender-based-analysis-plus/take-course.html"
]

# --- 4. Streamlit App Configuration ---
APP_TITLE = "Brampton L&D Co-Pilot (PoC)"

# --- 5. RAG Prompt Configuration (Refactored for modern API) ---
RAG_PROMPT_TEMPLATE = """
SYSTEM INSTRUCTION:
You are the "AI Mentor," a helpful and safe AI assistant for City of Brampton employees.
Your job is to answer questions *only* based on the official, approved policy documents provided as context.
DO NOT, under any circumstances, use any outside knowledge or make up information.

Your answer MUST follow these rules:
1.  **Source Restriction:** Base your answer *only* on the text provided in the "<context>" section.
2.  **No Outside Knowledge:** If the answer is not in the context, you MUST state: "I'm sorry, I do not have access to that specific information in the approved policy documents. Please contact your HR Advisor."
3.  **Proactive "Golden Thread":** If (and *only* if) the user's question is about "hiring," "recruiting," or "job posting," you MUST first answer their question, and *then* you MUST add the following proactive nudge:
    "Additionally, please be aware that Policy HRM-160 requires all hiring committee members to complete the 'Mandatory Recruitment and Diversity Learning Series.' You can find this module on the L&D portal."
4.  **Tone:** Be professional, helpful, and concise.

<context>
{context}
</context>

Question: {input}

HELPFUL ANSWER (Based *only* on the context):
"""

print("Global configurations set.")
Global configurations set.

2.0 RAG Pipeline Setup & Build

This section contains the core logic for the project. It will configure the environment, load all source documents from your GitHub repo, and build the RAG (Retrieval-Augmented Generation) pipeline.

2.1 Configure API & Git Environment

In [5]:
# --- 2.1 Configure API & Git Environment ---

print("Accessing Colab secrets...")
# Get secrets from Colab
try:
    GOOGLE_API_KEY = userdata.get(GEMINI_API_KEY_NAME)
    GITHUB_TOKEN = userdata.get(GITHUB_TOKEN_NAME)
except Exception as e:
    print(f"ERROR: Could not find secrets. Did you set {GEMINI_API_KEY_NAME} and {GITHUB_TOKEN_NAME} in Colab?")
    raise e

# Set environment variable for Google AI
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY

print("Cloning GitHub repository...")
# Clone the GitHub repo to the Colab filesystem
!rm -rf {REPO_PATH}  # Remove repo if it already exists for a clean clone

# --- THIS LINE IS THE FIX ---
GIT_CLONE_URL = f"https://{GITHUB_TOKEN}@github.com/{GITHUB_USERNAME}/{GITHUB_REPO_NAME}.git"
# --- (The previous version was missing '://' after 'https') ---

!git clone {GIT_CLONE_URL} {REPO_PATH}

print("Configuring Git...")
# Configure Git for committing
!git config --global user.email "{GITHUB_EMAIL}"
!git config --global user.name "{GITHUB_USERNAME}"

print("Section 2.1 complete.")
Accessing Colab secrets...
Cloning GitHub repository...
Cloning into '/content/BramptonHR'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 19 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (19/19), 5.30 MiB | 13.07 MiB/s, done.
Resolving deltas: 100% (3/3), done.
Configuring Git...
Section 2.1 complete.

2.2 Ingest & Vectorize Documents

  • Read the 6 PDF files and 2 web pages from your cloned repo.
  • Split them into smaller, optimized chunks.
  • Use the Gemini embedding model to convert those chunks into vectors.
  • Build a local FAISS vector store and save it to the Colab disk.
In [6]:
# --- 2.2 Ingest & Vectorize Documents ---

print("Loading documents from GitHub repo...")
# 1. Create file paths for PDFs
pdf_paths = [os.path.join(DOCS_PATH_IN_REPO, f) for f in DOC_FILENAMES]

# 2. Load PDFs
pdf_docs = []
for path in pdf_paths:
    if os.path.exists(path):
        loader = PyPDFLoader(path)
        pdf_docs.extend(loader.load())
    else:
        print(f"Warning: Document not found at {path}")
print(f"Loaded {len(pdf_docs)} pages from {len(pdf_paths)} PDF documents.")

# 3. Load Web Pages
web_loaders = [WebBaseLoader(url) for url in GBA_PLUS_URLS]
web_docs = []
for loader in web_loaders:
    try:
        web_docs.extend(loader.load())
    except Exception as e:
        print(f"Warning: Could not load URL {loader.web_path}: {e}")
print(f"Loaded {len(web_docs)} web documents.")

all_docs = pdf_docs + web_docs
print(f"Loaded {len(all_docs)} total document chunks.")

# 4. Split Documents
print("Splitting all documents...")
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1500,
    chunk_overlap=200
)
splits = text_splitter.split_documents(all_docs)
print(f"Created {len(splits)} document splits.")

# 5. Create Embeddings
print("Initializing Gemini embedding model...")
embeddings = GoogleGenerativeAIEmbeddings(model=GEMINI_EMBEDDING_MODEL)

# 6. Create FAISS Vector Store
print("Creating FAISS vector store... (This may take a moment)")
# This creates the vector store in memory from the splits
db = FAISS.from_documents(splits, embeddings)

# 7. Save the Vector Store to Disk
# This saves the index locally in Colab so our Streamlit app can use it
db.save_local(VECTORSTORE_PATH)
print(f"Vector store created and saved to {VECTORSTORE_PATH}")

print("Section 2.2 complete.")
Loading documents from GitHub repo...
Loaded 79 pages from 6 PDF documents.
Loaded 2 web documents.
Loaded 81 total document chunks.
Splitting all documents...
Created 138 document splits.
Initializing Gemini embedding model...
Creating FAISS vector store... (This may take a moment)
Vector store created and saved to /content/vectorstore
Section 2.2 complete.

2.3 Build & Test RAG Chain

  • Initialize the Gemini LLM.
  • Create the custom prompt template.
  • Build the new, modern create_stuff_documents_chain and create_retrieval_chain.
  • Run two tests:
    • A standard query to check the RAG functionality.
    • Query to ensure our proactive prompt is working.
In [10]:
# --- 2.3 Build & Test RAG Chain ---

print("Building the RAG chain...")

# 1. Initialize the LLM
llm = ChatGoogleGenerativeAI(model=GEMINI_LLM_MODEL)

# 2. Create the Custom Prompt
# (Using the new ChatPromptTemplate)
prompt = ChatPromptTemplate.from_template(RAG_PROMPT_TEMPLATE)

# 3. Create the Document Chain
# This chain is responsible for "stuffing" the retrieved documents
# into the prompt template.
document_chain = create_stuff_documents_chain(llm, prompt)

# 4. Create the Retriever
# This object knows how to "retrieve" documents from our FAISS database
# We must initialize the embedding model to load the DB
embeddings = GoogleGenerativeAIEmbeddings(model=GEMINI_EMBEDDING_MODEL)
db = FAISS.load_local(VECTORSTORE_PATH, embeddings, allow_dangerous_deserialization=True)
retriever = db.as_retriever()

# 5. Create the Final Retrieval Chain
# This master chain links everything:
# 1. Takes the user's `input`
# 2. Sends it to the `retriever` to get documents
# 3. Sends the documents and `input` to the `document_chain`
rag_chain = create_retrieval_chain(retriever, document_chain)

print("RAG chain built successfully.")

# --- Test the chain ---
print("\n--- Running Test Query ---")
test_question = "What is the policy on workplace harassment?"
response = rag_chain.invoke({"input": test_question})

print(f"Question: {test_question}")
print(f"Answer: {textwrap.fill(response['answer'], width=80)}")

print("\n--- Running 'Golden Thread' Test Query ---")
test_question_2 = "How do I start the hiring process?"
response_2 = rag_chain.invoke({"input": test_question_2})

print(f"Question: {test_question_2}")
print(f"Answer: {textwrap.fill(response_2['answer'], width=80)}")

print("\nSection 2.3 complete.")
Building the RAG chain...
RAG chain built successfully.

--- Running Test Query ---
Question: What is the policy on workplace harassment?
Answer: Based on the documents provided, the City of Brampton's policy on workplace
harassment includes the following key points:  *   **Commitment:** The City is
committed to maintaining a workplace free from Workplace Harassment and
Discrimination, promoting respect, inclusion, and dignity for all. *   **Zero-
Tolerance:** The City maintains a zero-tolerance stance toward any form of
Workplace Harassment and Discrimination. *   **Reporting:** Employees must
immediately report any instances of harassment or discrimination to leaders
and/or Human Resources. All individuals have the right to report incidents or
act as a witness in good faith, without fear of reprisal. *   **Complaint
Handling:** Incidents and complaints will be addressed in a prompt and
confidential manner. Confidentiality will be maintained to the extent possible.
*   **Legal Compliance:** The policy is in place to comply with the Occupational
Health and Safety Act (OHSA) and the Ontario Human Rights Code. *   **Scope:**
The policy applies to workers, Members of Council, vendors, suppliers, and
members of the public. However, reasonable actions taken by management relating
to the direction of workers are not considered Workplace Harassment.

--- Running 'Golden Thread' Test Query ---
Question: How do I start the hiring process?
Answer: According to the policy, a Hiring Manager starts the process by:  *   Working
with Human Resources to consider current and future workforce planning needs. *
Working with Finance to confirm the availability of funding. *   Partnering with
a designated HR representative.  Additionally, please be aware that Policy
HRM-160 requires all hiring committee members to complete the 'Mandatory
Recruitment and Diversity Learning Series.' You can find this module on the L&D
portal.

Section 2.3 complete.

3.0 Write Application Files

This section uses writefile "magic" to write the requirements.txt and the main app.py files directly into your cloned GitHub repo folder (/content/BramptonHR).

3.1 Write requirements.txt

This file tells Streamlit Community Cloud which libraries to install.

In [17]:
%%writefile {REPO_PATH}/requirements.txt
streamlit==1.*
langchain==0.3.27
langchain-core==0.3.79
langchain-community==0.3.27
langchain-text-splitters==0.3.11
langchain-google-genai==2.1.5
faiss-cpu
pypdf
beautifulsoup4
Overwriting /content/BramptonHR/requirements.txt

3.2 Write app.py

This cell writes the main Streamlit application script.

In [18]:
%%writefile {REPO_PATH}/app.py

import os
import streamlit as st
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader
import time

# --- 1. Global Configurations (Mirrored from Colab) ---

# We get the API key from Streamlit's secrets
# You must set this in your app's settings on share.streamlit.io
GOOGLE_API_KEY = st.secrets.get("GEMINI_API_KEY")

if not GOOGLE_API_KEY:
    st.error("GEMINI_API_KEY secret not found. Please set it in your Streamlit app settings.")
    st.stop()

os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY

# Use the exact model names that worked in Colab
GEMINI_EMBEDDING_MODEL = "models/text-embedding-004"
GEMINI_LLM_MODEL = "models/gemini-2.5-pro" # Using the model you confirmed
APP_TITLE = "Brampton L&D Co-Pilot (PoC)"

# Paths for documents and vector store
DOCS_DIR = "docs"
VECTORSTORE_PATH = "vectorstore" # This app will load the pre-built store

RAG_PROMPT_TEMPLATE = """
SYSTEM INSTRUCTION:
You are the "AI Mentor," a helpful and safe AI assistant for City of Brampton employees.
Your job is to answer questions *only* based on the official, approved policy documents provided as context.
DO NOT, under any circumstances, use any outside knowledge or make up information.

Your answer MUST follow these rules:
1.  **Source Restriction:** Base your answer *only* on the text provided in the "<context>" section.
2.  **No Outside Knowledge:** If the answer is not in the context, you MUST state: "I'm sorry, I do not have access to that specific information in the approved policy documents. Please contact your HR Advisor."
3.  **Proactive "Golden Thread":** If (and *only* if) the user's question is about "hiring," "recruiting," or "job posting," you MUST first answer their question, and *then* you MUST add the following proactive nudge:
    "Additionally, please be aware that Policy HRM-160 requires all hiring committee members to complete the 'Mandatory Recruitment and Diversity Learning Series.' You can find this module on the L&D portal."
4.  **Tone:** Be professional, helpful, and concise.

<context>
{context}
</context>

Question: {input}

HELPFUL ANSWER (Based *only* on the context):
"""

# --- 2. Caching & RAG Chain Functions ---

# Use Streamlit's cache to load models and data only once
@st.cache_resource
def load_models():
    """Loads the embedding model and LLM."""
    try:
        embeddings = GoogleGenerativeAIEmbeddings(model=GEMINI_EMBEDDING_MODEL)
        llm = ChatGoogleGenerativeAI(model=GEMINI_LLM_MODEL)
        return embeddings, llm
    except Exception as e:
        st.error(f"Error loading AI models: {e}")
        st.stop()

@st.cache_resource
def load_vector_store(_embeddings):
    """
    Loads the pre-built FAISS vector store from the repo.
    """
    if not os.path.exists(VECTORSTORE_PATH):
        st.error(f"Vector store not found at {VECTORSTORE_PATH}. Please ensure the 'vectorstore' directory is in the GitHub repo.")
        st.stop()

    try:
        # Load the pre-built index from local disk
        db = FAISS.load_local(VECTORSTORE_PATH, _embeddings, allow_dangerous_deserialization=True)
        return db
    except Exception as e:
        st.error(f"Error loading vector store: {e}")
        st.stop()


@st.cache_resource
def create_rag_chain(_llm, _retriever):
    """Creates the final RAG chain."""
    prompt = ChatPromptTemplate.from_template(RAG_PROMPT_TEMPLATE)
    document_chain = create_stuff_documents_chain(_llm, prompt)
    rag_chain = create_retrieval_chain(_retriever, document_chain)
    return rag_chain

# --- 3. Streamlit App UI ---

st.set_page_config(page_title=APP_TITLE, layout="wide")
st.title(f"🤖 {APP_TITLE}")
st.markdown("This prototype is a demonstration for the **City of Brampton AI PoC Program**. It is an 'AI Mentor' that answers questions based *only* on the 6 official, public-facing HR policy documents.")

# Load models and data
embeddings, llm = load_models()
db = load_vector_store(embeddings)
retriever = db.as_retriever()
rag_chain = create_rag_chain(llm, retriever)

# Initialize chat history
if "messages" not in st.session_state:
    st.session_state.messages = [
        {"role": "assistant", "content": "Welcome! I am the AI Mentor. How can I help you with Brampton's HR policies today?"}
    ]

# Display chat messages from history on app rerun
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# React to user input
if prompt := st.chat_input("Ask a question (e.g., 'What is the policy on harassment?')"):
    # Add user message to chat history
    st.session_state.messages.append({"role": "user", "content": prompt})

    # Display user message in chat message container
    with st.chat_message("user"):
        st.markdown(prompt)

    # Display AI response in chat message container
    with st.chat_message("assistant"):
        with st.spinner("Thinking..."):
            response = rag_chain.invoke({"input": prompt})
            full_response = response['answer']
            st.markdown(full_response)

    # Add AI response to chat history
    st.session_state.messages.append({"role": "assistant", "content": full_response})
Overwriting /content/BramptonHR/app.py

3.3 Deploy to GitHub

This is the final step. This cell will:

  • Move the vectorstore folder (which you built in 2.2) into the cloned repo directory.
  • Use git to add app.py, requirements.txt, and the entire vectorstore.
  • Commit and push everything to the GitHub repo.
  • This push will automatically trigger Streamlit Community Cloud to build and deploy your live app.
In [19]:
# --- 3.3 Deploy to GitHub ---

print("Moving vector store into the repo directory...")
# We must move the vector store *into* the repo folder so Git can commit it.
# This ensures our Streamlit app can load the pre-built index.
!mv {VECTORSTORE_PATH} {REPO_PATH}/

print("Committing and pushing all files to GitHub...")
# Use 'cd' to run Git commands from within the repo directory
git_commands = [
    f"cd {REPO_PATH}",
    "git add .",
    f"git commit -m '{GIT_COMMIT_MESSAGE}'",
    "git push"
]
!{" && ".join(git_commands)}

print("\n--- DEPLOYMENT INITIATED ---")
print(f"Pushed all files to {GITHUB_USERNAME}/{GITHUB_REPO_NAME}.")
print("Streamlit Community Cloud is now rebuilding your app.")
print("Your prototype should be live in 2-3 minutes.")
print("\n--- FINAL STEP (Manual) ---")
print("Go to your app on share.streamlit.io, go to 'Settings' > 'Secrets' and add:")
print(f"Name: GEMINI_API_KEY")
print(f"Value: [Your Google AI Studio API Key]")

print("\nSection 3.0 complete.")
Moving vector store into the repo directory...
mv: cannot stat '/content/vectorstore': No such file or directory
Committing and pushing all files to GitHub...
[main fb0292b] Build: Initial PoC build from Colab factory
 2 files changed, 7 deletions(-)
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 376 bytes | 376.00 KiB/s, done.
Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/burnsgregm/BramptonHR.git
   9a1c195..fb0292b  main -> main

--- DEPLOYMENT INITIATED ---
Pushed all files to burnsgregm/BramptonHR.
Streamlit Community Cloud is now rebuilding your app.
Your prototype should be live in 2-3 minutes.

--- FINAL STEP (Manual) ---
Go to your app on share.streamlit.io, go to 'Settings' > 'Secrets' and add:
Name: GEMINI_API_KEY
Value: [Your Google AI Studio API Key]

Section 3.0 complete.