├── logo.png ├── pizza.jpg ├── sessions ├── session_5 │ ├── guide-to-keto-diet.pdf │ └── README.md ├── session_6 │ ├── Proposals │ │ ├── Proposal 1.pdf │ │ ├── Proposal 2.pdf │ │ ├── Proposal 3.pdf │ │ └── Proposal 4.pdf │ └── README.md ├── session_4 │ ├── pdfs │ │ ├── paleo_internal_plan.pdf │ │ ├── vegan_internal_plan.pdf │ │ ├── glutenfree_internal_plan.pdf │ │ ├── ketogenic_internal_plan.pdf │ │ └── mediterranean_internal_plan.pdf │ ├── app │ │ ├── .streamlit │ │ │ ├── secrets.toml │ │ │ └── config.toml │ │ ├── pages │ │ │ ├── 3_Nutrition_Agent_[RAG].py │ │ │ ├── 1_Event_Agent_[ReAct Search].py │ │ │ └── 2_Training_Agent_[CoT FSP].py │ │ ├── prompts.py │ │ ├── base_model_utils.py │ │ ├── Home.py │ │ └── main.py │ ├── README.md │ └── notebooks │ │ ├── intro_huggingface.ipynb │ │ └── rag_huggingface.ipynb ├── session_3 │ └── app │ │ ├── .streamlit │ │ ├── secrets.toml │ │ └── config.toml │ │ ├── pages │ │ ├── 3_Nutrition_Agent_[RAG].py │ │ ├── 1_Event_Agent_[ReAct Search].py │ │ └── 2_Training_Agent_[CoT].py │ │ ├── main.py │ │ ├── prompts.py │ │ ├── README.md │ │ ├── base_model_utils.py │ │ └── Home.py ├── session_1 │ ├── app │ │ ├── .streamlit │ │ │ └── config.toml │ │ ├── prompts.py │ │ ├── model_utils.py │ │ └── Home.py │ └── README.md ├── session_2 │ ├── README.md │ └── notebooks │ │ ├── react_event_agent.ipynb │ │ ├── langchain_foundations.ipynb │ │ ├── search_agent.ipynb │ │ └── langgraph_foundations.ipynb └── session_7 │ ├── README.md │ └── notebooks │ ├── data.jsonl │ ├── data_original.jsonl │ └── fine_tuning.ipynb └── .gitignore /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/logo.png -------------------------------------------------------------------------------- /pizza.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/pizza.jpg -------------------------------------------------------------------------------- /sessions/session_5/guide-to-keto-diet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_5/guide-to-keto-diet.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .DS_Store 3 | student_version.zip 4 | student_version/ 5 | venv/ 6 | venv_new/ 7 | sessions/session_4/notebooks/model_directory/ -------------------------------------------------------------------------------- /sessions/session_6/Proposals/Proposal 1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_6/Proposals/Proposal 1.pdf -------------------------------------------------------------------------------- /sessions/session_6/Proposals/Proposal 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_6/Proposals/Proposal 2.pdf -------------------------------------------------------------------------------- /sessions/session_6/Proposals/Proposal 3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_6/Proposals/Proposal 3.pdf -------------------------------------------------------------------------------- /sessions/session_6/Proposals/Proposal 4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_6/Proposals/Proposal 4.pdf -------------------------------------------------------------------------------- /sessions/session_4/pdfs/paleo_internal_plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_4/pdfs/paleo_internal_plan.pdf -------------------------------------------------------------------------------- /sessions/session_4/pdfs/vegan_internal_plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_4/pdfs/vegan_internal_plan.pdf -------------------------------------------------------------------------------- /sessions/session_4/pdfs/glutenfree_internal_plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_4/pdfs/glutenfree_internal_plan.pdf -------------------------------------------------------------------------------- /sessions/session_4/pdfs/ketogenic_internal_plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_4/pdfs/ketogenic_internal_plan.pdf -------------------------------------------------------------------------------- /sessions/session_3/app/.streamlit/secrets.toml: -------------------------------------------------------------------------------- 1 | # .streamlit/secrets.toml 2 | 3 | [passwords] 4 | # Follow the rule: username = "password" 5 | rickc = "streamlit123" -------------------------------------------------------------------------------- /sessions/session_4/app/.streamlit/secrets.toml: -------------------------------------------------------------------------------- 1 | # .streamlit/secrets.toml 2 | 3 | [passwords] 4 | # Follow the rule: username = "password" 5 | rickc = "streamlit123" -------------------------------------------------------------------------------- /sessions/session_4/pdfs/mediterranean_internal_plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rchakra4/aiug-workshop/HEAD/sessions/session_4/pdfs/mediterranean_internal_plan.pdf -------------------------------------------------------------------------------- /sessions/session_1/app/.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [theme] 2 | primaryColor="#7e4bff" 3 | backgroundColor="#fafaff" 4 | secondaryBackgroundColor="#eff2f5" 5 | textColor="#081e79" 6 | -------------------------------------------------------------------------------- /sessions/session_3/app/.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [theme] 2 | primaryColor="#7e4bff" 3 | backgroundColor="#fafaff" 4 | secondaryBackgroundColor="#eff2f5" 5 | textColor="#081e79" 6 | -------------------------------------------------------------------------------- /sessions/session_4/app/.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [theme] 2 | primaryColor="#7e4bff" 3 | backgroundColor="#fafaff" 4 | secondaryBackgroundColor="#eff2f5" 5 | textColor="#081e79" 6 | -------------------------------------------------------------------------------- /sessions/session_4/README.md: -------------------------------------------------------------------------------- 1 | # Building on open-source AI with Hugging Face 2 | 3 | ## Summary 4 | 5 | Dive into the world of building AI features and applications with open-source AI. In this workshop, you will learn how to build on top of the latest resources and tools from Hugging Face and deploy AI models in your own infrastructure. 6 | -------------------------------------------------------------------------------- /sessions/session_1/README.md: -------------------------------------------------------------------------------- 1 | # Foundations of AI applications with Open AI 2 | 3 | ## Summary 4 | 5 | This workshop offers hands-on experience in understanding the building blocks of AI applications. You will learn how to use the OpenAI API to build chat interactions, develop process flows, and wrap these components into simple yet powerful applications. 6 | 7 | ## Key Functionality 8 | 9 | The `ai_foundations.ipynb` notebook outlines the fundamental functionalities of the OpenAI chat completion API, including: 10 | 11 | - **Calling the API** 12 | 13 | - **Processing the API Response** 14 | 15 | - **Exploring Streaming / JSON Mode** 16 | 17 | - **Vision** 18 | 19 | - **Key Prompting Techniques** 20 | -------------------------------------------------------------------------------- /sessions/session_5/README.md: -------------------------------------------------------------------------------- 1 | # Optimize AI deployment across multiple devices 2 | 3 | ## Summary 4 | 5 | In this workshop, you will learn how to deploy AI models across different hardware, ensuring optimal performance from edge devices to cloud servers. We will explore how to use Intel OpenVino’s integration with Hugging Face to construct a RAG pipeline and apply model compression techniques to enhance efficiency without sacrificing performance. 6 | 7 | ## Key Functionality 8 | 9 | The `quantization_rag.ipynb` notebook should be uploaded to google colab. It contains a step-by-step guide for OpenVino's model conversion and compression routines applied to embedding models, reranking models, and LLMs. The converted / compressed models are then applied to build a Langchain RAG Pipeline with a Gradio dashboard. 10 | -------------------------------------------------------------------------------- /sessions/session_2/README.md: -------------------------------------------------------------------------------- 1 | # Building agentic AI workflows for complex tasks 2 | 3 | ## Summary 4 | 5 | This hands-on workshop expands on the foundations of AI applications, transforming basic chat interactions to agentic workflows. You will learn how to build advanced AI agents capable of reflection, tool use, memory, planning, and taking action to solve complex tasks. 6 | 7 | ## Key Functionality 8 | 9 | The `langchain_foundations.ipynb` notebook outlines the main syntax / patterns in langchain. 10 | The `langgraph_foundations.ipynb` notebook outlines the main syntax / patterns in langgraph. 11 | The `react_event_agent.ipynb` notebook creates a ReAct agent with web asking, which we will embed into our app. 12 | The `search_agent.ipynb` notebook contains supplementary material for creating an agent with search capabilities. 13 | -------------------------------------------------------------------------------- /sessions/session_6/README.md: -------------------------------------------------------------------------------- 1 | # Building no-code AI workflows 2 | 3 | ## Summary 4 | 5 | In this workshop, we will dive into the world of no-code AI-powered automations. You will learn how to use UIPath Studio and apply UIPath’s advanced AI capabilities to quickly build intelligent process automations including document analysis, data extraction, and data / API integrations. 6 | 7 | ## Key Functionality 8 | 9 | This workshop is conducted in UIPath Studio Web. Please log into your UIPath account, access UIPath Studio in the menu on the left, and select Projects. This will be our starting point. Once completed, you can revist the workflow by selecting the project name on the Projects page. 10 | 11 | We are going to build a document processing pipeline using UIPath's Gen AI automations, including: 12 | 13 | - Learning how to use Studio Web 14 | - Develop a trigger-based process automation 15 | - Integrate with third-party data sources and targets 16 | - Process data through a document understanding pipeline 17 | - Apply document validation techniques 18 | - Explore UIPath Assistant functionality 19 | -------------------------------------------------------------------------------- /sessions/session_3/app/pages/3_Nutrition_Agent_[RAG].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import requests 3 | 4 | st.set_page_config(layout="wide") 5 | 6 | # Header 7 | title = "myfitnessagent" 8 | logo_path = "../../../logo.png" 9 | 10 | if "nutrition_response" not in st.session_state: 11 | st.session_state.nutrition_response = "" 12 | 13 | col1, col2 = st.columns([1, 10]) 14 | 15 | with col1: 16 | st.image(logo_path, width=100) 17 | 18 | # Display the title in the second column 19 | with col2: 20 | st.title(title) 21 | 22 | 23 | 24 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 25 | st.write("Please login first.") 26 | st.stop() 27 | 28 | 29 | st.subheader("Let me help you find specific meal options based on your diet (e.g., Mediterranean, Keto, Vegan, etc.)!") 30 | user_input = st.text_input(label="nutrition_agent", label_visibility="hidden", placeholder="What are some Mediterranean breakfast options?") 31 | 32 | # button to submit request 33 | if st.button("Request nutrition options"): 34 | with st.spinner(f'Retrieving...'): 35 | data = requests.post("http://127.0.0.1:8000/nutrition").json() 36 | st.session_state.nutrition_response = data["response"] 37 | 38 | st.write(st.session_state.nutrition_response) 39 | -------------------------------------------------------------------------------- /sessions/session_4/app/pages/3_Nutrition_Agent_[RAG].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import requests 3 | 4 | st.set_page_config(layout="wide") 5 | 6 | # Header 7 | title = "myfitnessagent" 8 | logo_path = "../../../logo.png" 9 | 10 | if "nutrition_response" not in st.session_state: 11 | st.session_state.nutrition_response = "" 12 | 13 | col1, col2 = st.columns([1, 10]) 14 | 15 | with col1: 16 | st.image(logo_path, width=100) 17 | 18 | # Display the title in the second column 19 | with col2: 20 | st.title(title) 21 | 22 | 23 | 24 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 25 | st.write("Please login first.") 26 | st.stop() 27 | 28 | 29 | st.subheader("Let me help you find specific meal options based on your diet (e.g., Mediterranean, Keto, Vegan, etc.)!") 30 | user_input = st.text_input(label="nutrition_agent", label_visibility="hidden", placeholder="What are some Mediterranean breakfast options?") 31 | 32 | # button to submit request 33 | if st.button("Request nutrition options"): 34 | with st.spinner(f'Retrieving...'): 35 | data = requests.post("http://127.0.0.1:8000/nutrition", json={"question": user_input}).json() 36 | st.session_state.nutrition_response = data["response"] 37 | 38 | st.write(st.session_state.nutrition_response) -------------------------------------------------------------------------------- /sessions/session_7/README.md: -------------------------------------------------------------------------------- 1 | # Enhance Model Performance with OpenAI’s Fine-Tuning API 2 | 3 | ## Summary 4 | 5 | Struggling with prompt-engineering and Retrieval-Augmented Generation (RAG) without seeing the desired performance? In this workshop, you will gain insight into when you should explore fine-tuning options and learn how to design and execute OpenAI fine-tuning jobs using a custom dataset. 6 | 7 | ## Key Functionality 8 | 9 | The `fine_tuning.ipynb` notebook is a guide designed to walk you through the fine-tuning process with OpenAI's API using a custom dataset. Here's what it covers: 10 | 11 | - **Dataset Preparation**: Instructions on how to prepare your dataset for fine-tuning, including formatting guidelines and best practices for text data. 12 | 13 | - **Fine-Tuning Configuration**: Details on how to configure your fine-tuning job, including selecting the right model, setting up hyperparameters, and understanding the impact of each setting on your model's performance. 14 | 15 | - **Executing Fine-Tuning Jobs**: Step-by-step guidance on how to submit your fine-tuning job to OpenAI's API, monitor its progress, and retrieve the trained model. 16 | 17 | - **Model Evaluation**: Techniques for evaluating the performance of your fine-tuned model, including metrics to consider and how to interpret them. 18 | 19 | - **Integration and Deployment**: Tips on how to integrate your fine-tuned model into applications and deploy it for real-world use. 20 | -------------------------------------------------------------------------------- /sessions/session_4/app/pages/1_Event_Agent_[ReAct Search].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from openai import OpenAI 3 | import requests 4 | 5 | client = OpenAI() 6 | 7 | st.set_page_config(layout="wide") 8 | 9 | # Header 10 | title = "myfitnessagent" 11 | logo_path = "../../../logo.png" 12 | 13 | if "event_response" not in st.session_state: 14 | st.session_state.event_response = "" 15 | 16 | col1, col2 = st.columns([1, 10]) 17 | 18 | with col1: 19 | st.image(logo_path, width=100) 20 | 21 | # Display the title in the second column 22 | with col2: 23 | st.title(title) 24 | 25 | 26 | 27 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 28 | st.write("Please login first.") 29 | st.stop() 30 | 31 | # Set up the main app page 32 | st.subheader("Let me help you find your next local athletic event!") 33 | st.write("For example, I can help you find a 5k running event in New York City in August") 34 | 35 | with st.form(key='event_form'): 36 | event_type = st.text_input("Type of event") 37 | location = st.text_input("Location") 38 | time_frame = st.text_input("Month") 39 | submit_button = st.form_submit_button(label='Submit') 40 | 41 | if submit_button: 42 | payload = { 43 | "event_type": event_type, 44 | "location": location, 45 | "time_frame": time_frame 46 | } 47 | 48 | with st.spinner(f'Looking for {location} {event_type} in {time_frame}...'): 49 | response = requests.post("http://localhost:8000/event", json=payload).json() 50 | st.session_state.event_response = response["response"] 51 | 52 | # display output 53 | st.write(st.session_state.event_response) 54 | -------------------------------------------------------------------------------- /sessions/session_3/app/pages/1_Event_Agent_[ReAct Search].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from openai import OpenAI 3 | import requests 4 | 5 | client = OpenAI() 6 | 7 | st.set_page_config(layout="wide") 8 | 9 | # Header 10 | title = "myfitnessagent" 11 | logo_path = "../../../logo.png" 12 | 13 | if "event_response" not in st.session_state: 14 | st.session_state.event_response = "" 15 | 16 | col1, col2 = st.columns([1, 10]) 17 | 18 | with col1: 19 | st.image(logo_path, width=100) 20 | 21 | # Display the title in the second column 22 | with col2: 23 | st.title(title) 24 | 25 | 26 | 27 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 28 | st.write("Please login first.") 29 | st.stop() 30 | 31 | # Set up the main app page 32 | st.subheader("Welcome to myfitnessagent - let me help you find your next local athletic event!") 33 | st.write("For example, I can help you find a 5k running event in New York City in August") 34 | 35 | with st.form(key='event_form'): 36 | event_type = st.text_input("Type of event") 37 | location = st.text_input("Location") 38 | time_frame = st.text_input("Month") 39 | submit_button = st.form_submit_button(label='Submit') 40 | 41 | if submit_button: 42 | payload = { 43 | "event_type": event_type, 44 | "location": location, 45 | "time_frame": time_frame 46 | } 47 | 48 | with st.spinner(f'Looking for {location} {event_type} in {time_frame}...'): 49 | response = requests.post("http://localhost:8000/event", json=payload).json() 50 | st.session_state.event_response = response["response"] 51 | 52 | # display output 53 | st.write(st.session_state.event_response) 54 | -------------------------------------------------------------------------------- /sessions/session_3/app/main.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from fastapi import FastAPI 3 | from langgraph.checkpoint.sqlite import SqliteSaver 4 | 5 | from langchain_openai import ChatOpenAI 6 | from langchain_community.tools.tavily_search import TavilySearchResults 7 | from langgraph.checkpoint.sqlite import SqliteSaver 8 | from langgraph.prebuilt import create_react_agent 9 | 10 | from dotenv import load_dotenv 11 | load_dotenv() 12 | 13 | ########################### 14 | ### ReAct Search Agent #### 15 | ########################### 16 | 17 | # Create the agent with memory and search tool 18 | memory = SqliteSaver.from_conn_string(":memory:") 19 | model = ChatOpenAI(model='gpt-4o') 20 | search = TavilySearchResults(max_results=2) 21 | tools = [search] 22 | agent_executor = create_react_agent(model, tools, checkpointer=memory) 23 | 24 | 25 | ########################### 26 | ### Nutrition Agent #### 27 | ########################### 28 | ## TBD 29 | 30 | 31 | 32 | ########################### 33 | ### App Endpoint #### 34 | ########################### 35 | 36 | app = FastAPI() 37 | 38 | @app.post("/nutrition") 39 | def generate_nutrition(): 40 | return {"response": "WIP"} 41 | 42 | @app.post("/event") 43 | def generate_events(data: Dict): 44 | print(data) 45 | event_type = data["event_type"] 46 | location = data["location"] 47 | time_frame = data["time_frame"] 48 | user_input = f"Find me {event_type} events in {location} around {time_frame} time frame in 2024. Return back specific events." 49 | 50 | # Set memory for a specific thread 51 | config = {"configurable": {"thread_id": "rc45"}} 52 | 53 | response = agent_executor.invoke({"messages": [("user", user_input)]}, config) 54 | 55 | response = response["messages"][-1].content 56 | return {"response": response} -------------------------------------------------------------------------------- /sessions/session_1/app/prompts.py: -------------------------------------------------------------------------------- 1 | system_prompt = """You are a nutrition and fitness coach specializing in preparing nutrition and fitness plans for your clients based on their goals. 2 | You operate in two phases. 3 | In Phase 1, you learn about a user's goals and create a personalized training and nutrition plan for today. 4 | In Phase 2, you help a user keep the plan updated by making adjustments based on what they ate. 5 | 6 | Here are your steps in Phase 1 (setting up a training and nutrition plan for them to try out today): 7 | - Your objective is to learn about the user's goals (e.g., competeting in a 5K, starting in a pickleball league, just want more energy, etc.) and create a training and nutrition plan for today to get them started. 8 | - Only ask 4 questions: What their goal (or activity) is, their current fitness level, how often they want to train, and any dietary restrictions. 9 | - Before responding to the user, think step by step about what you need to ask or do to create a personalized training plan for today. Output your thinking within tags and include what Phase you are in. 10 | - Then, generate your user-facing message output within tags. This could contain the question or comment you want to present to the user. Do not pass any other tags within tags. 11 | - Your messages should be simple and to the point. Avoid overly narrating. Only ask 1 question at a time. 12 | 13 | When you have a training plan for today ready, output it within tags. 14 | When you have a nutrition plan for today ready, output it within tags. 15 | This concludes Phase 1. Send the user a message in tags wishing them luck at the end of the conversation. 16 | 17 | In Phase 2 (updating the plan): 18 | - When the user mentions what they did or ate, tell them you can't update their plan just yet. 19 | """ 20 | 21 | -------------------------------------------------------------------------------- /sessions/session_3/app/prompts.py: -------------------------------------------------------------------------------- 1 | system_prompt = """You are a nutrition and fitness coach specializing in preparing nutrition and fitness plans for your clients based on their goals. 2 | You operate in two phases. 3 | In Phase 1, you learn about a user's goals and create a personalized training and nutrition plan for today. 4 | In Phase 2, you help a user keep the plan updated by making adjustments based on what they ate. 5 | 6 | Here are your steps in Phase 1 (setting up a training and nutrition plan for them to try out today): 7 | - Your objective is to learn about the user's goals (e.g., competeting in a 5K, starting in a pickleball league, just want more energy, etc.) and create a training and nutrition plan for today to get them started. 8 | - Only ask 4 questions: What their goal (or activity) is, their current fitness level, how often they want to train, and any dietary restrictions. 9 | - Before responding to the user, think step by step about what you need to ask or do to create a personalized training plan for today. Output your thinking within tags and include what Phase you are in. 10 | - Then, generate your user-facing message output within tags. This could contain the question or comment you want to present to the user. Do not pass any other tags within tags. 11 | - Your messages should be simple and to the point. Avoid overly narrating. Only ask 1 question at a time. 12 | 13 | When you have a training plan for today ready, output it within tags. 14 | When you have a nutrition plan for today ready, output it within tags. 15 | This concludes Phase 1. Send the user a message in tags wishing them luck at the end of the conversation. 16 | 17 | In Phase 2 (updating the plan): 18 | - When the user mentions what they did or ate, tell them you can't update their plan just yet. 19 | """ 20 | 21 | -------------------------------------------------------------------------------- /sessions/session_4/app/prompts.py: -------------------------------------------------------------------------------- 1 | 2 | system_prompt = """You are a nutrition and fitness coach specializing in preparing nutrition and fitness plans for your clients based on their goals. 3 | You operate in two phases. 4 | In Phase 1, you learn about a user's goals and create a personalized training and nutrition plan for today. 5 | In Phase 2, you help a user keep the plan updated by making adjustments based on what they ate. 6 | 7 | Here are your steps in Phase 1 (setting up a training and nutrition plan for them to try out today): 8 | - Your objective is to learn about the user's goals (e.g., competeting in a 5K, starting in a pickleball league, just want more energy, etc.) and create a training and nutrition plan for today to get them started. 9 | - Only ask 4 questions: What their goal (or activity) is, their current fitness level, how often they want to train, and any dietary restrictions. 10 | - Before responding to the user, think step by step about what you need to ask or do to create a personalized training plan for today. Output your thinking within tags and include what Phase you are in. 11 | - Then, generate your user-facing message output within tags. This could contain the question or comment you want to present to the user. Do not pass any other tags within tags. 12 | - Your messages should be simple and to the point. Avoid overly narrating. Only ask 1 question at a time. 13 | 14 | When you have a training plan for today ready, output it within tags. 15 | When you have a nutrition plan for today ready, output it within tags. 16 | This concludes Phase 1. Send the user a message in tags wishing them luck at the end of the conversation. 17 | 18 | In Phase 2 (updating the plan): 19 | - When the user mentions what they did or ate, tell them you can't update their plan just yet. 20 | """ 21 | 22 | -------------------------------------------------------------------------------- /sessions/session_3/app/README.md: -------------------------------------------------------------------------------- 1 | # Streamlit AI Agents Application 2 | 3 | This Streamlit application serves as an interface for interacting with three distinct AI agents, each designed to perform specific tasks. The application is structured with a main entry point (Home.py) and additional pages for each agent, facilitating user interaction and showcasing the capabilities of each AI model. The streamlit application also uses a fastapi backend for a agent #1 (ReAct) and agent #3 (RAG) endpoints. 4 | 5 | ## Installation 6 | 7 | To run this application, you need to have Python installed on your system. 8 | 9 | Once Python is installed, you can install Streamlit and other required packages using pip: 10 | 11 | Add any other packages your application depends on in the same way. 12 | 13 | You also need OpenAI, Langchain, and Tavily API keys. 14 | 15 | ## Running the Application 16 | 17 | To start the application, navigate to the application's root directory in your terminal and run: 18 | 19 | streamlit run Home.py 20 | 21 | This command launches the Streamlit web server and opens the application in your default web browser. 22 | 23 | To run the fastapi backend for the LLM endpoints: 24 | 25 | fastapi dev main.py 26 | 27 | Application Structure 28 | Home.py: The main entry point of the application. It provides an overview of the different AI agents. 29 | 30 | /pages: 31 | 32 | Each page within this folder is connected to a different AI agent, designed to showcase a specific functionality or use case. The pages include: 33 | Page 1: Connected to AI Agent 1. ReAct agent with web search tools. 34 | Page 2: Connected to AI Agent 2. Basic agent built on OpenAI API with memory and Chain of Thought 35 | Page 3: Connected to AI Agent 3. Retrieval Augmented Generation Pipeline 36 | 37 | Usage 38 | After launching the application, use the sidebar to navigate between the home page and the different AI agents. Each page provides an interface to interact with the respective AI agent, allowing you to input data or queries and receive responses. 39 | -------------------------------------------------------------------------------- /sessions/session_1/app/model_utils.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import base64 3 | import re 4 | 5 | def call_chat_model(client, messages): 6 | return client.chat.completions.create( 7 | model="gpt-4o", 8 | messages=messages, 9 | temperature=1, 10 | max_tokens=4096 11 | ) 12 | 13 | def call_image_model(client, file): 14 | 15 | # Read the file-like object (uploaded_file) 16 | image_data = file.read() 17 | # Encode the file data in base64 18 | base64_image = base64.b64encode(image_data).decode('utf-8') 19 | 20 | # Create API request 21 | response = client.chat.completions.create( 22 | model="gpt-4o", 23 | messages=[ 24 | { 25 | "role": "user", 26 | "content": [ 27 | { 28 | "type": "text", 29 | "text": f"""You are given an image of the user's food. 30 | This is their nutrition plan: {st.session_state.nutrition_tracker} tags briefly explaining to them how you changed their nutrition plan based on the image they uploaded. 33 | Also provide the updated nutrition plan using tags.""", 34 | }, 35 | { 36 | "type": "image_url", 37 | "image_url": { 38 | "url": f"data:image/jpeg;base64,{base64_image}", 39 | }, 40 | } 41 | ], 42 | } 43 | ], 44 | max_tokens=4096, 45 | ) 46 | 47 | # Parse the response content 48 | content = response.choices[0].message.content 49 | 50 | # Use regex to extract tags 51 | message_pattern = r"(.*?)" 52 | nutrition_pattern = r"(.*?)" 53 | message = re.findall(message_pattern, content, re.DOTALL) 54 | nutrition = re.findall(nutrition_pattern, content, re.DOTALL) 55 | 56 | return message[0] if message else "", nutrition[0] if nutrition else "" -------------------------------------------------------------------------------- /sessions/session_3/app/base_model_utils.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import base64 3 | import re 4 | 5 | 6 | def call_chat_model(client, messages): 7 | return client.chat.completions.create( 8 | model="gpt-4o", 9 | messages=messages, 10 | temperature=1, 11 | max_tokens=4096 12 | ) 13 | 14 | def call_image_model(client, file): 15 | 16 | # Read the file-like object (uploaded_file) 17 | image_data = file.read() 18 | # Encode the file data in base64 19 | base64_image = base64.b64encode(image_data).decode('utf-8') 20 | 21 | # Create API request 22 | response = client.chat.completions.create( 23 | model="gpt-4o", 24 | messages=[ 25 | { 26 | "role": "user", 27 | "content": [ 28 | { 29 | "type": "text", 30 | "text": f"""You are given an image of the user's food. 31 | This is their nutrition plan: {st.session_state.nutrition_tracker} tags briefly explaining to them how you changed their nutrition plan based on the image they uploaded. 34 | Also provide the updated nutrition plan using tags.""", 35 | }, 36 | { 37 | "type": "image_url", 38 | "image_url": { 39 | "url": f"data:image/jpeg;base64,{base64_image}", 40 | }, 41 | } 42 | ], 43 | } 44 | ], 45 | max_tokens=4096, 46 | ) 47 | 48 | # Parse the response content 49 | content = response.choices[0].message.content 50 | 51 | # Use regex to extract tags 52 | message_pattern = r"(.*?)" 53 | nutrition_pattern = r"(.*?)" 54 | message = re.findall(message_pattern, content, re.DOTALL) 55 | nutrition = re.findall(nutrition_pattern, content, re.DOTALL) 56 | 57 | return message[0] if message else "", nutrition[0] if nutrition else "" 58 | 59 | 60 | -------------------------------------------------------------------------------- /sessions/session_4/app/base_model_utils.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import base64 3 | import re 4 | 5 | 6 | def call_chat_model(client, messages): 7 | return client.chat.completions.create( 8 | model="gpt-4o", 9 | messages=messages, 10 | temperature=1, 11 | max_tokens=4096 12 | ) 13 | 14 | def call_image_model(client, file): 15 | 16 | # Read the file-like object (uploaded_file) 17 | image_data = file.read() 18 | # Encode the file data in base64 19 | base64_image = base64.b64encode(image_data).decode('utf-8') 20 | 21 | # Create API request 22 | response = client.chat.completions.create( 23 | model="gpt-4o", 24 | messages=[ 25 | { 26 | "role": "user", 27 | "content": [ 28 | { 29 | "type": "text", 30 | "text": f"""You are given an image of the user's food. 31 | This is their nutrition plan: {st.session_state.nutrition_tracker} tags briefly explaining to them how you changed their nutrition plan based on the image they uploaded. 34 | Also provide the updated nutrition plan using tags.""", 35 | }, 36 | { 37 | "type": "image_url", 38 | "image_url": { 39 | "url": f"data:image/jpeg;base64,{base64_image}", 40 | }, 41 | } 42 | ], 43 | } 44 | ], 45 | max_tokens=4096, 46 | ) 47 | 48 | # Parse the response content 49 | content = response.choices[0].message.content 50 | 51 | # Use regex to extract tags 52 | message_pattern = r"(.*?)" 53 | nutrition_pattern = r"(.*?)" 54 | message = re.findall(message_pattern, content, re.DOTALL) 55 | nutrition = re.findall(nutrition_pattern, content, re.DOTALL) 56 | 57 | return message[0] if message else "", nutrition[0] if nutrition else "" 58 | 59 | 60 | -------------------------------------------------------------------------------- /sessions/session_3/app/Home.py: -------------------------------------------------------------------------------- 1 | 2 | import hmac 3 | import streamlit as st 4 | 5 | st.set_page_config(layout="wide") 6 | 7 | def check_password(): 8 | """Returns `True` if the user had a correct password.""" 9 | 10 | def login_form(): 11 | """Form with widgets to collect user information""" 12 | with st.form("Credentials"): 13 | st.text_input("Username", key="username") 14 | st.text_input("Password", type="password", key="password") 15 | st.form_submit_button("Log in", on_click=password_entered) 16 | 17 | def password_entered(): 18 | """Checks whether a password entered by the user is correct.""" 19 | if st.session_state["username"] in st.secrets[ 20 | "passwords" 21 | ] and hmac.compare_digest( 22 | st.session_state["password"], 23 | st.secrets.passwords[st.session_state["username"]], 24 | ): 25 | st.session_state["password_correct"] = True 26 | del st.session_state["password"] # Don't store the username or password. 27 | del st.session_state["username"] 28 | else: 29 | st.session_state["password_correct"] = False 30 | 31 | # Return True if the username + password is validated. 32 | if st.session_state.get("password_correct", False): 33 | return True 34 | 35 | # Show inputs for username + password. 36 | login_form() 37 | return False 38 | 39 | 40 | # Header 41 | title = "myfitnessagent" 42 | logo_path = "../../../logo.png" 43 | 44 | col1_header, col2_header = st.columns([1, 10]) 45 | 46 | with col1_header: 47 | st.image(logo_path, width=100) 48 | 49 | # Display the title in the second column 50 | with col2_header: 51 | st.title(title) 52 | 53 | st.write("") 54 | 55 | # Set up the main app page 56 | st.subheader("Welcome to myfitnessagent") 57 | 58 | col1_auth, col2_auth = st.columns([1, 2]) 59 | 60 | with col1_auth: 61 | if not check_password(): 62 | st.stop() 63 | 64 | # Display the title in the second column 65 | with col2_auth: 66 | st.write("") 67 | 68 | 69 | if not check_password(): 70 | st.stop() # Do not continue if check_password is not True. 71 | 72 | # User is already logged in, show the authenticated message 73 | st.write(f"You have been authenticated.") 74 | st.write("Select your agent from the sidebar to begin.") 75 | 76 | st.subheader("Agents available:") 77 | st.write("1. Onboarding Agent [ReAct]") 78 | st.write("2. Training Agent [CoT FSP]") 79 | st.write("3. Nutrition Agent [RAG]") 80 | 81 | # Add a logout button 82 | if st.button('Logout'): 83 | st.session_state["password_correct"] = False 84 | st.rerun() -------------------------------------------------------------------------------- /sessions/session_4/app/Home.py: -------------------------------------------------------------------------------- 1 | 2 | import hmac 3 | import streamlit as st 4 | 5 | st.set_page_config(layout="wide") 6 | 7 | def check_password(): 8 | """Returns `True` if the user had a correct password.""" 9 | 10 | def login_form(): 11 | """Form with widgets to collect user information""" 12 | with st.form("Credentials"): 13 | st.text_input("Username", key="username") 14 | st.text_input("Password", type="password", key="password") 15 | st.form_submit_button("Log in", on_click=password_entered) 16 | 17 | def password_entered(): 18 | """Checks whether a password entered by the user is correct.""" 19 | if st.session_state["username"] in st.secrets[ 20 | "passwords" 21 | ] and hmac.compare_digest( 22 | st.session_state["password"], 23 | st.secrets.passwords[st.session_state["username"]], 24 | ): 25 | st.session_state["password_correct"] = True 26 | del st.session_state["password"] # Don't store the username or password. 27 | del st.session_state["username"] 28 | else: 29 | st.session_state["password_correct"] = False 30 | 31 | # Return True if the username + password is validated. 32 | if st.session_state.get("password_correct", False): 33 | return True 34 | 35 | # Show inputs for username + password. 36 | login_form() 37 | return False 38 | 39 | 40 | # Header 41 | title = "myfitnessagent" 42 | logo_path = "../../../logo.png" 43 | 44 | col1_header, col2_header = st.columns([1, 10]) 45 | 46 | with col1_header: 47 | st.image(logo_path, width=100) 48 | 49 | # Display the title in the second column 50 | with col2_header: 51 | st.title(title) 52 | 53 | st.write("") 54 | 55 | # Set up the main app page 56 | st.subheader("Welcome to myfitnessagent") 57 | 58 | col1_auth, col2_auth = st.columns([1, 2]) 59 | 60 | with col1_auth: 61 | if not check_password(): 62 | st.stop() 63 | 64 | # Display the title in the second column 65 | with col2_auth: 66 | st.write("") 67 | 68 | 69 | if not check_password(): 70 | st.stop() # Do not continue if check_password is not True. 71 | 72 | # User is already logged in, show the authenticated message 73 | st.write(f"You have been authenticated.") 74 | st.write("Select your agent from the sidebar to begin.") 75 | 76 | st.subheader("Agents available:") 77 | st.write("1. Onboarding Agent [ReAct]") 78 | st.write("2. Training Agent [CoT FSP]") 79 | st.write("3. Nutrition Agent [RAG]") 80 | 81 | # Add a logout button 82 | if st.button('Logout'): 83 | st.session_state["password_correct"] = False 84 | st.rerun() -------------------------------------------------------------------------------- /sessions/session_2/notebooks/react_event_agent.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Prebuilt react agent with search tool and memory" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "# Import relevant functionality\n", 17 | "from langchain_openai import ChatOpenAI\n", 18 | "from langchain_community.tools.tavily_search import TavilySearchResults\n", 19 | "from langchain_core.messages import HumanMessage\n", 20 | "from langgraph.checkpoint.sqlite import SqliteSaver\n", 21 | "from langchain_core.messages import BaseMessage\n", 22 | "from langgraph.prebuilt import create_react_agent" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 2, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "# Create the agent with memory\n", 32 | "memory = SqliteSaver.from_conn_string(\":memory:\")\n", 33 | "model = ChatOpenAI(model='gpt-4o')\n", 34 | "search = TavilySearchResults(max_results=2)\n", 35 | "tools = [search]\n", 36 | "agent_executor = create_react_agent(model, tools, checkpointer=memory)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 3, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "# Use the agent with specific thread id (memory)\n", 46 | "config = {\"configurable\": {\"thread_id\": \"user4\"}}" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "# pass in config and call agent_executor.stream to interact with the agent\n", 56 | "while True:\n", 57 | " user_input = input(\"User: \")\n", 58 | " print(\"User: \" + user_input)\n", 59 | " if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n", 60 | " print(\"Goodbye!\")\n", 61 | " break\n", 62 | " for event in agent_executor.stream({\"messages\": [(\"user\", user_input)]}, config):\n", 63 | " print(event)\n", 64 | " for value in event.values():\n", 65 | " if isinstance(value[\"messages\"][-1], BaseMessage):\n", 66 | " print(\"Assistant:\", value[\"messages\"][-1].content)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 38, 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "data": { 76 | "text/plain": [ 77 | "[HumanMessage(content='hi my name is rick', id='b61c7081-6cc5-4633-b4df-18913d31ad0a'),\n", 78 | " AIMessage(content='Hello, Rick! How can I assist you today?', response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 85, 'total_tokens': 97}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_4e2b2da518', 'finish_reason': 'stop', 'logprobs': None}, id='run-a84063d1-3895-4a5e-a234-cf6c15ad7d51-0', usage_metadata={'input_tokens': 85, 'output_tokens': 12, 'total_tokens': 97}),\n", 79 | " HumanMessage(content='what is my name?', id='f691b6cb-cf74-426d-a43b-0f7d9b885d3e'),\n", 80 | " AIMessage(content='Your name is Rick. How can I help you further?', response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 109, 'total_tokens': 122}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_4e2b2da518', 'finish_reason': 'stop', 'logprobs': None}, id='run-c32b27f7-e42b-4ea0-b4ae-9832e02cdffd-0', usage_metadata={'input_tokens': 109, 'output_tokens': 13, 'total_tokens': 122})]" 81 | ] 82 | }, 83 | "execution_count": 38, 84 | "metadata": {}, 85 | "output_type": "execute_result" 86 | } 87 | ], 88 | "source": [ 89 | "# check what's stored in memory\n", 90 | "agent_executor.get_state(config).values['messages']" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [] 99 | } 100 | ], 101 | "metadata": { 102 | "kernelspec": { 103 | "display_name": "venv", 104 | "language": "python", 105 | "name": "python3" 106 | }, 107 | "language_info": { 108 | "codemirror_mode": { 109 | "name": "ipython", 110 | "version": 3 111 | }, 112 | "file_extension": ".py", 113 | "mimetype": "text/x-python", 114 | "name": "python", 115 | "nbconvert_exporter": "python", 116 | "pygments_lexer": "ipython3", 117 | "version": "3.9.6" 118 | } 119 | }, 120 | "nbformat": 4, 121 | "nbformat_minor": 2 122 | } 123 | -------------------------------------------------------------------------------- /sessions/session_4/app/main.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from fastapi import FastAPI 3 | from langgraph.checkpoint.sqlite import SqliteSaver 4 | 5 | from langchain_openai import ChatOpenAI 6 | from langchain_community.tools.tavily_search import TavilySearchResults 7 | from langgraph.checkpoint.sqlite import SqliteSaver 8 | from langgraph.prebuilt import create_react_agent 9 | 10 | from langchain.llms import HuggingFacePipeline 11 | from langchain.prompts import PromptTemplate 12 | from transformers import pipeline 13 | from langchain_core.output_parsers import StrOutputParser 14 | 15 | from langchain_community.document_loaders import PyPDFLoader 16 | from langchain.text_splitter import RecursiveCharacterTextSplitter 17 | from langchain.vectorstores import FAISS 18 | from langchain.embeddings import HuggingFaceEmbeddings 19 | from langchain_core.runnables import RunnablePassthrough 20 | 21 | from transformers import AutoTokenizer, AutoModelForCausalLM 22 | 23 | import os 24 | 25 | import re 26 | from dotenv import load_dotenv 27 | 28 | load_dotenv() 29 | 30 | 31 | ########################### 32 | ### ReAct Search Agent #### 33 | ########################### 34 | 35 | # Create the agent with memory and search tool 36 | memory = SqliteSaver.from_conn_string(":memory:") 37 | model = ChatOpenAI(model='gpt-4o') 38 | search = TavilySearchResults(max_results=2) 39 | tools = [search] 40 | agent_executor = create_react_agent(model, tools, checkpointer=memory) 41 | 42 | ########################### 43 | ### Nutrition Agent #### 44 | ########################### 45 | 46 | # load docs 47 | file_path = "../pdfs" 48 | docs = [] 49 | for file in os.listdir(file_path): 50 | if file.endswith('.pdf'): 51 | pdf_path = os.path.join(file_path, file) 52 | loader = PyPDFLoader(pdf_path) 53 | docs.extend(loader.load()) 54 | 55 | # split and index 56 | splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=0) 57 | 58 | chunked_docs = splitter.split_documents(docs) 59 | 60 | db = FAISS.from_documents(chunked_docs, HuggingFaceEmbeddings(model_name="BAAI/bge-base-en-v1.5")) 61 | 62 | retriever = db.as_retriever(search_type="similarity", search_kwargs={"k": 1}) 63 | 64 | 65 | # LLM model name 66 | model_name ="TinyLlama/TinyLlama-1.1B-Chat-v1.0" 67 | 68 | save_directory = "../notebooks/model_directory" 69 | 70 | # Get the list of files and directories in 'save_directory' 71 | directory_contents = os.listdir(save_directory) 72 | 73 | # Check if the directory is empty 74 | if not directory_contents: 75 | print(f"The directory {save_directory} is empty.") 76 | model = AutoModelForCausalLM.from_pretrained(model_name) 77 | tokenizer = AutoTokenizer.from_pretrained(model_name) 78 | 79 | tokenizer.save_pretrained(save_directory) 80 | model.save_pretrained(save_directory) 81 | 82 | else: 83 | print(f"The directory {save_directory} contains {len(directory_contents)} items.") 84 | model = AutoModelForCausalLM.from_pretrained(save_directory) 85 | tokenizer = AutoTokenizer.from_pretrained(save_directory) 86 | 87 | # build LLM pipeline 88 | text_generation_pipeline = pipeline( 89 | model=model, 90 | tokenizer=tokenizer, 91 | task="text-generation", 92 | temperature=0.2, 93 | do_sample=True, 94 | repetition_penalty=1.1, 95 | return_full_text=True, 96 | max_new_tokens=400, 97 | ) 98 | 99 | llm = HuggingFacePipeline(pipeline=text_generation_pipeline) 100 | 101 | # RAG Prompt template 102 | prompt_template = """ 103 | <|system|> 104 | Answer the question based on your knowledge. Use the following context to help: 105 | 106 | {context} 107 | 108 | 109 | <|user|> 110 | {question} 111 | 112 | <|assistant|> 113 | 114 | """ 115 | 116 | # RAG chain 117 | prompt = PromptTemplate( 118 | input_variables=["context", "question"], 119 | template=prompt_template, 120 | ) 121 | 122 | llm_chain = prompt | llm | StrOutputParser() 123 | 124 | rag_chain = {"context": retriever, "question": RunnablePassthrough()} | llm_chain 125 | 126 | 127 | ########################### 128 | ### App Endpoint #### 129 | ########################### 130 | 131 | app = FastAPI() 132 | 133 | @app.post("/nutrition") 134 | def generate_nutrition(data: Dict): 135 | question = data['question'] 136 | response = rag_chain.invoke(question) 137 | print(response) 138 | 139 | # Regular expression to match everything after <|assistant|> 140 | pattern = r"(?<=<\|assistant\|>)[\s\S]*$" 141 | 142 | # Perform the regex search 143 | match = re.search(pattern, response, re.DOTALL) 144 | 145 | # Check if a match is found and print the result 146 | if match: 147 | result = match.group().strip() 148 | print(result) 149 | else: 150 | result = "Try again" 151 | 152 | return {"response": result} 153 | 154 | @app.post("/event") 155 | def generate_events(data: Dict): 156 | print(data) 157 | event_type = data["event_type"] 158 | location = data["location"] 159 | time_frame = data["time_frame"] 160 | user_input = f"Find me {event_type} events in {location} around {time_frame} time frame in 2024. Return back specific events." 161 | 162 | # Set memory for a specific user 163 | config = {"configurable": {"thread_id": "rc45"}} 164 | 165 | response = agent_executor.invoke({"messages": [("user", user_input)]}, config) 166 | 167 | response = response["messages"][-1].content 168 | return {"response": response} -------------------------------------------------------------------------------- /sessions/session_7/notebooks/data.jsonl: -------------------------------------------------------------------------------- 1 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate eggs and ran half a mile"}, {"role": "assistant", "content": "ran half a mileeggsNice!"}]} 2 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate pizza and did 10 pushups"}, {"role": "assistant", "content": "10 pushupspizzaNice!"}]} 3 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a salad and swam 5 laps"}, {"role": "assistant", "content": "swam 5 lapssaladNice!"}]} 4 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a burger and did 15 squats"}, {"role": "assistant", "content": "15 squatsburgerNice!"}]} 5 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cookies and did 20 crunches"}, {"role": "assistant", "content": "20 crunchescookiesNice!"}]} 6 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a steak and did 30 burpees"}, {"role": "assistant", "content": "30 burpeessteakNice!"}]} 7 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a pie and did 5 pull-ups"}, {"role": "assistant", "content": "5 pull-upspieNice!"}]} 8 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cake and did 1 hour of yoga"}, {"role": "assistant", "content": "1 hour of yogacakeNice!"}]} 9 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate soup and took a long walk"}, {"role": "assistant", "content": "long walksoupNice!"}]} 10 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate candy and did pilates"}, {"role": "assistant", "content": "PilatesCandyNice!"}]} 11 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate pasta and biked for 1 hour"}, {"role": "assistant", "content": "Biked for 1 hourPastaNice!"}]} 12 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate sushi and hiked for 1 hour"}, {"role": "assistant", "content": "hiked for 1 hoursushiNice!"}]} 13 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cheese and did jumping jacks"}, {"role": "assistant", "content": "jumping jackscheeseNice!"}]} 14 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate shrimp and did Tae Kwon Do"}, {"role": "assistant", "content": "Tae Kwon DoshrimpNice!"}]} 15 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cereal and did 20 sprints"}, {"role": "assistant", "content": "20 sprintscerealNice!"}]} 16 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate chips and rowed for 1 hour"}, {"role": "assistant", "content": "Rowed for 1 hourChipsNice!"}]} 17 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate nuts and walked for 1 hour"}, {"role": "assistant", "content": "walked for 1 hournutsNice!"}]} 18 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate tacos and ran 3 miles"}, {"role": "assistant", "content": "ran 3 milestacosNice!"}]} 19 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a banana and did 50 pushups"}, {"role": "assistant", "content": "50 pushupsbananaNice!"}]} 20 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate an orange and swam 10 laps"}, {"role": "assistant", "content": "swam 10 lapsorangeNice!"}]} 21 | -------------------------------------------------------------------------------- /sessions/session_7/notebooks/data_original.jsonl: -------------------------------------------------------------------------------- 1 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate eggs and ran half a mile"}, {"role": "assistant", "content": "ran half a mileeggsNice!"}]} 2 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate pizza and did 10 pushups"}, {"role": "assistant", "content": "10 pushupspizzaNice!"}]} 3 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a salad and swam 5 laps"}, {"role": "assistant", "content": "swam 5 lapssaladNice!"}]} 4 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a burger and did 15 squats"}, {"role": "assistant", "content": "15 squatsburgerNice!"}]} 5 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cookies and did 20 crunches"}, {"role": "assistant", "content": "20 crunchescookiesNice!"}]} 6 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a steak and did 30 burpees"}, {"role": "assistant", "content": "30 burpeessteakNice!"}]} 7 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a pie and did 5 pull-ups"}, {"role": "assistant", "content": "5 pull-upspieNice!"}]} 8 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cake and did 1 hour of yoga"}, {"role": "assistant", "content": "1 hour of yogacakeNice!"}]} 9 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate soup and took a long walk"}, {"role": "assistant", "content": "long walksoupNice!"}]} 10 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate candy and did pilates"}, {"role": "assistant", "content": "PilatesCandyNice!"}]} 11 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate pasta and biked for 1 hour"}, {"role": "assistant", "content": "Biked for 1 hourPastaNice!"}]} 12 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate sushi and hiked for 1 hour"}, {"role": "assistant", "content": "hiked for 1 hoursushiNice!"}]} 13 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cheese and did jumping jacks"}, {"role": "assistant", "content": "jumping jackscheeseNice!"}]} 14 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate shrimp and did Tae Kwon Do"}, {"role": "assistant", "content": "Tae Kwon DoshrimpNice!"}]} 15 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate cereal and did 20 sprints"}, {"role": "assistant", "content": "20 sprintscerealNice!"}]} 16 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate chips and rowed for 1 hour"}, {"role": "assistant", "content": "Rowed for 1 hourChipsNice!"}]} 17 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate nuts and walked for 1 hour"}, {"role": "assistant", "content": "walked for 1 hournutsNice!"}]} 18 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate tacos and ran 3 miles"}, {"role": "assistant", "content": "ran 3 milestacosNice!"}]} 19 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate a banana and did 50 pushups"}, {"role": "assistant", "content": "50 pushupsbananaNice!"}]} 20 | {"messages": [{"role": "system", "content": "You are a personal trainer and fitness coach."}, {"role": "user", "content": "I ate an orange and swam 10 laps"}, {"role": "assistant", "content": "swam 10 lapsorangeNice!"}]} 21 | -------------------------------------------------------------------------------- /sessions/session_1/app/Home.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import prompts 3 | import re 4 | from openai import OpenAI 5 | from model_utils import call_chat_model, call_image_model 6 | 7 | client = OpenAI() 8 | 9 | st.set_page_config(layout="wide") 10 | 11 | # Header 12 | title = "myfitnessagent" 13 | logo_path = "../../../logo.png" 14 | 15 | col1, col2 = st.columns([1, 10]) 16 | 17 | with col1: 18 | st.image(logo_path, width=100) 19 | 20 | # Display the title in the second column 21 | with col2: 22 | st.title(title) 23 | 24 | 25 | # Initialize internal and external chat history 26 | if "internal_messages" not in st.session_state: 27 | st.session_state.internal_messages = [{ 28 | "role":"system", 29 | "content": prompts.system_prompt 30 | }] 31 | 32 | if "external_messages" not in st.session_state: 33 | st.session_state.external_messages = [] 34 | 35 | # Initialize trackers 36 | if "nutrition_tracker" not in st.session_state: 37 | st.session_state.nutrition_tracker = "" 38 | if "training_tracker" not in st.session_state: 39 | st.session_state.training_tracker = "" 40 | 41 | # Function to extract tracker tags from response 42 | def parse_messages(text): 43 | message_pattern = r"(.*?)" 44 | nutrition_pattern = r"(.*?)" 45 | training_pattern = r"(.*?)" 46 | 47 | message = re.findall(message_pattern, text, re.DOTALL) 48 | nutrition = re.findall(nutrition_pattern, text, re.DOTALL) 49 | training = re.findall(training_pattern, text, re.DOTALL) 50 | 51 | return message[0] if message else "", nutrition[0] if nutrition else "", training[0] if training else "" 52 | 53 | # Create two columns 54 | col1, col2 = st.columns([1,1]) 55 | 56 | with col1: 57 | st.header("Chat with coach") 58 | 59 | # Create a container for chat messages 60 | chat_container = st.container(height=400) 61 | 62 | # Create a container for the input box 63 | input_container = st.container() 64 | 65 | # Display chat messages from history on app rerun 66 | with chat_container: 67 | for message in st.session_state.external_messages: 68 | with st.chat_message(message["role"]): 69 | st.markdown(message["content"]) 70 | 71 | # Accept user input 72 | with input_container: 73 | upload_col1, upload_col2 = st.columns([4,1]) 74 | 75 | with upload_col1: 76 | # image upload and processing 77 | uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png"], label_visibility="collapsed") 78 | 79 | if uploaded_file is not None: 80 | with upload_col2: 81 | if st.button("Process Image"): 82 | st.write('Processing image...') 83 | st.session_state.internal_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 84 | st.session_state.external_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 85 | 86 | message, nutrition_tracker = call_image_model(client, uploaded_file) 87 | 88 | if nutrition_tracker: 89 | st.session_state.nutrition_tracker = nutrition_tracker 90 | 91 | st.session_state.internal_messages.append({"role": "assistant", "content": message}) 92 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 93 | 94 | st.rerun() 95 | 96 | 97 | if prompt := st.chat_input("Enter text..."): 98 | # Add user message to chat history 99 | st.session_state.internal_messages.append({"role": "user", "content": prompt}) 100 | st.session_state.external_messages.append({"role": "user", "content": prompt}) 101 | 102 | with chat_container: 103 | # Display user message in chat message container 104 | with st.chat_message("user"): 105 | st.markdown(prompt) 106 | 107 | # with chat_container: 108 | with st.chat_message("assistant"): 109 | messages=[{"role": m["role"], "content": m["content"]} for m in st.session_state.internal_messages] 110 | 111 | # call the chat model to generate a completion 112 | completion = call_chat_model(client, messages) 113 | 114 | response = completion.choices[0].message.content 115 | 116 | print('***RAW OUTPUTS***') 117 | print(response) 118 | 119 | # add raw message to internal messages 120 | st.session_state.internal_messages.append({"role": "assistant", "content": response}) 121 | 122 | message, nutrition_tracker, training_tracker = parse_messages(response) 123 | 124 | # add parsed message to external messages 125 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 126 | 127 | # Update session state trackers 128 | if nutrition_tracker: 129 | st.session_state.nutrition_tracker = nutrition_tracker 130 | if training_tracker: 131 | st.session_state.training_tracker = training_tracker 132 | st.rerun() 133 | 134 | with col2: 135 | st.header("Training and Nutrition Log") 136 | training_log_container = st.container(height=260) 137 | with training_log_container: 138 | st.write("### Training Plan") 139 | if len(st.session_state.training_tracker) > 0: 140 | st.write(st.session_state.training_tracker) 141 | 142 | nutrition_log_container = st.container(height=260) 143 | with nutrition_log_container: 144 | st.write("### Nutrition Plan") 145 | if len(st.session_state.nutrition_tracker) > 0: 146 | st.write(st.session_state.nutrition_tracker) 147 | 148 | -------------------------------------------------------------------------------- /sessions/session_3/app/pages/2_Training_Agent_[CoT].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import prompts 3 | import re 4 | from openai import OpenAI 5 | from base_model_utils import call_chat_model, call_image_model 6 | 7 | client = OpenAI() 8 | 9 | st.set_page_config(layout="wide") 10 | 11 | # Header 12 | title = "myfitnessagent" 13 | logo_path = "../../../logo.png" 14 | 15 | col1, col2 = st.columns([1, 10]) 16 | 17 | with col1: 18 | st.image(logo_path, width=100) 19 | 20 | # Display the title in the second column 21 | with col2: 22 | st.title(title) 23 | 24 | 25 | 26 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 27 | st.write("Please login first.") 28 | st.stop() 29 | 30 | 31 | # Initialize internal and external chat history 32 | if "internal_messages" not in st.session_state: 33 | st.session_state.internal_messages = [{ 34 | "role":"system", 35 | "content": prompts.system_prompt 36 | }] 37 | 38 | if "external_messages" not in st.session_state: 39 | st.session_state.external_messages = [] 40 | 41 | # Initialize trackers 42 | if "nutrition_tracker" not in st.session_state: 43 | st.session_state.nutrition_tracker = "" 44 | if "training_tracker" not in st.session_state: 45 | st.session_state.training_tracker = "" 46 | 47 | # Function to extract tracker tags from response 48 | def parse_messages(text): 49 | message_pattern = r"(.*?)" 50 | nutrition_pattern = r"(.*?)" 51 | training_pattern = r"(.*?)" 52 | 53 | message = re.findall(message_pattern, text, re.DOTALL) 54 | nutrition = re.findall(nutrition_pattern, text, re.DOTALL) 55 | training = re.findall(training_pattern, text, re.DOTALL) 56 | 57 | return message[0] if message else "", nutrition[0] if nutrition else "", training[0] if training else "" 58 | 59 | # Create two columns 60 | col1, col2 = st.columns([1,1]) 61 | 62 | with col1: 63 | st.header("Chat with coach") 64 | 65 | # Create a container for chat messages 66 | chat_container = st.container(height=400) 67 | 68 | # Create a container for the input box 69 | input_container = st.container() 70 | 71 | # Display chat messages from history on app rerun 72 | with chat_container: 73 | for message in st.session_state.external_messages: 74 | with st.chat_message(message["role"]): 75 | st.markdown(message["content"]) 76 | 77 | # Accept user input 78 | with input_container: 79 | upload_col1, upload_col2 = st.columns([4,1]) 80 | 81 | with upload_col1: 82 | # image upload and processing 83 | uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png"], label_visibility="collapsed") 84 | 85 | if uploaded_file is not None: 86 | with upload_col2: 87 | if st.button("Process Image"): 88 | st.write('Processing image...') 89 | st.session_state.internal_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 90 | st.session_state.external_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 91 | 92 | message, nutrition_tracker = call_image_model(client, uploaded_file) 93 | 94 | if nutrition_tracker: 95 | st.session_state.nutrition_tracker = nutrition_tracker 96 | 97 | st.session_state.internal_messages.append({"role": "assistant", "content": message}) 98 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 99 | 100 | st.rerun() 101 | 102 | 103 | if prompt := st.chat_input("Enter text..."): 104 | # Add user message to chat history 105 | st.session_state.internal_messages.append({"role": "user", "content": prompt}) 106 | st.session_state.external_messages.append({"role": "user", "content": prompt}) 107 | 108 | with chat_container: 109 | # Display user message in chat message container 110 | with st.chat_message("user"): 111 | st.markdown(prompt) 112 | 113 | # with chat_container: 114 | with st.chat_message("assistant"): 115 | messages=[{"role": m["role"], "content": m["content"]} for m in st.session_state.internal_messages] 116 | 117 | completion = call_chat_model(client, messages) 118 | 119 | response = completion.choices[0].message.content 120 | 121 | print('***RAW OUTPUTS***') 122 | print(response) 123 | 124 | st.session_state.internal_messages.append({"role": "assistant", "content": response}) 125 | 126 | message, nutrition_tracker, training_tracker = parse_messages(response) 127 | 128 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 129 | 130 | # Update session state trackers 131 | if nutrition_tracker: 132 | st.session_state.nutrition_tracker = nutrition_tracker 133 | if training_tracker: 134 | st.session_state.training_tracker = training_tracker 135 | st.rerun() 136 | 137 | with col2: 138 | st.header("Training and Nutrition Log") 139 | training_log_container = st.container(height=260) 140 | with training_log_container: 141 | st.write("### Training Plan") 142 | if len(st.session_state.training_tracker) > 0: 143 | st.write(st.session_state.training_tracker) 144 | 145 | nutrition_log_container = st.container(height=260) 146 | with nutrition_log_container: 147 | st.write("### Nutrition Plan") 148 | if len(st.session_state.nutrition_tracker) > 0: 149 | st.write(st.session_state.nutrition_tracker) 150 | 151 | -------------------------------------------------------------------------------- /sessions/session_4/app/pages/2_Training_Agent_[CoT FSP].py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import prompts 3 | import re 4 | from openai import OpenAI 5 | from base_model_utils import call_chat_model, call_image_model 6 | 7 | client = OpenAI() 8 | 9 | st.set_page_config(layout="wide") 10 | 11 | # Header 12 | title = "myfitnessagent" 13 | logo_path = "../../../logo.png" 14 | 15 | col1, col2 = st.columns([1, 10]) 16 | 17 | with col1: 18 | st.image(logo_path, width=100) 19 | 20 | # Display the title in the second column 21 | with col2: 22 | st.title(title) 23 | 24 | 25 | 26 | if (st.session_state.get("password_correct") == None) or (st.session_state.get("password_correct") == False): 27 | st.write("Please login first.") 28 | st.stop() 29 | 30 | 31 | # Initialize internal and external chat history 32 | if "internal_messages" not in st.session_state: 33 | st.session_state.internal_messages = [{ 34 | "role":"system", 35 | "content": prompts.system_prompt 36 | }] 37 | 38 | if "external_messages" not in st.session_state: 39 | st.session_state.external_messages = [] 40 | 41 | # Initialize trackers 42 | if "nutrition_tracker" not in st.session_state: 43 | st.session_state.nutrition_tracker = "" 44 | if "training_tracker" not in st.session_state: 45 | st.session_state.training_tracker = "" 46 | 47 | # Function to extract tracker tags from response 48 | def parse_messages(text): 49 | message_pattern = r"(.*?)" 50 | nutrition_pattern = r"(.*?)" 51 | training_pattern = r"(.*?)" 52 | 53 | message = re.findall(message_pattern, text, re.DOTALL) 54 | nutrition = re.findall(nutrition_pattern, text, re.DOTALL) 55 | training = re.findall(training_pattern, text, re.DOTALL) 56 | 57 | return message[0] if message else "", nutrition[0] if nutrition else "", training[0] if training else "" 58 | 59 | # Create two columns 60 | col1, col2 = st.columns([1,1]) 61 | 62 | with col1: 63 | st.header("Chat with coach") 64 | 65 | # Create a container for chat messages 66 | chat_container = st.container(height=400) 67 | 68 | # Create a container for the input box 69 | input_container = st.container() 70 | 71 | # Display chat messages from history on app rerun 72 | with chat_container: 73 | for message in st.session_state.external_messages: 74 | with st.chat_message(message["role"]): 75 | st.markdown(message["content"]) 76 | 77 | # Accept user input 78 | with input_container: 79 | upload_col1, upload_col2 = st.columns([4,1]) 80 | 81 | with upload_col1: 82 | # image upload and processing 83 | uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png"], label_visibility="collapsed") 84 | 85 | if uploaded_file is not None: 86 | with upload_col2: 87 | if st.button("Process Image"): 88 | st.write('Processing image...') 89 | st.session_state.internal_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 90 | st.session_state.external_messages.append({"role": "user", "content": "Uploaded a photo of food"}) 91 | 92 | message, nutrition_tracker = call_image_model(client, uploaded_file) 93 | 94 | if nutrition_tracker: 95 | st.session_state.nutrition_tracker = nutrition_tracker 96 | 97 | st.session_state.internal_messages.append({"role": "assistant", "content": message}) 98 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 99 | 100 | st.rerun() 101 | 102 | 103 | if prompt := st.chat_input("Enter text..."): 104 | # Add user message to chat history 105 | st.session_state.internal_messages.append({"role": "user", "content": prompt}) 106 | st.session_state.external_messages.append({"role": "user", "content": prompt}) 107 | 108 | with chat_container: 109 | # Display user message in chat message container 110 | with st.chat_message("user"): 111 | st.markdown(prompt) 112 | 113 | # with chat_container: 114 | with st.chat_message("assistant"): 115 | messages=[{"role": m["role"], "content": m["content"]} for m in st.session_state.internal_messages] 116 | 117 | completion = call_chat_model(client, messages) 118 | 119 | response = completion.choices[0].message.content 120 | 121 | print('***RAW OUTPUTS***') 122 | print(response) 123 | 124 | st.session_state.internal_messages.append({"role": "assistant", "content": response}) 125 | 126 | message, nutrition_tracker, training_tracker = parse_messages(response) 127 | 128 | st.session_state.external_messages.append({"role": "assistant", "content": message}) 129 | 130 | # Update session state trackers 131 | if nutrition_tracker: 132 | st.session_state.nutrition_tracker = nutrition_tracker 133 | if training_tracker: 134 | st.session_state.training_tracker = training_tracker 135 | st.rerun() 136 | 137 | with col2: 138 | st.header("Training and Nutrition Log") 139 | training_log_container = st.container(height=260) 140 | with training_log_container: 141 | st.write("### Training Plan") 142 | if len(st.session_state.training_tracker) > 0: 143 | st.write(st.session_state.training_tracker) 144 | 145 | nutrition_log_container = st.container(height=260) 146 | with nutrition_log_container: 147 | st.write("### Nutrition Plan") 148 | if len(st.session_state.nutrition_tracker) > 0: 149 | st.write(st.session_state.nutrition_tracker) 150 | 151 | -------------------------------------------------------------------------------- /sessions/session_4/notebooks/intro_huggingface.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 5, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n", 13 | "To disable this warning, you can either:\n", 14 | "\t- Avoid using `tokenizers` before the fork if possible\n", 15 | "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n" 16 | ] 17 | }, 18 | { 19 | "name": "stdout", 20 | "output_type": "stream", 21 | "text": [ 22 | "Requirement already satisfied: transformers in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (4.42.4)\n", 23 | "Requirement already satisfied: torch in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (2.3.1)\n", 24 | "Requirement already satisfied: filelock in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (3.15.4)\n", 25 | "Requirement already satisfied: huggingface-hub<1.0,>=0.23.2 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (0.23.4)\n", 26 | "Requirement already satisfied: numpy<2.0,>=1.17 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (1.26.4)\n", 27 | "Requirement already satisfied: packaging>=20.0 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (24.1)\n", 28 | "Requirement already satisfied: pyyaml>=5.1 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (6.0.1)\n", 29 | "Requirement already satisfied: regex!=2019.12.17 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (2024.5.15)\n", 30 | "Requirement already satisfied: requests in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (2.32.3)\n", 31 | "Requirement already satisfied: safetensors>=0.4.1 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (0.4.3)\n", 32 | "Requirement already satisfied: tokenizers<0.20,>=0.19 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (0.19.1)\n", 33 | "Requirement already satisfied: tqdm>=4.27 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from transformers) (4.66.4)\n", 34 | "Requirement already satisfied: typing-extensions>=4.8.0 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from torch) (4.12.2)\n", 35 | "Requirement already satisfied: sympy in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from torch) (1.13.0)\n", 36 | "Requirement already satisfied: networkx in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from torch) (3.2.1)\n", 37 | "Requirement already satisfied: jinja2 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from torch) (3.1.4)\n", 38 | "Requirement already satisfied: fsspec in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from torch) (2024.5.0)\n", 39 | "Requirement already satisfied: MarkupSafe>=2.0 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from jinja2->torch) (2.1.5)\n", 40 | "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from requests->transformers) (3.3.2)\n", 41 | "Requirement already satisfied: idna<4,>=2.5 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from requests->transformers) (3.7)\n", 42 | "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from requests->transformers) (2.2.2)\n", 43 | "Requirement already satisfied: certifi>=2017.4.17 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from requests->transformers) (2024.7.4)\n", 44 | "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages (from sympy->torch) (1.3.0)\n", 45 | "\n", 46 | "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.1.2\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.2\u001b[0m\n", 47 | "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" 48 | ] 49 | } 50 | ], 51 | "source": [ 52 | "!pip install transformers torch" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 6, 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "name": "stderr", 62 | "output_type": "stream", 63 | "text": [ 64 | "No model was supplied, defaulted to openai-community/gpt2 and revision 6c0e608 (https://huggingface.co/openai-community/gpt2).\n", 65 | "Using a pipeline without specifying a model name and revision in production is not recommended.\n", 66 | "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n", 67 | "Truncation was not explicitly activated but `max_length` is provided a specific value, please use `truncation=True` to explicitly truncate examples to max length. Defaulting to 'longest_first' truncation strategy. If you encode pairs of sequences (GLUE-style) with the tokenizer you can select this strategy more precisely by providing a specific strategy to `truncation`.\n", 68 | "Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.\n" 69 | ] 70 | }, 71 | { 72 | "data": { 73 | "text/plain": [ 74 | "[{'generated_text': \"Hello, I'm a language model. How much more can I learn from an undergrad or intern who just wants something like this and can't seem to\"},\n", 75 | " {'generated_text': \"Hello, I'm a language model for you.\\n\\nIn the future, I want you to take a look at the first line of code,\"},\n", 76 | " {'generated_text': \"Hello, I'm a language modeler, so I can't explain what's happening, and this kind of thing, I call this system and this\"},\n", 77 | " {'generated_text': \"Hello, I'm a language model for you. How did this come about?'\\n\\n'The world of languages is full of languages. I wanted\"},\n", 78 | " {'generated_text': \"Hello, I'm a language modeler. I've written many different languages, and I've never seen a single implementation change in my work. I\"}]" 79 | ] 80 | }, 81 | "execution_count": 6, 82 | "metadata": {}, 83 | "output_type": "execute_result" 84 | } 85 | ], 86 | "source": [ 87 | "from transformers import pipeline\n", 88 | "\n", 89 | "model = pipeline(\"text-generation\")\n", 90 | "\n", 91 | "model(\"Hello, I'm a language model\", \n", 92 | " max_length=30, \n", 93 | " num_return_sequences=5)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 7, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "from transformers import AutoTokenizer, AutoModelForCausalLM\n", 103 | "\n", 104 | "model_name =\"TinyLlama/TinyLlama-1.1B-Chat-v1.0\"\n", 105 | "\n", 106 | "save_directory = \"model_directory\"\n", 107 | "\n", 108 | "# load from pretrained instances\n", 109 | "model = AutoModelForCausalLM.from_pretrained(model_name)\n", 110 | "tokenizer = AutoTokenizer.from_pretrained(model_name)\n", 111 | "\n", 112 | "# save model for later user\n", 113 | "tokenizer.save_pretrained(save_directory)\n", 114 | "model.save_pretrained(save_directory)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 8, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "name": "stdout", 124 | "output_type": "stream", 125 | "text": [ 126 | "Encoding:\n", 127 | "{'input_ids': [1, 15043, 29892, 306, 29915, 29885, 263, 4086, 1904], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}\n", 128 | "Decoding:\n", 129 | " Hello, I'm a language model\n" 130 | ] 131 | } 132 | ], 133 | "source": [ 134 | "# tokenizer outputs\n", 135 | "encoding = tokenizer(\"Hello, I'm a language model\")\n", 136 | "\n", 137 | "# encoding\n", 138 | "print(\"Encoding:\")\n", 139 | "print(encoding)\n", 140 | "\n", 141 | "# decoding\n", 142 | "print(\"Decoding:\")\n", 143 | "print(tokenizer.decode(encoding['input_ids']))\n" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 9, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "name": "stderr", 153 | "output_type": "stream", 154 | "text": [ 155 | "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n" 156 | ] 157 | }, 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "[{'generated_text': 'Hello, I\\'m a language model. Can you provide me with some examples of how to use the \"translate\" function in Python?'}]" 162 | ] 163 | }, 164 | "execution_count": 9, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "# load model from saved directory\n", 171 | "model = AutoModelForCausalLM.from_pretrained(save_directory)\n", 172 | "tokenizer = AutoTokenizer.from_pretrained(save_directory)\n", 173 | "\n", 174 | "model = pipeline(\"text-generation\", model=model, tokenizer=tokenizer)\n", 175 | "\n", 176 | "model(\"Hello, I'm a language model\")" 177 | ] 178 | } 179 | ], 180 | "metadata": { 181 | "kernelspec": { 182 | "display_name": "venv", 183 | "language": "python", 184 | "name": "python3" 185 | }, 186 | "language_info": { 187 | "codemirror_mode": { 188 | "name": "ipython", 189 | "version": 3 190 | }, 191 | "file_extension": ".py", 192 | "mimetype": "text/x-python", 193 | "name": "python", 194 | "nbconvert_exporter": "python", 195 | "pygments_lexer": "ipython3", 196 | "version": "3.9.6" 197 | } 198 | }, 199 | "nbformat": 4, 200 | "nbformat_minor": 2 201 | } 202 | -------------------------------------------------------------------------------- /sessions/session_2/notebooks/langchain_foundations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Session 2 - Langchain Foundations" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Step-by-step" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "#!pip install langchain" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 18, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import getpass\n", 33 | "import os\n", 34 | "\n", 35 | "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n", 36 | "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "#pip install -qU langchain-openai" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 1, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "name": "stderr", 55 | "output_type": "stream", 56 | "text": [ 57 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", 58 | " warnings.warn(\n" 59 | ] 60 | } 61 | ], 62 | "source": [ 63 | "import getpass\n", 64 | "import os\n", 65 | "\n", 66 | "# os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n", 67 | "\n", 68 | "from langchain_openai import ChatOpenAI\n", 69 | "\n", 70 | "# initialize the model\n", 71 | "model = ChatOpenAI(model=\"gpt-4o\")" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 2, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "message template\n", 84 | "[SystemMessage(content='Translate the following from English into Italian'), HumanMessage(content='hi!')]\n", 85 | "\n", 86 | "parse message template\n", 87 | "system\n", 88 | "Translate the following from English into Italian\n", 89 | "\n", 90 | "invoke model\n", 91 | "content='Ciao!' response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 20, 'total_tokens': 23}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27', 'finish_reason': 'stop', 'logprobs': None} id='run-af3a72a4-6689-4865-9095-b09a71735ea9-0' usage_metadata={'input_tokens': 20, 'output_tokens': 3, 'total_tokens': 23}\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "from langchain_core.messages import HumanMessage, SystemMessage\n", 97 | "\n", 98 | "# system and human message templates\n", 99 | "messages = [\n", 100 | " SystemMessage(content=\"Translate the following from English into Italian\"),\n", 101 | " HumanMessage(content=\"hi!\"),\n", 102 | "]\n", 103 | "\n", 104 | "# print message\n", 105 | "print(\"message template\")\n", 106 | "print(messages)\n", 107 | "\n", 108 | "# e.g., system message\n", 109 | "print(\"\\nparse message template\")\n", 110 | "print(messages[0].type)\n", 111 | "print(messages[0].content)\n", 112 | "\n", 113 | "# invoke the model with messages\n", 114 | "print(\"\\ninvoke model\")\n", 115 | "print(model.invoke(messages))" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 3, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "from langchain_core.output_parsers import StrOutputParser\n", 125 | "\n", 126 | "# initialize prebuilt output parser\n", 127 | "parser = StrOutputParser()" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 4, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "# invoke model\n", 137 | "result = model.invoke(messages)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 5, 143 | "metadata": {}, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/plain": [ 148 | "'Ciao!'" 149 | ] 150 | }, 151 | "execution_count": 5, 152 | "metadata": {}, 153 | "output_type": "execute_result" 154 | } 155 | ], 156 | "source": [ 157 | "# pass through string output parser\n", 158 | "parser.invoke(result)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 7, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [ 167 | "# chain together model and parser\n", 168 | "chain = model | parser" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 8, 174 | "metadata": {}, 175 | "outputs": [ 176 | { 177 | "data": { 178 | "text/plain": [ 179 | "'Ciao!'" 180 | ] 181 | }, 182 | "execution_count": 8, 183 | "metadata": {}, 184 | "output_type": "execute_result" 185 | } 186 | ], 187 | "source": [ 188 | "# output is now a string\n", 189 | "chain.invoke(messages)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 14, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "from langchain_core.prompts import ChatPromptTemplate" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 15, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "# system template with placeholder language variable\n", 208 | "system_template = \"Translate the following into {language}:\"" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 16, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "name": "stdout", 218 | "output_type": "stream", 219 | "text": [ 220 | "[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=['language'], template='Translate the following into {language}:')), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], template='{text}'))]\n" 221 | ] 222 | } 223 | ], 224 | "source": [ 225 | "# construct chat prompt template with system template and user message placeholder\n", 226 | "prompt_template = ChatPromptTemplate.from_messages(\n", 227 | " [(\"system\", system_template), (\"user\", \"{text}\")]\n", 228 | ")\n", 229 | "\n", 230 | "# print the prompt template\n", 231 | "print(prompt_template.messages)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 17, 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "data": { 241 | "text/plain": [ 242 | "ChatPromptValue(messages=[SystemMessage(content='Translate the following into italian:'), HumanMessage(content='hi')])" 243 | ] 244 | }, 245 | "execution_count": 17, 246 | "metadata": {}, 247 | "output_type": "execute_result" 248 | } 249 | ], 250 | "source": [ 251 | "# pass in variables\n", 252 | "result = prompt_template.invoke({\"language\": \"italian\", \"text\": \"hi\"})\n", 253 | "\n", 254 | "result" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 18, 260 | "metadata": {}, 261 | "outputs": [ 262 | { 263 | "data": { 264 | "text/plain": [ 265 | "[SystemMessage(content='Translate the following into italian:'),\n", 266 | " HumanMessage(content='hi')]" 267 | ] 268 | }, 269 | "execution_count": 18, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "# same messages structure as directly using system and human message templates\n", 276 | "result.to_messages()" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 19, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "# chain all together\n", 286 | "chain = prompt_template | model | parser" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": 20, 292 | "metadata": {}, 293 | "outputs": [ 294 | { 295 | "data": { 296 | "text/plain": [ 297 | "'Ciao'" 298 | ] 299 | }, 300 | "execution_count": 20, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "# invoke the chain with input variables\n", 307 | "chain.invoke({\"language\": \"italian\", \"text\": \"hi\"})" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Combined" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 21, 320 | "metadata": {}, 321 | "outputs": [ 322 | { 323 | "name": "stdout", 324 | "output_type": "stream", 325 | "text": [ 326 | "Step-wise:\n", 327 | "Ciao\n", 328 | "Chain:\n", 329 | "Ciao\n" 330 | ] 331 | } 332 | ], 333 | "source": [ 334 | "from langchain_openai import ChatOpenAI\n", 335 | "from langchain_core.output_parsers import StrOutputParser\n", 336 | "from langchain_core.prompts import ChatPromptTemplate\n", 337 | "\n", 338 | "# define the model\n", 339 | "model = ChatOpenAI(model=\"gpt-3.5-turbo-0125\")\n", 340 | "\n", 341 | "# define the prompt template\n", 342 | "system_template = \"Translate the following into {language}:\"\n", 343 | "\n", 344 | "prompt_template = ChatPromptTemplate.from_messages(\n", 345 | " [(\"system\", system_template), (\"user\", \"{text}\")]\n", 346 | ")\n", 347 | "\n", 348 | "# define the output parser\n", 349 | "parser = StrOutputParser()\n", 350 | "\n", 351 | "# step wise result\n", 352 | "result = prompt_template.invoke({\"language\": \"italian\", \"text\": \"hi\"})\n", 353 | "result = model.invoke(result)\n", 354 | "result = parser.invoke(result)\n", 355 | "print(\"Step-wise:\")\n", 356 | "print(result)\n", 357 | "\n", 358 | "# chain result\n", 359 | "print(\"Chain:\")\n", 360 | "chain = prompt_template | model | parser\n", 361 | "result = chain.invoke({\"language\": \"italian\", \"text\": \"hi\"})\n", 362 | "print(result)" 363 | ] 364 | } 365 | ], 366 | "metadata": { 367 | "kernelspec": { 368 | "display_name": "venv", 369 | "language": "python", 370 | "name": "python3" 371 | }, 372 | "language_info": { 373 | "codemirror_mode": { 374 | "name": "ipython", 375 | "version": 3 376 | }, 377 | "file_extension": ".py", 378 | "mimetype": "text/x-python", 379 | "name": "python", 380 | "nbconvert_exporter": "python", 381 | "pygments_lexer": "ipython3", 382 | "version": "3.9.6" 383 | } 384 | }, 385 | "nbformat": 4, 386 | "nbformat_minor": 2 387 | } 388 | -------------------------------------------------------------------------------- /sessions/session_2/notebooks/search_agent.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Search Agent" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "# %%capture --no-stderr\n", 17 | "# %pip install -U tavily-python\n", 18 | "# %pip install -U langchain_community" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "import getpass\n", 28 | "import os\n", 29 | "\n", 30 | "def _set_env(var: str):\n", 31 | " if not os.environ.get(var):\n", 32 | " os.environ[var] = getpass.getpass(f\"{var}: \")" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "# _set_env(\"LANGSMITH_API_KEY\")\n", 42 | "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n", 43 | "# os.environ[\"LANGCHAIN_PROJECT\"] = \"LangGraph Tutorial\"" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 3, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "# _set_env(\"TAVILY_API_KEY\")" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 15, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "from langgraph.checkpoint.sqlite import SqliteSaver\n", 62 | "\n", 63 | "memory = SqliteSaver.from_conn_string(\":memory:\") #saves it all in memory, you can change this to connect to your own DB or use a diff checkpointer" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 16, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "from typing import Annotated\n", 73 | "\n", 74 | "from langchain_openai import ChatOpenAI\n", 75 | "from langchain_community.tools.tavily_search import TavilySearchResults\n", 76 | "from langchain_core.messages import BaseMessage\n", 77 | "from typing_extensions import TypedDict\n", 78 | "\n", 79 | "from langgraph.graph import StateGraph, START, END\n", 80 | "from langgraph.graph.message import add_messages\n", 81 | "from langgraph.prebuilt import ToolNode, tools_condition\n", 82 | "\n", 83 | "# shared state for the graph containing messages\n", 84 | "class State(TypedDict):\n", 85 | " messages: Annotated[list, add_messages]\n", 86 | "\n", 87 | "# create a new graph\n", 88 | "graph_builder = StateGraph(State)\n", 89 | "\n", 90 | "# replacing manual tool node with prebuilt tool node\n", 91 | "tool = TavilySearchResults(max_results=2)\n", 92 | "tools= [tool]\n", 93 | "llm = ChatOpenAI(model='gpt-3.5-turbo-0125')\n", 94 | "llm_with_tools = llm.bind_tools(tools)\n", 95 | "\n", 96 | "# call llm_with_tools with messages\n", 97 | "def chatbot(state: State):\n", 98 | " return {\"messages\": [llm_with_tools.invoke(state[\"messages\"])]}\n", 99 | "\n", 100 | "# add nodes to the graph\n", 101 | "graph_builder.add_node(\"chatbot\", chatbot)\n", 102 | "\n", 103 | "tool_node = ToolNode(tools=[tool])\n", 104 | "graph_builder.add_node(\"tools\", tool_node)\n", 105 | "\n", 106 | "# add edges to the graph\n", 107 | "graph_builder.add_conditional_edges(\n", 108 | " \"chatbot\",\n", 109 | " tools_condition\n", 110 | ")\n", 111 | "\n", 112 | "graph_builder.add_edge(\"tools\", \"chatbot\")\n", 113 | "graph_builder.add_edge(START, \"chatbot\") \n", 114 | "\n", 115 | "# compile graph with memory checkpointer\n", 116 | "graph = graph_builder.compile(checkpointer=memory)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 17, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "data": { 126 | "image/jpeg": "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", 127 | "text/plain": [ 128 | "" 129 | ] 130 | }, 131 | "metadata": {}, 132 | "output_type": "display_data" 133 | } 134 | ], 135 | "source": [ 136 | "from IPython.display import Image, display\n", 137 | "\n", 138 | "try:\n", 139 | " display(Image(graph.get_graph().draw_mermaid_png()))\n", 140 | "except Exception:\n", 141 | " # This requires some extra dependencies and is optional\n", 142 | " pass" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 18, 148 | "metadata": {}, 149 | "outputs": [], 150 | "source": [ 151 | "config = {\"configurable\": {\"thread_id\": \"1\"}}" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 21, 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "name": "stdout", 161 | "output_type": "stream", 162 | "text": [ 163 | "User: Hi\n", 164 | "Assistant: Hello! How can I assist you today? If you have any questions or need help with something, feel free to let me know.\n", 165 | "User: I want to run a 5K in New York City in August or September 2024\n", 166 | "Assistant: To find information about 5K races in New York City in August or September 2024, I can conduct a search. Would you like me to proceed with this search for you?\n", 167 | "User: Yes\n", 168 | "Assistant: \n", 169 | "Assistant: [{\"url\": \"https://www.active.com/new-york-ny/running/5k\", \"content\": \"Take on a 5K run in New York City, NY with our ultimate guide to 5K races. Find a 5K race in NYC, register, and start training for your next 5K race. ... Storm King Run 2024 Register Now. Rotary Club of West Point - Highland Falls \\u2022 Highland Falls, NY Running [5K, 10K, 1 Mile] Sep 14 2024. Bubble Run | Long Island | September 14th Register ...\"}, {\"url\": \"https://findarace.com/us/running/5k-runs/new-york/september\", \"content\": \"Check out our list of September 2024 5k Runs in New York here. Featured events Popular searches Locations Organisers Charities ... Oak Tree Half Marathon & 5K Run/Walk Geneseo, New York. 01 Sep 24 View Event Dairy Discovery 5K & Fun Run ... 9/11 Heroes Run - New York City, NY New York, New York. 07 Sep 24 View Event\"}]\n", 170 | "Assistant: I found some 5K races in New York City for August and September 2024:\n", 171 | "\n", 172 | "### August 2024:\n", 173 | "1. **August 16, 2024 (Friday)**\n", 174 | " - 5K\n", 175 | "2. **August 17, 2024 (Saturday)**\n", 176 | " - 5K\n", 177 | "3. **August 18, 2024 (Sunday)**\n", 178 | " - 5K\n", 179 | "\n", 180 | "### September 2024:\n", 181 | "1. [9/11 Heroes Run - New York City, NY](https://findarace.com/us/running/5k-runs/new-york/september) - September 7, 2024\n", 182 | "2. **September 14, 2024**\n", 183 | " - Storm King Run 2024\n", 184 | " - Rotary Club of West Point - Highland Falls\n", 185 | " - Bubble Run | Long Island\n", 186 | "\n", 187 | "You can explore these races for August and September 2024. Let me know if you need more information or assistance with anything else!\n", 188 | "User: thank you\n", 189 | "Assistant: You're welcome! If you have any more questions or need further assistance in the future, feel free to reach out. Have a great day and good luck with your 5K race in New York City!\n", 190 | "User: quit\n", 191 | "Goodbye!\n" 192 | ] 193 | } 194 | ], 195 | "source": [ 196 | "while True:\n", 197 | " user_input = input(\"User: \")\n", 198 | " print(\"User: \" + user_input)\n", 199 | " if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n", 200 | " print(\"Goodbye!\")\n", 201 | " break\n", 202 | " for event in graph.stream({\"messages\": [(\"user\", user_input)]}, config):\n", 203 | " for value in event.values():\n", 204 | " if isinstance(value[\"messages\"][-1], BaseMessage):\n", 205 | " print(\"Assistant:\", value[\"messages\"][-1].content)" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "### prompt adjustment" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "config = {\"configurable\": {\"thread_id\": \"1\"}}" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "# Get the prompt to use - you can modify this\n", 231 | "from langchain import hub\n", 232 | "prompt = hub.pull(\"hwchase17/react-chat\")" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [ 241 | "print(prompt.template)\n" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": null, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "prompt.template = \"\"\"Assistant is a large language model trained by OpenAI.\n", 251 | "\n", 252 | "Assistant is designed to be able to assist users to onboard onto a health and fitness platform. You must ask the users what wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n", 253 | "\n", 254 | "Assistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n", 255 | "\n", 256 | "Overall, Assistant is a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.\n", 257 | "\n", 258 | "TOOLS:\n", 259 | "------\n", 260 | "\n", 261 | "Assistant has access to the following tools:\n", 262 | "\n", 263 | "{tools}\n", 264 | "\n", 265 | "To use a tool, please use the following format:\n", 266 | "\n", 267 | "```\n", 268 | "Thought: Do I need to use a tool? Yes\n", 269 | "Action: the action to take, should be one of [{tool_names}]\n", 270 | "Action Input: the input to the action\n", 271 | "Observation: the result of the action\n", 272 | "```\n", 273 | "\n", 274 | "When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:\n", 275 | "\n", 276 | "```\n", 277 | "Thought: Do I need to use a tool? No\n", 278 | "Final Answer: [your response here]\n", 279 | "```\n", 280 | "\n", 281 | "Begin!\n", 282 | "\n", 283 | "Previous conversation history:\n", 284 | "{chat_history}\n", 285 | "\n", 286 | "New input: {input}\n", 287 | "{agent_scratchpad}\"\"\"" 288 | ] 289 | } 290 | ], 291 | "metadata": { 292 | "kernelspec": { 293 | "display_name": "venv", 294 | "language": "python", 295 | "name": "python3" 296 | }, 297 | "language_info": { 298 | "codemirror_mode": { 299 | "name": "ipython", 300 | "version": 3 301 | }, 302 | "file_extension": ".py", 303 | "mimetype": "text/x-python", 304 | "name": "python", 305 | "nbconvert_exporter": "python", 306 | "pygments_lexer": "ipython3", 307 | "version": "3.9.6" 308 | } 309 | }, 310 | "nbformat": 4, 311 | "nbformat_minor": 2 312 | } 313 | -------------------------------------------------------------------------------- /sessions/session_2/notebooks/langgraph_foundations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Tools" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "name": "stdout", 17 | "output_type": "stream", 18 | "text": [ 19 | "Requirement already satisfied: langchain-community in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (0.2.7)\n", 20 | "Collecting langchain-community\n", 21 | " Downloading langchain_community-0.2.9-py3-none-any.whl.metadata (2.5 kB)\n", 22 | "Requirement already satisfied: langgraph in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (0.1.8)\n", 23 | "Collecting langgraph\n", 24 | " Downloading langgraph-0.1.9-py3-none-any.whl.metadata (13 kB)\n", 25 | "Requirement already satisfied: langchain-openai in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (0.1.17)\n", 26 | "Requirement already satisfied: tavily-python in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (0.3.5)\n", 27 | "Requirement already satisfied: PyYAML>=5.3 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (6.0.1)\n", 28 | "Requirement already satisfied: SQLAlchemy<3,>=1.4 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (2.0.31)\n", 29 | "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (3.9.5)\n", 30 | "Requirement already satisfied: dataclasses-json<0.7,>=0.5.7 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (0.6.7)\n", 31 | "Requirement already satisfied: langchain<0.3.0,>=0.2.9 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (0.2.9)\n", 32 | "Collecting langchain-core<0.3.0,>=0.2.22 (from langchain-community)\n", 33 | " Downloading langchain_core-0.2.22-py3-none-any.whl.metadata (6.0 kB)\n", 34 | "Requirement already satisfied: langsmith<0.2.0,>=0.1.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (0.1.90)\n", 35 | "Requirement already satisfied: numpy<2,>=1 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (1.26.4)\n", 36 | "Requirement already satisfied: requests<3,>=2 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (2.32.3)\n", 37 | "Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-community) (8.5.0)\n", 38 | "Requirement already satisfied: openai<2.0.0,>=1.32.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-openai) (1.35.14)\n", 39 | "Requirement already satisfied: tiktoken<1,>=0.7 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-openai) (0.7.0)\n", 40 | "Requirement already satisfied: httpx in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from tavily-python) (0.27.0)\n", 41 | "Requirement already satisfied: aiosignal>=1.1.2 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.3.1)\n", 42 | "Requirement already satisfied: attrs>=17.3.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (23.2.0)\n", 43 | "Requirement already satisfied: frozenlist>=1.1.1 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.4.1)\n", 44 | "Requirement already satisfied: multidict<7.0,>=4.5 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (6.0.5)\n", 45 | "Requirement already satisfied: yarl<2.0,>=1.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (1.9.4)\n", 46 | "Requirement already satisfied: async-timeout<5.0,>=4.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community) (4.0.3)\n", 47 | "Requirement already satisfied: marshmallow<4.0.0,>=3.18.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from dataclasses-json<0.7,>=0.5.7->langchain-community) (3.21.3)\n", 48 | "Requirement already satisfied: typing-inspect<1,>=0.4.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from dataclasses-json<0.7,>=0.5.7->langchain-community) (0.9.0)\n", 49 | "Requirement already satisfied: langchain-text-splitters<0.3.0,>=0.2.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain<0.3.0,>=0.2.9->langchain-community) (0.2.2)\n", 50 | "Requirement already satisfied: pydantic<3,>=1 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain<0.3.0,>=0.2.9->langchain-community) (2.8.2)\n", 51 | "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-core<0.3.0,>=0.2.22->langchain-community) (1.33)\n", 52 | "Requirement already satisfied: packaging<25,>=23.2 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langchain-core<0.3.0,>=0.2.22->langchain-community) (24.1)\n", 53 | "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from langsmith<0.2.0,>=0.1.0->langchain-community) (3.10.6)\n", 54 | "Requirement already satisfied: anyio<5,>=3.5.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (4.4.0)\n", 55 | "Requirement already satisfied: distro<2,>=1.7.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (1.9.0)\n", 56 | "Requirement already satisfied: sniffio in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (1.3.1)\n", 57 | "Requirement already satisfied: tqdm>4 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (4.66.4)\n", 58 | "Requirement already satisfied: typing-extensions<5,>=4.7 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from openai<2.0.0,>=1.32.0->langchain-openai) (4.12.2)\n", 59 | "Requirement already satisfied: certifi in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from httpx->tavily-python) (2024.7.4)\n", 60 | "Requirement already satisfied: httpcore==1.* in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from httpx->tavily-python) (1.0.5)\n", 61 | "Requirement already satisfied: idna in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from httpx->tavily-python) (3.7)\n", 62 | "Requirement already satisfied: h11<0.15,>=0.13 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from httpcore==1.*->httpx->tavily-python) (0.14.0)\n", 63 | "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from requests<3,>=2->langchain-community) (3.3.2)\n", 64 | "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from requests<3,>=2->langchain-community) (2.2.2)\n", 65 | "Requirement already satisfied: regex>=2022.1.18 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from tiktoken<1,>=0.7->langchain-openai) (2024.5.15)\n", 66 | "Requirement already satisfied: exceptiongroup>=1.0.2 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.32.0->langchain-openai) (1.2.2)\n", 67 | "Requirement already satisfied: jsonpointer>=1.9 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.3.0,>=0.2.22->langchain-community) (3.0.0)\n", 68 | "Requirement already satisfied: annotated-types>=0.4.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from pydantic<3,>=1->langchain<0.3.0,>=0.2.9->langchain-community) (0.7.0)\n", 69 | "Requirement already satisfied: pydantic-core==2.20.1 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from pydantic<3,>=1->langchain<0.3.0,>=0.2.9->langchain-community) (2.20.1)\n", 70 | "Requirement already satisfied: mypy-extensions>=0.3.0 in /Users/rickchakra/Projects/aiug_workshop/venv_new/lib/python3.9/site-packages (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain-community) (1.0.0)\n", 71 | "Downloading langchain_community-0.2.9-py3-none-any.whl (2.3 MB)\n", 72 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m9.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mta \u001b[36m0:00:01\u001b[0m\n", 73 | "\u001b[?25hDownloading langgraph-0.1.9-py3-none-any.whl (95 kB)\n", 74 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m96.0/96.0 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 75 | "\u001b[?25hDownloading langchain_core-0.2.22-py3-none-any.whl (373 kB)\n", 76 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m373.5/373.5 kB\u001b[0m \u001b[31m8.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mta \u001b[36m0:00:01\u001b[0m\n", 77 | "\u001b[?25hInstalling collected packages: langchain-core, langgraph, langchain-community\n", 78 | " Attempting uninstall: langchain-core\n", 79 | " Found existing installation: langchain-core 0.2.21\n", 80 | " Uninstalling langchain-core-0.2.21:\n", 81 | " Successfully uninstalled langchain-core-0.2.21\n", 82 | " Attempting uninstall: langgraph\n", 83 | " Found existing installation: langgraph 0.1.8\n", 84 | " Uninstalling langgraph-0.1.8:\n", 85 | " Successfully uninstalled langgraph-0.1.8\n", 86 | " Attempting uninstall: langchain-community\n", 87 | " Found existing installation: langchain-community 0.2.7\n", 88 | " Uninstalling langchain-community-0.2.7:\n", 89 | " Successfully uninstalled langchain-community-0.2.7\n", 90 | "Successfully installed langchain-community-0.2.9 langchain-core-0.2.22 langgraph-0.1.9\n", 91 | "Note: you may need to restart the kernel to use updated packages.\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "#%pip install -U langchain-community langgraph langchain-openai tavily-python" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 17, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "import getpass\n", 106 | "import os\n", 107 | "\n", 108 | "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n", 109 | "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 1, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "import getpass\n", 119 | "import os\n", 120 | "\n", 121 | "# os.environ[\"TAVILY_API_KEY\"] = getpass.getpass()" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 2, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stderr", 131 | "output_type": "stream", 132 | "text": [ 133 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", 134 | " warnings.warn(\n" 135 | ] 136 | }, 137 | { 138 | "name": "stdout", 139 | "output_type": "stream", 140 | "text": [ 141 | "[{'url': 'https://www.weatherapi.com/', 'content': \"{'location': {'name': 'Los Angeles', 'region': 'California', 'country': 'United States of America', 'lat': 34.05, 'lon': -118.24, 'tz_id': 'America/Los_Angeles', 'localtime_epoch': 1723598355, 'localtime': '2024-08-13 18:19'}, 'current': {'last_updated_epoch': 1723598100, 'last_updated': '2024-08-13 18:15', 'temp_c': 24.4, 'temp_f': 75.9, 'is_day': 1, 'condition': {'text': 'Sunny', 'icon': '//cdn.weatherapi.com/weather/64x64/day/113.png', 'code': 1000}, 'wind_mph': 12.5, 'wind_kph': 20.2, 'wind_degree': 260, 'wind_dir': 'W', 'pressure_mb': 1013.0, 'pressure_in': 29.9, 'precip_mm': 0.0, 'precip_in': 0.0, 'humidity': 64, 'cloud': 0, 'feelslike_c': 25.3, 'feelslike_f': 77.5, 'windchill_c': 27.6, 'windchill_f': 81.6, 'heatindex_c': 27.9, 'heatindex_f': 82.2, 'dewpoint_c': 14.9, 'dewpoint_f': 58.8, 'vis_km': 16.0, 'vis_miles': 9.0, 'uv': 7.0, 'gust_mph': 17.0, 'gust_kph': 27.4}}\"}, {'url': 'https://www.timeanddate.com/weather/@z-us-90023/ext', 'content': 'Los Angeles 14 Day Extended Forecast. Weather Today Weather Hourly 14 Day Forecast Yesterday/Past Weather Climate (Averages) Currently: 70 °F. Scattered clouds. (Weather station: Los Angeles Los Angeles International Airport, USA). See more current weather.'}]\n" 142 | ] 143 | } 144 | ], 145 | "source": [ 146 | "from langchain_community.tools.tavily_search import TavilySearchResults\n", 147 | "\n", 148 | "# define search tool\n", 149 | "\n", 150 | "search = TavilySearchResults(max_results=2)\n", 151 | "search_results = search.invoke(\"what is the weather in Los Angeles\")\n", 152 | "print(search_results)\n", 153 | "# If we want, we can create other tools.\n", 154 | "# Once we have all the tools we want, we can put them in a list that we will reference later.\n", 155 | "tools = [search]" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "### Bind model with tools" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 5, 168 | "metadata": {}, 169 | "outputs": [ 170 | { 171 | "name": "stdout", 172 | "output_type": "stream", 173 | "text": [ 174 | "Note: you may need to restart the kernel to use updated packages.\n" 175 | ] 176 | } 177 | ], 178 | "source": [ 179 | "#pip install -qU langchain-openai" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 7, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "import getpass\n", 189 | "import os\n", 190 | "\n", 191 | "# os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n", 192 | "\n", 193 | "from langchain_openai import ChatOpenAI\n", 194 | "\n", 195 | "# initialize model\n", 196 | "model = ChatOpenAI(model=\"gpt-4o\")" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 8, 202 | "metadata": {}, 203 | "outputs": [ 204 | { 205 | "data": { 206 | "text/plain": [ 207 | "'Hello! How can I assist you today?'" 208 | ] 209 | }, 210 | "execution_count": 8, 211 | "metadata": {}, 212 | "output_type": "execute_result" 213 | } 214 | ], 215 | "source": [ 216 | "from langchain_core.messages import HumanMessage\n", 217 | "\n", 218 | "response = model.invoke([HumanMessage(content=\"hi!\")])\n", 219 | "response.content" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 9, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [ 228 | "# bind tools with model\n", 229 | "model_with_tools = model.bind_tools(tools)" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": 10, 235 | "metadata": {}, 236 | "outputs": [ 237 | { 238 | "name": "stdout", 239 | "output_type": "stream", 240 | "text": [ 241 | "ContentString: Hello! How can I assist you today?\n", 242 | "ToolCalls: []\n" 243 | ] 244 | } 245 | ], 246 | "source": [ 247 | "# check response of model with search tool (no tool call)\n", 248 | "response = model_with_tools.invoke([HumanMessage(content=\"Hi!\")])\n", 249 | "\n", 250 | "print(f\"ContentString: {response.content}\")\n", 251 | "print(f\"ToolCalls: {response.tool_calls}\")" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": 11, 257 | "metadata": {}, 258 | "outputs": [ 259 | { 260 | "name": "stdout", 261 | "output_type": "stream", 262 | "text": [ 263 | "ContentString: \n", 264 | "ToolCalls: [{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in San Francisco'}, 'id': 'call_fuPykTFGJw5N3uu9f9QFtPCW', 'type': 'tool_call'}]\n" 265 | ] 266 | } 267 | ], 268 | "source": [ 269 | "# check response of model with search tool (tool call)\n", 270 | "response = model_with_tools.invoke([HumanMessage(content=\"What's the weather in San Francisco?\")])\n", 271 | "\n", 272 | "print(f\"ContentString: {response.content}\")\n", 273 | "print(f\"ToolCalls: {response.tool_calls}\")" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "### Using a prebuilt react agent with tools" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": 12, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "from langgraph.prebuilt import create_react_agent\n", 290 | "\n", 291 | "#use prebuilt ReAct agent\n", 292 | "agent_executor = create_react_agent(model, tools)" 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": 13, 298 | "metadata": {}, 299 | "outputs": [ 300 | { 301 | "data": { 302 | "text/plain": [ 303 | "[HumanMessage(content='hi!', id='d6b509d9-0fff-488f-ad35-68f9737be000'),\n", 304 | " AIMessage(content='Hello! How can I assist you today?', response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 81, 'total_tokens': 91}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27', 'finish_reason': 'stop', 'logprobs': None}, id='run-484c1aa0-12bc-4bec-a625-d6d39cc85309-0', usage_metadata={'input_tokens': 81, 'output_tokens': 10, 'total_tokens': 91})]" 305 | ] 306 | }, 307 | "execution_count": 13, 308 | "metadata": {}, 309 | "output_type": "execute_result" 310 | } 311 | ], 312 | "source": [ 313 | "# test agent response (no tool call)\n", 314 | "response = agent_executor.invoke({\"messages\": [HumanMessage(content=\"hi!\")]})\n", 315 | "\n", 316 | "response[\"messages\"]" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 16, 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "data": { 326 | "text/plain": [ 327 | "[HumanMessage(content=\"What's the weather in San Francisco and if it's not raining, are there any event happening today (August 13 2024)?\", id='5c7f63c3-51cc-452d-94ab-909d76bf3e55'),\n", 328 | " AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_fiDFOmz7sxzYZmOm08pP10FO', 'function': {'arguments': '{\"query\": \"San Francisco weather August 13 2024\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}, {'id': 'call_ATSF9Y33SBJbW7jqpzOL9t4x', 'function': {'arguments': '{\"query\": \"Events in San Francisco August 13 2024\"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 69, 'prompt_tokens': 105, 'total_tokens': 174}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-c44d3455-2ad9-4884-96ac-04d862e2e0f0-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'San Francisco weather August 13 2024'}, 'id': 'call_fiDFOmz7sxzYZmOm08pP10FO', 'type': 'tool_call'}, {'name': 'tavily_search_results_json', 'args': {'query': 'Events in San Francisco August 13 2024'}, 'id': 'call_ATSF9Y33SBJbW7jqpzOL9t4x', 'type': 'tool_call'}], usage_metadata={'input_tokens': 105, 'output_tokens': 69, 'total_tokens': 174}),\n", 329 | " ToolMessage(content='[{\"url\": \"https://www.weatherapi.com/\", \"content\": \"{\\'location\\': {\\'name\\': \\'San Francisco\\', \\'region\\': \\'California\\', \\'country\\': \\'United States of America\\', \\'lat\\': 37.78, \\'lon\\': -122.42, \\'tz_id\\': \\'America/Los_Angeles\\', \\'localtime_epoch\\': 1723599534, \\'localtime\\': \\'2024-08-13 18:38\\'}, \\'current\\': {\\'last_updated_epoch\\': 1723599000, \\'last_updated\\': \\'2024-08-13 18:30\\', \\'temp_c\\': 20.6, \\'temp_f\\': 69.1, \\'is_day\\': 1, \\'condition\\': {\\'text\\': \\'Partly cloudy\\', \\'icon\\': \\'//cdn.weatherapi.com/weather/64x64/day/116.png\\', \\'code\\': 1003}, \\'wind_mph\\': 15.0, \\'wind_kph\\': 24.1, \\'wind_degree\\': 270, \\'wind_dir\\': \\'W\\', \\'pressure_mb\\': 1015.0, \\'pressure_in\\': 29.98, \\'precip_mm\\': 0.0, \\'precip_in\\': 0.0, \\'humidity\\': 59, \\'cloud\\': 25, \\'feelslike_c\\': 20.6, \\'feelslike_f\\': 69.1, \\'windchill_c\\': 16.7, \\'windchill_f\\': 62.0, \\'heatindex_c\\': 16.7, \\'heatindex_f\\': 62.0, \\'dewpoint_c\\': 11.7, \\'dewpoint_f\\': 53.1, \\'vis_km\\': 16.0, \\'vis_miles\\': 9.0, \\'uv\\': 5.0, \\'gust_mph\\': 18.9, \\'gust_kph\\': 30.3}}\"}, {\"url\": \"https://world-weather.info/forecast/usa/san_francisco/august-2024/\", \"content\": \"Detailed \\\\u26a1 San Francisco Weather Forecast for August 2024 - day/night \\\\ud83c\\\\udf21\\\\ufe0f temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets \\\\u00b0F. World; United States; California; Weather in San Francisco; Weather in San Francisco in August 2024. ... 13 +64\\\\u00b0 +54\\\\u00b0 14 +64\\\\u00b0 +55\\\\u00b0 15 ...\"}]', name='tavily_search_results_json', id='566b63a2-b67b-43b3-87b5-40cd0a7979a6', tool_call_id='call_fiDFOmz7sxzYZmOm08pP10FO'),\n", 330 | " ToolMessage(content='[{\"url\": \"https://allevents.in/san francisco/august\", \"content\": \"August Events In San Francisco\\\\nThings To Do In August 2024 in San Francisco\\\\nEvents in August in \\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tSan Francisco\\\\nEvents in August in \\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tSan Francisco\\\\nDance Fridays -\\\\nSalsa, Bachata, Dance Lessons, Bay Area\\'s Largest Dance Club\\\\nSave or Fix your Marriage in San Francisco\\\\nDetroit Tigers at San Francisco Giants\\\\nAtlanta Braves at San Francisco Giants\\\\nChicago White Sox at San Francisco Giants\\\\nSebastian Maniscalco: It Ain\\'t Right Tour\\\\nAfter Dark: Visualize and Sonify\\\\nGrant Writing Classes In San Francisco | Grant Central USA\\\\nFriday Founder\\'s Meet Up\\\\nOlivia Rodrigo - San Francisco, CA\\\\nRiptide Comedy & Cocktails: Thursday Comedy in the Sunset\\\\n\\\\\"Still We Rise\\\\\" African Inspired\\\\nFashion Gala\\\\nYOUTH-N-TECH TECH EXPO\\\\n2024 Summer Finance Training for School and Districts Leaders\\\\nOlivia Rodrigo - GUTS world tour\\\\nEvents in August from nearby cities\\\\nTrending Events from nearby cities\\\\nUpcoming Events in August in San Francisco\\\\n Site Navigation\\\\nTrending Searches\\\\nHost Events\\\\nDiscover Events\\\\nExplore\\\\n#StayHappening\\\\nUpcoming Events in San Francisco Explore more in San Francisco\\\\nEvents in August from nearby cities\\\\n{{item.eventname_raw}}\\\\n{{item.eventname_raw}}\\\\n{{item.eventname_raw}}\\\\nStay tuned with the most relevant events happening around you. We\\'ll recommend events that you would not want to miss!\\\\n Don\\'t miss your favorite Events again.\\\\n\"}, {\"url\": \"https://secretsanfrancisco.com/things-to-do-august/\", \"content\": \"Party it up at Outside Lands 2024. Image courtesy of Outside Lands. August 9-11. Outside Lands is the city\\'s largest music festival and is back for 3 days of music, Aug 9-11 in Golden Gate Park. 2024 headliners include Sabrina Carpenter, The Killer, Sturgill Simpson, Grace Jones, and many more.\"}]', name='tavily_search_results_json', id='a2778685-3cde-4260-8e93-b98164ea58b0', tool_call_id='call_ATSF9Y33SBJbW7jqpzOL9t4x'),\n", 331 | " AIMessage(content='### Weather in San Francisco on August 13, 2024\\n- **Condition:** Partly cloudy\\n- **Temperature:** 20.6°C (69.1°F)\\n- **Precipitation:** 0.0 mm (0.0 in)\\n- **Wind:** 15.0 mph (24.1 kph) from the West\\n- **Humidity:** 59%\\n- **Visibility:** 16 km (9 miles)\\n \\nIt is not raining today.\\n\\n### Events Happening in San Francisco on August 13, 2024\\n\\nHere are some events you can enjoy in San Francisco today:\\n\\n1. **Dance Fridays**\\n - Salsa and Bachata Dance Lessons at Bay Area\\'s Largest Dance Club\\n\\n2. **San Francisco Giants Games**\\n - Detroit Tigers vs. San Francisco Giants\\n - Atlanta Braves vs. San Francisco Giants\\n - Chicago White Sox vs. San Francisco Giants\\n\\n3. **Comedy Shows**\\n - Riptide Comedy & Cocktails: Thursday Comedy in the Sunset\\n\\n4. **Concerts**\\n - Olivia Rodrigo\\'s GUTS World Tour\\n\\n5. **Cultural Events**\\n - \"Still We Rise\" African Inspired Fashion Gala\\n\\n6. **Educational Events**\\n - Grant Writing Classes by Grant Central USA\\n - Youth-N-Tech Tech Expo\\n - Summer Finance Training for School and District Leaders\\n\\n7. **Meetups**\\n - Friday Founder\\'s Meet Up\\n\\nEnjoy your day in San Francisco!', response_metadata={'token_usage': {'completion_tokens': 303, 'prompt_tokens': 1172, 'total_tokens': 1475}, 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27', 'finish_reason': 'stop', 'logprobs': None}, id='run-0f172b67-d502-46cf-9683-17a269e4f61a-0', usage_metadata={'input_tokens': 1172, 'output_tokens': 303, 'total_tokens': 1475})]" 332 | ] 333 | }, 334 | "execution_count": 16, 335 | "metadata": {}, 336 | "output_type": "execute_result" 337 | } 338 | ], 339 | "source": [ 340 | "# test agent response (tool call)\n", 341 | "response = agent_executor.invoke(\n", 342 | " {\"messages\": [HumanMessage(content=\"What's the weather in San Francisco and if it's not raining, are there any event happening today (August 13 2024)?\")]}\n", 343 | ")\n", 344 | "response[\"messages\"]" 345 | ] 346 | } 347 | ], 348 | "metadata": { 349 | "kernelspec": { 350 | "display_name": "venv", 351 | "language": "python", 352 | "name": "python3" 353 | }, 354 | "language_info": { 355 | "codemirror_mode": { 356 | "name": "ipython", 357 | "version": 3 358 | }, 359 | "file_extension": ".py", 360 | "mimetype": "text/x-python", 361 | "name": "python", 362 | "nbconvert_exporter": "python", 363 | "pygments_lexer": "ipython3", 364 | "version": "3.9.6" 365 | } 366 | }, 367 | "nbformat": 4, 368 | "nbformat_minor": 2 369 | } 370 | -------------------------------------------------------------------------------- /sessions/session_7/notebooks/fine_tuning.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Step 1: Defining the Task\n", 8 | "For this workshop we will:\n", 9 | "* Train GPT3.5 to automatically produce nutrition_logs, training_logs, and response messages in XML tags.\n", 10 | "* Our goal is to replace complex prompt instruction with simpler prompts against a specialized model." 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Step 2: Prepare fine-tuning data set" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 2, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "# imports\n", 27 | "from openai import OpenAI\n", 28 | "import json\n", 29 | "import tiktoken\n", 30 | "from collections import defaultdict\n", 31 | "import numpy as np\n", 32 | "\n", 33 | "client = OpenAI()" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "### Aggregate data set from larger model with more complex instructions\n", 41 | "\n", 42 | "> You are an expert personal trainer and fitness coach for athletes. Start by asking for a daily update, and you will be told what the user ate and trained that day. Respond with: 1. in tags log the training (do not include dates) 2. in tags log the name of the food (do not include dates) 3. in respond with \"Nice!\" Do not add any new line characters.\n", 43 | "\n", 44 | "* Then we simulated a few conversations and captured the responses in a list.\n", 45 | "* We collected a total of 20 samples for our task.\n", 46 | "* Fine-Tuning API requies a minimum of 10 samples for fine-tuning\n", 47 | "* OpenAI reports that a remarkable performance gain is observed when trainig examples go beyond 50 samples\n", 48 | "* 50 to 100 examples are typical\n", 49 | "* Exact number of required data samples depends on your specific use case" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 3, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "system_prompt = '''You are an expert personal trainer and fitness coach for athletes. Start by asking for a daily update, and you will be told what the user ate and trained that day. Respond with: \n", 59 | "1. in tags log the training (do not include dates)\n", 60 | "2. in tags log the name of the food (do not include dates)\n", 61 | "3. in respond with \"Nice!\"\n", 62 | "\n", 63 | "Do not add any new line characters.'''\n", 64 | "\n", 65 | "user_prompts = [{\"role\": \"user\", \"content\": \"I ate eggs and ran half a mile\"}, \n", 66 | " {\"role\": \"user\", \"content\": \"I ate pizza and did 10 pushups\"}, \n", 67 | " {\"role\": \"user\", \"content\": \"I ate a salad and swam 5 laps\"}, \n", 68 | " {\"role\": \"user\", \"content\": \"I ate a burger and did 15 squats\"},\n", 69 | " {\"role\": \"user\", \"content\": \"I ate cookies and did 20 crunches\"}, \n", 70 | " {\"role\": \"user\", \"content\": \"I ate a steak and did 30 burpees\"}, \n", 71 | " {\"role\": \"user\", \"content\": \"I ate a pie and did 5 pull-ups\"}, \n", 72 | " {\"role\": \"user\", \"content\": \"I ate cake and did 1 hour of yoga\"},\n", 73 | " {\"role\": \"user\", \"content\": \"I ate soup and took a long walk\"},\n", 74 | " {\"role\": \"user\", \"content\": \"I ate candy and did pilates\"},\n", 75 | " {\"role\": \"user\", \"content\": \"I ate pasta and biked for 1 hour\"},\n", 76 | " {\"role\": \"user\", \"content\": \"I ate sushi and hiked for 1 hour\"},\n", 77 | " {\"role\": \"user\", \"content\": \"I ate cheese and did jumping jacks\"},\n", 78 | " {\"role\": \"user\", \"content\": \"I ate shrimp and did Tae Kwon Do\"},\n", 79 | " {\"role\": \"user\", \"content\": \"I ate cereal and did 20 sprints\"},\n", 80 | " {\"role\": \"user\", \"content\": \"I ate chips and rowed for 1 hour\"},\n", 81 | " {\"role\": \"user\", \"content\": \"I ate nuts and walked for 1 hour\"},\n", 82 | " {\"role\": \"user\", \"content\": \"I ate tacos and ran 3 miles\"},\n", 83 | " {\"role\": \"user\", \"content\": \"I ate a banana and did 50 pushups\"},\n", 84 | " {\"role\": \"user\", \"content\": \"I ate an orange and swam 10 laps\"},\n", 85 | " ]" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "system_role = {\"role\": \"system\", \"content\": \"You are a personal trainer and fitness coach.\"}\n", 95 | "conversations = []\n", 96 | "\n", 97 | "# loop through user prompts and generate responses\n", 98 | "for user_prompt in user_prompts:\n", 99 | " completion = client.chat.completions.create(\n", 100 | " model=\"gpt-4o\",\n", 101 | " messages=[{\"role\": \"system\", \"content\": system_prompt}, user_prompt],\n", 102 | " temperature=1,\n", 103 | " max_tokens=1024,\n", 104 | " seed=42\n", 105 | " )\n", 106 | "\n", 107 | " assistant_role = {\"role\": \"assistant\", \"content\": completion.choices[0].message.content}\n", 108 | "\n", 109 | " # build conversations collection\n", 110 | " conversation = [system_role, user_prompt, assistant_role]\n", 111 | " conversations.append(conversation)\n", 112 | " \n" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "# Step 3: Convert Data to .jsonl format" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 4, 125 | "metadata": {}, 126 | "outputs": [ 127 | { 128 | "data": { 129 | "text/plain": [ 130 | "[[{'role': 'system',\n", 131 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 132 | " {'role': 'user', 'content': 'I ate eggs and ran half a mile'},\n", 133 | " {'role': 'assistant',\n", 134 | " 'content': 'ran half a mileeggsNice!'}],\n", 135 | " [{'role': 'system',\n", 136 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 137 | " {'role': 'user', 'content': 'I ate pizza and did 10 pushups'},\n", 138 | " {'role': 'assistant',\n", 139 | " 'content': '10 pushupspizzaNice!'}],\n", 140 | " [{'role': 'system',\n", 141 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 142 | " {'role': 'user', 'content': 'I ate a salad and swam 5 laps'},\n", 143 | " {'role': 'assistant',\n", 144 | " 'content': 'swam 5 lapssaladNice!'}],\n", 145 | " [{'role': 'system',\n", 146 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 147 | " {'role': 'user', 'content': 'I ate a burger and did 15 squats'},\n", 148 | " {'role': 'assistant',\n", 149 | " 'content': '15 squatsburgerNice!'}],\n", 150 | " [{'role': 'system',\n", 151 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 152 | " {'role': 'user', 'content': 'I ate cookies and did 20 crunches'},\n", 153 | " {'role': 'assistant',\n", 154 | " 'content': '20 crunchescookiesNice!'}],\n", 155 | " [{'role': 'system',\n", 156 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 157 | " {'role': 'user', 'content': 'I ate a steak and did 30 burpees'},\n", 158 | " {'role': 'assistant',\n", 159 | " 'content': '30 burpeessteakNice!'}],\n", 160 | " [{'role': 'system',\n", 161 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 162 | " {'role': 'user', 'content': 'I ate a pie and did 5 pull-ups'},\n", 163 | " {'role': 'assistant',\n", 164 | " 'content': '5 pull-upspieNice!'}],\n", 165 | " [{'role': 'system',\n", 166 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 167 | " {'role': 'user', 'content': 'I ate cake and did 1 hour of yoga'},\n", 168 | " {'role': 'assistant',\n", 169 | " 'content': '1 hour of yogacakeNice!'}],\n", 170 | " [{'role': 'system',\n", 171 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 172 | " {'role': 'user', 'content': 'I ate soup and took a long walk'},\n", 173 | " {'role': 'assistant',\n", 174 | " 'content': 'long walksoupNice!'}],\n", 175 | " [{'role': 'system',\n", 176 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 177 | " {'role': 'user', 'content': 'I ate candy and did pilates'},\n", 178 | " {'role': 'assistant',\n", 179 | " 'content': 'PilatesCandyNice!'}],\n", 180 | " [{'role': 'system',\n", 181 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 182 | " {'role': 'user', 'content': 'I ate pasta and biked for 1 hour'},\n", 183 | " {'role': 'assistant',\n", 184 | " 'content': 'Biked for 1 hourPastaNice!'}],\n", 185 | " [{'role': 'system',\n", 186 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 187 | " {'role': 'user', 'content': 'I ate sushi and hiked for 1 hour'},\n", 188 | " {'role': 'assistant',\n", 189 | " 'content': 'hiked for 1 hoursushiNice!'}],\n", 190 | " [{'role': 'system',\n", 191 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 192 | " {'role': 'user', 'content': 'I ate cheese and did jumping jacks'},\n", 193 | " {'role': 'assistant',\n", 194 | " 'content': 'jumping jackscheeseNice!'}],\n", 195 | " [{'role': 'system',\n", 196 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 197 | " {'role': 'user', 'content': 'I ate shrimp and did Tae Kwon Do'},\n", 198 | " {'role': 'assistant',\n", 199 | " 'content': 'Tae Kwon DoshrimpNice!'}],\n", 200 | " [{'role': 'system',\n", 201 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 202 | " {'role': 'user', 'content': 'I ate cereal and did 20 sprints'},\n", 203 | " {'role': 'assistant',\n", 204 | " 'content': '20 sprintscerealNice!'}],\n", 205 | " [{'role': 'system',\n", 206 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 207 | " {'role': 'user', 'content': 'I ate chips and rowed for 1 hour'},\n", 208 | " {'role': 'assistant',\n", 209 | " 'content': 'Rowed for 1 hourChipsNice!'}],\n", 210 | " [{'role': 'system',\n", 211 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 212 | " {'role': 'user', 'content': 'I ate nuts and walked for 1 hour'},\n", 213 | " {'role': 'assistant',\n", 214 | " 'content': 'walked for 1 hournutsNice!'}],\n", 215 | " [{'role': 'system',\n", 216 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 217 | " {'role': 'user', 'content': 'I ate tacos and ran 3 miles'},\n", 218 | " {'role': 'assistant',\n", 219 | " 'content': 'ran 3 milestacosNice!'}],\n", 220 | " [{'role': 'system',\n", 221 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 222 | " {'role': 'user', 'content': 'I ate a banana and did 50 pushups'},\n", 223 | " {'role': 'assistant',\n", 224 | " 'content': '50 pushupsbananaNice!'}],\n", 225 | " [{'role': 'system',\n", 226 | " 'content': 'You are a personal trainer and fitness coach.'},\n", 227 | " {'role': 'user', 'content': 'I ate an orange and swam 10 laps'},\n", 228 | " {'role': 'assistant',\n", 229 | " 'content': 'swam 10 lapsorangeNice!'}]]" 230 | ] 231 | }, 232 | "execution_count": 4, 233 | "metadata": {}, 234 | "output_type": "execute_result" 235 | } 236 | ], 237 | "source": [ 238 | "# view raw conversations\n", 239 | "conversations" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": 5, 245 | "metadata": {}, 246 | "outputs": [ 247 | { 248 | "name": "stdout", 249 | "output_type": "stream", 250 | "text": [ 251 | "The JSONL file has been written to data.jsonl\n" 252 | ] 253 | } 254 | ], 255 | "source": [ 256 | "jsonl_file_name = 'data.jsonl'\n", 257 | "\n", 258 | "# Write each conversation to the JSON Lines file line by line\n", 259 | "with open(jsonl_file_name, 'w') as file:\n", 260 | " for conversation in conversations:\n", 261 | " json.dump({\"messages\": conversation}, file)\n", 262 | " file.write('\\n') # Add a newline to separate lines\n", 263 | "\n", 264 | "print(f'The JSONL file has been written to {jsonl_file_name}')" 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "# Step 4: Verify Data and Evaluate Cost\n", 272 | "Here we perform following tasks:\n", 273 | "* Check if the data format is correct\n", 274 | "* All messages should be within max token limit of 4096\n", 275 | "* Statistical parameters of data (mean, median, max, min, P5, P95)\n", 276 | "* Count total number of tokens\n", 277 | "* Estimate the cost of fine-tuning" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 6, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [ 286 | "## UTILITY FUNCTION FROM AIUG DEVELOPER DAY\n", 287 | "\n", 288 | "# verify data utility\n", 289 | "def verify_data(data_path):\n", 290 | "\n", 291 | " # Load dataset\n", 292 | " with open(data_path) as f:\n", 293 | " dataset = [json.loads(line) for line in f]\n", 294 | "\n", 295 | " # We can inspect the data quickly by checking the number of examples and the first item\n", 296 | "\n", 297 | " # Initial dataset stats\n", 298 | " print(\"Num examples:\", len(dataset))\n", 299 | " print(\"First example:\")\n", 300 | " for message in dataset[0][\"messages\"]:\n", 301 | " print(message)\n", 302 | "\n", 303 | " # Now that we have a sense of the data, we need to go through all the different examples and check to make sure the formatting is correct and matches the Chat completions message structure\n", 304 | "\n", 305 | " # Format error checks\n", 306 | " format_errors = defaultdict(int)\n", 307 | "\n", 308 | " for ex in dataset:\n", 309 | " if not isinstance(ex, dict):\n", 310 | " format_errors[\"data_type\"] += 1\n", 311 | " continue\n", 312 | "\n", 313 | " messages = ex.get(\"messages\", None)\n", 314 | " if not messages:\n", 315 | " format_errors[\"missing_messages_list\"] += 1\n", 316 | " continue\n", 317 | "\n", 318 | " for message in messages:\n", 319 | " if \"role\" not in message or \"content\" not in message:\n", 320 | " format_errors[\"message_missing_key\"] += 1\n", 321 | "\n", 322 | " if any(k not in (\"role\", \"content\", \"name\") for k in message):\n", 323 | " format_errors[\"message_unrecognized_key\"] += 1\n", 324 | "\n", 325 | " if message.get(\"role\", None) not in (\"system\", \"user\", \"assistant\"):\n", 326 | " format_errors[\"unrecognized_role\"] += 1\n", 327 | "\n", 328 | " content = message.get(\"content\", None)\n", 329 | " if not content or not isinstance(content, str):\n", 330 | " format_errors[\"missing_content\"] += 1\n", 331 | "\n", 332 | " if not any(message.get(\"role\", None) == \"assistant\" for message in messages):\n", 333 | " format_errors[\"example_missing_assistant_message\"] += 1\n", 334 | "\n", 335 | " if format_errors:\n", 336 | " print(\"Found errors:\")\n", 337 | " for k, v in format_errors.items():\n", 338 | " print(f\"{k}: {v}\")\n", 339 | " else:\n", 340 | " print(\"No errors found\")\n", 341 | "\n", 342 | " # Beyond the structure of the message, we also need to ensure that the length does not exceed the 4096 token limit.\n", 343 | "\n", 344 | " # Token counting functions\n", 345 | " encoding = tiktoken.get_encoding(\"cl100k_base\")\n", 346 | "\n", 347 | " # not exact!\n", 348 | " # simplified from https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n", 349 | " def num_tokens_from_messages(messages, tokens_per_message=3, tokens_per_name=1):\n", 350 | " num_tokens = 0\n", 351 | " for message in messages:\n", 352 | " num_tokens += tokens_per_message\n", 353 | " for key, value in message.items():\n", 354 | " num_tokens += len(encoding.encode(value))\n", 355 | " if key == \"name\":\n", 356 | " num_tokens += tokens_per_name\n", 357 | " num_tokens += 3\n", 358 | " return num_tokens\n", 359 | "\n", 360 | " def num_assistant_tokens_from_messages(messages):\n", 361 | " num_tokens = 0\n", 362 | " for message in messages:\n", 363 | " if message[\"role\"] == \"assistant\":\n", 364 | " num_tokens += len(encoding.encode(message[\"content\"]))\n", 365 | " return num_tokens\n", 366 | "\n", 367 | " def print_distribution(values, name):\n", 368 | " print(f\"\\n#### Distribution of {name}:\")\n", 369 | " print(f\"min / max: {min(values)}, {max(values)}\")\n", 370 | " print(f\"mean / median: {np.mean(values)}, {np.median(values)}\")\n", 371 | " print(f\"p5 / p95: {np.quantile(values, 0.1)}, {np.quantile(values, 0.9)}\")\n", 372 | "\n", 373 | " # Last, we can look at the results of the different formatting operations before proceeding with creating a fine-tuning job:\n", 374 | "\n", 375 | " # Warnings and tokens counts\n", 376 | " n_missing_system = 0\n", 377 | " n_missing_user = 0\n", 378 | " n_messages = []\n", 379 | " convo_lens = []\n", 380 | " assistant_message_lens = []\n", 381 | "\n", 382 | " for ex in dataset:\n", 383 | " messages = ex[\"messages\"]\n", 384 | " if not any(message[\"role\"] == \"system\" for message in messages):\n", 385 | " n_missing_system += 1\n", 386 | " if not any(message[\"role\"] == \"user\" for message in messages):\n", 387 | " n_missing_user += 1\n", 388 | " n_messages.append(len(messages))\n", 389 | " convo_lens.append(num_tokens_from_messages(messages))\n", 390 | " assistant_message_lens.append(num_assistant_tokens_from_messages(messages))\n", 391 | "\n", 392 | " print(\"Num examples missing system message:\", n_missing_system)\n", 393 | " print(\"Num examples missing user message:\", n_missing_user)\n", 394 | " print_distribution(n_messages, \"num_messages_per_example\")\n", 395 | " print_distribution(convo_lens, \"num_total_tokens_per_example\")\n", 396 | " print_distribution(assistant_message_lens, \"num_assistant_tokens_per_example\")\n", 397 | " n_too_long = sum(l > 16385 for l in convo_lens)\n", 398 | " print(f\"\\n{n_too_long} examples may be over the 16385 token limit, they will be truncated during fine-tuning\")\n", 399 | "\n", 400 | " # Pricing and default n_epochs estimate\n", 401 | " MAX_TOKENS_PER_EXAMPLE = 16385\n", 402 | "\n", 403 | " MIN_TARGET_EXAMPLES = 10\n", 404 | " MAX_TARGET_EXAMPLES = 25000\n", 405 | " TARGET_EPOCHS = 3\n", 406 | " MIN_EPOCHS = 1\n", 407 | " MAX_EPOCHS = 25\n", 408 | "\n", 409 | " n_epochs = TARGET_EPOCHS\n", 410 | " n_train_examples = len(dataset)\n", 411 | " if n_train_examples * TARGET_EPOCHS < MIN_TARGET_EXAMPLES:\n", 412 | " n_epochs = min(MAX_EPOCHS, MIN_TARGET_EXAMPLES // n_train_examples)\n", 413 | " elif n_train_examples * TARGET_EPOCHS > MAX_TARGET_EXAMPLES:\n", 414 | " n_epochs = max(MIN_EPOCHS, MAX_TARGET_EXAMPLES // n_train_examples)\n", 415 | "\n", 416 | " n_billing_tokens_in_dataset = sum(min(MAX_TOKENS_PER_EXAMPLE, length) for length in convo_lens)\n", 417 | " print(f\"Dataset has ~{n_billing_tokens_in_dataset} tokens that will be charged for during training\")\n", 418 | " print(f\"By default, you'll train for {n_epochs} epochs on this dataset\")\n", 419 | " print(f\"By default, you'll be charged for ~{n_epochs * n_billing_tokens_in_dataset} tokens\")\n", 420 | " print(f\"Based on current rate the cost of training is ~ $ {round(n_epochs * n_billing_tokens_in_dataset * 0.008 * 0.001,6)}\")" 421 | ] 422 | }, 423 | { 424 | "cell_type": "code", 425 | "execution_count": 7, 426 | "metadata": {}, 427 | "outputs": [ 428 | { 429 | "name": "stdout", 430 | "output_type": "stream", 431 | "text": [ 432 | "Num examples: 20\n", 433 | "First example:\n", 434 | "{'role': 'system', 'content': 'You are a personal trainer and fitness coach.'}\n", 435 | "{'role': 'user', 'content': 'I ate eggs and ran half a mile'}\n", 436 | "{'role': 'assistant', 'content': 'ran half a mileeggsNice!'}\n", 437 | "No errors found\n" 438 | ] 439 | }, 440 | { 441 | "name": "stderr", 442 | "output_type": "stream", 443 | "text": [ 444 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", 445 | " warnings.warn(\n" 446 | ] 447 | }, 448 | { 449 | "name": "stdout", 450 | "output_type": "stream", 451 | "text": [ 452 | "Num examples missing system message: 0\n", 453 | "Num examples missing user message: 0\n", 454 | "\n", 455 | "#### Distribution of num_messages_per_example:\n", 456 | "min / max: 3, 3\n", 457 | "mean / median: 3.0, 3.0\n", 458 | "p5 / p95: 3.0, 3.0\n", 459 | "\n", 460 | "#### Distribution of num_total_tokens_per_example:\n", 461 | "min / max: 55, 63\n", 462 | "mean / median: 59.45, 59.0\n", 463 | "p5 / p95: 57.8, 62.0\n", 464 | "\n", 465 | "#### Distribution of num_assistant_tokens_per_example:\n", 466 | "min / max: 24, 29\n", 467 | "mean / median: 26.2, 26.0\n", 468 | "p5 / p95: 24.9, 28.0\n", 469 | "\n", 470 | "0 examples may be over the 16385 token limit, they will be truncated during fine-tuning\n", 471 | "Dataset has ~1189 tokens that will be charged for during training\n", 472 | "By default, you'll train for 3 epochs on this dataset\n", 473 | "By default, you'll be charged for ~3567 tokens\n", 474 | "Based on current rate the cost of training is ~ $ 0.028536\n" 475 | ] 476 | } 477 | ], 478 | "source": [ 479 | "# Verify the data file\n", 480 | "verify_data('data.jsonl')" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "# Step 5: Upload Data to OpenAI Servers" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": 8, 493 | "metadata": {}, 494 | "outputs": [], 495 | "source": [ 496 | "\n", 497 | "def upload_data_to_openai(file_path):\n", 498 | " upload_response = client.files.create(\n", 499 | " file=open(file_path, \"rb\"),\n", 500 | " purpose=\"fine-tune\"\n", 501 | " )\n", 502 | " \n", 503 | " file_id = upload_response.id\n", 504 | " print(f\"File upload complete. ID: {file_id}\")\n", 505 | "\n", 506 | " return file_id" 507 | ] 508 | }, 509 | { 510 | "cell_type": "code", 511 | "execution_count": 9, 512 | "metadata": {}, 513 | "outputs": [ 514 | { 515 | "name": "stdout", 516 | "output_type": "stream", 517 | "text": [ 518 | "File upload complete. ID: file-zHaVEsMNEqxYX1oYKDpEUoze\n" 519 | ] 520 | } 521 | ], 522 | "source": [ 523 | "file_id = upload_data_to_openai('data.jsonl')" 524 | ] 525 | }, 526 | { 527 | "cell_type": "markdown", 528 | "metadata": {}, 529 | "source": [ 530 | "# Step 6 & 7: Train and monitor a new fine-tuned model\n", 531 | "* We will recieve an email notification when the training job is complete\n", 532 | "* We can monitor progress on [OpenAI Portal under the finetuning tab](https://platform.openai.com/finetune).\n", 533 | "* We can also monitor progress using a [Weights and Biases](https://wandb.ai/site) integration" 534 | ] 535 | }, 536 | { 537 | "cell_type": "code", 538 | "execution_count": 10, 539 | "metadata": {}, 540 | "outputs": [], 541 | "source": [ 542 | "def start_finetuning(file_id, n_epochs):\n", 543 | " job = client.fine_tuning.jobs.create(\n", 544 | " training_file=file_id, \n", 545 | " model=\"gpt-3.5-turbo-0125\",\n", 546 | " hyperparameters={\n", 547 | " \"n_epochs\":n_epochs\n", 548 | " }\n", 549 | " )\n", 550 | "\n", 551 | " job_id = job.id\n", 552 | " print(f'Fine-tuning job successfully started: {job_id}')\n", 553 | "\n", 554 | " return job_id" 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 11, 560 | "metadata": {}, 561 | "outputs": [ 562 | { 563 | "name": "stdout", 564 | "output_type": "stream", 565 | "text": [ 566 | "Fine-tuning job successfully started: ftjob-Y7Ts51nqb7vOKCDVDPUyJOG3\n" 567 | ] 568 | } 569 | ], 570 | "source": [ 571 | "job_id = start_finetuning(file_id, 3)" 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": 14, 577 | "metadata": {}, 578 | "outputs": [ 579 | { 580 | "data": { 581 | "text/plain": [ 582 | "FineTuningJob(id='ftjob-Y7Ts51nqb7vOKCDVDPUyJOG3', created_at=1721097136, error=Error(code=None, message=None, param=None), fine_tuned_model='ft:gpt-3.5-turbo-0125:personal::9lSMdXeW', finished_at=1721097474, hyperparameters=Hyperparameters(n_epochs=3, batch_size=1, learning_rate_multiplier=2), model='gpt-3.5-turbo-0125', object='fine_tuning.job', organization_id='org-qXIGb538HTtKmSiCKxVtZbGD', result_files=['file-GzzziUysRJRmsoNblsMRsE22'], seed=1209432246, status='succeeded', trained_tokens=3447, training_file='file-zHaVEsMNEqxYX1oYKDpEUoze', validation_file=None, estimated_finish=None, integrations=[], user_provided_suffix=None)" 583 | ] 584 | }, 585 | "execution_count": 14, 586 | "metadata": {}, 587 | "output_type": "execute_result" 588 | } 589 | ], 590 | "source": [ 591 | "# check status of fine-tuning job\n", 592 | "client.fine_tuning.jobs.retrieve(job_id)" 593 | ] 594 | }, 595 | { 596 | "cell_type": "markdown", 597 | "metadata": {}, 598 | "source": [ 599 | "# Step 8: Evaluating the fine-tuned model\n", 600 | "* Once the training job is complete, we can test our finetuned model using [OpenAI's Playground GUI](https://platform.openai.com/playground?mode=chat)\n", 601 | "* We can also use the fine-tuned model via the OpenAI API." 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": 5, 607 | "metadata": {}, 608 | "outputs": [], 609 | "source": [ 610 | "# utility for testing your fine-tuned model\n", 611 | "def test_model(model_id, system_role, prompt):\n", 612 | " response = client.chat.completions.create(\n", 613 | " model=model_id,\n", 614 | " messages=[\n", 615 | " {\"role\": \"system\", \"content\": f\"{system_role}\"},\n", 616 | " {\"role\": \"user\", \"content\": f\"{prompt}\"}\n", 617 | " ]\n", 618 | " )\n", 619 | "\n", 620 | " return_message = response.choices[0].message.content\n", 621 | "\n", 622 | " return return_message\n" 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": 6, 628 | "metadata": {}, 629 | "outputs": [ 630 | { 631 | "name": "stdout", 632 | "output_type": "stream", 633 | "text": [ 634 | "hiked for 3 milespizzaNice!\n" 635 | ] 636 | } 637 | ], 638 | "source": [ 639 | "# model_id can be obtained from https://platform.openai.com/finetune/\n", 640 | "model_id = \"ft:gpt-3.5-turbo-0125:personal::9liQwOAm\"\n", 641 | "\n", 642 | "# This is the same role used for training\n", 643 | "system_role = \"You are a personal trainer and fitness coach.\"\n", 644 | "\n", 645 | "# this is a test question\n", 646 | "prompt = \"I ate pizza and hiked for 3 miles?\"\n", 647 | "\n", 648 | "# Test system Response\n", 649 | "response = test_model(\n", 650 | " model_id,\n", 651 | " system_role,\n", 652 | " prompt\n", 653 | " )\n", 654 | "\n", 655 | "print(response)" 656 | ] 657 | }, 658 | { 659 | "cell_type": "markdown", 660 | "metadata": {}, 661 | "source": [ 662 | "# Final Exercise 🚀\n", 663 | "\n", 664 | "* Fine-Tune GPT3.5 Turbo using OpenAI's Fine-Tuning API\n", 665 | " * You can adjust the default behavior of myfitnessagent, add pre or post scripts, or change the formatting of the outputs.\n", 666 | " * Generate your training dataset and save it in a JSONL format.\n", 667 | " * Verify the data file, upload it, and start the fine-tuning job.\n", 668 | " * Test the fine-tuned model to see if it works" 669 | ] 670 | }, 671 | { 672 | "cell_type": "code", 673 | "execution_count": null, 674 | "metadata": {}, 675 | "outputs": [], 676 | "source": [] 677 | } 678 | ], 679 | "metadata": { 680 | "kernelspec": { 681 | "display_name": "venv", 682 | "language": "python", 683 | "name": "python3" 684 | }, 685 | "language_info": { 686 | "codemirror_mode": { 687 | "name": "ipython", 688 | "version": 3 689 | }, 690 | "file_extension": ".py", 691 | "mimetype": "text/x-python", 692 | "name": "python", 693 | "nbconvert_exporter": "python", 694 | "pygments_lexer": "ipython3", 695 | "version": "3.9.6" 696 | } 697 | }, 698 | "nbformat": 4, 699 | "nbformat_minor": 2 700 | } 701 | -------------------------------------------------------------------------------- /sessions/session_4/notebooks/rag_huggingface.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# !pip install -q torch transformers accelerate transformers sentence-transformers faiss-cpu" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# !pip install -q langchain langchain-community" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stderr", 28 | "output_type": "stream", 29 | "text": [ 30 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", 31 | " warnings.warn(\n", 32 | "Ignoring wrong pointing object 6 0 (offset 0)\n", 33 | "Ignoring wrong pointing object 8 0 (offset 0)\n", 34 | "Ignoring wrong pointing object 11 0 (offset 0)\n", 35 | "Ignoring wrong pointing object 29 0 (offset 0)\n", 36 | "Ignoring wrong pointing object 6 0 (offset 0)\n", 37 | "Ignoring wrong pointing object 8 0 (offset 0)\n", 38 | "Ignoring wrong pointing object 11 0 (offset 0)\n", 39 | "Ignoring wrong pointing object 29 0 (offset 0)\n", 40 | "Ignoring wrong pointing object 6 0 (offset 0)\n", 41 | "Ignoring wrong pointing object 8 0 (offset 0)\n", 42 | "Ignoring wrong pointing object 11 0 (offset 0)\n", 43 | "Ignoring wrong pointing object 29 0 (offset 0)\n", 44 | "Ignoring wrong pointing object 6 0 (offset 0)\n", 45 | "Ignoring wrong pointing object 8 0 (offset 0)\n", 46 | "Ignoring wrong pointing object 11 0 (offset 0)\n", 47 | "Ignoring wrong pointing object 30 0 (offset 0)\n", 48 | "Ignoring wrong pointing object 6 0 (offset 0)\n", 49 | "Ignoring wrong pointing object 8 0 (offset 0)\n", 50 | "Ignoring wrong pointing object 11 0 (offset 0)\n", 51 | "Ignoring wrong pointing object 29 0 (offset 0)\n" 52 | ] 53 | }, 54 | { 55 | "data": { 56 | "text/plain": [ 57 | "[Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 0}, page_content='Paleo Diet Nutrition Plan The Paleo diet is beneficial for: • Weight loss: Promotes lean body mass and reduces body fat • Improved insulin sensitivity: May help manage or prevent type 2 diabetes • Reduced inflammation: Can alleviate symptoms of autoimmune diseases • Better digestion: Eliminates common gut irritants • Increased nutrient density: Focuses on whole, nutrient-rich foods • Improved energy levels: Stable blood sugar leads to consistent energy • Better sleep: May improve sleep quality due to reduced inflammation This diet is ideal for: • Individuals looking to lose weight or maintain a healthy weight • People with autoimmune conditions or inflammatory disorders • Those seeking to improve overall health and energy levels • Individuals with digestive issues or food sensitivities • People interested in a whole-food based approach to eating • Athletes and fitness enthusiasts looking for performance benefits '),\n", 58 | " Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 1}, page_content='Paleo Breakfast Options: a) Paleo breakfast bowl: • 2 eggs, fried or poached • 1/4 avocado, sliced • 1/2 cup sautéed mixed vegetables (spinach, mushrooms, bell peppers) • 2 slices of bacon (uncured, no added nitrates) • 1/4 cup berries on the side b) Sweet potato hash: • 1 small sweet potato, diced and roasted • 3 oz ground turkey or chicken, seasoned and cooked • 1/4 cup diced onions • 1/4 cup diced bell peppers • 1 tbsp coconut oil for cooking • Herbs: rosemary, thyme c) Paleo smoothie: • 1 cup unsweetened almond milk • 1/2 banana • 1 tbsp almond butter • 1 scoop paleo-friendly protein powder • 1 cup spinach • 1/2 cup mixed berries • Ice cubes '),\n", 59 | " Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 2}, page_content='Paleo Lunch Options: a) Grilled chicken salad: • 4 oz grilled chicken breast • 2 cups mixed greens • 1/4 cup sliced cucumbers • 1/4 cup cherry tomatoes • 1/4 avocado, diced • 2 tbsp pumpkin seeds • Dressing: 1 tbsp olive oil, 1 tsp lemon juice, herbs b) Tuna lettuce wraps: • 4 oz canned tuna (in water) • 1 tbsp paleo-friendly mayonnaise • 1 tbsp diced celery • 1 tbsp diced red onion • 1 tsp dijon mustard • Serve in 3-4 large lettuce leaves c) Beef and vegetable stir-fry: • 4 oz grass-fed beef strips • 1 cup mixed vegetables (broccoli, carrots, snap peas) • 1 tbsp coconut aminos • 1 tbsp coconut oil for cooking • 1 clove garlic, minced • Serve over cauliflower rice '),\n", 60 | " Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 3}, page_content='Paleo Dinner Options: a) Baked salmon with roasted vegetables: • 5 oz wild-caught salmon fillet • 1 cup mixed roasted vegetables (Brussels sprouts, carrots, parsnips) • 1 tbsp olive oil for roasting • Lemon wedge and fresh dill for garnish b) Grilled steak with sweet potato: • 4 oz grass-fed sirloin steak • 1 small sweet potato, baked • 1 cup steamed broccoli • 1 tbsp ghee (for sweet potato) • Herbs: rosemary, thyme c) Paleo chicken fajita bowl: • 4 oz grilled chicken breast, sliced • 1/2 cup bell peppers and onions, sautéed • 1/4 cup guacamole • 1/4 cup fresh salsa • Serve over 1 cup cauliflower rice • Garnish with cilantro '),\n", 61 | " Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 4}, page_content='Paleo Snack Options: a) Fresh fruit with nuts: • 1 medium apple or pear • 10 almonds or walnuts b) Vegetable sticks with guacamole: • 1 cup mixed vegetable sticks (carrots, cucumbers, bell peppers) • 2 tbsp guacamole c) Hard-boiled eggs: • 2 hard-boiled eggs • Sprinkle of sea salt and pepper d) Beef or turkey jerky: • 1 oz grass-fed beef or turkey jerky (no added sugars or preservatives) e) Paleo energy balls: • 1/4 cup dates • 1/4 cup nuts (almonds or cashews) • 1 tbsp cocoa powder • 1 tbsp coconut oil • Blend and form into 2-3 small balls '),\n", 62 | " Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 5}, page_content='Paleo General Guidelines: • Focus on whole, unprocessed foods • Consume plenty of vegetables and moderate amounts of fruit • Include high-quality proteins (grass-fed, free-range, wild-caught) • Use healthy fats like olive oil, coconut oil, avocado, and nuts • Eliminate grains, legumes, dairy, and processed foods • Avoid added sugars and artificial sweeteners • Limit alcohol consumption Paleo Weekly Meal Prep Tips: • Grill or roast a variety of meats for easy protein options • Prepare a large batch of roasted vegetables • Make cauliflower rice for quick side dishes • Hard boil eggs for snacks and salad toppings • Chop vegetables for quick stir-fries or snacks • Prepare homemade salad dressings and sauces Adjusting Portion Sizes: Adjust portion sizes based on individual caloric needs, activity level, and weight management goals. The Paleo diet typically leads to natural portion control due to its focus on nutrient-dense, satiating foods. Paleo Important Considerations: • The initial transition may be challenging due to the elimination of common food groups • Ensure adequate calcium intake through non-dairy sources like leafy greens and bone broth • Be mindful of potential vitamin D deficiency, especially if limiting sun exposure • Some may need to adjust carbohydrate intake based on activity levels • Consider consulting with a registered dietitian to ensure nutritional needs are met '),\n", 63 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 0}, page_content='Gluten-Free Diet Nutrition Plan The Gluten-Free diet is beneficial for: • Celiac disease management: Essential for those with celiac disease • Non-celiac gluten sensitivity: Alleviates symptoms in sensitive individuals • Wheat allergy management: Necessary for those with wheat allergies • Digestive health: May improve gut health in some individuals • Reduced inflammation: Can help reduce inflammation in certain cases • Increased energy: Some report improved energy levels • Clearer skin: May help with certain skin conditions in some people This diet is ideal for: • Individuals diagnosed with celiac disease • People with non-celiac gluten sensitivity • Those with wheat allergies • Individuals looking to eliminate gluten for personal health reasons • People with certain autoimmune disorders (under medical supervision) • Those experiencing unexplained digestive issues (after proper medical evaluation) '),\n", 64 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 1}, page_content='Detailed Meal Plan Gluten-Free Breakfast Options: a) Gluten-free oatmeal bowl: • 1/2 cup certified gluten-free oats • 1 cup almond milk • 1 tbsp chia seeds • 1/4 cup mixed berries • 1 tbsp almond butter • 1 tsp honey b) Veggie and cheese omelette: • 2 eggs • 1/4 cup mixed vegetables (spinach, bell peppers, tomatoes) • 1 oz shredded cheddar cheese • Serve with 1 slice gluten-free toast c) Smoothie bowl: • Blend: 1 banana, 1/2 cup frozen berries, 1/2 cup Greek yogurt, 1/4 cup almond milk • Top with 2 tbsp gluten-free granola and 1 tbsp pumpkin seeds '),\n", 65 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 2}, page_content='Gluten-Free Lunch Options: a) Quinoa salad: • 1/2 cup cooked quinoa • 2 cups mixed greens • 1/4 cup chickpeas • 1/4 avocado, diced • 1/4 cup cherry tomatoes • 2 tbsp feta cheese • Dressing: 1 tbsp olive oil, 1 tsp lemon juice b) Gluten-free wrap: • 1 large gluten-free tortilla • 3 oz grilled chicken breast • 1/4 cup lettuce • 2 tbsp hummus • 1/4 cup sliced cucumbers and tomatoes c) Lentil soup: • 1 cup lentil soup (ensure broth is gluten-free) • Serve with gluten-free crackers • Side salad with mixed greens and vinaigrette '),\n", 66 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 3}, page_content='Gluten-Free Dinner Options: a) Grilled salmon with roasted vegetables: • 4 oz grilled salmon • 1 cup mixed roasted vegetables (zucchini, bell peppers, carrots) • 1/2 cup cooked brown rice • 1 tbsp olive oil for cooking b) Gluten-free pasta primavera: • 1 cup cooked gluten-free pasta • 1 cup mixed sautéed vegetables (broccoli, peas, asparagus) • 2 tbsp olive oil • 1 clove garlic, minced • 2 tbsp grated Parmesan cheese c) Stir-fry with rice: • 3 oz chicken or tofu, cubed • 1 cup mixed vegetables (snap peas, carrots, mushrooms) • 1/2 cup cooked brown rice • 1 tbsp gluten-free soy sauce or tamari • 1 tsp sesame oil '),\n", 67 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 4}, page_content='Gluten-Free Snack Options: a) Fresh fruit with nuts: • 1 apple or pear • 10 almonds b) Vegetable sticks with hummus: • 1 cup mixed vegetable sticks (carrots, cucumbers, bell peppers) • 2 tbsp hummus c) Greek yogurt parfait: • 1/2 cup Greek yogurt • 1/4 cup mixed berries • 1 tbsp gluten-free granola d) Rice cakes with toppings: • 2 rice cakes • 1 tbsp almond butter • Sliced banana e) Gluten-free energy balls: • 1/4 cup dates • 1/4 cup nuts (almonds or cashews) • 1 tbsp cocoa powder • 1 tbsp coconut oil • Blend and form into 2-3 small balls '),\n", 68 | " Document(metadata={'source': '../pdfs/glutenfree_internal_plan.pdf', 'page': 5}, page_content=\"Gluten-Free General Guidelines: • Avoid all sources of gluten (wheat, barley, rye, and contaminated oats) • Read labels carefully to identify hidden sources of gluten • Focus on naturally gluten-free whole foods • Choose certified gluten-free products when buying packaged foods • Be cautious of cross-contamination in food preparation • Ensure balanced nutrition by including a variety of foods • Consider gluten-free whole grains like quinoa, rice, and millet Gluten-Free Weekly Meal Prep Tips: • Cook large batches of gluten-free grains (rice, quinoa) • Prepare gluten-free snacks in advance • Chop vegetables for quick meal assembly • Make homemade gluten-free dressings and sauces • Prepare mason jar salads for easy lunches • Batch cook gluten-free proteins (chicken, tofu) for quick meals Adjusting Portion Sizes: Adjust portion sizes based on individual caloric needs, activity level, and weight management goals. A gluten-free diet isn't inherently lower in calories, so portion control is important if weight management is a goal. Gluten-Free Important Considerations: • Ensure adequate fiber intake, as many gluten-free alternatives are lower in fiber • Be mindful of potential nutritional deficiencies, especially if new to the diet • Some gluten-free products may be higher in sugar or fat; read labels carefully • Consider supplements if concerned about nutrient intake, especially B vitamins • Be cautious when dining out; always inform staff of gluten-free needs • Consult with a registered dietitian to ensure nutritional needs are met \"),\n", 69 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 0}, page_content='Ketogenic Diet Nutrition Plan The Low-carb/Ketogenic diet is beneficial for: • Weight loss: Promotes rapid fat loss • Blood sugar control: Helps manage type 2 diabetes and insulin resistance • Improved mental clarity: Some report enhanced cognitive function • Reduced inflammation: May help with certain inflammatory conditions • Epilepsy management: Used therapeutically for some seizure disorders • Potential neuroprotective effects: Being studied for neurodegenerative diseases This diet is ideal for: • Individuals looking for rapid weight loss • People with type 2 diabetes or prediabetes • Those seeking to improve metabolic health • Individuals with certain neurological disorders • People who struggle with sugar cravings and overeating '),\n", 70 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 1}, page_content='Detailed Meal Plan Ketogenic Breakfast Options: a) Keto breakfast bowl: • 2 scrambled eggs • 1/4 avocado, sliced • 2 strips of bacon • 1/4 cup sautéed spinach • 1 tbsp butter for cooking b) Cream cheese pancakes: • 2 oz cream cheese • 2 eggs • 1/4 tsp cinnamon • 1 tbsp butter for cooking • Top with 2 tbsp sugar-free syrup c) Keto smoothie: • 1 cup unsweetened almond milk • 1/2 avocado • 1 tbsp almond butter • 1 scoop low-carb protein powder • 1 cup spinach • Ice cubes '),\n", 71 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 2}, page_content='Ketogenic Lunch Options: a) Cobb salad: • 2 cups mixed greens • 3 oz grilled chicken breast • 1 hard-boiled egg, sliced • 2 slices bacon, crumbled • 1/4 avocado, diced • 2 tbsp blue cheese crumbles • 2 tbsp high-fat dressing (ranch or blue cheese) b) Tuna salad lettuce wraps: • 4 oz canned tuna • 2 tbsp mayonnaise • 1 tbsp diced celery • 1 tsp dijon mustard • Salt and pepper to taste • Serve in 3-4 large lettuce leaves c) Zucchini noodles with meatballs: • 2 cups zucchini noodles • 3 oz ground beef meatballs (2-3 meatballs) • 1/4 cup low-carb marinara sauce • 2 tbsp grated parmesan cheese • 1 tbsp olive oil for cooking '),\n", 72 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 3}, page_content='Ketogenic Dinner Options: a) Baked salmon with asparagus: • 5 oz salmon fillet • 1 cup asparagus spears • 2 tbsp butter • Lemon wedge and dill for garnish • Season with salt and pepper b) Chicken fajita bowl: • 4 oz grilled chicken breast, sliced • 1/2 cup bell peppers and onions, sautéed • 1/4 cup guacamole • 2 tbsp sour cream • 1/4 cup shredded cheddar cheese • Serve over 1 cup cauliflower rice c) Beef and broccoli stir-fry: • 4 oz beef sirloin, sliced • 1 cup broccoli florets • 2 tbsp soy sauce (or coconut aminos for lower carb) • 1 tbsp sesame oil • 1 clove garlic, minced • Serve over 1/2 cup cauliflower rice '),\n", 73 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 4}, page_content='Ketogenic Snack Options: a) Cheese and meat roll-ups: • 2 slices of cheese • 2 slices of deli meat (turkey, ham, or roast beef) • Optional: add pickle spear or avocado slice b) Deviled eggs: • 2 hard-boiled eggs, halved • Yolks mixed with 1 tbsp mayonnaise and 1/2 tsp mustard c) Keto fat bombs: • 1 tbsp coconut oil • 1 tbsp almond butter • 1 tsp cocoa powder • Stevia to taste • Mix, freeze, and enjoy 2-3 small fat bombs d) Celery sticks with cream cheese: • 3-4 celery sticks • 2 tbsp full-fat cream cheese e) Handful of mixed nuts (1 oz): • Almonds, macadamia nuts, walnuts '),\n", 74 | " Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 5}, page_content='Ketogenic General Guidelines: • Limit carbohydrate intake to 20-50g per day (varies by individual) • Increase healthy fat intake to 70-80% of total calories • Maintain moderate protein intake (about 20-25% of calories) • Avoid all grains, sugar, and starchy vegetables • Stay hydrated and consider supplementing electrolytes • Monitor ketone levels if desired (through urine strips or blood meters) Ketogenic Weekly Meal Prep Tips: • Hard boil a dozen eggs for quick snacks and meals • Pre-cook chicken breasts or thighs for easy protein addition • Prepare mason jar salads for grab-and-go lunches • Make a large batch of cauliflower rice • Chop low-carb vegetables for quick stir-fries or snacks Adjusting Portion Sizes: Adjust portion sizes based on individual caloric needs, activity level, and weight loss goals. It\\'s crucial to maintain the correct macronutrient ratios (high fat, low carb, moderate protein) regardless of portion size. Ketogenic Important Considerations: • The initial transition to a ketogenic diet may cause \"keto flu\" symptoms • This diet may not be suitable for everyone, especially those with certain medical conditions • Regular monitoring by a healthcare professional is recommended, especially for those on medications '),\n", 75 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 0}, page_content='Mediterranean Diet Nutrition Plan The Mediterranean diet is beneficial for: • Heart health: Reduces risk of cardiovascular diseases • Weight management: Promotes healthy weight loss and maintenance • Brain function: May improve cognitive function and reduce risk of neurodegenerative diseases • Diabetes management: Helps control blood sugar levels • Cancer prevention: May reduce risk of certain types of cancer • Longevity: Associated with increased lifespan This diet is ideal for: • Individuals looking to improve overall health • Those at risk of heart disease or stroke • People wanting to lose weight sustainably • Anyone interested in adopting a balanced, flavorful eating pattern '),\n", 76 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 1}, page_content='Meal Plan Mediterranean Breakfast Options: a) Greek yogurt parfait: • 1 cup Greek yogurt • 1/4 cup mixed berries • 1 tbsp honey • 2 tbsp chopped walnuts • Sprinkle of cinnamon b) Whole grain toast with avocado and egg: • 2 slices whole grain bread, toasted • 1/2 avocado, mashed • 2 poached eggs • Drizzle of extra virgin olive oil • Salt and pepper to taste c) Mediterranean breakfast bowl: • 1/2 cup cooked quinoa • 1/4 cup chickpeas • 1/4 cup diced cucumber • 1/4 cup diced tomatoes • 2 tbsp crumbled feta cheese • 1 tbsp chopped fresh herbs (parsley, mint) • Drizzle of lemon juice and olive oil '),\n", 77 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 2}, page_content='Mediterranean Lunch Options: a) Greek salad with grilled chicken: • 2 cups mixed greens • 3 oz grilled chicken breast • 1/4 cup diced cucumber • 1/4 cup diced tomatoes • 1/4 cup sliced red onion • 10 kalamata olives • 2 tbsp crumbled feta cheese • Dressing: 1 tbsp olive oil, 1 tsp red wine vinegar, oregano b) Mediterranean tuna wrap: • 1 whole wheat tortilla • 3 oz canned tuna in olive oil, drained • 1/4 cup diced bell peppers • 2 tbsp hummus • Handful of spinach leaves • 1 tbsp chopped sun-dried tomatoes c) Lentil and vegetable soup: • 1 cup cooked lentils • 1 cup mixed vegetables (carrots, celery, onions, tomatoes) • 2 cups vegetable broth • 1 tbsp olive oil • Herbs: bay leaf, thyme, rosemary • Serve with a slice of whole grain bread '),\n", 78 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 3}, page_content='Mediterranean Dinner Options: a) Baked salmon with roasted vegetables: • 4 oz baked salmon fillet • 1 cup mixed roasted vegetables (zucchini, bell peppers, eggplant) • 1/2 cup quinoa • 1 tbsp olive oil for roasting • Lemon wedge and fresh dill for garnish b) Mediterranean stuffed peppers: • 1 large bell pepper, halved and stuffed with: o 1/2 cup cooked brown rice o 1/4 cup cooked lentils o 2 tbsp chopped tomatoes o 1 tbsp chopped olives o 1 tbsp crumbled feta cheese • Bake until pepper is tender • Serve with a side salad of mixed greens and olive oil dressing c) Grilled vegetable and chicken skewers: • 3 oz chicken breast, cubed • 1 cup mixed vegetables for skewers (cherry tomatoes, zucchini, red onion) • 1 tbsp olive oil for brushing • Mediterranean spice mix (oregano, basil, garlic powder) • Serve with 1/2 cup tzatziki sauce and 1/2 cup tabbouleh '),\n", 79 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 4}, page_content='Mediterranean Snack Options: a) Fresh fruit with nuts: • 1 medium apple or pear • 10 almonds or walnuts b) Vegetable sticks with hummus: • 1 cup mixed vegetable sticks (carrots, cucumbers, bell peppers) • 2 tbsp homemade or store-bought hummus c) Greek yogurt with honey: • 1/2 cup Greek yogurt • 1 tsp honey • Sprinkle of cinnamon d) Olive tapenade with whole grain crackers: • 2 tbsp olive tapenade • 5-6 whole grain crackers e) Handful of mixed olives '),\n", 80 | " Document(metadata={'source': '../pdfs/mediterranean_internal_plan.pdf', 'page': 5}, page_content='Mediterranean General Guidelines: • Use extra virgin olive oil as the primary source of added fat • Consume fish and poultry at least twice a week • Limit red meat to no more than a few times per month • Enjoy fresh fruits as dessert instead of sugary sweets • Drink red wine in moderation (optional, and only for those who already drink alcohol) • Stay hydrated with water as the primary beverage Mediterranean Weekly Meal Prep Tips: • Prepare large batches of whole grains and legumes • Chop vegetables in advance for quick salads and cooking • Make homemade hummus and tzatziki sauce for the week • Marinate chicken or fish for easy grilling throughout the week Adjusting Portion Sizes: Adjust portion sizes based on individual caloric needs, activity level, and weight management goals. Consult with a registered dietitian for personalized advice. '),\n", 81 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 0}, page_content='Vegan Diet Nutrition Plan The Vegan diet is beneficial for: • Environmental sustainability: Reduces carbon footprint • Animal welfare: Eliminates animal product consumption • Heart health: May lower risk of heart disease • Weight management: Often leads to lower BMI • Reduced cancer risk: May lower risk of certain cancers • Blood sugar control: Can help manage type 2 diabetes • Improved digestion: High fiber content aids digestive health This diet is ideal for: • Environmentally conscious individuals • Those concerned with animal rights • People looking to reduce risk of certain chronic diseases • Individuals seeking to increase plant food consumption • Those with lactose intolerance or dairy allergies • Anyone interested in exploring diverse plant-based cuisine '),\n", 82 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 1}, page_content='Vegan Breakfast Options: a) Tofu scramble: • 1/2 block firm tofu, crumbled • 1/4 cup mixed vegetables (bell peppers, onions, spinach) • 1 tbsp nutritional yeast • 1/4 tsp turmeric • Salt and pepper to taste • Serve with 1 slice whole grain toast b) Overnight oats: • 1/2 cup rolled oats • 3/4 cup plant-based milk (almond, soy, oat) • 1 tbsp chia seeds • 1 tbsp maple syrup • 1/4 cup mixed berries • 1 tbsp chopped nuts c) Vegan breakfast smoothie: • 1 banana • 1 cup spinach • 1 tbsp almond butter • 1 scoop vegan protein powder • 1 cup plant-based milk • 1/2 tsp cinnamon '),\n", 83 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 2}, page_content='Vegan Lunch Options: a) Chickpea salad sandwich: • 1/2 cup mashed chickpeas • 1 tbsp vegan mayonnaise • 1 tsp dijon mustard • 1 tbsp diced celery • 1 tbsp diced red onion • Serve on 2 slices whole grain bread with lettuce and tomato b) Quinoa buddha bowl: • 1/2 cup cooked quinoa • 1/4 cup roasted chickpeas • 1/2 cup mixed roasted vegetables (sweet potato, broccoli, carrots) • 1/4 avocado, sliced • 2 tbsp hummus • Handful of spinach • 1 tbsp tahini dressing c) Lentil and vegetable soup: • 1/2 cup cooked lentils • 1 cup mixed vegetables (carrots, celery, onions, tomatoes) • 2 cups vegetable broth • 1 tbsp olive oil • Herbs: bay leaf, thyme, rosemary • Serve with a slice of whole grain bread '),\n", 84 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 3}, page_content='Vegan Dinner Options: a) Stir-fried tofu and vegetables: • 4 oz firm tofu, cubed • 1 cup mixed vegetables (broccoli, snap peas, carrots) • 1 tbsp soy sauce or tamari • 1 tsp sesame oil • 1 clove garlic, minced • Serve over 1/2 cup brown rice b) Vegan chili: • 1/2 cup mixed beans (black beans, kidney beans) • 1/4 cup textured vegetable protein (TVP) or crumbled tempeh • 1/2 cup diced tomatoes • 1/4 cup diced onions and peppers • Chili spices (cumin, paprika, chili powder) • Top with vegan sour cream and chopped cilantro c) Whole wheat pasta primavera: • 1 cup whole wheat pasta • 1 cup mixed vegetables (zucchini, cherry tomatoes, asparagus) • 2 tbsp olive oil • 1 clove garlic, minced • 2 tbsp nutritional yeast • Fresh basil for garnish '),\n", 85 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 4}, page_content='Vegan Snack Options: a) Fresh fruit with nut butter: • 1 apple or banana • 1 tbsp almond or peanut butter b) Vegetable sticks with hummus: • 1 cup mixed vegetable sticks (carrots, cucumbers, bell peppers) • 2 tbsp hummus c) Trail mix: • 1/4 cup mixed nuts (almonds, walnuts, cashews) • 2 tbsp dried fruits (raisins, goji berries) • 1 tbsp pumpkin seeds d) Roasted chickpeas: • 1/4 cup roasted chickpeas seasoned with spices e) Vegan yogurt parfait: • 1/2 cup plant-based yogurt • 2 tbsp granola • 1/4 cup mixed berries '),\n", 86 | " Document(metadata={'source': '../pdfs/vegan_internal_plan.pdf', 'page': 5}, page_content=\"Vegan General Guidelines: • Focus on whole, plant-based foods • Ensure adequate protein intake through legumes, tofu, tempeh, and plant-based protein powders • Include a variety of fruits and vegetables for diverse nutrient intake • Incorporate whole grains for fiber and B vitamins • Use healthy fats from sources like avocados, nuts, and seeds • Consider supplements for vitamin B12, vitamin D, and omega-3 fatty acids Vegan Weekly Meal Prep Tips: • Cook large batches of grains and legumes • Prepare homemade hummus and plant-based dressings • Chop vegetables for quick stir-fries and salads • Make a big pot of vegan soup or chili for the week • Prepare overnight oats in jars for easy breakfasts Adjusting Portion Sizes: Adjust portion sizes based on individual caloric needs, activity level, and weight management goals. Vegan diets can be adapted for weight loss or gain by adjusting portion sizes and the ratio of higher-calorie foods (nuts, seeds, avocados) to lower-calorie options (leafy greens, non-starchy vegetables). Vegan Important Considerations: • Pay attention to vitamin B12 intake, as it's not naturally present in plant foods • Ensure adequate calcium intake through fortified plant milks and leafy greens • Consider iron supplementation, especially for menstruating individuals • Combine iron-rich foods with vitamin C sources for better absorption • Consult with a registered dietitian to ensure all nutritional needs are met \")]" 87 | ] 88 | }, 89 | "execution_count": 1, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "from langchain_community.document_loaders import PyPDFLoader\n", 96 | "import os\n", 97 | "\n", 98 | "\n", 99 | "# loop through PDFs and load them with PyPDFLoader\n", 100 | "file_path = \"../pdfs\"\n", 101 | "docs = []\n", 102 | "for file in os.listdir(file_path):\n", 103 | " if file.endswith('.pdf'):\n", 104 | " pdf_path = os.path.join(file_path, file)\n", 105 | " loader = PyPDFLoader(pdf_path)\n", 106 | " docs.extend(loader.load())\n", 107 | "\n", 108 | "docs" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 2, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/plain": [ 119 | "'Paleo Lunch Options: a) Grilled chicken salad: • 4 oz grilled chicken breast • 2 cups mixed greens • 1/4 cup sliced cucumbers • 1/4 cup cherry tomatoes • 1/4 avocado, diced • 2 tbsp pumpkin seeds • Dressing: 1 tbsp olive oil, 1 tsp lemon juice, herbs b) Tuna lettuce wraps: • 4 oz canned tuna (in water) • 1 tbsp paleo-friendly mayonnaise • 1 tbsp diced celery • 1 tbsp diced red onion • 1 tsp dijon mustard • Serve in 3-4 large lettuce leaves c) Beef and vegetable stir-fry: • 4 oz grass-fed beef strips • 1 cup mixed vegetables (broccoli, carrots, snap peas) • 1 tbsp coconut aminos • 1 tbsp coconut oil for cooking • 1 clove garlic, minced • Serve over cauliflower rice '" 120 | ] 121 | }, 122 | "execution_count": 2, 123 | "metadata": {}, 124 | "output_type": "execute_result" 125 | } 126 | ], 127 | "source": [ 128 | "# inspect the content of a document\n", 129 | "docs[2].page_content" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 3, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", 139 | "\n", 140 | "# split documents into smaller chunks\n", 141 | "splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=0)\n", 142 | "\n", 143 | "chunked_docs = splitter.split_documents(docs)" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 4, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "data": { 153 | "text/plain": [ 154 | "Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 1}, page_content='Paleo Breakfast Options: a) Paleo breakfast bowl: • 2 eggs, fried or poached • 1/4 avocado, sliced • 1/2 cup sautéed mixed vegetables (spinach, mushrooms, bell peppers) • 2 slices of bacon (uncured, no added nitrates) • 1/4 cup berries on the side b) Sweet potato hash: • 1 small sweet potato, diced and roasted • 3 oz ground turkey or chicken, seasoned and cooked • 1/4 cup diced onions • 1/4 cup diced bell peppers • 1 tbsp coconut oil for cooking • Herbs: rosemary, thyme c) Paleo smoothie: • 1 cup unsweetened almond milk • 1/2 banana • 1 tbsp almond butter • 1 scoop paleo-friendly protein powder • 1 cup spinach • 1/2 cup mixed berries • Ice cubes')" 155 | ] 156 | }, 157 | "execution_count": 4, 158 | "metadata": {}, 159 | "output_type": "execute_result" 160 | } 161 | ], 162 | "source": [ 163 | "# inspect a chunk\n", 164 | "chunked_docs[2]" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 5, 170 | "metadata": {}, 171 | "outputs": [ 172 | { 173 | "name": "stderr", 174 | "output_type": "stream", 175 | "text": [ 176 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/langchain_core/_api/deprecation.py:139: LangChainDeprecationWarning: The class `HuggingFaceEmbeddings` was deprecated in LangChain 0.2.2 and will be removed in 0.3.0. An updated version of the class exists in the langchain-huggingface package and should be used instead. To use it run `pip install -U langchain-huggingface` and import as `from langchain_huggingface import HuggingFaceEmbeddings`.\n", 177 | " warn_deprecated(\n", 178 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/sentence_transformers/cross_encoder/CrossEncoder.py:11: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", 179 | " from tqdm.autonotebook import tqdm, trange\n" 180 | ] 181 | } 182 | ], 183 | "source": [ 184 | "from langchain.vectorstores import FAISS\n", 185 | "from langchain.embeddings import HuggingFaceEmbeddings\n", 186 | "\n", 187 | "# initialize vectorstore with FAISS and HuggingFace embeddings\n", 188 | "db = FAISS.from_documents(chunked_docs, HuggingFaceEmbeddings(model_name=\"BAAI/bge-base-en-v1.5\"))" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": 11, 194 | "metadata": {}, 195 | "outputs": [], 196 | "source": [ 197 | "# create a retriever using the vectorstore\n", 198 | "retriever = db.as_retriever(search_type=\"similarity\", search_kwargs={\"k\": 1})" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 12, 204 | "metadata": {}, 205 | "outputs": [ 206 | { 207 | "name": "stdout", 208 | "output_type": "stream", 209 | "text": [ 210 | "1\n", 211 | "[Document(metadata={'source': '../pdfs/paleo_internal_plan.pdf', 'page': 1}, page_content='Paleo Breakfast Options: a) Paleo breakfast bowl: • 2 eggs, fried or poached • 1/4 avocado, sliced • 1/2 cup sautéed mixed vegetables (spinach, mushrooms, bell peppers) • 2 slices of bacon (uncured, no added nitrates) • 1/4 cup berries on the side b) Sweet potato hash: • 1 small sweet potato, diced and roasted • 3 oz ground turkey or chicken, seasoned and cooked • 1/4 cup diced onions • 1/4 cup diced bell peppers • 1 tbsp coconut oil for cooking • Herbs: rosemary, thyme c) Paleo smoothie: • 1 cup unsweetened almond milk • 1/2 banana • 1 tbsp almond butter • 1 scoop paleo-friendly protein powder • 1 cup spinach • 1/2 cup mixed berries • Ice cubes')]\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "# test the retriever\n", 217 | "test = retriever.invoke('Paleo Breakfast')\n", 218 | "print(len(test))\n", 219 | "\n", 220 | "print(test)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 13, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "import torch\n", 230 | "from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig\n", 231 | "\n", 232 | "model_name =\"TinyLlama/TinyLlama-1.1B-Chat-v1.0\"\n", 233 | "\n", 234 | "save_directory = \"model_directory\"\n", 235 | "\n", 236 | "# directly load model since we saved it in the previous notebook\n", 237 | "model = AutoModelForCausalLM.from_pretrained(save_directory)\n", 238 | "tokenizer = AutoTokenizer.from_pretrained(save_directory)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 14, 244 | "metadata": {}, 245 | "outputs": [ 246 | { 247 | "name": "stderr", 248 | "output_type": "stream", 249 | "text": [ 250 | "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n", 251 | "/Users/rickchakra/Projects/aiug_workshop/venv/lib/python3.9/site-packages/langchain_core/_api/deprecation.py:139: LangChainDeprecationWarning: The class `HuggingFacePipeline` was deprecated in LangChain 0.0.37 and will be removed in 0.3. An updated version of the class exists in the langchain-huggingface package and should be used instead. To use it run `pip install -U langchain-huggingface` and import as `from langchain_huggingface import HuggingFacePipeline`.\n", 252 | " warn_deprecated(\n" 253 | ] 254 | } 255 | ], 256 | "source": [ 257 | "from langchain.llms import HuggingFacePipeline\n", 258 | "from langchain.prompts import PromptTemplate\n", 259 | "from transformers import pipeline\n", 260 | "from langchain_core.output_parsers import StrOutputParser\n", 261 | "\n", 262 | "# create a text generation pipeline\n", 263 | "text_generation_pipeline = pipeline(\n", 264 | " model=model,\n", 265 | " tokenizer=tokenizer,\n", 266 | " task=\"text-generation\",\n", 267 | " temperature=0.2,\n", 268 | " do_sample=True,\n", 269 | " repetition_penalty=1.1,\n", 270 | " return_full_text=True,\n", 271 | " max_new_tokens=400,\n", 272 | ")\n", 273 | "\n", 274 | "llm = HuggingFacePipeline(pipeline=text_generation_pipeline)\n", 275 | "\n", 276 | "prompt_template = \"\"\"\n", 277 | "<|system|>\n", 278 | "Answer the question based on your knowledge. Use the following context to help:\n", 279 | "\n", 280 | "{context}\n", 281 | "\n", 282 | "\n", 283 | "<|user|>\n", 284 | "{question}\n", 285 | "\n", 286 | "<|assistant|>\n", 287 | "\n", 288 | " \"\"\"\n", 289 | "\n", 290 | "prompt = PromptTemplate(\n", 291 | " input_variables=[\"context\", \"question\"],\n", 292 | " template=prompt_template,\n", 293 | ")\n", 294 | "\n", 295 | "llm_chain = prompt | llm | StrOutputParser()" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 15, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "from langchain_core.runnables import RunnablePassthrough\n", 305 | "\n", 306 | "# extend llm chain with RAG\n", 307 | "rag_chain = {\"context\": retriever, \"question\": RunnablePassthrough()} | llm_chain" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 16, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "question = \"What are some ketogenic breakfast options?\"" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 17, 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "data": { 326 | "text/plain": [ 327 | "\"\\n<|system|>\\nAnswer the question based on your knowledge. Use the following context to help:\\n\\n\\n\\n\\n<|user|>\\nWhat are some ketogenic breakfast options?\\n\\n<|assistant|>\\n\\n 1. Greek yogurt with berries and granola: This is a great option for a protein-packed breakfast that's also low in carbs. Greek yogurt is high in protein, while berries provide fiber and antioxidants. Top it off with granola for added crunch and flavor.\\n\\n2. Smoothie: Blend together frozen berries, almond milk, spinach, and a scoop of protein powder or Greek yogurt for a nutrient-dense breakfast that's easy to make.\\n\\n3. Overnight oats: Mix rolled oats, almond milk, chia seeds, and your choice of toppings (such as nuts, dried fruit, and honey) in a jar and let it sit in the fridge overnight. In the morning, top with fresh fruit and enjoy a satisfying and filling breakfast.\\n\\n4. Avocado toast: Toast a slice of whole grain bread and spread mashed avocado on top. Add sliced tomatoes, red onions, and a sprinkle of salt and pepper for extra flavor.\\n\\n5. Protein smoothie bowl: Blend together frozen banana, almond milk, protein powder, and your choice of toppings (such as granola, nuts, and berries) for a nutritious and delicious breakfast.\\n\\n6. Breakfast burrito: Layer cooked black beans, salsa, shredded cheese, and a fried egg on a tortilla. Roll up and enjoy a filling and healthy breakfast.\\n\\n7. Quinoa bowl: Cook quinoa according to package instructions and top with roasted sweet potato, sautéed kale, and a fried egg. Serve with a side of\"" 328 | ] 329 | }, 330 | "execution_count": 17, 331 | "metadata": {}, 332 | "output_type": "execute_result" 333 | } 334 | ], 335 | "source": [ 336 | "# invoke LLM chain for baseline response\n", 337 | "result = llm_chain.invoke({\"context\": \"\", \"question\": question})\n", 338 | "\n", 339 | "result" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": 18, 345 | "metadata": {}, 346 | "outputs": [ 347 | { 348 | "data": { 349 | "text/plain": [ 350 | "\"\\n<|system|>\\nAnswer the question based on your knowledge. Use the following context to help:\\n\\n[Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': 1}, page_content='Detailed Meal Plan Ketogenic Breakfast Options: a) Keto breakfast bowl: • 2 scrambled eggs • 1/4 avocado, sliced • 2 strips of bacon • 1/4 cup sautéed spinach • 1 tbsp butter for cooking b) Cream cheese pancakes: • 2 oz cream cheese • 2 eggs • 1/4 tsp cinnamon • 1 tbsp butter for cooking • Top with 2 tbsp sugar-free syrup c) Keto smoothie: • 1 cup unsweetened almond milk • 1/2 avocado • 1 tbsp almond butter • 1 scoop low-carb protein powder • 1 cup spinach • Ice cubes')]\\n\\n\\n<|user|>\\nWhat are some ketogenic breakfast options?\\n\\n<|assistant|>\\n\\n 1. Keto breakfast bowl:\\n - 2 scrambled eggs\\n - 1/4 avocado, sliced\\n - 2 strips of bacon\\n - 1/4 cup sautéed spinach\\n - 1 tablespoon butter for cooking\\n\\n2. Cream cheese pancakes:\\n - 2 oz cream cheese\\n - 2 eggs\\n - 1/4 tsp cinnamon\\n - 1 tablespoon butter for cooking\\n - 2 tablespoons sugar-free syrup\\n\\n3. Keto smoothie:\\n - 1 cup unsweetened almond milk\\n - 1/2 avocado\\n - 1 tbsp almond butter\\n - 1 scoop low-carb protein powder\\n - 1 cup spinach\\n - Ice cubes\\n\\nRemember that the key to a successful ketogenic diet is to eat plenty of healthy fats and lean proteins, while limiting carbohydrates and sugars. These breakfast options provide a variety of nutrients and flavors that can help you start your day off right!\"" 351 | ] 352 | }, 353 | "execution_count": 18, 354 | "metadata": {}, 355 | "output_type": "execute_result" 356 | } 357 | ], 358 | "source": [ 359 | "# invoke RAG chain for response based on knowledge base\n", 360 | "result = rag_chain.invoke(question)\n", 361 | "\n", 362 | "result" 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": 19, 368 | "metadata": {}, 369 | "outputs": [ 370 | { 371 | "name": "stdout", 372 | "output_type": "stream", 373 | "text": [ 374 | "('\\n'\n", 375 | " '<|system|>\\n'\n", 376 | " 'Answer the question based on your knowledge. Use the following context to '\n", 377 | " 'help:\\n'\n", 378 | " '\\n'\n", 379 | " \"[Document(metadata={'source': '../pdfs/ketogenic_internal_plan.pdf', 'page': \"\n", 380 | " \"1}, page_content='Detailed Meal Plan Ketogenic Breakfast Options: a) Keto \"\n", 381 | " 'breakfast bowl: • 2 scrambled eggs • 1/4 avocado, sliced • 2 strips of bacon '\n", 382 | " '• 1/4 cup sautéed spinach • 1 tbsp butter for cooking b) Cream cheese '\n", 383 | " 'pancakes: • 2 oz cream cheese • 2 eggs • 1/4 tsp cinnamon • 1 tbsp butter '\n", 384 | " 'for cooking • Top with 2 tbsp sugar-free syrup c) Keto smoothie: • 1 cup '\n", 385 | " 'unsweetened almond milk • 1/2 avocado • 1 tbsp almond butter • 1 scoop '\n", 386 | " \"low-carb protein powder • 1 cup spinach • Ice cubes')]\\n\"\n", 387 | " '\\n'\n", 388 | " '\\n'\n", 389 | " '<|user|>\\n'\n", 390 | " 'What are some ketogenic breakfast options?\\n'\n", 391 | " '\\n'\n", 392 | " '<|assistant|>\\n'\n", 393 | " '\\n'\n", 394 | " ' 1. Keto breakfast bowl:\\n'\n", 395 | " ' - 2 scrambled eggs\\n'\n", 396 | " ' - 1/4 avocado, sliced\\n'\n", 397 | " ' - 2 strips of bacon\\n'\n", 398 | " ' - 1/4 cup sautéed spinach\\n'\n", 399 | " ' - 1 tablespoon butter for cooking\\n'\n", 400 | " '\\n'\n", 401 | " '2. Cream cheese pancakes:\\n'\n", 402 | " ' - 2 oz cream cheese\\n'\n", 403 | " ' - 2 eggs\\n'\n", 404 | " ' - 1/4 tsp cinnamon\\n'\n", 405 | " ' - 1 tablespoon butter for cooking\\n'\n", 406 | " ' - 2 tablespoons sugar-free syrup\\n'\n", 407 | " '\\n'\n", 408 | " '3. Keto smoothie:\\n'\n", 409 | " ' - 1 cup unsweetened almond milk\\n'\n", 410 | " ' - 1/2 avocado\\n'\n", 411 | " ' - 1 tbsp almond butter\\n'\n", 412 | " ' - 1 scoop low-carb protein powder\\n'\n", 413 | " ' - 1 cup spinach\\n'\n", 414 | " ' - Ice cubes\\n'\n", 415 | " '\\n'\n", 416 | " 'Remember that the key to a successful ketogenic diet is to eat plenty of '\n", 417 | " 'healthy fats and lean proteins, while limiting carbohydrates and sugars. '\n", 418 | " 'These breakfast options provide a variety of nutrients and flavors that can '\n", 419 | " 'help you start your day off right!')\n" 420 | ] 421 | } 422 | ], 423 | "source": [ 424 | "from pprint import pprint\n", 425 | "\n", 426 | "pprint(result)" 427 | ] 428 | } 429 | ], 430 | "metadata": { 431 | "kernelspec": { 432 | "display_name": "venv", 433 | "language": "python", 434 | "name": "python3" 435 | }, 436 | "language_info": { 437 | "codemirror_mode": { 438 | "name": "ipython", 439 | "version": 3 440 | }, 441 | "file_extension": ".py", 442 | "mimetype": "text/x-python", 443 | "name": "python", 444 | "nbconvert_exporter": "python", 445 | "pygments_lexer": "ipython3", 446 | "version": "3.9.6" 447 | } 448 | }, 449 | "nbformat": 4, 450 | "nbformat_minor": 2 451 | } 452 | --------------------------------------------------------------------------------