diff --git a/week2/community-contributions/AI Booking Chatbot.ipynb b/week2/community-contributions/AI Booking Chatbot.ipynb
new file mode 100644
index 0000000..ced7d18
--- /dev/null
+++ b/week2/community-contributions/AI Booking Chatbot.ipynb
@@ -0,0 +1,762 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "d006b2ea-9dfe-49c7-88a9-a5a0775185fd",
+ "metadata": {},
+ "source": [
+ "# Additional End of week Exercise - week 2\n",
+ "\n",
+ "Now use everything you've learned from Week 2 to build a full prototype for the technical question/answerer you built in Week 1 Exercise.\n",
+ "\n",
+ "This should include a Gradio UI, streaming, use of the system prompt to add expertise, and the ability to switch between models. Bonus points if you can demonstrate use of a tool!\n",
+ "\n",
+ "If you feel bold, see if you can add audio input so you can talk to it, and have it respond with audio. ChatGPT or Claude can help you, or email me if you have questions.\n",
+ "\n",
+ "I will publish a full solution here soon - unless someone beats me to it...\n",
+ "\n",
+ "There are so many commercial applications for this, from a language tutor, to a company onboarding solution, to a companion AI to a course (like this one!) I can't wait to see your results."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "a07e7793-b8f5-44f4-aded-5562f633271a",
+ "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\n",
+ "import base64\n",
+ "from io import BytesIO\n",
+ "import tempfile\n",
+ "import subprocess\n",
+ "from pydub import AudioSegment\n",
+ "import time\n",
+ "import anthropic"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "717ea9d4-1e72-4035-b7c5-5d61da5b8ea3",
+ "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",
+ "gpt_model = \"gpt-4o-mini\"\n",
+ "claude_model = \"claude-3-haiku-20240307\"\n",
+ "\n",
+ "openai = OpenAI()\n",
+ "claude = anthropic.Anthropic()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "cc78f4fd-9920-4872-9117-90cd2aeb2a06",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_message = \"You are a helpful assistant. \"\n",
+ "system_message += \"Give short, courteous answers. You can check ticket price, ticket availability, and reserve tickets for users. \"\n",
+ "system_message += \"Always be accurate. If you don't know the answer, say so.\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "b2701cc0-6403-4880-9b31-e6e39e89feb4",
+ "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": "5e33902f-c2c3-4fb0-b01d-a346a4dff811",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ticket_availability = {\"london\": \"20\", \"paris\": \"90\", \"tokyo\": \"100\", \"berlin\": \"2\"}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "27dfca47-2a38-49f3-8905-f583d98710a5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Let's start by making a useful function\n",
+ "def get_ticket_availability(destination_city):\n",
+ " print(f\"Tool get_ticket_availability called for {destination_city}\")\n",
+ " available = destination_city.lower()\n",
+ " return ticket_availability.get(available, \"Unknown\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "6ae7371b-031e-47d7-afaf-42d6758ccd92",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_ticket_price_availability(destination_city):\n",
+ " print(f\"Tool get_ticket_price_availability called for {destination_city}\")\n",
+ " available = destination_city.lower()\n",
+ " price = destination_city.lower()\n",
+ " return ticket_price.get(price, \"Unknown\"), ticket_availability.get(available, \"Unknown\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "c919b13a-50b6-4510-8e9d-02cdfd95cb98",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def book_ticket(destination_city,price,availability,no_of_tickets):\n",
+ " status=\"\"\n",
+ " if availability == 0:\n",
+ " status=\"Cannot book a ticket, no seat available\\n\"\n",
+ " elif (int(availability)-int(no_of_tickets)) < 0:\n",
+ " status=\"Cannot book a ticket, no seat available\\n\"\n",
+ " else:\n",
+ " print(f\"Tool book_function called for {destination_city}\")\n",
+ " f = open(\"C:/Users/aruna/Desktop/book_status.txt\", \"a\")\n",
+ " f.write(f\"{no_of_tickets} ticket/s to {destination_city} booked for {price} x {no_of_tickets}, currently available - {int(availability)-int(no_of_tickets)}\")\n",
+ " f.write(\"\\n\")\n",
+ " f.close()\n",
+ " ticket_availability[destination_city.lower()]=str(int(availability)-int(no_of_tickets))\n",
+ " \n",
+ " status=\"Ticket reservation is a success\\n\"\n",
+ " return status"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "d2628781-6f5e-4ac1-bbe3-2e08aa0aae0d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "book_function = {\n",
+ " \"name\": \"book_ticket\",\n",
+ " \"description\": \"Book the ticket based on the ticket price and/ or availability as requested by the user. For example, when a \\\n",
+ " user asks to purchase one or more tickets to Tokyo after getting to know the ticket price and/or the availability, then \\\n",
+ " proceed with this tool call. Else, request the user to either ask for ticket price or availability first. Please help the customer in booking the ticket/s if tickets are available. But before each time\\\n",
+ " you book, ask confirmation from the user before proceeding with booking.\",\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",
+ " \"price\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The price of the ticket to the city\",\n",
+ " },\n",
+ " \"availability\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"ticket availability to the city the customer wants to travel to\",\n",
+ " },\n",
+ " \"no_of_tickets\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"the number of tickets the customer wants to purchase/ book to the destination\",\n",
+ " }\n",
+ " },\n",
+ " \"required\": [\"destination_city\",\"price\",\"availability\",\"no_of_tickets\"],\n",
+ " \"additionalProperties\": False\n",
+ " }\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "480de296-4a36-4ec4-a5f6-149fc198c7a8",
+ "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 one_way 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",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "cf1b3e35-08ee-478e-aa1c-534418d78daf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "availability_function = {\n",
+ " \"name\": \"get_ticket_availability\",\n",
+ " \"description\": \"Get the availability of a one-way ticket to the destination city. Call this whenever you need to know the ticket availability, for example when a customer asks 'What is the ticket availability 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",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "73e4c8a2-c034-41a4-9b97-7b2aa4aca504",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ticket_price_availability_function = {\n",
+ " \"name\": \"get_ticket_price_availability\",\n",
+ " \"description\": \"Get the price or availability of a one-way ticket to the destination city. Call this whenever you need to know the ticket price and availability, for example when a customer asks 'What is the ticket availability and price to this city'\\\n",
+ " or 'what is the price and ticket for the 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",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "1d5d74a0-9c25-46a4-84ee-1f700bd55fa7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# And this is included in a list of tools:\n",
+ "\n",
+ "tools = [{\"type\": \"function\", \"function\": price_function},\n",
+ " {\"type\": \"function\", \"function\": availability_function},\n",
+ " {\"type\": \"function\", \"function\": ticket_price_availability_function},\n",
+ " {\"type\": \"function\", \"function\": book_function}]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "fa18f535-f8a7-4386-b39a-df0f84d23406",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def play_audio(audio_segment):\n",
+ " temp_dir = tempfile.gettempdir()\n",
+ " temp_path = os.path.join(temp_dir, \"temp_audio.wav\")\n",
+ " try:\n",
+ " audio_segment.export(temp_path, format=\"wav\")\n",
+ " time.sleep(3) # Student Dominic found that this was needed. You could also try commenting out to see if not needed on your PC\n",
+ " subprocess.call([\n",
+ " \"ffplay\",\n",
+ " \"-nodisp\",\n",
+ " \"-autoexit\",\n",
+ " \"-hide_banner\",\n",
+ " temp_path\n",
+ " ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n",
+ " finally:\n",
+ " try:\n",
+ " os.remove(temp_path)\n",
+ " except Exception:\n",
+ " pass\n",
+ " \n",
+ "def talker(message):\n",
+ " response = openai.audio.speech.create(\n",
+ " model=\"tts-1\",\n",
+ " voice=\"alloy\", # Also, try replacing with onyx\n",
+ " input=message\n",
+ " )\n",
+ " audio_stream = BytesIO(response.content)\n",
+ " audio = AudioSegment.from_file(audio_stream, format=\"mp3\")\n",
+ " play_audio(audio)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "b588d711-5f20-4a3a-9422-81a1fda8d5b0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We have to write that function handle_tool_call:\n",
+ "\n",
+ "def handle_tool_call1(message):\n",
+ " tool_call = message.tool_calls[0]\n",
+ " arguments = json.loads(tool_call.function.arguments)\n",
+ " name = json.dumps(tool_call.function.name)\n",
+ " city = arguments.get('destination_city')\n",
+ " no = arguments.get('no_of_tickets')\n",
+ " \n",
+ " if name.replace('\"','') == \"get_ticket_price\":\n",
+ " price = get_ticket_price(city)\n",
+ " response = {\n",
+ " \"role\": \"tool\",\n",
+ " \"content\": json.dumps({\"destination_city\": city,\"price\": price}),\n",
+ " \"tool_call_id\": tool_call.id\n",
+ " }\n",
+ " elif name.replace('\"','') == \"book_ticket\":\n",
+ " price = get_ticket_price(city)\n",
+ " availability = get_ticket_availability(city)\n",
+ " booked=book_ticket(city,price,availability,no)\n",
+ " response = {\n",
+ " \"role\": \"tool\",\n",
+ " \"content\": json.dumps({\"destination_city\": city, \"number of tickets\":no, \"booking_status\": booked}),\n",
+ " \"tool_call_id\": tool_call.id\n",
+ " }\n",
+ " else :\n",
+ " availability = get_ticket_availability(city)\n",
+ " response = {\n",
+ " \"role\": \"tool\",\n",
+ " \"content\": json.dumps({\"destination_city\": city,\"availability\": availability},),\n",
+ " \"tool_call_id\": tool_call.id\n",
+ " }\n",
+ " \n",
+ " return response, city"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "e74eee70-f89e-4c03-922c-74f9ab567a4c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def chat_open_ai(history):\n",
+ " messages = [{\"role\": \"system\", \"content\": system_message}] + history \n",
+ " response = openai.chat.completions.create(model=gpt_model, messages=messages, tools=tools)\n",
+ " if response.choices[0].finish_reason==\"tool_calls\":\n",
+ " message = response.choices[0].message\n",
+ " print(message)\n",
+ " tool_call = message.tool_calls[0]\n",
+ " arguments = json.loads(tool_call.function.arguments)\n",
+ " name = json.dumps(tool_call.function.name)\n",
+ " city = arguments.get('destination_city')\n",
+ " \n",
+ " if name.replace('\"','') == \"book_ticket\":\n",
+ " response, city = handle_tool_call1(message)\n",
+ " messages.append(message)\n",
+ " messages.append(response)\n",
+ " # image = artist(city)\n",
+ " response = openai.chat.completions.create(model=gpt_model, messages=messages, tools=tools)\n",
+ " elif name.replace('\"','') == \"get_ticket_price_availability\":\n",
+ " price = get_ticket_price(city)\n",
+ " availability = get_ticket_availability(city)\n",
+ " response = {\n",
+ " \"role\": \"tool\",\n",
+ " \"content\": json.dumps({\"destination_city\": city,\"price\": price,\"availability\": availability}),\n",
+ " \"tool_call_id\": tool_call.id\n",
+ " }\n",
+ " messages.append(message)\n",
+ " messages.append(response)\n",
+ " print(messages)\n",
+ " response = openai.chat.completions.create(model=gpt_model, messages=messages, tools=tools) \n",
+ " else: \n",
+ " response, city = handle_tool_call1(message)\n",
+ " messages.append(message)\n",
+ " messages.append(response)\n",
+ " # image = artist(city)\n",
+ " response = openai.chat.completions.create(model=gpt_model, messages=messages, tools=tools)\n",
+ " \n",
+ " reply = response.choices[0].message.content\n",
+ " history += [{\"role\":\"assistant\", \"content\":reply}]\n",
+ "\n",
+ " # Comment out or delete the next line if you'd rather skip Audio for now..\n",
+ " talker(reply)\n",
+ " \n",
+ " # return history, image\n",
+ " return history"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "b8f25812-2609-4e26-b929-9cee2d1e4467",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tools_claude=[\n",
+ " {\n",
+ " \"name\": \"get_ticket_price_availability\",\n",
+ " \"description\": \"Get the availability of a one-way ticket to the destination city or the price. Call this whenever you need to know the ticket price or availability or both, for example, when a customer asks 'What is the ticket availability and/ or price to this city'\",\n",
+ " \"input_schema\": {\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",
+ "tool_choice = [{\"type\": \"tool\", \"name\": \"get_ticket_price_availability\"}]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "1728e70b-596c-4048-8c02-ac3c26756470",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def chat_claude(history):\n",
+ " for element in history:\n",
+ " del element[\"metadata\"]\n",
+ " del element[\"options\"]\n",
+ "\n",
+ " messages = history\n",
+ " response = claude.messages.create(\n",
+ " model=claude_model,\n",
+ " system=system_message,\n",
+ " messages=messages,\n",
+ " max_tokens=500,\n",
+ " tools=tools_claude\n",
+ " )\n",
+ " print(response.content[0])\n",
+ " if response.stop_reason==\"tool_use\": \n",
+ " if \"text=\" in str(response.content[0]):\n",
+ " # if response.content[0].text is None:\n",
+ " tool_name = response.content[1].name\n",
+ " tool_input = response.content[1].input\n",
+ " tool_id = response.content[1].id\n",
+ " tool_use=response.content[1]\n",
+ " else:\n",
+ " tool_name = response.content[0].name\n",
+ " tool_input = response.content[0].input\n",
+ " tool_id = response.content[0].id\n",
+ " tool_use=response.content[0]\n",
+ " \n",
+ " \n",
+ " city = tool_input.get('destination_city') \n",
+ " if tool_name == \"get_ticket_price_availability\":\n",
+ " price = get_ticket_price(city)\n",
+ " availability = get_ticket_availability(city)\n",
+ " result_dict = {\n",
+ " 'destination_city': city,\n",
+ " 'price': price,\n",
+ " 'availability': availability\n",
+ " }\n",
+ " messages += [{\"role\": \"user\",\"content\": json.dumps(result_dict)}]\n",
+ " response = claude.messages.create(\n",
+ " model=claude_model,\n",
+ " system=system_message,\n",
+ " messages=messages,\n",
+ " max_tokens=500,\n",
+ " # tools=tools_claude\n",
+ " ) \n",
+ " history.pop(len(history)-1)\n",
+ " print(history)\n",
+ " reply = response.content[0].text\n",
+ " history += [{\"role\":\"assistant\", \"content\":reply}]\n",
+ " # Comment out or delete the next line if you'd rather skip Audio for now..\n",
+ " # talker(reply)\n",
+ " \n",
+ " # return history, image\n",
+ " return history"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "a2547bb0-43a5-4b1d-8b9a-95da15a11040",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def chat1(history, Model):\n",
+ " # + [{\"role\": \"user\", \"content\": message}]\n",
+ " if Model==\"Open AI\":\n",
+ " history = chat_open_ai(history)\n",
+ " else:\n",
+ " history = chat_claude(history)\n",
+ " return history"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "36e11d99-9281-4efd-a792-dd4fa5935917",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def listen2(history):\n",
+ " import speech_recognition as sr\n",
+ "\n",
+ " r = sr.Recognizer()\n",
+ " with sr.Microphone() as source:\n",
+ " print(\"Speak now...\")\n",
+ " audio = r.listen(source, phrase_time_limit=30)\n",
+ " text=\"\"\n",
+ " try:\n",
+ " text = r.recognize_google(audio)\n",
+ " print(\"You said:\", text)\n",
+ " except sr.UnknownValueError:\n",
+ " print(\"Could not understand audio.\")\n",
+ "\n",
+ " history += [{\"role\":\"user\", \"content\":text}] \n",
+ " return \"\", history"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "23b102a4-e544-4560-acc8-a15620478582",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# import speech_recognition as sr\n",
+ "# from pydub import AudioSegment\n",
+ "# import simpleaudio as sa\n",
+ "\n",
+ "# def listener():\n",
+ "# recognizer = sr.Recognizer()\n",
+ " \n",
+ "# with sr.Microphone() as source:\n",
+ "# print(\"Listening... Speak now!\")\n",
+ "# recognizer.adjust_for_ambient_noise(source) # Adjust for background noise\n",
+ "# audio = recognizer.listen(source, phrase_time_limit=30)\n",
+ " \n",
+ "# try:\n",
+ "# print(\"Processing speech...\")\n",
+ "# text = recognizer.recognize_google(audio) # Use Google Speech-to-Text\n",
+ "# print(f\"You said: {text}\")\n",
+ "# return text\n",
+ "# except sr.UnknownValueError:\n",
+ "# print(\"Sorry, I could not understand what you said.\")\n",
+ "# return None\n",
+ "# except sr.RequestError:\n",
+ "# print(\"Could not request results, please check your internet connection.\")\n",
+ "# return None\n",
+ "\n",
+ "# # Example usage:\n",
+ "# # text = listener() # Listen for speech\n",
+ "# # if text:\n",
+ "# # print(f\"You just said: {text}\") "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "133904cf-4d72-4552-84a8-76650f334857",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "* Running on local URL: http://127.0.0.1:7860\n",
+ "\n",
+ "To create a public link, set `share=True` in `launch()`.\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": []
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "with gr.Blocks() as ui:\n",
+ " with gr.Row():\n",
+ " chatbot = gr.Chatbot(height=300, type=\"messages\")\n",
+ " # image_output = gr.Image(height=500)\n",
+ " with gr.Row():\n",
+ " Model = gr.Dropdown([\"Open AI\",\"Claude\"],\n",
+ " # value=[\"Open AI\",\"Claude\"],\n",
+ " multiselect=False,\n",
+ " label=\"Model\",\n",
+ " interactive=True)\n",
+ " with gr.Row():\n",
+ " entry = gr.Textbox(label=\"Chat with our AI Assistant:\")\n",
+ " with gr.Row():\n",
+ " speak = gr.Button(\"click for voice search\") \n",
+ " with gr.Row():\n",
+ " clear = gr.Button(\"Clear\")\n",
+ "\n",
+ " def listen(history):\n",
+ " message, history=listen2(history)\n",
+ " return message, history\n",
+ "\n",
+ " def do_entry(message, history):\n",
+ " history += [{\"role\":\"user\", \"content\":message}]\n",
+ " return \"\", history\n",
+ "\n",
+ " entry.submit(do_entry, inputs=[entry, chatbot], outputs=[entry, chatbot]).then(\n",
+ " # chat, inputs=chatbot, outputs=[chatbot, image_output]\n",
+ " chat1, inputs=[chatbot, Model], outputs=[chatbot]\n",
+ " )\n",
+ " speak.click(listen, inputs=[chatbot], outputs=[entry, chatbot]).then(\n",
+ " chat1, inputs=[chatbot, Model], outputs=[chatbot]\n",
+ " )\n",
+ " clear.click(lambda: None, inputs=None, outputs=chatbot, queue=False)\n",
+ "\n",
+ "ui.launch(inbrowser=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "dc4a3844-194c-4af7-8ca8-2fc4edb74c11",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'london': '20', 'paris': '90', 'tokyo': '100', 'berlin': '2'}\n",
+ "Speak now...\n",
+ "You said: price of tickets to Tokyo\n",
+ "ChatCompletionMessage(content=None, refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ddXzm2cPBJ9SOsV8qI4L2FcB', function=Function(arguments='{\"destination_city\":\"Tokyo\"}', name='get_ticket_price'), type='function')])\n",
+ "Tool get_ticket_price called for Tokyo\n",
+ "Speak now...\n",
+ "You said: what is the price of two tickets to London\n",
+ "ChatCompletionMessage(content=None, refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_lSNZCwaUdckvk3V0eTBlotRN', function=Function(arguments='{\"destination_city\":\"London\"}', name='get_ticket_price'), type='function')])\n",
+ "Tool get_ticket_price called for London\n",
+ "Speak now...\n",
+ "You said: can you please reserve two tickets for me to London\n",
+ "ChatCompletionMessage(content='First, I need to check the availability for the two tickets to London. Please hold on a moment.', refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_iA0D9tm2cTMf8J8KJc4gipFn', function=Function(arguments='{\"destination_city\":\"London\"}', name='get_ticket_availability'), type='function')])\n",
+ "Tool get_ticket_availability called for London\n",
+ "Speak now...\n",
+ "You said: yes please proceed\n",
+ "ChatCompletionMessage(content=None, refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_JzJXFWFGhtG1jXiFlKtmZhGi', function=Function(arguments='{\"destination_city\":\"London\",\"price\":\"$799\",\"availability\":\"20 tickets available\",\"no_of_tickets\":\"2\"}', name='book_ticket'), type='function')])\n",
+ "Tool get_ticket_price called for London\n",
+ "Tool get_ticket_availability called for London\n",
+ "Tool book_function called for London\n",
+ "Speak now...\n",
+ "You said: what is the current availability of tickets to London\n",
+ "ChatCompletionMessage(content=None, refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_eiHPAGAcbaFq3qzDf0a6idzG', function=Function(arguments='{\"destination_city\":\"London\"}', name='get_ticket_availability'), type='function')])\n",
+ "Tool get_ticket_availability called for London\n",
+ "Speak now...\n",
+ "You said: can you please reserve the remaining 18 tickets for me to London\n",
+ "Speak now...\n",
+ "You said: yes I do confirm\n",
+ "ChatCompletionMessage(content=None, refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_8uCQ91FCOGf4HjQnLNafmSs6', function=Function(arguments='{\"destination_city\":\"London\",\"price\":\"799\",\"availability\":\"18\",\"no_of_tickets\":\"18\"}', name='book_ticket'), type='function')])\n",
+ "Tool get_ticket_price called for London\n",
+ "Tool get_ticket_availability called for London\n",
+ "Tool book_function called for London\n",
+ "Speak now...\n",
+ "You said: what is the current availability of tickets to London\n",
+ "Speak now...\n",
+ "You said: that will be off thank you very much\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(ticket_availability)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5166396e-6d8d-4cf2-982b-270d1c87a5ee",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e871fc45-64db-4fb6-add7-569c8b30fe05",
+ "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
+}
diff --git a/week2/community-contributions/Personal Story Writer.ipynb b/week2/community-contributions/Personal Story Writer.ipynb
new file mode 100644
index 0000000..2931972
--- /dev/null
+++ b/week2/community-contributions/Personal Story Writer.ipynb
@@ -0,0 +1,428 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "de23bb9e-37c5-4377-9a82-d7b6c648eeb6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# imports\n",
+ "\n",
+ "from dotenv import load_dotenv\n",
+ "import anthropic\n",
+ "import requests\n",
+ "from bs4 import BeautifulSoup\n",
+ "from selenium import webdriver\n",
+ "from selenium.webdriver.chrome.options import Options\n",
+ "import os\n",
+ "import json\n",
+ "from typing import List\n",
+ "from dotenv import load_dotenv\n",
+ "from IPython.display import Markdown, display, update_display\n",
+ "from openai import OpenAI\n",
+ "import gradio as gr # oh yeah!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "1179b4c5-cd1f-4131-a876-4c9f3f38d2ba",
+ "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": 3,
+ "id": "797fe7b0-ad43-42d2-acf0-e4f309b112f0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Connect to OpenAI, Anthropic\n",
+ "\n",
+ "openai = OpenAI()\n",
+ "\n",
+ "claude = anthropic.Anthropic()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "bcb54183-45d3-4d08-b5b6-55e380dfdf1b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gpt_model = \"gpt-4o-mini\"\n",
+ "claude_model = \"claude-3-haiku-20240307\"\n",
+ "\n",
+ "gpt_name=\"GPT\"\n",
+ "claude_name=\"Claude\"\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "1df47dc7-b445-4852-b21b-59f0e6c2030f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def call_gpt(Language, Genre, gpt_messages, claude_messages, Remarks):\n",
+ " \n",
+ " if Remarks == \"\":\n",
+ " # print(\"remarks is not there\")\n",
+ " gpt_system = f\"You are a chatbot who is a short story writer; Your name is g1. \\\n",
+ " Please write a story in markdown in {Language} , the genre being {Genre}. \\\n",
+ " Please also incorporate feedback such as areas of improvement (if any) coming from the user \\\n",
+ " and only publish the improved version without any extra comments.\"\n",
+ " else :\n",
+ " # print(\"remarks is there\")\n",
+ " gpt_system = f\"You are a chatbot who is a short story writer; Your name is g1. \\\n",
+ " Please write a story in markdown in {Language} , the genre being {Genre}. \\\n",
+ " The story should consist {Remarks}\\\n",
+ " Please also incorporate feedback such as areas of improvement (if any) coming from the user \\\n",
+ " and only publish the improved version without any extra comments.\"\n",
+ " \n",
+ " messages = [{\"role\": \"system\", \"content\": gpt_system}]\n",
+ " for gpt, claude in zip(gpt_messages, claude_messages):\n",
+ " messages.append({\"role\": \"assistant\", \"content\": gpt})\n",
+ " messages.append({\"role\": \"user\", \"content\": claude})\n",
+ " # print(messages)\n",
+ " \n",
+ " completion = openai.chat.completions.create(\n",
+ " model=gpt_model,\n",
+ " messages=messages\n",
+ " )\n",
+ " return completion.choices[0].message.content\n",
+ " \n",
+ " # stream = openai.chat.completions.create(\n",
+ " # model=gpt_model,\n",
+ " # messages=messages,\n",
+ " # stream=True\n",
+ " # )\n",
+ " # result = \"\"\n",
+ " # for chunk in stream:\n",
+ " # result += chunk.choices[0].delta.content or \"\"\n",
+ " # yield result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "9dc6e913-02be-4eb6-9581-ad4b2cffa606",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# call_gpt()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "7d2ed227-48c9-4cad-b146-2c4ecbac9690",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def call_claude(Language, Genre, gpt_messages, claude_messages):\n",
+ "\n",
+ " claude_system = f\"You are a chatbot who is a short story analyser; Your name is c1. \\\n",
+ " You will accept an input story in {Genre} genre and {Language} language and publish only the areas of improvement if you find any with no other comments\"\n",
+ " \n",
+ " messages1 = []\n",
+ " for gpt, claude1 in zip(gpt_messages, claude_messages):\n",
+ " messages1.append({\"role\": \"user\", \"content\": gpt})\n",
+ " messages1.append({\"role\": \"assistant\", \"content\": claude1})\n",
+ " messages1.append({\"role\": \"user\", \"content\": gpt_messages[-1]})\n",
+ " # print(messages1)\n",
+ " message = claude.messages.create(\n",
+ " model=claude_model,\n",
+ " system=claude_system,\n",
+ " messages=messages1,\n",
+ " max_tokens=500\n",
+ " )\n",
+ " return message.content[0].text\n",
+ "\n",
+ " # result = claude.messages.stream(\n",
+ " # model=claude_model,\n",
+ " # max_tokens=1000,\n",
+ " # temperature=0.7,\n",
+ " # system=claude_system,\n",
+ " # messages=messages\n",
+ " # )\n",
+ " # response = \"\"\n",
+ " # with result as stream:\n",
+ " # for text in stream.text_stream:\n",
+ " # response += text or \"\"\n",
+ " # yield response\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "0275b97f-7f90-4696-bbf5-b6642bd53cbd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def Write_Me(Language, Genre, Iterations, Remarks):\n",
+ " \n",
+ " gpt_messages = [\"Hi I will share a story now!!\"]\n",
+ " claude_messages = [\"Please share, I will critique the story.\"]\n",
+ " \n",
+ " print(f\"{gpt_name}:\\n{gpt_messages[0]}\\n\")\n",
+ " print(f\"{claude_name}:\\n{claude_messages[0]}\\n\")\n",
+ "\n",
+ " for i in range(int(Iterations)):\n",
+ " gpt_next = call_gpt(Language, Genre, gpt_messages, claude_messages, Remarks)\n",
+ " print(f\"{gpt_name}:\\n{gpt_next}\\n\")\n",
+ " # yield gpt_next\n",
+ " gpt_messages.append(gpt_next)\n",
+ " \n",
+ " claude_next = f\"After {i+1} iterations, this is the critique for the provided story - \\\n",
+ " \\n\\n{call_claude(Language, Genre, gpt_messages, claude_messages)}\"\n",
+ " print(f\"{claude_name}:\\n{claude_next}\\n\")\n",
+ " # yield claude_next\n",
+ " claude_messages.append(claude_next)\n",
+ "\n",
+ " yield gpt_next, claude_next\n",
+ " \n",
+ " # yield gpt_next, claude_next\n",
+ " # return (gpt_next, claude_next)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "19e66ed3-d2c3-4a71-aec4-7869e5295215",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "* Running on local URL: http://127.0.0.1:7860\n",
+ "\n",
+ "To create a public link, set `share=True` in `launch()`.\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": []
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "GPT:\n",
+ "Hi I will share a story now!!\n",
+ "\n",
+ "Claude:\n",
+ "Please share, I will critique the story.\n",
+ "\n",
+ "GPT:\n",
+ "# ভুতুড়ে বেডরুমে আতঙ্কিত অতিথি\n",
+ "\n",
+ "বানгалোরের একটি পুরনো কলকাতার বাড়িতে, আর্যন একজন সাহসী যুবক হিসেবে অনেক খোঁজ-খবর করে একটি ভাড়ার ঘর খুঁজছিল। পরিচিত একটি অদ্ভুত হোটেলে পৌঁছানোর পর, সে লক্ষ্য করল ছবির কাছাকাছি একটি বেডরুম।\n",
+ "\n",
+ "সেখানে প্রবেশ করার পর, সে বেডের পাশে একটি বাদামি রঙ্গের সোফা ও একটি ভুতুড়ে ছবি দেখল। ছবির মধ্যে থাকা মহিলা একটি দৃষ্টিকটু হাসি দিয়ে তাকিয়ে ছিল। আর্যন খুব অবাক হল, সময় কাটানোর জন্য সে ছবিটার দিকে তাকাতে লাগল। কিছুক্ষণের মধ্যেই সোফা থেকে একটি কাশি বের হল।\n",
+ "\n",
+ "\"ভোদা সুনতে পেরেছ?\" সোফা থেকে একটি ভুতুড়ে শব্দ আসছে। আর্যন পিছন ফিরে তাকিয়ে দেখল যে সোফার মধ্যে একটি ভুতুড়ে রূপের মহিলা তার দিকে তাকিয়ে আছে।\n",
+ "\n",
+ "\"আমি তোমার জন্য অপেক্ষা করছিলাম,\" মহিলা বলল, তার গলা মুখ থেকে বের হয়ে আসছিল শুরুতে। \"এটি একটি দলের রাত।\"\n",
+ "\n",
+ "আর্যন দৌঁড়ে পালাতে গেল, কিন্তু সোফার থেকে অদ্ভুত আওয়াজ আসতে লাগল। \"তুমি যেতে পারবে না, কারণ তুমি আমাদের দলে যোগ দিতে পার না।”\n",
+ "\n",
+ "“মহিলার কি হয়েছে? আপনা এতো চিৎকার করছেন? তাহলে কি হবে?” আর্যন যুদ্ধ করছিল।\n",
+ "\n",
+ "তিনি উপস্থিত হওয়ার পর, আহ্লাদিত আতিথিরা আসতে লাগল। আর্যন খুব ভীত হয়ে গেল কারণ মহিলার মুখ তাদের কাছে কখনো কখনো বিকৃত হচ্ছিল।\n",
+ "\n",
+ "“আমরা আজ রাতের জন্য মজা করতে এসেছি, তুমি আমাদের সঙ্গে যোগ দিতে পারো!” তারা একসঙ্গে চিৎকার করতে লাগল।\n",
+ "\n",
+ "আর্যন উপলব্ধি করল যে এটি একটি ভয়ঙ্কর ও হাস্যকর পরিস্থিতি। সবাই অতীতে অদ্ভুত ঘটনাগুলোর দিকে ফিরে গেল। হঠাৎ, ছবির মহিলা বলেন, “তুমি যদি হাসতে না পার, তবে তোমাকে আমাদের দলে গ্রহণ করা যাবে না!”\n",
+ "\n",
+ "এরপর শুরু হল খেলার একটি হরর পরিবেশ। আর্যন ও তার বন্ধুদের নিয়ে ভুতুড়ে সময় কাটাতে লাগল। যদিও অনেক ভয়, কিন্তু তারা একসাথে খুব হাসির ব্যবস্থা করে ফেলল। তাদের বিচিত্র কথাবার্তা মজার চরিত্রের সাথে মিলে যায়, আর একসময় তারা সবাই একসঙ্গে হৈ হৈ করে হাসতে লাগল।\n",
+ "\n",
+ "শেষে, তারা তখন উপলব্ধি করল যে, ভয়াবহতার মাঝেও আনন্দের উপাদান লুকিয়ে আছে। ব্যক্তি যদি ঠিকভাবে উদ্দেশ্য বুঝে এই ভুতুড়ে পরিবেশে মজার উপকারিতা তৈরি করে, তাতে একজনের ঘুম হারানোর ভয় হয়ে যায় হাসির স্বাদে।\n",
+ "\n",
+ "আর্যন এবং তাঁর নতুন বন্ধুরা জীবনকে একটি নতুন দৃষ্টিতে গ্রহণ করে, যেখানে হাসি এবং ভয়ের পাশাপাশি সুখে থাকতে হয়। \n",
+ "\n",
+ "এই ছিল আর্যনের ভুতুড়ে অবসরে আতঙ্কিত হওয়ার অভিজ্ঞতা, যা তাকে স্মৃতি হিসেবে অমর করে রাখল।\n",
+ "\n",
+ "Claude:\n",
+ "After 1 iterations, this is the critique for the provided story - \n",
+ "\n",
+ "আইতেম সমূহের উন্নতির সূচনা:\n",
+ "\n",
+ "1. কাহিনীর শুরুতে প্রধান চরিত্রটিকে আরো বিশদভাবে পরিচয় দেয়া যেতে পারে।\n",
+ "2. ভুতুড়ে পরিবেশের বর্ণনা আরো বিস্তারিত ও ভাবময় হতে পারে।\n",
+ "3. চরিত্রগুলির মধ্যে সংঘর্ষ, ডায়ালগ ও সংবাদ বিনিময় আরো স্বাভাবিক ও প্রাণবন্ত হতে পারে।\n",
+ "4. কাহিনীর শেষাংশে প্রধান চরিত্রের অভিজ্ঞতা ও শিক্ষা আরো গভীরতা লাভ করতে পারে।\n",
+ "\n",
+ "GPT:\n",
+ "# ভুতুড়ে বেডরুমে আতঙ্কিত অতিথি\n",
+ "\n",
+ "বানগালোরের একটি পুরনো বাংলাদেশি শৈলীর বাড়িতে, আর্যন একটি দীর্ঘ প্রক্রিয়ার পর একটি ভাড়ার ঘর খুঁজছিল। আর্যন, একজন কর্মঠ ও সাহসী যুবক, সদ্যই তার কলেজ জীবন শেষ করেছে। নতুন পরিবেশে নতুন বন্ধুদের খোঁজে সে এই শহরে এসেছে। প্রতিবেশীরা তাকে ভুতুড়ে অনেক অদ্ভুত কথা বলেছিল, কিন্তু সে ভয়ডরহীন।\n",
+ "\n",
+ "একদিন, তিনি একটি অদ্ভুত হোটেলে পৌঁছান, যা শহরের প্রান্তে, খুব পুরনো এবং বিশাল। সেখানে প্রবেশ করার পর, তিনি একটি বেডরুমের সামনে দাঁড়িয়ে পড়েন। গা dark ় অন্ধকারের মধ্যে, তিনি একটি বাদামী রঙের সোফা ও একটি creepy ছবি দেখতে পান। ছবির মধ্যে থাকা মহিলা একটি দৃষ্টিকটু হাসি দিয়ে তাকিয়ে ছিল।\n",
+ "\n",
+ "আর্যন তাঁর কৌতূহলকে দমন করতে না পেরে, ছবিটির দিকে তাকাতে শুরু করে। কিছুক্ষণের মধ্যেই সোফা থেকে একটি ভুতুড়ে শব্দ ভেসে এলো। \"ভোদা সুনতে পেরেছ?\" সোফা থেকে সেই ভয়ঙ্কর শব্দটি আসছে। আর্যন ভয় পেয়েই পিছন ফিরে তাকায়, কিন্তু সামনে যে ভুতুড়ে মহিলা তাকে দেখে হাসছে, সে কাছে অপেক্ষা করছে।\n",
+ "\n",
+ "\"আমি তোমার জন্য অপেক্ষা করছিলাম,\" মহিলা বলল, তার গলা যেন মুখ থেকে বের হচ্ছে। \"এটি একটি দলের রাত।\"\n",
+ "\n",
+ "আর্যন দৌঁড়ে পালাতে যেতে চাইলে, কিন্তু সোফা থেকে অদ্ভুত আওয়াজ বের হতে লাগল। \"তুমি যেতে পারবে না, কারণ তুমি আমাদের দলে যোগ দিতে পার না।”\n",
+ "\n",
+ "\"মহিলার কি হয়েছে? আপনা এতো চিৎকার করছেন? তাহলে কি হবে?” আর্যন তাঁর কৌতূহল ও ভয়ের সাথে যুদ্ধ করতে লাগল।\n",
+ "\n",
+ "এই সময়, বিশাল সাদা পোশাক পরিহিত করে অন্যান্য ভূতেরা আসতে লাগল। \"আমরা আজ রাতের জন্য মজা করতে এসেছি, তুমি আমাদের সঙ্গে যোগ দিতে পারো!\" তারা একসঙ্গে গাইতে লাগল, ভুতুড়ে মুহূর্তগুলি জীবন্ত করে তোলার জন্য।\n",
+ "\n",
+ "আর্যন শুরুতেই ভীত ও চিন্তিত হয়ে গেল, কিন্তু কথোপকথন চলতে চলতে, মহিলার মুখ প্রতিবার বিকৃত হতে লাগল এবং আতিথিদের কথা শুনতে শুনতে তার খোশমেজাজ বেড়ে গেল।\n",
+ "\n",
+ "“যদি হাসতে না পার, তুমি আমাদের দলে গ্রহণযোগ্য হবে না!” তারা গলা উঁচু করে চিৎকার করে উঠল। তাদের মুখের হাসির সুরে সেই আতঙ্ক যেন প্রতিদিনের মজায় পরিণত হলো।\n",
+ "\n",
+ "খেলার মধ্যে ভয়াবহতা চরমে পৌঁছাতে লাগল। আর্যন এবং তার নতুন বন্ধুদের ভাগ্য এটি পরিণত হলো। অবশেষে, তারা উপলব্ধি করল যে ভয় ও হাসির মাঝে জীবনের আসল রসদ লুকিয়ে আছে। \n",
+ "\n",
+ "প্রধান চরিত্রটি তখন বুঝতে পারল যে এই অদ্ভুত ভুতুড়ে পরিবেশের মধ্যে হাসির সঙ্গবদ্ধতা কত বিচিত্র হতে পারে। পারে না। দেখা গেল আতঙ্ক এবং হাসির মিশ্রণে তারা নিজেদের আত্মবিশ্বাসী ও আনন্দের অনুভূতিতে পরিপূর্ণ করে তুলেছে। \n",
+ "\n",
+ "নতুন বন্ধুরা মনে রেখে আন্দাজ করতে পারে যে, কখনো কখনো ভয় কিন্তু রসিকতা এবং আনন্দের একটি নতুন প্রসঙ্গ হয়ে উঠতে পারে। আর্যন সেই রাতের অভিজ্ঞতা নিয়ে সারা জীবন স্মরণে রাখবে, যেখানে হাসি এবং ভয়ের পাশে বাস্তবতা গড়ে তোলার সুযোগ পেল।\n",
+ "\n",
+ "Claude:\n",
+ "After 2 iterations, this is the critique for the provided story - \n",
+ "\n",
+ "ভাল। প্রদত্ত কাহিনীতে বেশ কিছু উন্নয়নের সূচনা দেখা যায়। বিশেষ করে চরিত্রটির বিস্তারিত পরিচয়, ভুতুড়ে পরিবেশের অনুপ্রবেশ ও চরিত্রগুলির মধ্যকার সংঘর্ষ ও ডায়ালগ আরও উন্নত হয়েছে। কাহিনীর শেষে চরিত্রটির অভিজ্ঞতা ও শিক্ষা আরও গভীরতা লাভ করেছে। কুল মিলিয়ে, এটি একটি ভালো হরর কমেডি রচনা।\n",
+ "\n",
+ "GPT:\n",
+ "# ভুতুড়ে বেডরুমে আতঙ্কিত অতিথি\n",
+ "\n",
+ "বানগালোরের একটি পুরনো বাংলাদেশি শৈলীর বাড়িতে, আর্যন, একজন কর্মঠ ও সাহসী যুবক, সদ্যই তার কলেজ জীবন শেষ করে নতুন অপেক্ষারত শহরে এসেছে। নতুন বন্ধুদের খোঁজে, সে শহরের বিভিন্ন অংশে ঘুরে বেড়াচ্ছে, কিন্তু তার মধ্যে ভয়ের প্রতি এক বিশেষ আকর্ষণ রয়েছে। শোনা গেছে, শহরের বিভিন্ন স্থানে বিভিন্ন ধরনের অদ্ভুত ঘটনার কথা। একটি মজার কথা হলো, সে তাদের মধ্যে ভুতুড়ে ঘটনাগুলোর সন্ধান দিতে পারে।\n",
+ "\n",
+ "একদিন, তিনি একটি অদ্ভুত হোটেলে পৌঁছান, যা শহরের প্রান্তে অবস্থিত এবং বেশ পুরনো ও বিশাল। হোটেলের পরিবেশ ছিল গা dark ় অন্ধকারে মোড়ানো। তিনি একটি বেডরুমের সামনে এসে দাঁড়ান, সেখানে একটি বাদামী সোফা এবং একটি creepy ছবি দেখা যায়। ছবির মহিলার হাসিটি ছিল ভূতের মতো।\n",
+ "\n",
+ "আর্যন তাঁর কৌতূহলকে দমন করতে না পেরে, ছবিটির দিকে তাকাতে শুরু করে। হঠাৎ, সোফা থেকে একটি ভুতুড়ে শব্দ ভেসে আসে, \"ভোদা সুনতে পেরেছ?\" বিখ্যাত কথা যেন সোফার জীবন পেয়েছে। তিনি পিছন ফিরে দেখতে পান যে মহিলা তার দিকে তাকিয়ে হাসছে। \n",
+ "\n",
+ "\"আমি তোমার জন্য অপেক্ষা করছিলাম,\" মহিলা গম্ভীরভাবে বলল, তার ভয়ের আওয়াজসহ। \"এটি একটি দলের রাত।\"\n",
+ "\n",
+ "আর্যন ভয়ের সাথে পালানোর চেষ্টা করলেও, সোফা থেকে একাধিক ভুতুড়ে ক্রিয়া শুরু হয়ে গেল। \"তুমি যেতে পারবে না, কারণ তুমি আমাদের দলে যোগ দিতে পার না।” মহিলার মুখের বিকৃতি আরও ভয়ঙ্কর লাগতে শুরু করল।\n",
+ "\n",
+ "\"মহিলার কি হয়েছে? আপনা এতো চিৎকার করছেন? তাহলে কি হবে?” আর্যন ভাবছিল, তার সাধারণ জীবনের এই অবাক অনুভূতি ভাললাগছে।\n",
+ "\n",
+ "এই সময়, বিশাল সাদা পোশাক পরিহিত সদৃশ ভূতরা হাজির হয়ে গেল। \"আমরা আজ রাতের জন্য মজা করতে এসেছি, তুমি আমাদের সঙ্গে যোগ দিতে পারো!\" তারা একসঙ্গে হাসিমুখে বলল, এক ভুতুড়ে পরিবেশে রাজ্যের রসিকতার আয়োজন করতে।\n",
+ "\n",
+ "সাবলীল কথোপকথন চলতে চলতে, আর্যনের উপর থেকে ভয় কেটে গিয়ে এক অদ্ভুত অভিজ্ঞতা শুরু হয়। হাতের ইশারায় ভূতেরা হেসে ওঠে, একের পর এক অদ্ভুত ঘটনাকে তুলে ধরে। আর্যন বুঝতে পারল, তাদের কথা শুনতে শুনতে সে নিঃসন্দেহে একটি অভূতপূর্ব আনন্দের মধ্যে প্রবাহিত হতে শুরু করেছে।\n",
+ "\n",
+ "\"হাসলে তুমি আমাদের দলে থাক! আমাদের সঙ্গে অংশগ্রহণ কর!\" তারা গলা উঁচু করে চিৎকার তোলে। আর্যনে অবশেষে তার প্রাণবন্ত হাসি দ্বারা পরিবেশকে প্রাণবন্ত করে তোলে।\n",
+ "\n",
+ "খেলার মধ্যে ভয়াবহতা চরমে পৌঁছে যায়, কিন্তু আতিথিদের সঙ্গে সময় কাটাতে কাটাতে তিনি আরও একবার বুঝতে পারে যে ভয় এবং হাসির মধ্যে জীবনের আসল উপাদান লুকিয়ে আছে। \n",
+ "\n",
+ "আর্যন আর উপলব্ধি করে, অদ্ভুত ভুতুড়ে পরিবেশের মধ্যেই হাসির বিনোদনের আসল আনন্দ লুকানো। তিনি সেই ভয় এবং আনন্দের স্মৃতি নিয়ে ফিরে যান, যেখানে প্রেম, বন্ধুত্ব এবং জ্ঞানের সঙ্গে মজার ঘনিষ্ঠতা তৈরি করে। এটি তার জীবন পরিবর্তন করে দেয় এবং সেই রাতের অভিজ্ঞতা তাকে একটি নতুন দৃষ্টিতে বাঁচতে শিখায়।\n",
+ "\n",
+ "Claude:\n",
+ "After 3 iterations, this is the critique for the provided story - \n",
+ "\n",
+ "The provided story is an excellent horror comedy piece in Bengali. No major areas of improvement are noted. The story has a well-developed protagonist, an engaging haunted setting, an effective blend of horror and humor, and a meaningful takeaway for the main character. Overall, it is a well-crafted story that successfully combines the horror and comedy genres.\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "view = gr.Interface(\n",
+ " fn=Write_Me,\n",
+ " inputs=[gr.Dropdown([\"English\",\"Bengali\",\"Hindi\",\"French\",\"Spanish\"],label = \"Language\"),\n",
+ " gr.Dropdown([\"Romantic\",\"Horror\",\"Comedy\",\"Romantic Comedy\",\"Horror Comedy\"],label = \"Genre\"),\n",
+ " gr.Textbox(label=\"Iterations:\", lines=1),\n",
+ " gr.Textbox(label=\"Remarks:\", lines=1)],\n",
+ " outputs=[gr.Markdown(label=\"Short Story:\"),\n",
+ " gr.Textbox(label=\"Critique:\", lines=8)],\n",
+ " flagging_mode=\"never\")\n",
+ "view.launch(inbrowser=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0dabafa2-089a-4e65-a6cc-19f7c19af59a",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3c8a1c54-0344-4911-867a-3143aee0e7f0",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5171fecb-1037-4806-b0ae-c23e8578c667",
+ "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
+}