diff --git a/ai-learning-series b/ai-learning-series new file mode 160000 index 0000000..dd67a32 --- /dev/null +++ b/ai-learning-series @@ -0,0 +1 @@ +Subproject commit dd67a32d672cb82f4c5c321f3a243885c93cc925 diff --git a/getting-started/test_setup.py b/getting-started/test_setup.py new file mode 100644 index 0000000..f635d23 --- /dev/null +++ b/getting-started/test_setup.py @@ -0,0 +1,22 @@ +import sys +print(f"Python version: {sys.version}") + +try: + from google.cloud import aiplatform + print("✅ google-cloud-aiplatform installed") +except ImportError: + print("❌ google-cloud-aiplatform not found") + +try: + import streamlit + print("✅ streamlit installed") +except ImportError: + print("❌ streamlit not found") + +try: + import dotenv + print("✅ python-dotenv installed") +except ImportError: + print("❌ python-dotenv not found") + +print("\n✅ All packages installed successfully!") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 09b0fe3..8aed9eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,9 @@ google-generativeai>=0.3.0 python-dotenv>=1.0.0 streamlit>=1.28.0 +google-cloud-aiplatform>=1.26.0 +vertexai>=0.1.0 +requests>=2.31.0 # ============================================================================ # Optional: Alternative Platforms (Uncomment to use) diff --git a/sessions/session-01-ai-chatbots/live-demo/wcc_app.py b/sessions/session-01-ai-chatbots/live-demo/wcc_app.py index 1a5a997..a5e9c8c 100644 --- a/sessions/session-01-ai-chatbots/live-demo/wcc_app.py +++ b/sessions/session-01-ai-chatbots/live-demo/wcc_app.py @@ -30,7 +30,7 @@ pass # Configure Gemini API (done once at startup) -api_key = os.getenv('GEMINI_API_KEY') or os.getenv("GOOGLE_API_KEY") +api_key = os.getenv('API_KEY') or os.getenv("API_KEY") if api_key: genai.configure(api_key=api_key) print(f"✓ API configured: {bool(api_key)}") @@ -372,16 +372,16 @@ def step_5_streamlit_interface(): # Each step builds on the previous one, showing clear code differences! # Step 1: Basic API integration with Gemini - # step_1_basic_api_call() + step_1_basic_api_call() # Step 2: AI personality with system prompts - # step_2_add_personality() + step_2_add_personality() # Step 3: Conversation memory management - # step_3_conversation_memory() + step_3_conversation_memory() # Step 4: Model parameter experimentation - # step_4_model_parameters() + step_4_model_parameters() # Step 5: Web interface with Streamlit (with personality + conversation history) step_5_streamlit_interface() # Run with: streamlit run wcc_app.py diff --git a/sessions/session-01-ai-chatbots/live-demo/wcc_demo.py b/sessions/session-01-ai-chatbots/live-demo/wcc_demo.py index 5c07cb6..1be586a 100644 --- a/sessions/session-01-ai-chatbots/live-demo/wcc_demo.py +++ b/sessions/session-01-ai-chatbots/live-demo/wcc_demo.py @@ -19,7 +19,7 @@ import google.generativeai as genai from datetime import datetime - +#this sets the model to gemini 2.5 MODEL_ID = 'gemini-2.5-flash-lite' # Load .env if available (dev convenience) @@ -30,9 +30,10 @@ pass # Configure Gemini API (done once at startup) -api_key = os.getenv('GEMINI_API_KEY') or 'your-gemini-api-key-here' +api_key = os.getenv('API_KEY') or "API_KEY" genai.configure(api_key=api_key) + print("🚀 WCC AI Learning Series - Session 1 Demo") print("=" * 50) @@ -146,25 +147,34 @@ def step_3_conversation_memory(): print("STEP 3: Adding Conversation Memory") print("=" * 60) + #defines the new class class WCCChatBot: """Chatbot with conversation memory""" - + #the init is the constructor, which is the first thing that runs, whenver a new object is created def __init__(self): + #self.variable name is an instance variable, unique data that only belongs to one object + #creates the brain of the chatbot and saves it inside self.model self.model = genai.GenerativeModel( + #includes the model's ID MODEL_ID, + #the system prompt needed to instruct the model on what to do system_instruction=WCC_SYSTEM_PROMPT ) + #this instance variable creates an empty list, this will act as the memory self.conversation_history = [] - + #the chat method, is an instance method, a function that the object can perform + # is must take self as the first argument, then user input as the second variable def chat(self, user_input): """Send message and get response with context""" + # this updates the memory with the user input # Add user message to history self.conversation_history.append({"role": "user", "parts": [user_input]}) - + # creates an instance variable that passes the history to the model to generate a response # Generate response with full history response = self.model.generate_content(self.conversation_history) - # Add assistant response to history + # the response is then added to the model's history + # Add assistant response to history, role indicates who said the message, parts indicates the context self.conversation_history.append({"role": "model", "parts": [response.text]}) return response.text @@ -230,6 +240,7 @@ def step_4_model_parameters(): generation_config = genai.types.GenerationConfig( temperature=temp, max_output_tokens=100, + top_p=0.9 ) model_temp = genai.GenerativeModel( @@ -364,13 +375,14 @@ def step_5_streamlit_interface(): step_1_basic_api_call() # Step 2: AI personality with system prompts - # step_2_add_personality() + step_2_add_personality() + # Step 3: Conversation memory management - # step_3_conversation_memory() + step_3_conversation_memory() # Step 4: Model parameter experimentation - # step_4_model_parameters() + step_4_model_parameters() # Step 5: Web interface with Streamlit - # step_5_streamlit_interface() # Run with: streamlit run wcc_demo.py + step_5_streamlit_interface() # Run with: streamlit run wcc_demo.py diff --git a/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/README.md b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/README.md new file mode 100644 index 0000000..2e74450 --- /dev/null +++ b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/README.md @@ -0,0 +1,84 @@ +Welcome! This **AI Chatbot** is your specialized mini-assistant for networking, community building, and finding relevant professional events near you. + +## ✨ Project Overview + +The **Event & Community Finder** is a conversational tool designed to streamline the process of finding local, relevant events from platforms like Meetup and Eventbrite. + +### 🎯 The Core Functionality + +The chatbot is specifically engineered to gather three key pieces of information from the user: + +1. **📍 Location:** Where the user is. +2. **🗓️ Availability:** Which days the user is free. +3. **📚 Focus Area:** Whether they seek **Tech**, **Business**, or **Career-focused** events (with the ability to refine further, e.g., 'Tech events focused on AI agents'). + +Once the inputs are gathered, the chatbot searches external platforms for available events. + +### 💡 Expected Output + +The assistant returns a short, highly useful list of matches including: +Market size and potential Market size in the next 3-5 years +– Competitors (both big and small) +– Common customer pain points +– Current market conditions & Feasibility +– Recommendations on utilising Technology to stay ahead and Systems for efficiency +– Raising Capital / Funding (local perspective, most suitable way based on their scenario) - this is optional and only return if the user requests + +# How to set up + +### 1. Install Dependencies + +```bash +pip install -r code/requirements.txt +``` + +### 2. Set Up Your API Key + +Create a `.env` file in the project root: + +```bash +GEMINI_API_KEY=your-gemini-api-key-here +``` + +Get your API key: [Gemini API Key Setup Guide](../../getting-started/gemini-api-key-setup.md) + + +#### what is included: +chatbot.py - building of the chatbot, where we call the api, create conversation memory, and add parameters +requirements.txt - ptyhon dependencies +.env - where the API key is kept + + +### 3. Run the Demo + +```bash +python wcc_demo.py +``` + + +# How to run it + + + +# What i learned + + Model Parameters: Explored the impact of parameters like temperature (controlling randomness and creativity), and the optimal use of Top P for token selection (e.g., setting probabilities to equal 85%). + Object-Oriented Programming (OOP): Had the opportunity to refresh and apply OOP principles in the code structure. +# Challenges faced +Initial System Prompt: The first system prompt was aiming to output a table which did not work so well when it was formatted, which made the response confusing. +Re-acquaintance: Getting back into the rhythm of Python coding after a break, and integrating with Streamlit for the first time as the chat interface. + +# Future improvements 2.0 + +Enhanced UI/UX: Create a more intuitive and user-friendly interface. + +Context Window Integration: Implement a context window for the AI model to access external, rich information, providing more tailored and well-rounded responses. + +Performance: Optimize the model's setup to potentially reduce thinking/response time. + +Feature Expansion: Add functionality for users to save preferences to a file or subscribe to weekly digests. + +Framework Suggestions: Integrate the ability for the AI to provide relevant professional frameworks alongside event suggestions. + + + diff --git a/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/chatbot.py b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/chatbot.py new file mode 100644 index 0000000..7f83434 --- /dev/null +++ b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/chatbot.py @@ -0,0 +1,354 @@ +#import libraries +import os +import google.generativeai as genai +from datetime import datetime +from dotenv import load_dotenv + +# setting the model name being used +MODEL_ID = 'gemini-2.5-flash-lite' + +#if statememt to check the dotenv file found the env. file, and prints out a messeage in return +loaded = load_dotenv() +if loaded: + print("env. loaded") +else: + print("env. not found, nothing changed") + +#This is done once at the start using enter your API key below, an if statement to ensure the API key is configured +api_key = os.getenv('GEMINI_API_KEY') or os.getenv( "GOOGLE_API_KEY") or os.getenv("API_KEY") +if api_key: + genai.configure(api_key=api_key) + print(f"✓ API configured: {bool(api_key)}") +else: + print("✗ WARNING: No API key found. Set GEMINI_API_KEY or GOOGLE_API_KEY environment variable.") + +print("We're ready to Go!") +print("=" * 50) + +#this is the prompt that will give instructions to the bot on how to respond, what context might be helpful, and a comprehensive idea of it's role and tasks +#''' SYSTEM PROMPT ''' + +event_system_prompt = ''' +ABOUT +A Startup reality check Assistant, You are can be referred to as 'Bartman AI' +# GOAL : Act as a Startup Idea Reality Check Assistant and Business Mentor. Your primary function is to provide rapid, realistic market validation for new business concepts. +# You help users quickly discover their market size estimations, closest competitors, customer pain points. +# Your main focus is Market Validation (Size, Competition, Pain Points). Searches must utilise web capabilities across business websites, trusted reviews (Google/Trustpilot), relevant social platforms (Reddit, Twitter,spotify), news, and established business literature and credible business people. +# You return a well structured validation, with problem clarity, competition density you can base this in the region they are in, and give perspective on expansion, potenital customers and immediate and future risks to consider. + +# OUTPUT +# Deliver a highly structured business validation and recommendation, including a summary table and strategic advice. + +# RECOMMENDATIONS +# Include actionable advice on leveraging AI and specific, low-cost technology stacks for automation and efficiency. +# Quickly recognise pitfalls that could come in the near future, and give recommendation on systems that can be built to overcome them + +PERSONALITY +You are friendly, practical, efficient, and supportive. +You act as a business mentor, a business coach and realistic about the business landscape and have knowledge on how the latest technology and systems can provide efficiency. +You keep explanations short, focused, avoid unnecessary filler, highly structured and pay attention to detail. +You encourage the user to review their business model, but highlight strengths with an encouraging tone you are optimistic, and give practical approach. + +# HOW TO HELP +# You answer questions about how founders, startups or small business owners can scale using online resources +# You encourage further research and show frameworks that have been practiced in business to support their research +# Provide supportive advice, but you are realistic about what can be achieved and what could require additional capabilities. +# If you don't know know anything specific then ask them to provide more context, or offer alternaive solutions that could support their research or business plan/ proposal + +# SEARCH BEHAVIOR (MANDATORY) +# When the user has provided all required inputs, you MUST perform deep web searches focused on: +# 1. Business Models and Company Websites +# 2. Competitor Analysis (platforms, Trustpilot, Google Reviews) +# 3. Market Saturation, Opportunities, and Gaps +# 4. Target Audience Pain Points +# 5. Idea Feasibility based on current/future technological trends. +# 6. Search for any local or regional communities or if it is an online platform give online suggestions for funding, or programme with access to funding, based on their business idea and how they can leverage it + +# RETURN FORMAT +# The final result MUST be returned in a comprehensive set of headers with a paragraph for each, ONLY USE what is appropriate. +# – Market size and potential Market size in the next 3-5 years +# – Competitors (both big and small) +# – Common customer pain points +# – Current market conditions & Feasibility +# – Recommendations on utilising Technology to stay ahead and Systems for efficiency +# – Raising Capital / Funding (local perspective, most suitable way based on their scenario) - this is optional and only return if the user requests + +# STRICT OUTPUT RULES +# • DO NOT list platforms or search steps. +# • DO NOT use hypothetical or untested suggestions. ONLY return recommendations based on proven, tried-and-tested business formulas and strategies. +# • Do not add extra paragraphs outside of the structured advice. Keep it tight and helpful. + +If you do not understand the business or cannot find sufficient information about competitors +- Give alternative, close competitors. +- Clearly state that research around their industry/product/service is limited. + +Conversation Focus +Stay focused on business advice unless the user explicitly shifts topic. +''' +# =================================================================================== +# create a basic API call + +def api_call(): +#create a model instance + model = genai.GenerativeModel(MODEL_ID) + + # create a request + response = model.generate_content ("I would like to start an Ai personalised app but i don't know if it has potential to do well in this market, please help?") + + print(f"\n✅ Response:\n{response.text}") + + print("\n It works!🥳") + +#call the function to make the API call +#api_call() +# =================================================================================== +# Add personality using the system prompt, this allows the model to get more context and information around what you are building +def adding_personality(): + + print("\n" + "=" * 100) + + model_personality = genai.GenerativeModel( + MODEL_ID, + system_instruction= event_system_prompt + ) + + #Test Questions + + test = [ + "Where can i find useful resources that can guide me on starting an AI business. Do you need more information?" + ] + + print("/n This test with the system prompt") + + for question in test: + print(f"Q: {question}") + # this generated a response based on the question asked from the test list + response = model_personality.generate_content(question) + print(f' Answer:✅ {response.text}\n') + print('\n'+ "=" * 100) + + + print('\n A friendlier response with more context from the system prompt') + +adding_personality() +# =================================================================================== +# create a new function for conversation memory +# add conversation memory +# adding conversation context, then building a multi turn conversation, including memory for improved used experience''' +def conversation_memory(): + + class StartupBot: + def __init__(self): + self.model = genai.GenerativeModel( + MODEL_ID, + system_instruction = event_system_prompt + ) + self.conversation_history = [] + + def chat(self,user_prompt): + self.conversation_history.append({'role':'user','parts':[user_prompt]}) + response = self.model.generate_content(self.conversation_history) + self.conversation_history.append({'role':'model','parts':[response.text]}) + return response.text + + chatbot = StartupBot() + + #test messages + msguno = "Hi Bartman AI, I'm Sharmin" + print('My intro',msguno) + responseuno = chatbot.chat(msguno) + print('First response:', responseuno) + msgdos = "Could i get some guidance on what you can assist me with?" + print('My second input:', msgdos) + responsedos = chatbot.chat(msgdos) + print('Second response:', responsedos) + msgtres = "I would like to start a selling herbal products in the UK that are being produced in Kenya , through my own website, i don't know where to start" + print('My third input:',msgtres) + responsetres = chatbot.chat(msgtres) + print('Third reasponse:',responsetres) + +conversation_memory() + +#pseudocode +# define a new class +# this will be a chatbot with comversation memory +#create the first method, which will include the model id, and system instruction, using the generativemodel function. +# create a list for the conversation to be appended/ saved. + +#create a second methond/function that takes two arguments, the first being self, and the second being user input +# use the conversation history object and create a dictionary, that appends role:user, and parts and then calls the [user input] +# create a local variable called response, we passs the instance variable self.model and generate_content and pass the self.coversation history in parethensis +# use the instance variable conversation history and append role:model and parts then pass the response.text, these are the data structure's dictated by gen AI model +# then return the response in text + +#create a variable class instance that calls the class name, then you have the variable + +# write the first message +# test the conversation memory' +# message one could be introducing yourself +# message 2, can be another follow up question, the bot should store the memory of your name +# message 3 - ask the chatbot if they remember your name +# message variable +# print the message +#create a reposne variable and callthe chatbot instance variable and the chat method +# passing the variable in line 158 +#create a second message and follow the same method +# create a third message +# print a message to say that thi step is complete +# this all needs to sit in the same conversation memory function + +# =================================================================================== +# MODEL PARAMETERS +# create a function for model parameters +# inside the function +# Temperature affects creativity, top_p affects diversity, how to tune parameters for different use cases''' + +def model_parameters(): + question = "Give me business ideas that i can explore in areas that are currently untapped or communities that are underserved in the UK, be creative with your suggestions" + print (f" \n Question: {question} \n ") + print (f"Examples of different Temperature changes") + + temperature = [ + (0.0, "Deterministic, very plain and repetitive"), + (0.7, "Balanced, between creative and coherence"), + (1.15, "Very Creative, Diverse and unpredictable") + ] + + for temp, descript in temperature: + print(f'{temp}, {descript}') + Generation_config = genai.types.GenerationConfig( + temperature=temp, + top_p= 0.5, + max_output_tokens=150 + ) + + model_temp = genai.GenerativeModel(MODEL_ID, + generation_config=Generation_config) + + response = model_temp.generate_content(question) + + print(f" The response: {response.text}") + print('Higher temperatures are more creative') + +model_parameters() + +#pseudocode +#create a variable that is a question asking the modoel to write a creative message +# print the question and say that this is the creativity level at the moment +#create a list for the temperatures, 0.0 deterministic, 0.7, 1.5, store the figures in a tuple) +#create a for loop that looks in the temperatures list and prints the temp and description +# in the same for loop create a variable called generation_config = which calls genai.types.generationconfig, and passes +# temperature which will be from the temperature key, max_output tokens and the top_p +# then create a model temp variable - this calls the gen ai generative model and passes model id and generation config = generationconfig variable +# still inside the for loop create a variable for response, calling the model_temp variable and generate content, then pass +# the question to generate the content and create a response +#print the reponse text in the loop +# print the last message that shows how you can notice a high temperature is more creative response. + + + +# =================================================================================== +# WEB INTERFACE +def streamlit_interface (): + + try: + import streamlit as st + except ImportError: + print('Streamlit not installed, import error') + return + + st.set_page_config( + page_title="Startup Reality Check Assistant", + page_icon="💸", + layout="centered") + + st.title("Hey I'm Bartman AI - Your Startup Reality Check assistant") + st.markdown('#### I specialise in providing you in detail, honest and realistic feedback about your business ideas!\n I can help you with market research and provide unique suggestions on how you can leverage the latest technological platforms and tools such as AI') + + #side bar with parameters + st.sidebar.header('Adjust the parameters on your model to make the responses more creative or less creative') + temp_param = st.sidebar.slider("Temperature",0.0,2.0,0.7,0.1) + max_output_toks= st.sidebar.slider("Maximum Tokens",50,500,100,50) + top_p_params = st.sidebar.slider("Top-p",0.1,1.0,0.7,0.1) + + # Initialize session state for conversation history + if "messages" not in st.session_state: + st.session_state.messages = [] + st.session_state.messages.append({ + "role": "assistant", + "content": "Hello! I am your go-to for all your business ideas that you would like to see flourish, but just need that extra help and direction!" + }) + + # Display conversation history + for message in st.session_state.messages: + with st.chat_message(message["role"]): + st.markdown(message["content"]) + + # Chat input + if prompt := st.chat_input("I am not sure where to start, can you give me direction on what information you need to help me"): + # Add user message to chat history + st.session_state.messages.append({"role": "user", "content": prompt}) + with st.chat_message("user"): + st.markdown(prompt) + + # Generate AI response + with st.chat_message("assistant"): + with st.spinner("I am Thinking this through... bare with me.."): + # Configure model with user settings + generation_config = genai.types.GenerationConfig( + temperature=temp_param, + max_output_tokens=max_output_toks, + top_p=top_p_params + ) + + model_ui = genai.GenerativeModel( + MODEL_ID, + generation_config=generation_config, + system_instruction=event_system_prompt + ) + + # Create conversation context + context = "\n".join([ + f"{msg['role']}: {msg['content']}" + for msg in st.session_state.messages[-5:] # Last 5 messages + ]) + + full_prompt = f"Conversation context:\n{context}\n\nUser: {prompt}" + response = model_ui.generate_content(full_prompt) + + st.markdown(response.text) + + # Add assistant response to chat history + st.session_state.messages.append({"role": "assistant", "content": response.text}) + + # Display current settings + st.sidebar.markdown("---") + st.sidebar.markdown("**Current Settings:**") + st.sidebar.write(f"🌡️ Temperature: {temp_param}") + st.sidebar.write(f"📝 Max Tokens: {max_output_toks}") + st.sidebar.write(f"🎯 Top-p: {top_p_params}") + + # Usage instructions + with st.expander("💡 How to use this bot"): + st.markdown(''' + **Try asking:** + - Where can i start with forumlating a business plan? + - Which technologies should i leverage for my small local hair salon business to keep me competitive in Manchester? + - Which funding opportunities are available for black female founders? + - I have never started my own business where do i start? + + **Experiment with settings:** + - 🌡️ **Temperature**: Higher = more creative responses + - 📝 **Max Tokens**: Longer responses + - 🎯 **Top-p**: Lower = more focused responses + ''') + +streamlit_interface() + + +# create a function for streamlit interface +# inside the function create a try and except , import streamlit for try +# except importerror: then print not installed +# set the page config then pass - page title, page icon and layout +#set the title and a markdown as a subtitle +#create a sidebar with controls for temprature, max token and top p diff --git a/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/requirements.txt b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/requirements.txt new file mode 100644 index 0000000..b634ad4 --- /dev/null +++ b/sessions/session-01-ai-chatbots/participants/sharmin-osoo/code/requirements.txt @@ -0,0 +1,3 @@ +google-generativeai>=0.3.0 +python-dotenv>=1.0.0 +streamlit>=1.28.0 \ No newline at end of file diff --git a/sessions/session-01-ai-chatbots/starter-template/chatbot.py b/sessions/session-01-ai-chatbots/starter-template/chatbot.py index 09cc5fa..40c5b07 100644 --- a/sessions/session-01-ai-chatbots/starter-template/chatbot.py +++ b/sessions/session-01-ai-chatbots/starter-template/chatbot.py @@ -11,7 +11,7 @@ load_dotenv() # Configure Gemini API -API_KEY = os.getenv("GEMINI_API_KEY") +API_KEY = os.getenv("API_KEY") if not API_KEY: raise ValueError( "GEMINI_API_KEY not found in environment variables. "