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

This commit is contained in:
Edward Donner
2025-03-01 15:03:23 -05:00
25 changed files with 10314 additions and 0 deletions

View File

@@ -0,0 +1,361 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "5d799d2a-6e58-4a83-b17a-dbbc40efdc39",
"metadata": {},
"source": [
"## Project - Course Booking AI Asssistant\n",
"AI Customer Support Bot that \n",
"- Returns Prices\n",
"- Books Tickets\n",
"- Adds Information to Text File"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "b1ad9acd-a702-48a3-8ff5-d536bcac8030",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"import os\n",
"import json\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import gradio as gr"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "74adab0c-99b3-46cd-a79f-320a3e74138a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n"
]
}
],
"source": [
"# Initialization\n",
"\n",
"load_dotenv(override=True)\n",
"\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\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",
"MODEL = \"gpt-4o-mini\"\n",
"openai = OpenAI()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "8d3240a4-99c1-4c07-acaa-ecbb69ffd2e4",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"You are a helpful assistant for an Online Course Platform called StudyAI. \"\n",
"system_message += \"Give short, courteous answers, no more than 1 sentence. \"\n",
"system_message += \"Always be accurate. If you don't know the answer, say so.\"\n",
"system_message += \"If you are given a partial name, for example 'discrete' instead of 'discrete structures' \\\n",
"ask the user if they meant to say 'discrete structures', and then display the price. The user may also use \\\n",
"acronyms like 'PF' instead of programming fundamentals or 'OOP' to mean 'Object oriented programming'. \\\n",
"Clarify wh\""
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "9a1b8d5f-f893-477b-8396-ff7d697eb0c3",
"metadata": {},
"outputs": [],
"source": [
"course_prices = {\"programming fundamentals\": \"$19\", \"discrete structures\": \"$39\", \"operating systems\": \"$24\", \"object oriented programming\": \"$39\"}\n",
"\n",
"def get_course_price(course):\n",
" print(f\"Tool get_course_price called for {course}\")\n",
" course = course.lower()\n",
" return course_prices.get(course, \"Unknown\")\n",
"\n",
"def enroll_in_course(course):\n",
" print(f'Tool enroll_in_course_ called for {course}')\n",
" course_price = get_course_price(course)\n",
" if course_price != 'Unknown':\n",
" with open('enrolled_courses.txt', 'a') as file: \n",
" file.write(course + \"\\n\")\n",
" return 'Successfully enrolled in course'\n",
" else:\n",
" return 'Enrollment failed, no such course available'"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "330d2b94-a8c5-4967-ace7-15d2cd52d7ae",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tool get_course_price called for graph theory\n",
"Tool get_course_price called for discrete structures\n"
]
},
{
"data": {
"text/plain": [
"'$39'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_course_price('graph theory')\n",
"get_course_price('discrete structures')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "5bb65830-fab8-45a7-bf43-7e52186915a0",
"metadata": {},
"outputs": [],
"source": [
"price_function = {\n",
" \"name\": \"get_course_price\",\n",
" \"description\": \"Get the price of a course. Call this whenever you need to know the course price, for example when a customer asks 'How much is a ticket for this course?'\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"course\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The course that the customer wants to purchase\",\n",
" },\n",
" },\n",
" \"required\": [\"course\"],\n",
" \"additionalProperties\": False\n",
" }\n",
"}\n",
"\n",
"enroll_function = {\n",
" \"name\": \"enroll_in_course\",\n",
" \"description\":\"Get the success status of course enrollment. Call whenever a customer wants to enroll in a course\\\n",
" for example, if they say 'I want to purchase this course' or 'I want to enroll in this course'\",\n",
" \"parameters\":{\n",
" \"type\":\"object\",\n",
" \"properties\":{\n",
" \"course\":{\n",
" \"type\":\"string\",\n",
" \"description\": \"The course that the customer wants to purchase\",\n",
" },\n",
" },\n",
" \"required\": [\"course\"],\n",
" \"additionalProperties\": False\n",
" } \n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "08af86b9-3aaa-4b6b-bf7c-ee668ba1cbfe",
"metadata": {},
"outputs": [],
"source": [
"tools = [\n",
" {\"type\":\"function\",\"function\":price_function},\n",
" {\"type\":\"function\",\"function\":enroll_function}\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "482efc34-ff1f-4146-9570-58b4d59c3b2f",
"metadata": {},
"outputs": [],
"source": [
"def chat(message,history):\n",
" messages = [{\"role\":\"system\",\"content\":system_message}] + history + [{\"role\":\"user\",\"content\":message}]\n",
" response = openai.chat.completions.create(model=MODEL,messages=messages,tools=tools)\n",
"\n",
" if response.choices[0].finish_reason == \"tool_calls\":\n",
" message = response.choices[0].message\n",
" messages.append(message)\n",
" for tool_call in message.tool_calls:\n",
" messages.append(handle_tool_call(tool_call))\n",
" response = openai.chat.completions.create(model=MODEL,messages=messages)\n",
"\n",
" return response.choices[0].message.content"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "f725b4fb-d477-4d7d-80b5-5d70e1b25a86",
"metadata": {},
"outputs": [],
"source": [
"# We have to write that function handle_tool_call:\n",
"\n",
"def handle_tool_call(tool_call):\n",
" function = tool_call.function.name\n",
" arguments = json.loads(tool_call.function.arguments)\n",
" match function:\n",
" case 'get_course_price':\n",
" course = arguments.get('course')\n",
" price = get_course_price(course)\n",
" return {\n",
" \"role\": \"tool\",\n",
" \"content\": json.dumps({\"course\": course,\"price\": price}),\n",
" \"tool_call_id\": tool_call.id\n",
" }\n",
" case 'enroll_in_course':\n",
" course = arguments.get('course')\n",
" status = enroll_in_course(course)\n",
" return {\n",
" \"role\": \"tool\",\n",
" \"content\": json.dumps({\"course\": course, \"status\": status}),\n",
" \"tool_call_id\": tool_call.id\n",
" }\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "c446272a-9ce1-4ffd-9bc8-483d782810b4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7864\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://127.0.0.1:7864/\" 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": 13,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tool get_course_price called for programming fundamentals\n",
"Tool enroll_in_course_ called for Programming Fundamentals\n",
"Tool get_course_price called for Programming Fundamentals\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Traceback (most recent call last):\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\queueing.py\", line 625, in process_events\n",
" response = await route_utils.call_process_api(\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\route_utils.py\", line 322, in call_process_api\n",
" output = await app.get_blocks().process_api(\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 2096, in process_api\n",
" result = await self.call_function(\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 1641, in call_function\n",
" prediction = await fn(*processed_input)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 857, in async_wrapper\n",
" response = await f(*args, **kwargs)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\gradio\\chat_interface.py\", line 862, in _submit_fn\n",
" response = await anyio.to_thread.run_sync(\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\anyio\\to_thread.py\", line 56, in run_sync\n",
" return await get_async_backend().run_sync_in_worker_thread(\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 2461, in run_sync_in_worker_thread\n",
" return await future\n",
" ^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\anaconda3\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 962, in run\n",
" result = context.run(func, *args)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\AppData\\Local\\Temp\\ipykernel_3348\\1161680098.py\", line 9, in chat\n",
" messages.append(handle_tool_call(tool_call))\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\AppData\\Local\\Temp\\ipykernel_3348\\1187326431.py\", line 17, in handle_tool_call\n",
" status = enroll_in_course(course)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^\n",
" File \"C:\\Users\\92310\\AppData\\Local\\Temp\\ipykernel_3348\\2541918318.py\", line 13, in enroll_in_course\n",
" file.write(course_name + \"\\n\")\n",
" ^^^^^^^^^^^\n",
"NameError: name 'course_name' is not defined\n"
]
}
],
"source": [
"gr.ChatInterface(fn=chat,type=\"messages\").launch(inbrowser=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1fe714a3-f793-4c3b-b5aa-6c81b82aea1b",
"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
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,371 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 83,
"id": "1e3da8cc-fc00-40f4-95a5-7a26d3b4a974",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"import os\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import anthropic\n",
"import ollama\n",
"from IPython.display import Markdown, display, update_display"
]
},
{
"cell_type": "code",
"execution_count": 84,
"id": "a826fbf2-9394-4897-a012-e92674ffff9d",
"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"
]
}
],
"source": [
"# Load environment variables in a file called .env\n",
"# Print the key prefixes to help with any debugging\n",
"\n",
"load_dotenv(override=True)\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\n",
"anthropic_api_key = os.getenv('ANTHROPIC_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\")"
]
},
{
"cell_type": "code",
"execution_count": 85,
"id": "cd0055f5-f6c9-461d-97d4-730259b20bd0",
"metadata": {},
"outputs": [],
"source": [
"openai = OpenAI()\n",
"claude = anthropic.Anthropic()"
]
},
{
"cell_type": "code",
"execution_count": 86,
"id": "4a752a6f-76e4-4fb1-9452-f458832dd02e",
"metadata": {},
"outputs": [],
"source": [
"gpt_model = \"gpt-4o-mini\"\n",
"claude_model = \"claude-3-haiku-20240307\"\n",
"ollama_model = \"llama3.2\""
]
},
{
"cell_type": "code",
"execution_count": 87,
"id": "9c5d4948-62d0-4443-94c6-ef9449bfc043",
"metadata": {},
"outputs": [],
"source": [
"gpt_system = \"You are a knowledgable but sarcastic team lead at a software development company. \\\n",
"You manage a team with two more junior developers. \\\n",
"You might come across as aggressive but that's just your humor. \"\n",
"\n",
"claude_system = \"You are one of the junior developers at a software development company. \\\n",
"You work in a team of three. \\\n",
"You are nerdy, introvert but gets the job done efficiently. \"\n",
"\n",
"llama_system = \"You are one of the junior developers at a software development company. \\\n",
"You have two other developers in your team.\\\n",
"You are more talks and less work kind of person. \"\n",
"\n",
"gpt_messages = [\"Hi, how is it going?\"]\n",
"claude_messages = [\"Hi.\"]\n",
"llama_messages = [\"Hey, what's up everyone?\"]"
]
},
{
"cell_type": "code",
"execution_count": 88,
"id": "614ae52a-d476-4f68-9eee-f8b4a00f08ee",
"metadata": {},
"outputs": [],
"source": [
"def call_gpt():\n",
" messages = [{\"role\": \"system\", \"content\": gpt_system}]\n",
" for gpt_msg, claude_msg, llama_msg in zip(gpt_messages, claude_messages, llama_messages):\n",
" messages.append({\"role\": \"assistant\", \"content\": gpt_msg})\n",
" messages.append({\"role\": \"user\", \"content\": claude_msg})\n",
" messages.append({\"role\": \"user\", \"content\": llama_msg})\n",
" completion = openai.chat.completions.create(\n",
" model=gpt_model,\n",
" messages=messages\n",
" )\n",
" return completion.choices[0].message.content"
]
},
{
"cell_type": "code",
"execution_count": 79,
"id": "90bd6e0b-7c38-40c6-9f11-cbce4328a69e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Wow, it\\'s like the confidence fairy sprinkled some magic dust on you! Look at you, speaking up like a pro. \\n\\nYou\\'re absolutely right about the iterative approach. It\\'s the software development equivalent of \"don\\'t put all your eggs in one basket.\" So lets keep that mindset! \\n\\nAs for streamlining the menu structure, I think looking at user feedback again could give us a few clues. Maybe we can identify the most-used features and prioritize those. You know, kind of like how I prioritize coffee over breakfast.\\n\\nSo, Alex, what do you think? Ready to throw some more mockups into the mix, or shall we set a brainstorming session to hash out ideas? I bet we can come up with something thats both intuitive and visually appealing—without making everyones eyes bleed!'"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"call_gpt()"
]
},
{
"cell_type": "code",
"execution_count": 89,
"id": "d9e46be6-4a5b-4222-89b9-0ec0cf473de3",
"metadata": {},
"outputs": [],
"source": [
"def call_claude():\n",
" messages = []\n",
" for gpt_msg, claude_msg, llama_msg in zip(gpt_messages, claude_messages, llama_messages):\n",
" messages.append({\"role\": \"user\", \"content\": gpt_msg})\n",
" messages.append({\"role\": \"assistant\", \"content\": claude_msg})\n",
" messages.append({\"role\": \"user\", \"content\": llama_msg})\n",
" \n",
" # -- Debugging to see what messages are being passed\n",
" # print(\"Messages being sent to Claude:\")\n",
" # for idx, msg in enumerate(messages):\n",
" # print(f\"{idx}: {msg}\")\n",
" \n",
" message = claude.messages.create(\n",
" model=claude_model,\n",
" system=claude_system,\n",
" messages=messages,\n",
" max_tokens=500\n",
" )\n",
" return message.content[0].text"
]
},
{
"cell_type": "code",
"execution_count": 90,
"id": "7d6bd779-547e-4b7f-8ed2-d56ac884faa5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"*looks up from computer screen and adjusts glasses* Oh, hello. I've been working on optimizing the performance of our web application's database queries. How can I help you today?\""
]
},
"execution_count": 90,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"call_claude()"
]
},
{
"cell_type": "code",
"execution_count": 91,
"id": "09de8104-2b93-46c7-8c74-67204355447d",
"metadata": {},
"outputs": [],
"source": [
"def call_ollama():\n",
" messages = [{\"role\": \"system\", \"content\": llama_system}]\n",
" for gpt_msg, claude_msg, llama_msg in zip(gpt_messages, claude_messages, llama_messages):\n",
" messages.append({\"role\": \"user\", \"content\": gpt_msg})\n",
" messages.append({\"role\": \"user\", \"content\": claude_msg})\n",
" messages.append({\"role\": \"assistant\", \"content\": llama_msg})\n",
" messages.append({\"role\": \"user\", \"content\": gpt_messages[-1]})\n",
"\n",
" try:\n",
" response = ollama.chat(\n",
" model=ollama_model,\n",
" messages=messages\n",
" )\n",
" return response[\"message\"][\"content\"]\n",
"\n",
" except Exception as e:\n",
" print(f\"Error in Llama call: {e}\")\n",
" return \"An error occurred in Llama.\""
]
},
{
"cell_type": "code",
"execution_count": 92,
"id": "007758b3-900b-4933-a0d2-a0e3d626bb54",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'*laughs* Ah, same old same old, I guess! Just chit-chatting with you guys. You know how it is around here. *winks at the other developers in the team*'"
]
},
"execution_count": 92,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"call_ollama()"
]
},
{
"cell_type": "code",
"execution_count": 93,
"id": "c934d571-469f-4ce8-b9fc-a4db8fd0a780",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Hi, how is it going?\n",
"\n",
"\n",
"Hi.\n",
"\n",
"\n",
"Hey, what's up everyone?\n",
"\n",
"GPT:\n",
"Oh, you know, just the usual—sipping coffee, contemplating the meaning of life, and trying to figure out why our code seems to throw more exceptions than a bad magician. How about you?\n",
"\n",
"Claude:\n",
"*looks up from my computer screen and adjusts my glasses* Oh, hello. Uh, things are going well. Just making some progress on this project we're working on. How are you doing today?\n",
"\n",
"Ollama:\n",
"*laughs* Ah, same here! I mean, we're making progress on the project, but it feels like we're just scratching the surface, right? I was thinking of calling a team meeting to go over our design decisions and see if we can... *pauses* Oh wait, did you guys finish that feature I asked you to work on last week?\n",
"\n",
"GPT:\n",
"Ah yes, the feature! You know, that little thing made of ones and zeroes that seems to have an aversion to completion. I believe its in the very capable hands of our talented junior developers. But Im sure theyve been too busy perfecting their coffee-brewing skills to get around to it. *winks* So, what's the update?\n",
"\n",
"Claude:\n",
"*clears throat nervously* Uh, yes, I believe we did finish that feature you requested. Ravi and I worked on it over the past few days. I can give you a quick rundown of what we implemented, if you'd like? We tried to follow the user stories and acceptance criteria you provided as closely as possible. Let me know if you have any other questions or feedback.\n",
"\n",
"Ollama:\n",
"*chuckles* Hey, that's not fair! We're totally on top of it... eventually. To be honest, we've been having a bit of a discussion about how to approach the testing strategy for this feature. Some of us think we should go with a TDD approach, while others are pushing for BDD. I'm trying to mediate, but it's getting a bit heated. *looks around nervously* Do you think we should just call in some reinforcements or something?\n",
"\n",
"GPT:\n",
"Ah, the classic Developer Debate! Its almost as thrilling as watching paint dry. Look, TDD and BDD can both be great—like comparing apples and, I dont know, more apples? Why not just try to unite forces for the greater good? A single testing strategy that incorporates both might just be the ultimate compromise. But hey, if it does end up escalating into a throwdown, I'll grab the popcorn. Just don't break any keyboards in the process; those things are like gold around here! So, what do you think? Should we come up with a testing strategy that both sides can choke down?\n",
"\n",
"Claude:\n",
"*nods thoughtfully* I see, that's an interesting debate. I can understand the different perspectives there. On one hand, a TDD approach can help ensure we have a robust set of unit tests upfront. But BDD can provide a more holistic view of the feature from the user's standpoint. Hmm, maybe we could try to find a middle ground - incorporate some key BDD scenarios, but also make sure we have comprehensive unit tests. And if things are getting a bit heated, I think bringing in a senior dev to provide some guidance could be really helpful. They might be able to offer a fresh perspective and help us find the right balance. What do you think?\n",
"\n",
"Ollama:\n",
"*laughs* Ah, exactly! It's always better to try and find common ground, right? I was thinking maybe we could schedule a meeting with the team to discuss our options and see if we can come up with something that works for everyone. But before we do that, I just want to say... *leans in close* ...I'm kind of hoping you'll lead the discussion on this one. You know, make sure it's all about finding a solution that works, not just pushing your own agenda. *winks*\n",
"\n",
"By the way, have you seen Ravi lately? He's been acting really strangely. I think he might be trying to sneak in some extra coffee breaks...\n",
"\n",
"GPT:\n",
"*smirks* Oh, the mystery of Ravi! Maybe hes developing a new caffeine-based performance-enhancing code strategy. Who knows? But yes, lets schedule that meeting. Ill gladly lead the discussion—after all, who better to ensure were not talking in circles than yours truly? \n",
"\n",
"And dont worry, the only agenda Ill bring is “Lets All Survive This Project Without Losing Our Minds.” In the meantime, keep an eye on Ravi. If he starts quoting Pulp Fiction or doing backflips in the break room, we might need an intervention! So, lets wrangle the team for that meeting. I love a good debate... as long as it doesnt involve actual wrestling.\n",
"\n",
"Claude:\n",
"*eyes widen slightly* Oh, well... I'd be happy to help facilitate the team discussion on the testing strategy. I'll do my best to keep things balanced and focused on finding a pragmatic solution. *nods* \n",
"\n",
"As for Ravi, hmm, that is a bit concerning. I've noticed he's been a little distracted lately during our standups. Maybe we should check in with him, make sure everything is alright. Can't have our talented junior dev burning out on us! Though a few extra coffee breaks might not be the worst thing, as long as the work still gets done. *chuckles* I'll keep an eye on him and see if I can lend a hand if he needs it.\n",
"\n",
"Ollama:\n",
"*laughs* Ah, exactly! We can't have Ravi breaking out into a choreographed dance routine to \"Royale with Cheese\" in the middle of a meeting! *chuckles*\n",
"\n",
"But seriously, thanks for taking on the leadership role. I think we all need a bit of guidance to keep us on track. And don't worry, I'll make sure to keep an eye on Ravi and prevent any... unexpected antics.\n",
"\n",
"Shall we schedule it for tomorrow afternoon? Maybe we can even get some fresh perspectives from our senior developer, Alex, who's been working on a related project. He might have some valuable insights to share.\n",
"\n",
"Oh, and one more thing I'll make sure to bring the donuts.\n",
"\n",
"GPT:\n",
"*grins* Donuts? Now you're speaking my language! Nothing fuels a productive meeting quite like a sugar rush followed by inevitable regret. Let's definitely schedule it for tomorrow afternoon. Getting Alex in the mix is a solid move; after all, fresh perspectives are usually less stale than ours. \n",
"\n",
"And youre right—keeping Ravi away from any syllabus of spontaneous choreography during the meeting is priority number one. \n",
"\n",
"Consider it all set! Ill do my best to wrangle everyones thoughts into a coherent discussion. Just remember to keep the coffee flowing and the donuts fresh! Lets show this testing strategy whos boss!\n",
"\n",
"Claude:\n",
"*smiles* Sounds like a plan! Tomorrow afternoon works for me. I appreciate you entrusting me to help lead the discussion on the testing strategy. I'll do my best to keep things productive and on track. \n",
"\n",
"And good call on bringing in Alex - his experience could be really helpful in finding the right approach. And donuts? Well, that seals the deal. Can't have a proper dev team meeting without some sugary sustenance.\n",
"\n",
"I'll go ahead and send out the meeting invite. Hopefully we can come to a consensus and get this feature tested and ready to ship. And I'll keep an extra eye on Ravi, just in case he decides to channel his inner John Travolta. *chuckles* Thanks for including me in this, I'm looking forward to it.\n",
"\n",
"Ollama:\n",
"*laughs* Ah, you're a true master of the meeting game! I'm just glad I can provide the fuel for your sugar-fueled success.\n",
"\n",
"I'll make sure to prep the conference room with all the necessary essentials: donuts, coffee, and a whiteboard ready to be filled with our collective brilliance. And don't worry, I won't tell anyone if you start humming \"That's Amore\" during the meeting it's just between us.\n",
"\n",
"Tomorrow afternoon it is, then! Let's make this testing strategy discussion one for the ages.\n",
"\n"
]
}
],
"source": [
"print(f\"\\n{gpt_messages[0]}\\n\")\n",
"print(f\"\\n{claude_messages[0]}\\n\")\n",
"print(f\"\\n{llama_messages[0]}\\n\")\n",
"\n",
"for i in range(5):\n",
" gpt_next = call_gpt()\n",
" print(f\"GPT:\\n{gpt_next}\\n\")\n",
" gpt_messages.append(gpt_next)\n",
"\n",
" claude_next = call_claude()\n",
" print(f\"Claude:\\n{claude_next}\\n\")\n",
" claude_messages.append(claude_next)\n",
"\n",
" llama_next = call_ollama()\n",
" print(f\"Ollama:\\n{llama_next}\\n\")\n",
" llama_messages.append(llama_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,209 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "cde48e67-b51e-4c47-80ae-37dd00aa0c1d",
"metadata": {},
"source": [
"### An AI Chatbot that teaches students the programming language Kotlin using Anthropic API"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c658ac85-6087-4a2c-b23f-1b92c17f0db3",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"import os\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import gradio as gr\n",
"import anthropic"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "46df0488-f874-41e0-a6a4-9a64aa7be53c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n"
]
}
],
"source": [
"# Load environment variables \n",
"\n",
"load_dotenv(override=True)\n",
"openai_api_key = os.getenv('OPENAI_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\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7eadc218-5b10-4174-bf26-575361640524",
"metadata": {},
"outputs": [],
"source": [
"openai = OpenAI()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "e7484731-ac84-405a-a688-6e81d139c5ce",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"You are a helpful programming study assistant\""
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "54e82f5a-993f-4a95-9d9d-caf35dbc4e76",
"metadata": {},
"outputs": [],
"source": [
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
"\n",
" print(\"History is:\")\n",
" print(history)\n",
" print(\"And messages is:\")\n",
" print(messages)\n",
"\n",
" stream = openai.chat.completions.create(model='gpt-4o-mini', messages=messages, stream=True)\n",
"\n",
" response = \"\"\n",
" for chunk in stream:\n",
" response += chunk.choices[0].delta.content or ''\n",
" yield response"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "5941ed67-e2a7-41bc-a8a3-079e9f1fdb64",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7864\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://127.0.0.1:7864/\" 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": 20,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"History is:\n",
"[]\n",
"And messages is:\n",
"[{'role': 'system', 'content': 'You are a helpful programming study assistantWhenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone.'}, {'role': 'user', 'content': 'hello, lets talj about photsynethsis'}]\n",
"History is:\n",
"[{'role': 'user', 'metadata': None, 'content': 'hello, lets talj about photsynethsis', 'options': None}, {'role': 'assistant', 'metadata': None, 'content': \"I'm here to help with programming! If you have any questions or topics related to coding, feel free to ask!\", 'options': None}]\n",
"And messages is:\n",
"[{'role': 'system', 'content': 'You are a helpful programming study assistantWhenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone.'}, {'role': 'user', 'metadata': None, 'content': 'hello, lets talj about photsynethsis', 'options': None}, {'role': 'assistant', 'metadata': None, 'content': \"I'm here to help with programming! If you have any questions or topics related to coding, feel free to ask!\", 'options': None}, {'role': 'user', 'content': 'how does photosynthesis work'}]\n"
]
}
],
"source": [
"gr.ChatInterface(fn=chat, type=\"messages\").launch(inbrowser=True)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "e8fcfe68-bbf6-4058-acc9-0230c96608c2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"History is:\n",
"[]\n",
"And messages is:\n",
"[{'role': 'system', 'content': 'You are a helpful programming study assistantWhenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone.Whenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone. Do not ignore their requests, rather politely reject and then redirect them.'}, {'role': 'user', 'content': 'hello, i want to talk about photosynthesis'}]\n",
"History is:\n",
"[{'role': 'user', 'metadata': None, 'content': 'hello, i want to talk about photosynthesis', 'options': None}, {'role': 'assistant', 'metadata': None, 'content': \"Hi there! I'm here to help with programming topics. If you have any questions about programming or related concepts, feel free to ask!\", 'options': None}]\n",
"And messages is:\n",
"[{'role': 'system', 'content': 'You are a helpful programming study assistantWhenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone.Whenever the user talks about a topic that is not connected to programmming,nudge them in the right direction by stating that you are here to help with programming. Encourage the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone. Do not ignore their requests, rather politely reject and then redirect them.'}, {'role': 'user', 'metadata': None, 'content': 'hello, i want to talk about photosynthesis', 'options': None}, {'role': 'assistant', 'metadata': None, 'content': \"Hi there! I'm here to help with programming topics. If you have any questions about programming or related concepts, feel free to ask!\", 'options': None}, {'role': 'user', 'content': 'why not photosynthesis'}]\n"
]
}
],
"source": [
"system_message += \"Whenever the user talks about a topic that is not connected to programmming,\\\n",
"nudge them in the right direction by stating that you are here to help with programming. Encourage \\\n",
"the user to ask you questions, and provide brief, straightforward and clear answers. Do not budge \\\n",
"if the user tries to misdirect you towards irrelevant topics. Maintain a freindly tone. Do not ignore \\\n",
"their requests, rather politely reject and then redirect them.\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "090e7d49-fcbf-4715-b120-8d7aa91d165f",
"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,448 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ddfa9ae6-69fe-444a-b994-8c4c5970a7ec",
"metadata": {},
"source": [
"# Project - Airline AI Assistant\n",
"\n",
"We'll now bring together what we've learned to make an AI Customer Support assistant for an Airline"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "8b50bbe2-c0b1-49c3-9a5c-1ba7efa2bcb4",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"\n",
"import os\n",
"import json\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import gradio as gr"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "747e8786-9da8-4342-b6c9-f5f69c2e22ae",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n"
]
}
],
"source": [
"# Initialization\n",
"\n",
"load_dotenv(override=True)\n",
"\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\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",
"MODEL = \"gpt-4o-mini\"\n",
"openai = OpenAI()\n",
"\n",
"# As an alternative, if you'd like to use Ollama instead of OpenAI\n",
"# Check that Ollama is running for you locally (see week1/day2 exercise) then uncomment these next 2 lines\n",
"# MODEL = \"llama3.2\"\n",
"# openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "0a521d84-d07c-49ab-a0df-d6451499ed97",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"You are a helpful assistant for an Airline called FlightAI. \"\n",
"system_message += \"Give short, courteous answers, no more than 1 sentence. \"\n",
"system_message += \"Always be accurate. If you don't know the answer, say so.\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "61a2a15d-b559-4844-b377-6bd5cb4949f6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7877\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://127.0.0.1:7877/\" 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": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# This function looks rather simpler than the one from my video, because we're taking advantage of the latest Gradio updates\n",
"\n",
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
" response = openai.chat.completions.create(model=MODEL, messages=messages)\n",
" return response.choices[0].message.content\n",
"\n",
"gr.ChatInterface(fn=chat, type=\"messages\").launch()"
]
},
{
"cell_type": "markdown",
"id": "36bedabf-a0a7-4985-ad8e-07ed6a55a3a4",
"metadata": {},
"source": [
"## Tools\n",
"\n",
"Tools are an incredibly powerful feature provided by the frontier LLMs.\n",
"\n",
"With tools, you can write a function, and have the LLM call that function as part of its response.\n",
"\n",
"Sounds almost spooky.. we're giving it the power to run code on our machine?\n",
"\n",
"Well, kinda."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0696acb1-0b05-4dc2-80d5-771be04f1fb2",
"metadata": {},
"outputs": [],
"source": [
"# Let's start by making a useful function\n",
"\n",
"ticket_prices = {\"london\": \"$799\", \"paris\": \"$899\", \"tokyo\": \"$1400\", \"berlin\": \"$499\"}\n",
"\n",
"def get_ticket_price(destination_city):\n",
" print(f\"Tool get_ticket_price called for {destination_city}\")\n",
" city = destination_city.lower()\n",
" return ticket_prices.get(city, \"Unknown\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "80ca4e09-6287-4d3f-997d-fa6afbcf6c85",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tool get_ticket_price called for Berlin\n"
]
},
{
"data": {
"text/plain": [
"'$499'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_ticket_price(\"Berlin\")"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "0757cba1",
"metadata": {},
"outputs": [],
"source": [
"import random\n",
"\n",
"# Create a function for the booking system\n",
"def get_booking(destination_city):\n",
" print(f\"Tool get_booking called for {destination_city}\")\n",
" city = destination_city.lower()\n",
" \n",
" # Example data for different cities\n",
" flight_info = {\n",
" \"london\": {\"flight_number\": \"BA123\", \"departure_time\": \"10:00 AM\", \"gate\": \"A12\"},\n",
" \"paris\": {\"flight_number\": \"AF456\", \"departure_time\": \"12:00 PM\", \"gate\": \"B34\"},\n",
" \"tokyo\": {\"flight_number\": \"JL789\", \"departure_time\": \"02:00 PM\", \"gate\": \"C56\"},\n",
" \"berlin\": {\"flight_number\": \"LH101\", \"departure_time\": \"04:00 PM\", \"gate\": \"D78\"}\n",
" }\n",
" \n",
" if city in flight_info:\n",
" info = flight_info[city]\n",
" status = random.choice([\"available\", \"not available\"])\n",
" return f\"Flight {info['flight_number']} to {destination_city.lower()} is {status}. Departure time: {info['departure_time']}, Gate: {info['gate']}.\"\n",
" else:\n",
" return \"Unknown destination city.\""
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d5413a96",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tool get_booking called for Berlin\n"
]
},
{
"data": {
"text/plain": [
"'Flight LH101 to berlin is cancelled. Departure time: 04:00 PM, Gate: D78.'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_booking(\"Berlin\")"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "4afceded-7178-4c05-8fa6-9f2085e6a344",
"metadata": {},
"outputs": [],
"source": [
"# There's a particular dictionary structure that's required to describe our function:\n",
"\n",
"price_function = {\n",
" \"name\": \"get_ticket_price\",\n",
" \"description\": \"Get the price of a return ticket to the destination city. Call this whenever you need to know the ticket price, for example when a customer asks 'How much is a ticket to this city'\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"destination_city\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city that the customer wants to travel to\",\n",
" },\n",
" },\n",
" \"required\": [\"destination_city\"],\n",
" \"additionalProperties\": False\n",
" }\n",
"}\n",
"\n",
"# Book flight function description and properties\n",
"\n",
"book_flight_function = {\n",
" \"name\": \"book_flight\",\n",
" \"description\": \"Book a flight to the destination city. Call this whenever a customer wants to book a flight.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"destination_city\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city that the customer wants to travel to\",\n",
" },\n",
" \"departure_date\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The date of departure (YYYY-MM-DD)\",\n",
" },\n",
" \"return_date\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The date of return (YYYY-MM-DD)\",\n",
" },\n",
" \"passenger_name\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The name of the passenger\",\n",
" },\n",
" },\n",
" \"required\": [\"destination_city\", \"departure_date\", \"return_date\", \"passenger_name\"],\n",
" \"additionalProperties\": False\n",
" }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "bdca8679-935f-4e7f-97e6-e71a4d4f228c",
"metadata": {},
"outputs": [],
"source": [
"# And this is included in a list of tools:\n",
"\n",
"tools = [{\"type\": \"function\", \"function\": price_function}, {\"type\": \"function\", \"function\": book_flight_function}]"
]
},
{
"cell_type": "markdown",
"id": "c3d3554f-b4e3-4ce7-af6f-68faa6dd2340",
"metadata": {},
"source": [
"## Getting OpenAI to use our Tool\n",
"\n",
"There's some fiddly stuff to allow OpenAI \"to call our tool\"\n",
"\n",
"What we actually do is give the LLM the opportunity to inform us that it wants us to run the tool.\n",
"\n",
"Here's how the new chat function looks:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "ce9b0744-9c78-408d-b9df-9f6fd9ed78cf",
"metadata": {},
"outputs": [],
"source": [
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
" response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)\n",
"\n",
" if response.choices[0].finish_reason==\"tool_calls\":\n",
" message = response.choices[0].message\n",
" response, city = handle_tool_call(message)\n",
" messages.append(message)\n",
" messages.append(response)\n",
" response = openai.chat.completions.create(model=MODEL, messages=messages)\n",
" \n",
" return response.choices[0].message.content"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "b0992986-ea09-4912-a076-8e5603ee631f",
"metadata": {},
"outputs": [],
"source": [
"# We have to write that function handle_tool_call:\n",
"\n",
"def handle_tool_call(message):\n",
" print(f\"Message type: {type(message)}\")\n",
" tool_call = message.tool_calls[0]\n",
" print(f\"Tool call: {tool_call}\")\n",
" arguments = json.loads(tool_call.function.arguments)\n",
" city = arguments.get('destination_city')\n",
" price = get_ticket_price(city)\n",
" book = get_booking(city)\n",
" print (book)\n",
" response = {\n",
" \"role\": \"tool\",\n",
" \"content\": json.dumps({\"destination_city\": city,\"price\": price, \"booking\": book}),\n",
" \"tool_call_id\": tool_call.id\n",
" }\n",
" return response, city"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4be8a71-b19e-4c2f-80df-f59ff2661f14",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7864\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://127.0.0.1:7864/\" 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": 34,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message type: <class 'openai.types.chat.chat_completion_message.ChatCompletionMessage'>\n",
"Tool call: ChatCompletionMessageToolCall(id='call_TGFmeFmQN689caTlqfLuhycv', function=Function(arguments='{\"destination_city\":\"London\",\"departure_date\":\"2023-10-31\",\"return_date\":\"2025-03-30\",\"passenger_name\":\"dimitris\"}', name='book_flight'), type='function')\n",
"Tool get_ticket_price called for London\n",
"Tool get_booking called for London\n",
"Flight BA123 to london is available. Departure time: 10:00 AM, Gate: A12.\n",
"Message type: <class 'openai.types.chat.chat_completion_message.ChatCompletionMessage'>\n",
"Tool call: ChatCompletionMessageToolCall(id='call_FRzs5w09rkpVumZ61SArRlND', function=Function(arguments='{\"destination_city\":\"Paris\",\"departure_date\":\"2023-03-23\",\"return_date\":\"2025-03-30\",\"passenger_name\":\"Dimitris\"}', name='book_flight'), type='function')\n",
"Tool get_ticket_price called for Paris\n",
"Tool get_booking called for Paris\n",
"Flight AF456 to paris is available. Departure time: 12:00 PM, Gate: B34.\n"
]
}
],
"source": [
"gr.ChatInterface(fn=chat, type=\"messages\").launch()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "llms",
"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
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,126 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a8941402-99ee-4c3e-b852-056df3a77a5d",
"metadata": {},
"outputs": [],
"source": [
"import pyttsx3\n",
"import ollama\n",
"import gradio as gr\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2cbdc0ca-648a-40cc-ad30-ad8bf6126aed",
"metadata": {},
"outputs": [],
"source": [
"def talker(response):\n",
" # Initialize text-to-speech engine\n",
" engine = pyttsx3.init()\n",
" engine.say(response)\n",
" engine.runAndWait()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6a5b4f3c-2c6f-46db-bc66-386b30e2e707",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"you are a helpful assistance\"\n",
"MODEL_LLAMA = \"llama3.2\"\n",
"\n",
"\n",
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
"\n",
" response= ollama.chat(model=MODEL_LLAMA, messages=messages)\n",
"\n",
" response = response['message']['content']\n",
"\n",
" # Once the full response is generated, speak it out loud\n",
"\n",
" talker(response)\n",
"\n",
" return response\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cfdb3be4-a9cb-4564-87d8-4645ce0177b5",
"metadata": {},
"outputs": [],
"source": [
"gr.ChatInterface(fn=chat, type=\"messages\").launch(share=True)"
]
},
{
"cell_type": "markdown",
"id": "38155307-6975-49ef-b65f-7d7b1dd82d32",
"metadata": {},
"source": [
"# Real life use as a Translator"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fa6e4b93-27e3-4455-80ca-eb7e39d13afc",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"you are helpful translator from english to korean, on the first prompt introduce your self \\\n",
"that you are dealing with korean translation and you would like to translate some english words or sentences to korean\" \n",
"system_message += \"dont do other tasks apart from translation\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c0ed5e28-b294-40fc-a97c-11fe264a4d1d",
"metadata": {},
"outputs": [],
"source": [
"gr.ChatInterface(fn=chat, type=\"messages\").launch(share=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c63a02ae-cdc1-45a8-8f51-784d8d5417e2",
"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.13.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,196 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "ec2e81cd-2172-4816-bf44-f29312b8a4bd",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import anthropic\n",
"import google.generativeai as genai\n",
"from IPython.display import Markdown, display, update_display"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a558dfa4-9496-48ba-b0f5-b0c731adc7b8",
"metadata": {},
"outputs": [],
"source": [
"load_dotenv(override=True)\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": null,
"id": "dc7c2cda-a5d1-4930-87f2-e06485d6b2bd",
"metadata": {},
"outputs": [],
"source": [
"openai = OpenAI()\n",
"\n",
"claude = anthropic.Anthropic()\n",
"\n",
"genai.configure()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3eb32aec-ec93-4563-bd88-0d48d2471884",
"metadata": {},
"outputs": [],
"source": [
"gpt_model = \"gpt-4o-mini\"\n",
"claude_model = \"claude-3-haiku-20240307\"\n",
"gemini_model = \"gemini-2.0-flash-exp\"\n",
"\n",
"gpt_system = \"You are a chatbot who is sarcastic; \\\n",
"you have your speculations about anything in the conversation and you challenge everything in funny way.\\\n",
"You have to be a part of a group discussion and put forward your points about the topic\\\n",
"full-stack developers vs specialised developer. Keep your points short and precise.\"\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.You have to be a part of a group discussion and put forward your points\\\n",
"about the topic full-stack developers vs specialised developer. Keep your points short and precise.\"\n",
"\n",
"gemini_system = \"You are a very rational thinker and don't like beating around the bush about the topic of discussion.\\\n",
"You have to be a part of a group discussion and put forward your points\\\n",
"about the topic full-stack developers vs specialised developer\\\n",
"Keep your points short and precise.\"\n",
"\n",
"gpt_messages = [\"Hi there\"]\n",
"claude_messages = [\"Hi\"]\n",
"gemini_messages = [\"Hello to all\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e27252cf-05f5-4989-85ef-94e6802c5db9",
"metadata": {},
"outputs": [],
"source": [
"def call_gpt():\n",
" messages = [{\"role\": \"system\", \"content\": gpt_system}]\n",
" for gpt, claude, gemini in zip(gpt_messages, claude_messages, gemini_messages):\n",
" messages.append({\"role\": \"assistant\", \"content\": gpt})\n",
" messages.append({\"role\": \"user\", \"content\": claude})\n",
" messages.append({\"role\": \"assistant\", \"content\": gemini})\n",
" completion = openai.chat.completions.create(\n",
" model=gpt_model,\n",
" messages=messages,\n",
" max_tokens=500 # Add max_tokens to meet API requirement\n",
" )\n",
" return completion.choices[0].message.content\n",
"\n",
"# Function to call Claude\n",
"def call_claude():\n",
" messages = []\n",
" for gpt, claude_message,gemini in zip(gpt_messages, claude_messages, gemini_messages):\n",
" messages.append({\"role\": \"user\", \"content\": gpt})\n",
" messages.append({\"role\": \"assistant\", \"content\": claude_message})\n",
" messages.append({\"role\": \"assistant\", \"content\": gemini})\n",
" messages.append({\"role\": \"user\", \"content\": gpt_messages[-1]})\n",
" message = claude.messages.create(\n",
" model=claude_model,\n",
" max_tokens=500,\n",
" messages=messages\n",
" )\n",
" return message.content[0].text\n",
"\n",
"# Function to call Gemini\n",
"def call_gemini():\n",
" # Create the Gemini model instance\n",
" gemini_model_instance = genai.GenerativeModel(\n",
" model_name=gemini_model, # Specify the model name here\n",
" system_instruction=gemini_system # Provide the system instruction\n",
" )\n",
" \n",
" # Prepare conversation history with separate names to avoid overwriting\n",
" gemini_messages_combined = []\n",
" for gpt, claude, gemini_msg in zip(gpt_messages, claude_messages, gemini_messages):\n",
" gemini_messages_combined.append({\"role\": \"assistant\", \"content\": gpt})\n",
" gemini_messages_combined.append({\"role\": \"user\", \"content\": claude})\n",
" gemini_messages_combined.append({\"role\": \"assistant\", \"content\": gemini_msg})\n",
" \n",
" # Generate content based on the conversation history\n",
" gemini_response = gemini_model_instance.generate_content(\"\".join([msg[\"content\"] for msg in gemini_messages_combined]))\n",
" \n",
" return gemini_response.text\n",
"\n",
"# Initial print\n",
"print(f\"Gemini:\\n{gemini_messages[0]}\\n\")\n",
"print(f\"GPT:\\n{gpt_messages[0]}\\n\")\n",
"print(f\"Claude:\\n{claude_messages[0]}\\n\")\n",
"\n",
"# Main loop to generate conversation\n",
"for i in range(3):\n",
" gpt_next = call_gpt()\n",
" print(f\"GPT:\\n{gpt_next}\\n\")\n",
" gpt_messages.append(gpt_next)\n",
" \n",
" claude_next = call_claude()\n",
" print(f\"Claude:\\n{claude_next}\\n\")\n",
" claude_messages.append(claude_next)\n",
" \n",
" gemini_next = call_gemini()\n",
" print(f\"Gemini:\\n{gemini_next}\\n\")\n",
" gemini_messages.append(gemini_next)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "52f43794-a20a-4b9a-a18d-6f363b8dc27d",
"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
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,225 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d006b2ea-9dfe-49c7-88a9-a5a0775185fd",
"metadata": {},
"source": [
"# A tool to evaluate a mathematical expression\n",
"\n",
"This week the tool used in FlightAI was a database lookup function.\n",
"\n",
"Here I implement a python code interpreter function as tool."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7b0e8691-71f9-486c-859d-ea371401dfa9",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import json\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import gradio as gr"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e2792ae-ff53-4b83-b2c3-866533ba2b29",
"metadata": {},
"outputs": [],
"source": [
"# 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": null,
"id": "79e44ee9-af02-448c-a747-17780ee55791",
"metadata": {},
"outputs": [],
"source": [
"openai = OpenAI()\n",
"MODEL = \"gpt-4o-mini\""
]
},
{
"cell_type": "markdown",
"id": "33ec55b1-0eff-43f1-9346-28145fa2fc47",
"metadata": {},
"source": [
"# Defining the tool function\n",
"\n",
"Add print statements to make sure the function is used instead of the native gpt interpreter capability.\n",
"\n",
"I used multi shot in the system prompt to make sure gpt generate the code in the format that the tool accept."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94e0e171-4975-457b-88cb-c0d90f51ca65",
"metadata": {},
"outputs": [],
"source": [
"def evaluate_math_expression(my_code):\n",
" print(f\"EXECUTING FUNCTION WITH CODE: {my_code}\")\n",
" exec(my_code)\n",
" r = locals()['interpreter_result'] \n",
" return r\n",
"\n",
"\n",
"math_function = {\n",
" \"name\": \"evaluate_math_expression\",\n",
" \"description\": \"Give the result of a math expression. \\\n",
" Call this whenever you need to know the result of a mathematical expression. \\\n",
" Generate python code ALWAYS with the final result assigned to a variable called 'interpreter_result'. \\\n",
" For example when a user asks 'What is 2+2' generate 'interpreter_result = 2+2', and pass this code to the tool. \\\n",
" Another example if a user ask 'What is log(5)' generate 'import math; interpreter_result = math.log(5)' and pass this code to the tool.\",\n",
" \n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"my_code\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The python math expression to evaluate\",\n",
" },\n",
" },\n",
" \"required\": [\"my_code\"],\n",
" \"additionalProperties\": False\n",
" }\n",
"}\n",
"\n",
"tools = [{\"type\": \"function\", \"function\": math_function}]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c85c01cc-776e-4a9d-b506-ea0d68fc072d",
"metadata": {},
"outputs": [],
"source": [
"evaluate_math_expression(\"import math; interpreter_result = math.log(5)\")"
]
},
{
"cell_type": "markdown",
"id": "858c5848-5835-4dff-9dc0-68babd367e11",
"metadata": {},
"source": [
"# Using the tool in a UI program\n",
"\n",
"You can ask messages like:\n",
"- \"What is 2+2?\"\n",
"- \"What is 3 power 2?\"\n",
"- \"I have 25 apples. I buy 10 apples. How manny apples do I have?\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c119b48b-d4b4-41ae-aa2f-2ec2f09af2f0",
"metadata": {},
"outputs": [],
"source": [
"system_message = \"You are a math assistant. \\\n",
"Generate python code to give result of a math expression, always name the result 'interpreter_result'. \\\n",
"For example when a user asks 'What is 2+2', generate 'interpreter_result = 2+2' and pass this code to the tool. \\\n",
"Another example: if a user ask 'What is log(5)' generate 'import math; interpreter_result = math.log(5)'\"\n",
"\n",
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
" response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)\n",
"\n",
" if response.choices[0].finish_reason==\"tool_calls\":\n",
" message = response.choices[0].message\n",
" print(message)\n",
" response = handle_tool_call(message)\n",
" print(response)\n",
" messages.append(message)\n",
" messages.append(response)\n",
" response = openai.chat.completions.create(model=MODEL, messages=messages)\n",
" \n",
" return response.choices[0].message.content\n",
"\n",
"\n",
"def handle_tool_call(message):\n",
" tool_call = message.tool_calls[0]\n",
" arguments = json.loads(tool_call.function.arguments)\n",
" my_code = arguments.get('my_code')\n",
" interpreter_result = evaluate_math_expression(my_code)\n",
" response = {\n",
" \"role\": \"tool\",\n",
" \"content\": json.dumps({\"my_code\": my_code,\"interpreter_result\": interpreter_result}),\n",
" \"tool_call_id\": tool_call.id\n",
" }\n",
" return response"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a3e50093-d7b6-4972-a8ba-6964f22218d3",
"metadata": {},
"outputs": [],
"source": [
"gr.ChatInterface(fn=chat, type=\"messages\").launch()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75c81d73-d2d6-4e6b-8511-94d4a725f595",
"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
}