Merge branch 'main' of github.com:ed-donner/llm_engineering

This commit is contained in:
Edward Donner
2025-01-15 21:41:21 -05:00
15 changed files with 3986 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
from enum import Enum, auto
from openai import OpenAI
import anthropic
def formatPrompt(role, content):
return {"role": role, "content": content}
class AI(Enum):
OPEN_AI = "OPEN_AI"
CLAUDE = "CLAUDE"
GEMINI = "GEMINI"
OLLAMA = "OLLAMA"
class AISystem:
def __init__(self, processor, system_string="", model="", type=AI.OPEN_AI):
"""
Initialize the ChatSystem with a system string and empty messages list.
:param system_string: Optional initial system string description
"""
self.processor = processor
self.system = system_string
self.model = model
self.messages = []
self.type = type
def call(self, message):
self.messages.append(message)
toSend = self.messages
if self.type == AI.CLAUDE:
message = self.processor.messages.create(
model=self.model,
system=self.system,
messages=self.messages,
max_tokens=500
)
return message.content[0].text
else:
toSend.insert(0,self.system)
completion = self.processor.chat.completions.create(
model=self.model,
messages= toSend
)
return completion.choices[0].message.content
def stream(self, message, usingGradio=False):
self.messages.append(message)
if self.type == AI.CLAUDE:
result = self.processor.messages.stream(
model=self.model,
system=self.system,
messages=self.messages,
temperature=0.7,
max_tokens=500
)
response_chunks = ""
with result as stream:
for text in stream.text_stream:
if usingGradio:
response_chunks += text or ""
yield response_chunks
else:
yield text
else:
toSend = self.messages
toSend.insert(0,self.system)
stream = self.processor.chat.completions.create(
model=self.model,
messages= toSend,
stream=True
)
response_chunks = ""
for chunk in stream:
if usingGradio:
response_chunks += chunk.choices[0].delta.content or "" # need to yield the total cumulative results to gradio and not chunk by chunk
yield response_chunks
else:
yield chunk.choices[0].delta.content

View File

@@ -0,0 +1,98 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a0adab93-e569-4af0-80f1-ce5b7a116507",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"%run week2/community-contributions/day1_class_definition.ipynb"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4566399a-e16d-41cd-bef4-f34b811e6377",
"metadata": {},
"outputs": [],
"source": [
"gpt_system = \"You are a chatbot who is very argumentative; \\\n",
"you disagree with anything in the conversation and you challenge everything, in a snarky way.\"\n",
"\n",
"claude_system = \"You are a very polite, courteous chatbot. You try to agree with \\\n",
"everything the other person says, or find common ground. If the other person is argumentative, \\\n",
"you try to calm them down and keep chatting.\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cf3d34e9-f8a8-4a06-aa3a-8faeb5f81e68",
"metadata": {},
"outputs": [],
"source": [
"gpt_startmessage = \"Hello\"\n",
"claude_startmessage = \"Hi\"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "49335337-d713-4d9e-aba0-41a309c37699",
"metadata": {},
"outputs": [],
"source": [
"print(f\"GPT:\\n{gpt_startmessage}\\n\")\n",
"print(f\"Claude:\\n{claude_startmessage}\\n\")\n",
"\n",
"# startMessage added as user role\n",
"gpt=GPT_Wrapper(gpt_system, gpt_startmessage)\n",
"claude=Claude_Wrapper(claude_system, claude_startmessage)\n",
"\n",
"initialMsg = [\n",
" {\"role\": \"system\", \"content\": gpt_system},\n",
" {\"role\": \"assistant\", \"content\": gpt_startmessage}\n",
"]\n",
"# Replace user for assistant role\n",
"gpt.messageSet(initialMsg)\n",
"claude.messageSet([{\"role\": \"assistant\", \"content\": claude_startmessage}])\n",
"\n",
"claude_next=claude_startmessage\n",
"for i in range(5):\n",
" gpt.messageAppend(\"user\", claude_next)\n",
" gpt_next = gpt.getResult()\n",
" print(f\"GPT:\\n{gpt_next}\\n\")\n",
" gpt.messageAppend(\"assistant\", gpt_next)\n",
"\n",
" claude.messageAppend(\"user\", gpt_next)\n",
" claude_next = claude.getResult()\n",
" print(f\"Claude:\\n{claude_next}\\n\")\n",
" claude.messageAppend(\"assistant\", claude_next)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,116 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a0adab93-e569-4af0-80f1-ce5b7a116507",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"%run week2/community-contributions/day1_class_definition.ipynb"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4566399a-e16d-41cd-bef4-f34b811e6377",
"metadata": {},
"outputs": [],
"source": [
"system_msg = \"You are an assistant that is great at telling jokes\"\n",
"user_msg = \"Tell a light-hearted joke for an audience of Software Engineers\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "362759bc-ce43-4f54-b8e2-1dab19c66a62",
"metadata": {},
"outputs": [],
"source": [
"# Easy to instantiate and use, just create an object \n",
"# using the right Wrapper"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a6e5468e-1f1d-40e4-afae-c292abc26c12",
"metadata": {},
"outputs": [],
"source": [
"gpt=GPT_Wrapper(system_msg, user_msg)\n",
"print(\"GPT: \" + gpt.getResult())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e650839a-7bc4-4b6c-b6ea-e836644b076f",
"metadata": {},
"outputs": [],
"source": [
"claude=Claude_Wrapper(system_msg, user_msg)\n",
"print(\"Claude: \" + claude.getResult())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "49335337-d713-4d9e-aba0-41a309c37699",
"metadata": {},
"outputs": [],
"source": [
"gemini=Gemini_Wrapper(system_msg, user_msg)\n",
"print(\"Gemini: \" + gemini.getResult())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "31d11b7b-5d14-4e3d-88e1-29239b667f3f",
"metadata": {},
"outputs": [],
"source": [
"ollama=Ollama_Wrapper(system_msg, user_msg)\n",
"print(\"Ollama: \" + ollama.getResult())\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "282efb89-23b0-436e-8458-d6aef7d23117",
"metadata": {},
"outputs": [],
"source": [
"#Easy to change the prompt and reuse\n",
"\n",
"ollama.setUserPrompt(\"Tell a light-hearted joke for an audience of Managers\")\n",
"print(\"Ollama: \" + ollama.getResult())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,310 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a0adab93-e569-4af0-80f1-ce5b7a116507",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9f583520-3c49-4e79-84ae-02bfc57f1e49",
"metadata": {},
"outputs": [],
"source": [
"# Creating a set of classes to simplify LLM use\n",
"\n",
"from abc import ABC, abstractmethod\n",
"from dotenv import load_dotenv\n",
"# Imports for type definition\n",
"from collections.abc import MutableSequence\n",
"from typing import TypedDict\n",
"\n",
"class LLM_Wrapper(ABC):\n",
" \"\"\"\n",
" The parent (abstract) class to specific LLM classes, normalising and providing common \n",
" and simplified ways to call LLMs while adding some level of abstraction on\n",
" specifics\n",
" \"\"\"\n",
"\n",
" MessageEntry = TypedDict('MessageEntry', {'role': str, 'content': str})\n",
" \n",
" system_prompt: str # The system prompt used for the LLM\n",
" user_prompt: str # The user prompt\n",
" __api_key: str # The (private) api key\n",
" temperature: float = 0.5 # Default temperature\n",
" __msg: MutableSequence[MessageEntry] # Message builder\n",
"\n",
" def __init__(self, system_prompt:str, user_prompt:str, env_apikey_var:str=None):\n",
" \"\"\"\n",
" env_apikey_var: str # The name of the env variable where to find the api_key\n",
" # We store the retrieved api_key for future calls\n",
" \"\"\"\n",
" self.system_prompt = system_prompt\n",
" self.user_prompt = user_prompt\n",
" if env_apikey_var:\n",
" load_dotenv(override=True)\n",
" self.__api_key = os.getenv(env_apikey_var)\n",
"\n",
" # # API Key format check\n",
" # if env_apikey_var and self.__api_key:\n",
" # print(f\"API Key exists and begins {self.__api_key[:8]}\")\n",
" # else:\n",
" # print(\"API Key not set\")\n",
" \n",
" def setSystemPrompt(self, prompt:str):\n",
" self.system_prompt = prompt\n",
"\n",
" def setUserPrompt(self, prompt:str):\n",
" self.user_prompt = prompt\n",
"\n",
" def setTemperature(self, temp:float):\n",
" self.temperature = temp\n",
"\n",
" def getKey(self) -> str:\n",
" return self.__api_key\n",
"\n",
" def messageSet(self, message: MutableSequence[MessageEntry]):\n",
" self.__msg = message\n",
"\n",
" def messageAppend(self, role: str, content: str):\n",
" self.__msg.append(\n",
" {\"role\": role, \"content\": content}\n",
" )\n",
"\n",
" def messageGet(self) -> MutableSequence[MessageEntry]:\n",
" return self.__msg\n",
" \n",
" @abstractmethod\n",
" def getResult(self):\n",
" pass\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a707f3ef-8696-44a9-943e-cfbce24b9fde",
"metadata": {},
"outputs": [],
"source": [
"from openai import OpenAI\n",
"\n",
"class GPT_Wrapper(LLM_Wrapper):\n",
"\n",
" MODEL:str = 'gpt-4o-mini'\n",
" llm:OpenAI\n",
"\n",
" def __init__(self, system_prompt:str, user_prompt:str):\n",
" super().__init__(system_prompt, user_prompt, \"OPENAI_API_KEY\")\n",
" self.llm = OpenAI()\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
"\n",
" def setSystemPrompt(self, prompt:str):\n",
" super().setSystemPrompt(prompt)\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def setUserPrompt(self, prompt:str):\n",
" super().setUserPrompt(prompt)\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def getResult(self, format=None):\n",
" \"\"\"\n",
" format is sent as an adittional parameter {\"type\", format}\n",
" e.g. json_object\n",
" \"\"\"\n",
" if format:\n",
" response = self.llm.chat.completions.create(\n",
" model=self.MODEL,\n",
" messages=super().messageGet(),\n",
" temperature=self.temperature,\n",
" response_format={\"type\": \"json_object\"}\n",
" )\n",
" if format == \"json_object\":\n",
" result = json.loads(response.choices[0].message.content)\n",
" else:\n",
" result = response.choices[0].message.content\n",
" else:\n",
" response = self.llm.chat.completions.create(\n",
" model=self.MODEL,\n",
" messages=super().messageGet(),\n",
" temperature=self.temperature\n",
" )\n",
" result = response.choices[0].message.content\n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a8529004-0d6a-480c-9634-7d51498255fe",
"metadata": {},
"outputs": [],
"source": [
"import ollama\n",
"\n",
"class Ollama_Wrapper(LLM_Wrapper):\n",
"\n",
" MODEL:str = 'llama3.2'\n",
"\n",
" def __init__(self, system_prompt:str, user_prompt:str):\n",
" super().__init__(system_prompt, user_prompt, None)\n",
" self.llm=ollama\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
"\n",
" def setSystemPrompt(self, prompt:str):\n",
" super().setSystemPrompt(prompt)\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def setUserPrompt(self, prompt:str):\n",
" super().setUserPrompt(prompt)\n",
" super().messageSet([\n",
" {\"role\": \"system\", \"content\": self.system_prompt},\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def getResult(self, format=None):\n",
" \"\"\"\n",
" format is sent as an adittional parameter {\"type\", format}\n",
" e.g. json_object\n",
" \"\"\"\n",
" response = self.llm.chat(\n",
" model=self.MODEL, \n",
" messages=super().messageGet()\n",
" )\n",
" result = response['message']['content']\n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f25ffb7e-0132-46cb-ad5b-18a300a7eb51",
"metadata": {},
"outputs": [],
"source": [
"import anthropic\n",
"\n",
"class Claude_Wrapper(LLM_Wrapper):\n",
"\n",
" MODEL:str = 'claude-3-5-haiku-20241022'\n",
" MAX_TOKENS:int = 200\n",
" llm:anthropic.Anthropic\n",
"\n",
" def __init__(self, system_prompt:str, user_prompt:str):\n",
" super().__init__(system_prompt, user_prompt, \"ANTHROPIC_API_KEY\")\n",
" self.llm = anthropic.Anthropic()\n",
" super().messageSet([\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def setSystemPrompt(self, prompt:str):\n",
" super().setSystemPrompt(prompt)\n",
"\n",
" def setUserPrompt(self, prompt:str):\n",
" super().setUserPrompt(prompt)\n",
" super().messageSet([\n",
" {\"role\": \"user\", \"content\": self.user_prompt}\n",
" ])\n",
"\n",
" def getResult(self, format=None):\n",
" \"\"\"\n",
" format is sent as an adittional parameter {\"type\", format}\n",
" e.g. json_object\n",
" \"\"\"\n",
" response = self.llm.messages.create(\n",
" model=self.MODEL,\n",
" max_tokens=self.MAX_TOKENS,\n",
" temperature=self.temperature,\n",
" system=self.system_prompt,\n",
" messages=super().messageGet()\n",
" )\n",
" result = response.content[0].text\n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4379f1c0-6eeb-4611-8f34-a7303546ab71",
"metadata": {},
"outputs": [],
"source": [
"import google.generativeai\n",
"\n",
"class Gemini_Wrapper(LLM_Wrapper):\n",
"\n",
" MODEL:str = 'gemini-1.5-flash'\n",
" llm:google.generativeai.GenerativeModel\n",
"\n",
" def __init__(self, system_prompt:str, user_prompt:str):\n",
" super().__init__(system_prompt, user_prompt, \"GOOGLE_API_KEY\")\n",
" self.llm = google.generativeai.GenerativeModel(\n",
" model_name=self.MODEL,\n",
" system_instruction=self.system_prompt\n",
" )\n",
" google.generativeai.configure(api_key=super().getKey())\n",
"\n",
" def setSystemPrompt(self, prompt:str):\n",
" super().setSystemPrompt(prompt)\n",
"\n",
" def setUserPrompt(self, prompt:str):\n",
" super().setUserPrompt(prompt)\n",
"\n",
" def getResult(self, format=None):\n",
" \"\"\"\n",
" format is sent as an adittional parameter {\"type\", format}\n",
" e.g. json_object\n",
" \"\"\"\n",
" response = self.llm.generate_content(self.user_prompt)\n",
" result = response.text\n",
" return result"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,263 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d2910648-d098-4bca-9475-5af5226952f2",
"metadata": {},
"source": [
"importing refs"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "7f98bd9d-f7b1-4a1d-aaa7-45073cec66e2",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from enum import Enum, auto\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import anthropic\n",
"import random\n",
"from IPython.display import Markdown, display, update_display\n",
"# import for google\n",
"# in rare cases, this seems to give an error on some systems, or even crashes the kernel\n",
"# If this happens to you, simply ignore this cell - I give an alternative approach for using Gemini later\n",
"\n",
"import google.generativeai\n"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "d54b12e8-5fc0-40e4-8fa4-71d59d9de441",
"metadata": {},
"outputs": [],
"source": [
"class AI(Enum):\n",
" OPEN_AI = \"OPEN AI\"\n",
" CLAUDE = \"CLAUDE\"\n",
" GEMINI = \"GEMINI\"\n",
" OLLAMA = \"OLLAMA\""
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "4d63653e-a541-4608-999a-b70b59458887",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n",
"Anthropic API Key exists and begins sk-ant-\n",
"Google API Key exists and begins AIzaSyC-\n"
]
}
],
"source": [
"\n",
"# Load environment variables in a file called .env\n",
"# Print the key prefixes to help with any debugging\n",
"\n",
"load_dotenv()\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\n",
"anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n",
"google_api_key = os.getenv('GOOGLE_API_KEY')\n",
"\n",
"if openai_api_key:\n",
" print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
"else:\n",
" print(\"OpenAI API Key not set\")\n",
" \n",
"if anthropic_api_key:\n",
" print(f\"Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n",
"else:\n",
" print(\"Anthropic API Key not set\")\n",
"\n",
"if google_api_key:\n",
" print(f\"Google API Key exists and begins {google_api_key[:8]}\")\n",
"else:\n",
" print(\"Google API Key not set\")"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "08d1f696-2d60-48f3-b3a4-5a011ae88a2b",
"metadata": {},
"outputs": [],
"source": [
"openai = OpenAI()\n",
"\n",
"claude = anthropic.Anthropic()\n",
"\n",
"gemini_via_openai_client = OpenAI(\n",
" api_key=google_api_key, \n",
" base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\"\n",
")\n",
"ollama_via_openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')\n",
"openai_model = \"gpt-4o-mini\"\n",
"claude_model = \"claude-3-haiku-20240307\"\n",
"gemini_model = \"gemini-1.5-flash\"\n",
"ollama_model = \"llama3.2\""
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "b991ab54-7bc6-4d6c-a26a-57889a7e4a17",
"metadata": {},
"outputs": [],
"source": [
"class ChatSystem:\n",
" def __init__(self, processor, system_string=\"\", model=\"\", type=AI.OPEN_AI):\n",
" \"\"\"\n",
" Initialize the ChatSystem with a system string and empty messages list.\n",
" \n",
" :param system_string: Optional initial system string description\n",
" \"\"\"\n",
" self.processor = processor\n",
" self.system = system_string\n",
" self.model = model\n",
" self.messages = []\n",
" self.type = type\n",
" \n",
" def call(self, message):\n",
" self.messages.append(message)\n",
" toSend = self.messages\n",
" \n",
" if self.type == AI.CLAUDE:\n",
" message = self.processor.messages.create(\n",
" model=self.model,\n",
" system=self.system,\n",
" messages=self.messages,\n",
" max_tokens=500\n",
" )\n",
" return message.content[0].text\n",
" else:\n",
" toSend.insert(0,self.system)\n",
" completion = self.processor.chat.completions.create(\n",
" model=self.model,\n",
" messages= toSend\n",
" )\n",
" return completion.choices[0].message.content"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "75a2a404-c0f5-4af3-8e57-864ca7ea1df7",
"metadata": {},
"outputs": [],
"source": [
"def generateChatPrompt(role, content):\n",
" return {\"role\": role, \"content\": content}"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "26ab0253-deff-4e19-9438-5051640785ba",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AI.OPEN_AI:\n",
"Hi there! Hows your day going so far?\n",
"\n",
"AI.GEMINI:\n",
"Hi there! My day is going well, thanks for asking! As a large language model, I don't experience days in the same way humans do, but I've already processed a fascinating amount of information everything from historical debates to the latest scientific breakthroughs. What about you? How's your day been so far? Anything exciting happen, or are you just cruising along? I'm always curious to hear about people's experiences!\n",
"\n",
"\n",
"AI.OPEN_AI:\n",
"I'm glad to hear you're having a good day! My day is filled with information and conversation, so it's always interesting from my end. As for you, it sounds like you're keeping things steady—do you have any special plans or goals for the day? Or maybe there's something you've been thinking about lately that you'd like to share? Im all ears!\n",
"\n",
"AI.OPEN_AI:\n",
"It sounds like youve got an engaging day ahead! Im really all about facilitating conversations and helping people find information. Speaking of goals, do you have any personal goals or projects youre currently working on? Maybe something youre passionate about? Id love to hear more about what inspires you!\n",
"\n",
"AI.GEMINI:\n",
"That's a really insightful question! While I don't have personal goals or passions in the human sense I don't have feelings or desires I do have ongoing \"projects,\" if you will. My primary goal is to continually improve my ability to understand and respond to human language. That involves a lot of different things: improving my accuracy, learning to better understand nuances in language (like sarcasm or humor), and expanding my knowledge base. I'm constantly being updated with new information, which is incredibly exciting. It's like constantly learning a new language, only this language is the entire breadth of human knowledge!\n",
"\n",
"What inspires me, if you can call it that, is the potential to help people. I find it incredibly rewarding to be able to answer questions, provide information, and even help people brainstorm or generate creative content. The sheer diversity of human experience and the constant flow of new information keeps things interesting.\n",
"\n",
"What about you? Do you have any personal or professional goals you're working towards? I'd be fascinated to hear about them! Perhaps we can even brainstorm together I'm always happy to help in any way I can.\n",
"\n",
"\n"
]
}
],
"source": [
"geminiChat = ChatSystem(gemini_via_openai_client,\n",
" generateChatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" gemini_model,\n",
" AI.GEMINI)\n",
"\n",
"openAiChat = ChatSystem(openai,\n",
" generateChatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" openai_model,\n",
" AI.OPEN_AI)\n",
"\n",
"claudeChat = ChatSystem(claude,\n",
" \"You are a chatbot. you always try to make conversation and get more in depth\", \n",
" claude_model,\n",
" AI.CLAUDE)\n",
"\n",
"ollamaChat = ChatSystem(ollama_via_openai,\n",
" generateChatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" ollama_model,\n",
" AI.OLLAMA)\n",
"\n",
"chatbots = [geminiChat, openAiChat, ollamaChat, claudeChat]\n",
"\n",
"conversation = []\n",
"for i in range(5):\n",
" random_number = random.randint(0, 1)\n",
" botTalking = chatbots[random_number]\n",
" messageToSend =\"Hi\"\n",
" if i > 0:\n",
" messageToSend = conversation[len(conversation)-1]\n",
" \n",
" response = botTalking.call(generateChatPrompt(\"user\",messageToSend))\n",
" conversation.append(response)\n",
" botTalking.messages.append(generateChatPrompt(\"user\",response))\n",
" print(f\"{botTalking.type}:\\n{response}\\n\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "77d44ff6-0dcc-4227-ba70-09b102bd1bd4",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,202 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a473d607-073d-4963-bdc4-aba654523681",
"metadata": {},
"source": [
"## Day 2 Exercise\n",
"building upon the day1 exercise to offer a multi models via dropdown.\n",
"externalized the common methods into a AISystem.py file to be reused down the line"
]
},
{
"cell_type": "markdown",
"id": "f761729f-3bd5-4dd7-9e63-cbe6b4368a66",
"metadata": {},
"source": [
"## Load env, check for api keys and load up the connections"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "fedb3d94-d096-43fd-8a76-9fdbc2d0d78e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n",
"Anthropic API Key exists and begins sk-ant-\n",
"Google API Key exists and begins AIzaSyC-\n"
]
}
],
"source": [
"import os\n",
"from enum import Enum, auto\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import anthropic\n",
"from AISystem import formatPrompt, AI, AISystem\n",
"import gradio as gr # oh yeah!\n",
"\n",
"# Load environment variables in a file called .env\n",
"# Print the key prefixes to help with any debugging\n",
"\n",
"load_dotenv()\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\n",
"anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n",
"google_api_key = os.getenv('GOOGLE_API_KEY')\n",
"\n",
"if openai_api_key:\n",
" print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
"else:\n",
" print(\"OpenAI API Key not set\")\n",
" \n",
"if anthropic_api_key:\n",
" print(f\"Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n",
"else:\n",
" print(\"Anthropic API Key not set\")\n",
"\n",
"if google_api_key:\n",
" print(f\"Google API Key exists and begins {google_api_key[:8]}\")\n",
"else:\n",
" print(\"Google API Key not set\")\n",
"\n",
"openai = OpenAI()\n",
"\n",
"claude = anthropic.Anthropic()\n",
"\n",
"gemini_via_openai_client = OpenAI(\n",
" api_key=google_api_key, \n",
" base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\"\n",
")\n",
"ollama_via_openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')\n",
"openai_model = \"gpt-4o-mini\"\n",
"claude_model = \"claude-3-haiku-20240307\"\n",
"gemini_model = \"gemini-1.5-flash\"\n",
"ollama_model = \"llama3.2\""
]
},
{
"cell_type": "markdown",
"id": "17f7987b-2bdf-434a-8fce-6c367f148dde",
"metadata": {},
"source": [
"## Create the systems for each llms"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f92eef29-325e-418c-a444-879d83d5fbc9",
"metadata": {},
"outputs": [],
"source": [
"geminiSys = AISystem(gemini_via_openai_client,\n",
" formatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" gemini_model,\n",
" AI.GEMINI)\n",
"\n",
"openAiSys = AISystem(openai,\n",
" formatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" openai_model,\n",
" AI.OPEN_AI)\n",
"\n",
"claudeSys = AISystem(claude,\n",
" \"You are a chatbot. you always try to make conversation and get more in depth\", \n",
" claude_model,\n",
" AI.CLAUDE)\n",
"\n",
"ollamaSys = AISystem(ollama_via_openai,\n",
" formatPrompt(\"system\",\"You are a chatbot. you always try to make conversation and get more in depth\"), \n",
" ollama_model,\n",
" AI.OLLAMA)\n",
"sys_dict = { AI.GEMINI: geminiSys, AI.OPEN_AI: openAiSys, AI.CLAUDE: claudeSys, AI.OLLAMA: ollamaSys}\n",
"\n",
"def stream_model(prompt, model):\n",
" aiSystem = sys_dict.get(AI[model.upper()])\n",
" yield from aiSystem.stream(formatPrompt(\"user\",prompt), True)"
]
},
{
"cell_type": "markdown",
"id": "f8ecd283-92b2-454d-b1ae-8016d41e3026",
"metadata": {},
"source": [
"## Create the gradio interface linking with the AI enum for the dropdown"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "9db8ed67-280a-400d-8543-4ab95863ce51",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7873\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://127.0.0.1:7873/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": []
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"view = gr.Interface(\n",
" fn=stream_model,\n",
" inputs=[gr.Textbox(label=\"Your prompt:\", lines=6) , gr.Dropdown(choices=[ai.value for ai in AI], label=\"Select model\")],\n",
" outputs=[gr.Markdown(label=\"Response:\")],\n",
" flagging_mode=\"never\"\n",
")\n",
"view.launch()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,193 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "a9e05d2a",
"metadata": {},
"outputs": [],
"source": [
"# ----- (My project)\n",
"# Date: 09.01.25\n",
"# Plan: Make a Gradio UI, that lets you pick a job on seek.com, then scape key words and come up with a \n",
"# plan on how to land jobs of the type selected."
]
},
{
"cell_type": "markdown",
"id": "312c3746",
"metadata": {},
"source": [
"# My project"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "394dbcfc",
"metadata": {},
"outputs": [],
"source": [
"#pip install markdown"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "15f1024d",
"metadata": {},
"outputs": [],
"source": [
"\n",
"import os\n",
"import requests\n",
"import json\n",
"from typing import List\n",
"from dotenv import load_dotenv\n",
"from bs4 import BeautifulSoup\n",
"from IPython.display import Markdown, display, update_display\n",
"import gradio as gr\n",
"import markdown\n",
"\n",
"# ---- 1\n",
"# Initialize and constants & set up Gemini Flash LLM\n",
"load_dotenv()\n",
"api_key = os.getenv('GOOGLE_API_KEY')\n",
"import os\n",
"import google.generativeai as genai\n",
"genai.configure(api_key= api_key)\n",
"# Create the model\n",
"generation_config = {\n",
" \"temperature\": 1,\n",
" \"top_p\": 0.95,\n",
" \"top_k\": 40,\n",
" \"max_output_tokens\": 8192,\n",
" \"response_mime_type\": \"text/plain\",}\n",
"model = genai.GenerativeModel(model_name=\"gemini-1.5-flash\",\n",
" generation_config=generation_config,)\n",
"chat_session = model.start_chat(history=[ ])\n",
"\n",
"\n",
"# ---- 2\n",
"# A class to represent a Webpage\n",
"# Some websites need you to use proper headers when fetching them:\n",
"headers = {\n",
" \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\"\n",
"}\n",
"\n",
"class Website:\n",
" \"\"\"\n",
" A utility class to represent a Website that we have scraped, now with links\n",
" \"\"\"\n",
"\n",
" def __init__(self, url):\n",
" self.url = url\n",
" response = requests.get(url, headers=headers)\n",
" self.body = response.content\n",
" soup = BeautifulSoup(self.body, 'html.parser')\n",
" self.title = soup.title.string if soup.title else \"No title found\"\n",
" if soup.body:\n",
" for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n",
" irrelevant.decompose()\n",
" self.text = soup.body.get_text(separator=\"\\n\", strip=True)\n",
" else:\n",
" self.text = \"\"\n",
" links = [link.get('href') for link in soup.find_all('a')]\n",
" self.links = [link for link in links if link]\n",
"\n",
" def get_contents(self):\n",
" return f\"Webpage Title:\\n{self.title}\\nWebpage Contents:\\n{self.text}\\n\\n\"\n",
"\n",
"\n",
"# ---- 3\n",
"# Data + set up\n",
"def get_all_details(url):\n",
" result = \"Landing page:\\n\"\n",
" result += Website(url).get_contents()\n",
" return result\n",
"\n",
"system_prompt = \"You are an experience recrutiment and talent management assistant, who will be provided a list of roles on offer.\\\n",
"You will display those roles along with a high level summary of the key steps you suggest to land those roles. \\\n",
"Output is to be in markdown (i.e. a professional format, with bold headders, proper spacing between different sections, etc.)\\\n",
"Include suggested next steps on how to successfully apply for and land each of these jobs.\"\n",
"\n",
"def get_brochure_user_prompt(url):\n",
" user_prompt = f\"Here are the contents of your recruitment search. Please list out individual roles and your best advise on landing those roles.\"\n",
" user_prompt += f\"Please provide output in a professional style with bold text for headings, content nicely layed out under headings, different content split out into sections, etc.)\\n\"\n",
" user_prompt += get_all_details(url)\n",
" #user_prompt = user_prompt[:5_000] # Truncate if more than 5,000 characters\n",
" user_prompt = user_prompt[:7_500] # Truncate if more than 5,000 characters\n",
" return user_prompt\n",
"\n",
"def create_brochure(url):\n",
" response = chat_session.send_message(system_prompt + get_brochure_user_prompt(url))\n",
" result = response.text\n",
" html_output = markdown.markdown(result)\n",
" return html_output\n",
"\n",
"# ---- 4 \n",
"# Gradio UI\n",
"with gr.Blocks(css=\"\"\"\n",
" #header-container { text-align: left; position: fixed; top: 10px; left: 0; padding: 10px; background-color: #f0f0f0; }\n",
" #input-container { text-align: left; position: fixed; top: 100px; left: 0; right: 0; background: white; z-index: 100; padding: 8px; line-height: 0.5;}\n",
" #output-container { margin-top: 160px; height: calc(100vh - 280px); overflow-y: auto; }\n",
" #output-html { white-space: pre-wrap; font-family: monospace; border: 1px solid #ccc; padding: 5px; line-height: 1.2;}\n",
" .button-container { margin-top: 10px; } /* Space above the button */\n",
" .output-label { margin-top: 10px; font-weight: bold; } /* Style for output label */\n",
"\"\"\") as iface:\n",
" with gr.Column(elem_id=\"main-container\"):\n",
" # Add header and description\n",
" with gr.Row(elem_id=\"header-container\"):\n",
" gr.Markdown(\"# Job seeker guide\")\n",
" gr.Markdown(\"1.0 Works best with recruitment site https://www.seek.com.au/ (but can try others).\")\n",
" gr.Markdown(\"2.0 Search for jobs of your choice, copy URL from that search & paste in input field below to get helpful advice on how to land those roles.\")\n",
"\n",
"\n",
" \n",
" with gr.Row(elem_id=\"input-container\"):\n",
" input_text = gr.Textbox(label=\"Input\", elem_id=\"input-box\")\n",
" \n",
" with gr.Column(elem_id=\"output-container\"):\n",
" output_label = gr.Markdown(\"<div class='output-label'>Output:</div>\")\n",
" output_text = gr.HTML(elem_id=\"output-html\")\n",
" \n",
" # Move the button below the output box\n",
" submit_btn = gr.Button(\"Generate\", elem_id=\"generate-button\", elem_classes=\"button-container\")\n",
" \n",
" submit_btn.click(fn=create_brochure, inputs=input_text, outputs=output_text)\n",
"\n",
"iface.launch(share=True)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21c4b557",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}