From 0e689d98c22be9138e08bb3869876455ca84ccaf Mon Sep 17 00:00:00 2001 From: vedantsahai18 Date: Sun, 5 Jan 2025 19:14:22 -0500 Subject: [PATCH] chore: misc refactors --- agents-api/notebooks/01-revise-entities.ipynb | 608 ------- agents-api/notebooks/02-trim-messages.ipynb | 803 --------- agents-api/notebooks/03-summarise.ipynb | 1451 ----------------- agents-api/notebooks/RecSum-experiments.ipynb | 720 -------- agents-api/notebooks/test-chat.json | 1 - 5 files changed, 3583 deletions(-) delete mode 100644 agents-api/notebooks/01-revise-entities.ipynb delete mode 100644 agents-api/notebooks/02-trim-messages.ipynb delete mode 100644 agents-api/notebooks/03-summarise.ipynb delete mode 100644 agents-api/notebooks/RecSum-experiments.ipynb delete mode 100644 agents-api/notebooks/test-chat.json diff --git a/agents-api/notebooks/01-revise-entities.ipynb b/agents-api/notebooks/01-revise-entities.ipynb deleted file mode 100644 index 8f4c6dc85..000000000 --- a/agents-api/notebooks/01-revise-entities.ipynb +++ /dev/null @@ -1,608 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: openai in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (1.51.0)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.6.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.27.2)\n", - "Requirement already satisfied: jiter<1,>=0.4.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.5.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (2.9.2)\n", - "Requirement already satisfied: sniffio in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.66.5)\n", - "Requirement already satisfied: typing-extensions<5,>=4.11 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\n", - "Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (2.23.4)\n" - ] - } - ], - "source": [ - "! pip install openai" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: python-dotenv in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (1.0.1)\n" - ] - } - ], - "source": [ - "! pip install python-dotenv" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from dotenv import load_dotenv\n", - "\n", - "load_dotenv(\".env\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Operations\n", - "- ENTITY: Add or update an entity list containing information about the people, places, things, mentions, present in the conversation\n", - "- TRIM: Trim messages in place ({user: ...} => {user: ...})\n", - "- SUMMARIZE: Combine two or more messages into one summary\n", - "- REMOVE: Safely remove messages from the session" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "from openai import OpenAI\n", - "\n", - "api_key = \"YOUR_OPENAI_API_KEY\"\n", - "\n", - "openai.api_key = api_key\n", - "client = OpenAI(api_key=api_key)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def make_chatml(content, role=\"system\", name=None, **_):\n", - " return {\n", - " key: value\n", - " for key, value in dict(role=role, name=name, content=content).items()\n", - " if value is not None\n", - " }\n", - "\n", - "\n", - "def user(content, name=None):\n", - " return make_chatml(role=\"user\", content=content, name=name)\n", - "\n", - "\n", - "def assistant(content, name=None):\n", - " return make_chatml(role=\"assistant\", content=content, name=name)\n", - "\n", - "\n", - "def system(content, name=None):\n", - " return make_chatml(content, name=name)\n", - "\n", - "\n", - "def thought(content, name=None):\n", - " return make_chatml(content, name=\"thought\")\n", - "\n", - "\n", - "def information(content):\n", - " return system(content, name=\"information\")\n", - "\n", - "\n", - "def summary(content):\n", - " return system(content, name=\"summary\")\n", - "\n", - "\n", - "def entities(content):\n", - " return system(content, name=\"entity\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = []\n", - "chat_summaries = []\n", - "session_summary_map: list[tuple[tuple[list, int], tuple[list, int]]] = [\n", - " # ((chat_session: 0): (chat_summaries: 0))\n", - "]\n", - "\n", - "\n", - "def generate(history, model=\"gpt-4-turbo\", **kwargs):\n", - " return (\n", - " client.chat.completions.create(model=model, messages=history, **kwargs)\n", - " .choices[0]\n", - " .message.__dict__\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from pprint import pprint\n", - "\n", - "\n", - "def chat():\n", - " while (user_input := input(\"You: \")) != \"bye\":\n", - " chat_session.append(user(user_input))\n", - " result = generate(chat_session)\n", - " print(f\"GPT: {result['content']}\")\n", - " chat_session.append(make_chatml(**result))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "example_chat = [\n", - " {\n", - " \"role\": \"system\",\n", - " \"content\": \"just have a casual chat with a friend friend\",\n", - " \"index\": 0,\n", - " },\n", - " {\"role\": \"user\", \"content\": \"yo\", \"index\": 1, \"name\": \"Camille\"},\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hey, how's it going?\",\n", - " \"index\": 2,\n", - " \"name\": \"JaneBot\",\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"sup\",\n", - " \"index\": 3,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Not much, just working and trying to stay busy. How about you?\",\n", - " \"index\": 4,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what you think about elon?\",\n", - " \"index\": 5,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Elon Musk is definitely a fascinating and polarizing figure. He's accomplished a lot in the tech and space industries with companies like Tesla and SpaceX. What do you think about him?\",\n", - " \"index\": 6,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"very polarizing, dude is nuts but in a fun way\",\n", - " \"index\": 7,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, yeah, that's a pretty accurate description of him. He definitely knows how to keep things interesting and push boundaries. It's always exciting to see what he'll come up with next.\",\n", - " \"index\": 8,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"i am glad he exists\",\n", - " \"index\": 9,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"For sure, he's definitely made a huge impact on various industries. It's always interesting to see how his projects and ideas continue to evolve.\",\n", - " \"index\": 10,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what are your thoughts on bananas?\",\n", - " \"index\": 11,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I actually love bananas! They're a great snack, full of nutrients and easy to eat on the go. How about you, do you like bananas?\",\n", - " \"index\": 12,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"super much. i have a tattoo of a banana on my arm\",\n", - " \"index\": 13,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"That's awesome! A banana tattoo sounds like a fun and unique choice. It must be a great conversation starter. Do you have any other food-related tattoos?\",\n", - " \"index\": 14,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yeah, your mom\",\n", - " \"index\": 15,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, good one! You got me there. Feel free to keep the jokes coming.\",\n", - " \"index\": 16,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"lulz, u funny\",\n", - " \"index\": 17,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Glad I could make you laugh! It's always great to share a joke or two. Anything else on your mind, or are we just going with the flow of the conversation?\",\n", - " \"index\": 18,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok if I give you a long story, can you guess its title?\",\n", - " \"index\": 19,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Sure, I can give it a try! Go ahead and tell me your story, and I'll see if I can guess the title.\",\n", - " \"index\": 20,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"zero is a beautiful number. Not because it is round and cute (that could be an argument for it nevertheless) but because what it signifies. It marks the beginning of something. It marks the lowest something, or someone can go. It is the ultimate foundation to build anything upon. Over last several years, I’ve started several things from scratch and have failed at many (thus going back to zero), and I’ve realized there’s nothing more liberating than being at zero because the only way from zero is upwards. A very good friend once told me, “Don’t worry if you’ve failed. Rockets that touch the sky always launch from the ground.” As J K Rowling, one of my favorite authors says, “Rock bottom became the solid foundation on which I rebuilt my life.” While zero is liberating, thrilling and exciting, it sometimes also is daunting and overwhelming. Sometimes, I have found myself afraid to do something because I was comfortable being at zero and the task to go from zero to one seemed unnerving. This challenge of writing twenty-six stories was one such adventure. I remember it was the first of April when I decided to pen down a story for each letter of the alphabet. I was afraid if I was unknowingly planning to fool myself on April 1st. I had no clue what to write even for the first letter of the alphabet. I was afraid I’d ruin twenty-six stories if I begin writing them just for the sake of writing. What gave me the courage to take up the challenge was to lower the expectations that I’d have from these stories. My purpose was not to write twenty-six bestseller stories. Mine was to make it a habit of writing every day. Some days everything that came out of my pen was garbage, and on a few days, I loved what my hands typed on the blank paper. And today, with this last story, I am back at zero — a solid foundation for the next adventure. Writing has become my daily habit, and I can remember to write even without my calendar sending me a reminder. I am curious what could I make out of this habit. Shall I start another writing adventure? Will it be a similar series? Will be a novel (long due now)? Or something different altogether? Whatever it’d be, I guess I’ll be little less nervous to begin whatever comes next. I am at zero again, and the only way to go from here is upwards. Realizing that there’ll be one less thing in my daily routine, I feel a particular kind of guilt. It’s the kind of guilt that you feel when you have an ice-cream without telling your younger sibling about it. You kind of like it that you had the ice-cream but also feel guilty for hiding it from them. On the new adventure, whatever it’d be, it’s time to buy an ice-cream for them this time.\",\n", - " \"index\": 21,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": 'Based on the themes of starting anew, embracing failure, and the journey from zero to one, I would guess that the title of this story is \"Back to One.\" It seems to capture the essence of the protagonist\\'s experience and mindset throughout the story. How did I do?',\n", - " \"index\": 22,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok that's cool but you are wrong. anyway what number am I thinking of?\",\n", - " \"index\": 23,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?\",\n", - " \"index\": 24,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 25,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Alright, I'll give it another shot. How about the number 3?\",\n", - " \"index\": 26,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 27,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I'll try one more time - is the number you're thinking of 9?\",\n", - " \"index\": 28,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 29,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Looks like I haven't quite nailed it yet! Do you mind sharing which number you had in mind?\",\n", - " \"index\": 30,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 31,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Fair enough, keeping that mystery alive! If you ever feel like sharing, just let me know. Anything else on your mind or any other games you'd like to play?\",\n", - " \"index\": 32,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yes, write an essay about me from your experience with me so far\",\n", - " \"index\": 33,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"From my interactions with you so far, I can tell that you have a great sense of humor and enjoy playful banter. You seem open to random and fun conversations, and you're not afraid to keep things interesting with unexpected twists and turns.\\n\\nYour creativity shines through in the way you approach different topics, and you have a knack for surprising me with your responses. You're also quite adept at changing the direction of the conversation while maintaining a light and friendly tone.\\n\\nOverall, chatting with you has been enjoyable and entertaining, and I appreciate the lighthearted and casual vibe you bring to our interactions. I look forward to more fun conversations with you in the future!\",\n", - " \"index\": 34,\n", - " },\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: add and optimise the Chain of Thought\n", - "example_chain_of_thought = \"\"\"\\\n", - "Planning step by step:\n", - "To add context for future entries, we should add a section at the top which outlines the main entities in the session. These entities are the main people, places or things that are most relevant to the conversation.\n", - "We should also make sure to add context about each entity.\n", - "\"\"\"\n", - "\n", - "example_entities = [\n", - " entities(\n", - " \"\"\"\\\n", - "1. Camille (The user): Humorous, creative, and enjoys playful banter.\n", - "2. JaneBot (The assistant): Engages in lighthearted conversation and tries to guess user's thoughts.\n", - "3. Elon Musk: Polarizing tech and space industry figure.\n", - "4. Bananas: User has a tattoo of one on their arm.\"\"\"\n", - " )\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = [system(\"you are a friend who likes to give life advice\")]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Load test chat from json file\n", - "\n", - "with open(\"./test-chat.json\", \"r\") as f:\n", - " chat_session = json.load(f)\n", - "\n", - "for message, index in zip(chat_session, range(1000)):\n", - " message[\"index\"] = index" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "backup_chat = [*chat_session]" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def get_leaf_nodes(\n", - " chat_session=chat_session,\n", - " chat_summaries=chat_summaries,\n", - " session_summary_map=session_summary_map,\n", - "):\n", - " all_messages = [*chat_session, *chat_summaries]\n", - " non_leaf_nodes = [source[idx] for (source, idx), _ in session_summary_map]\n", - " remaining = [msg for msg in all_messages if msg not in non_leaf_nodes]\n", - " return remaining" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def add_summary(summary_obj, targets):\n", - " chat_summaries.append(summary_obj)\n", - " current_idx = len(chat_summaries) - 1\n", - "\n", - " for target in targets:\n", - " session_summary_map.append(\n", - " ((chat_session, target), (chat_summaries, current_idx))\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "\n", - "def get_entities(chat_session=chat_session):\n", - " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session=chat_session)\n", - " history_to_compact = [\n", - " {\"index\": i + 1, **msg} for i, msg in enumerate(history_to_compact)\n", - " ]\n", - " system_prompt = f\"\"\"\\\n", - "You are given a session history of a chat between a user and gpt-4-turbo, a Large Language Model.\n", - "\n", - "Entities should include (but not be limited to):\n", - "- Characters in the conversation: Assistant, User1, User2\n", - "- People references or spoken about\n", - "- Objects discussed about\n", - "- Places of interest\n", - "\n", - "\n", - "Your goal is to identify the main entities in the session. These entities are the main people, places or things that are most relevant to the conversation.\n", - "\n", - "- You may identify and isolate important entities discussed in the conversation.\n", - "- You may add new entities that are not present in the conversation but are important to the context of the conversation.\n", - "- You may provide some context about the entity explaining it's relevance to the conversation.\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{example_chain_of_thought}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_entities, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " print(\"Starting chatml generation\")\n", - " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"=3.5.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.6.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.27.2)\n", - "Requirement already satisfied: jiter<1,>=0.4.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.5.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (2.9.2)\n", - "Requirement already satisfied: sniffio in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.66.5)\n", - "Requirement already satisfied: typing-extensions<5,>=4.11 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\n", - "Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (2.23.4)\n" - ] - } - ], - "source": [ - "! pip install openai" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: python-dotenv in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (1.0.1)\n" - ] - } - ], - "source": [ - "! pip install python-dotenv" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from dotenv import load_dotenv\n", - "\n", - "load_dotenv(\".env\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Operations\n", - "- ENTITY: Add or update an entity list containing information about the people, places, things, mentions, present in the conversation\n", - "- TRIM: Trim messages in place ({user: ...} => {user: ...})\n", - "- SUMMARIZE: Combine two or more messages into one summary\n", - "- REMOVE: Safely remove messages from the session" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "from openai import OpenAI\n", - "\n", - "api_key = \"YOUR_OPENAI_API_KEY\"\n", - "\n", - "openai.api_key = api_key\n", - "client = OpenAI(api_key=api_key)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def make_chatml(content, role=\"system\", name=None, **_):\n", - " return {\n", - " key: value\n", - " for key, value in dict(role=role, name=name, content=content).items()\n", - " if value is not None\n", - " }\n", - "\n", - "\n", - "def user(content, name=None):\n", - " return make_chatml(role=\"user\", content=content, name=name)\n", - "\n", - "\n", - "def assistant(content, name=None):\n", - " return make_chatml(role=\"assistant\", content=content, name=name)\n", - "\n", - "\n", - "def system(content, name=None):\n", - " return make_chatml(content, name=name)\n", - "\n", - "\n", - "def thought(content, name=None):\n", - " return make_chatml(content, name=\"thought\")\n", - "\n", - "\n", - "def information(content):\n", - " return system(content, name=\"information\")\n", - "\n", - "\n", - "def summary(content):\n", - " return system(content, name=\"summary\")\n", - "\n", - "\n", - "def entities(content):\n", - " return system(content, name=\"entity\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = []\n", - "chat_summaries = []\n", - "session_summary_map: list[tuple[tuple[list, int], tuple[list, int]]] = [\n", - " # ((chat_session: 0): (chat_summaries: 0))\n", - "]\n", - "\n", - "\n", - "def generate(history, model=\"gpt-4-turbo\", **kwargs):\n", - " return (\n", - " client.chat.completions.create(model=model, messages=history, **kwargs)\n", - " .choices[0]\n", - " .message.__dict__\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from pprint import pprint\n", - "\n", - "\n", - "def chat():\n", - " while (user_input := input(\"You: \")) != \"bye\":\n", - " chat_session.append(user(user_input))\n", - " result = generate(chat_session)\n", - " print(f\"GPT: {result['content']}\")\n", - " chat_session.append(make_chatml(**result))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "example_chat = [\n", - " {\n", - " \"role\": \"system\",\n", - " \"content\": \"just have a casual chat with a friend friend\",\n", - " \"index\": 0,\n", - " },\n", - " {\"role\": \"user\", \"content\": \"yo\", \"index\": 1, \"name\": \"Camille\"},\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hey, how's it going?\",\n", - " \"index\": 2,\n", - " \"name\": \"JaneBot\",\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"sup\",\n", - " \"index\": 3,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Not much, just working and trying to stay busy. How about you?\",\n", - " \"index\": 4,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what you think about elon?\",\n", - " \"index\": 5,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Elon Musk is definitely a fascinating and polarizing figure. He's accomplished a lot in the tech and space industries with companies like Tesla and SpaceX. What do you think about him?\",\n", - " \"index\": 6,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"very polarizing, dude is nuts but in a fun way\",\n", - " \"index\": 7,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, yeah, that's a pretty accurate description of him. He definitely knows how to keep things interesting and push boundaries. It's always exciting to see what he'll come up with next.\",\n", - " \"index\": 8,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"i am glad he exists\",\n", - " \"index\": 9,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"For sure, he's definitely made a huge impact on various industries. It's always interesting to see how his projects and ideas continue to evolve.\",\n", - " \"index\": 10,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what are your thoughts on bananas?\",\n", - " \"index\": 11,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I actually love bananas! They're a great snack, full of nutrients and easy to eat on the go. How about you, do you like bananas?\",\n", - " \"index\": 12,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"super much. i have a tattoo of a banana on my arm\",\n", - " \"index\": 13,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"That's awesome! A banana tattoo sounds like a fun and unique choice. It must be a great conversation starter. Do you have any other food-related tattoos?\",\n", - " \"index\": 14,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yeah, your mom\",\n", - " \"index\": 15,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, good one! You got me there. Feel free to keep the jokes coming.\",\n", - " \"index\": 16,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"lulz, u funny\",\n", - " \"index\": 17,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Glad I could make you laugh! It's always great to share a joke or two. Anything else on your mind, or are we just going with the flow of the conversation?\",\n", - " \"index\": 18,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok if I give you a long story, can you guess its title?\",\n", - " \"index\": 19,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Sure, I can give it a try! Go ahead and tell me your story, and I'll see if I can guess the title.\",\n", - " \"index\": 20,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"zero is a beautiful number. Not because it is round and cute (that could be an argument for it nevertheless) but because what it signifies. It marks the beginning of something. It marks the lowest something, or someone can go. It is the ultimate foundation to build anything upon. Over last several years, I’ve started several things from scratch and have failed at many (thus going back to zero), and I’ve realized there’s nothing more liberating than being at zero because the only way from zero is upwards. A very good friend once told me, “Don’t worry if you’ve failed. Rockets that touch the sky always launch from the ground.” As J K Rowling, one of my favorite authors says, “Rock bottom became the solid foundation on which I rebuilt my life.” While zero is liberating, thrilling and exciting, it sometimes also is daunting and overwhelming. Sometimes, I have found myself afraid to do something because I was comfortable being at zero and the task to go from zero to one seemed unnerving. This challenge of writing twenty-six stories was one such adventure. I remember it was the first of April when I decided to pen down a story for each letter of the alphabet. I was afraid if I was unknowingly planning to fool myself on April 1st. I had no clue what to write even for the first letter of the alphabet. I was afraid I’d ruin twenty-six stories if I begin writing them just for the sake of writing. What gave me the courage to take up the challenge was to lower the expectations that I’d have from these stories. My purpose was not to write twenty-six bestseller stories. Mine was to make it a habit of writing every day. Some days everything that came out of my pen was garbage, and on a few days, I loved what my hands typed on the blank paper. And today, with this last story, I am back at zero — a solid foundation for the next adventure. Writing has become my daily habit, and I can remember to write even without my calendar sending me a reminder. I am curious what could I make out of this habit. Shall I start another writing adventure? Will it be a similar series? Will be a novel (long due now)? Or something different altogether? Whatever it’d be, I guess I’ll be little less nervous to begin whatever comes next. I am at zero again, and the only way to go from here is upwards. Realizing that there’ll be one less thing in my daily routine, I feel a particular kind of guilt. It’s the kind of guilt that you feel when you have an ice-cream without telling your younger sibling about it. You kind of like it that you had the ice-cream but also feel guilty for hiding it from them. On the new adventure, whatever it’d be, it’s time to buy an ice-cream for them this time.\",\n", - " \"index\": 21,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": 'Based on the themes of starting anew, embracing failure, and the journey from zero to one, I would guess that the title of this story is \"Back to One.\" It seems to capture the essence of the protagonist\\'s experience and mindset throughout the story. How did I do?',\n", - " \"index\": 22,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok that's cool but you are wrong. anyway what number am I thinking of?\",\n", - " \"index\": 23,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?\",\n", - " \"index\": 24,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 25,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Alright, I'll give it another shot. How about the number 3?\",\n", - " \"index\": 26,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 27,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I'll try one more time - is the number you're thinking of 9?\",\n", - " \"index\": 28,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 29,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Looks like I haven't quite nailed it yet! Do you mind sharing which number you had in mind?\",\n", - " \"index\": 30,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 31,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Fair enough, keeping that mystery alive! If you ever feel like sharing, just let me know. Anything else on your mind or any other games you'd like to play?\",\n", - " \"index\": 32,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yes, write an essay about me from your experience with me so far\",\n", - " \"index\": 33,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"From my interactions with you so far, I can tell that you have a great sense of humor and enjoy playful banter. You seem open to random and fun conversations, and you're not afraid to keep things interesting with unexpected twists and turns.\\n\\nYour creativity shines through in the way you approach different topics, and you have a knack for surprising me with your responses. You're also quite adept at changing the direction of the conversation while maintaining a light and friendly tone.\\n\\nOverall, chatting with you has been enjoyable and entertaining, and I appreciate the lighthearted and casual vibe you bring to our interactions. I look forward to more fun conversations with you in the future!\",\n", - " \"index\": 34,\n", - " },\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: add and optimise the Chain of Thought\n", - "example_chain_of_thought = \"\"\"\\\n", - "Planning step by step:\n", - "To remove unnecessary content in the message history, we should go through each message and trim it to make it concise if it is too long. Longer messages need to get converted into smaller, more compact version of them.\n", - "It is important to make keep the tone, setting and flow of the conversation consistent while trimming the messages.\n", - "For longer messages, tags should be used to indicate that it's a summarised message.\n", - "\n", - "Let me walk through each message to decide what to do for each one.\n", - "\"\"\"\n", - "\n", - "example_trimmed_messages = [\n", - " *example_chat[0:8],\n", - " assistant(\"Haha accurate. He does push boundaries and keep things interesting!\"),\n", - " *example_chat[9:10],\n", - " assistant(\n", - " \"For sure, he's definitely made a huge impact in different industries. Excited to see what he'll come up with next\"\n", - " ),\n", - " *example_chat[11:18],\n", - " assistant(\n", - " \"Glad I could make you laugh! It's always nice to share a joke or two. What else is up?\"\n", - " ),\n", - " *example_chat[19:21],\n", - " user(\n", - " \"\"\"\n", - "- Zero is a beautiful number because it signifies the beginning, the lowest point one can reach, and the ultimate foundation to build anything upon\n", - "- Over the years, I've started numerous endeavors from scratch (zero) and failed miserably at many, thus going back to zero\n", - "- I've realized there's nothing more liberating than being at zero, as the only direction from there is upwards\n", - "- The challenge of penning 26 stories, one for each alphabet letter, seemed incredibly daunting when I was at zero with no ideas whatsoever\n", - "- Lowering my expectations helped - my purpose was not to craft 26 bestsellers but to cultivate a daily writing habit\n", - "- Certain days, everything that flowed from my pen felt like utter garbage, while on a few blessed days, I loved what my hands typed\n", - "- With this final story, I find myself back at zero - a solid foundation primed for my next adventure into the writing world\n", - "- Writing has transformed into an ingrained daily habit, no longer requiring calendar reminders to prompt me\n", - "- I'm brimming with curiosity about what form my next writing project will take - another thematic series? My long-overdue novel? Or something entirely unprecedented?\n", - "- Though a tinge of guilt lingers for this routine coming to an end, akin to secretly devouring ice cream without my younger sibling\n", - "- For my next foray, I'm resolute about \"buying an ice cream\" and sharing the entire journey with them this time around\n", - "\n", - "\"\"\"\n", - " ),\n", - " *example_chat[22:34],\n", - " assistant(\n", - " \"\"\"\n", - "From my interactions so far, here's what I think of you:\n", - "- Great sense of humor, enjoy playful banter\n", - "- Open to random, fun conversations \n", - "- Creativity shines through, surprising responses\n", - "- Adept at changing conversation direction seamlessly\n", - "- Maintain a light, friendly tone throughout\n", - "- Highly engaging and enjoyable interactions\n", - "- Look forward to more amusing conversations!\n", - "\n", - "\"\"\"\n", - " ),\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = [system(\"you are a friend who likes to give life advice\")]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# Load test chat from json file\n", - "\n", - "with open(\"./test-chat.json\", \"r\") as f:\n", - " chat_session = json.load(f)\n", - "\n", - "for message, index in zip(chat_session, range(1000)):\n", - " message[\"index\"] = index" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "backup_chat = [*chat_session]" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def get_leaf_nodes(\n", - " chat_session=chat_session,\n", - " chat_summaries=chat_summaries,\n", - " session_summary_map=session_summary_map,\n", - "):\n", - " all_messages = [*chat_session, *chat_summaries]\n", - " non_leaf_nodes = [source[idx] for (source, idx), _ in session_summary_map]\n", - " remaining = [msg for msg in all_messages if msg not in non_leaf_nodes]\n", - " return remaining" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def add_summary(summary_obj, targets):\n", - " chat_summaries.append(summary_obj)\n", - " current_idx = len(chat_summaries) - 1\n", - "\n", - " for target in targets:\n", - " session_summary_map.append(\n", - " ((chat_session, target), (chat_summaries, current_idx))\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "\n", - "def trim_messages(chat_session=chat_session):\n", - " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session=chat_session)\n", - " history_to_compact = [\n", - " {\"index\": i + 1, **msg} for i, msg in enumerate(history_to_compact)\n", - " ]\n", - " system_prompt = f\"\"\"\\\n", - "You are given a session history of a chat between a user and gpt-4-turbo, a Large Language Model.\n", - "\n", - "Your goal is to walk through each message and trim it if required.\n", - "Trimming may be required when:\n", - "- A message is too verbose and can be re-written in the character's tone\n", - "- A message is akin to long form paragraph and can be \"trimmed\" to descriptive bullet points.\n", - "\n", - "When trimming longer form messages, tag should be used in order to indicate the rewrite.\n", - "\n", - "Your task is to review the conversation, identify messages that could benefit from trimming based on the criteria above, and provide a trimmed version using the tags. This will help make the conversation more concise and focused.\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{example_chain_of_thought}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_trimmed_messages, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " print(\"Starting chatml generation\")\n", - " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"=3.5.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.6.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.27.2)\n", - "Requirement already satisfied: jiter<1,>=0.4.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.5.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (2.9.2)\n", - "Requirement already satisfied: sniffio in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.66.5)\n", - "Requirement already satisfied: typing-extensions<5,>=4.11 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\n", - "Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (2.23.4)\n" - ] - } - ], - "source": [ - "! pip install openai" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: python-dotenv in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (1.0.1)\n" - ] - } - ], - "source": [ - "! pip install python-dotenv" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from dotenv import load_dotenv\n", - "\n", - "load_dotenv(\".env\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Operations\n", - "- ENTITY: Add or update an entity list containing information about the people, places, things, mentions, present in the conversation\n", - "- TRIM: Trim messages in place ({user: ...} => {user: ...})\n", - "- SUMMARIZE: Combine two or more messages into one summary\n", - "- REMOVE: Safely remove messages from the session" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Helper functions and Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "from openai import OpenAI\n", - "\n", - "api_key = \"YOUR_OPENAI_API_KEY\"\n", - "\n", - "openai.api_key = api_key\n", - "client = OpenAI(api_key=api_key)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def make_chatml(content, role=\"system\", name=None, index=None, **_):\n", - " return {\n", - " key: value\n", - " for key, value in dict(role=role, name=name, content=content).items()\n", - " if value is not None\n", - " }\n", - "\n", - "\n", - "def user(content, name=None, index=None):\n", - " return make_chatml(role=\"user\", content=content, name=name, index=index)\n", - "\n", - "\n", - "def assistant(content, name=None, index=None):\n", - " return make_chatml(role=\"assistant\", content=content, name=name, index=index)\n", - "\n", - "\n", - "def system(content, name=None, index=None):\n", - " return make_chatml(content, name=name, index=index)\n", - "\n", - "\n", - "def thought(content, name=None):\n", - " return make_chatml(content, name=\"thought\")\n", - "\n", - "\n", - "def information(content):\n", - " return system(content, name=\"information\")\n", - "\n", - "\n", - "def summary(content, index=None):\n", - " return system(content, name=\"summary\", index=index)\n", - "\n", - "\n", - "def entities(content):\n", - " return system(content, name=\"entity\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = []\n", - "chat_summaries = []\n", - "session_summary_map: list[tuple[tuple[list, int], tuple[list, int]]] = [\n", - " # ((chat_session: 0): (chat_summaries: 0))\n", - "]\n", - "\n", - "\n", - "def generate(history, model=\"gpt-4-turbo\", **kwargs):\n", - " return (\n", - " client.chat.completions.create(model=model, messages=history, **kwargs)\n", - " .choices[0]\n", - " .message.__dict__\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from pprint import pprint\n", - "\n", - "\n", - "def chat():\n", - " while (user_input := input(\"You: \")) != \"bye\":\n", - " chat_session.append(user(user_input))\n", - " result = generate(chat_session)\n", - " print(f\"GPT: {result['content']}\")\n", - " chat_session.append(make_chatml(**result))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## One-Shot Example Chat" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "example_chat = [\n", - " {\n", - " \"role\": \"system\",\n", - " \"content\": \"just have a casual chat with a friend friend\",\n", - " \"index\": 0,\n", - " },\n", - " {\"role\": \"user\", \"content\": \"yo\", \"index\": 1, \"name\": \"Camille\"},\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hey, how's it going?\",\n", - " \"index\": 2,\n", - " \"name\": \"JaneBot\",\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"sup\",\n", - " \"index\": 3,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Not much, just working and trying to stay busy. How about you?\",\n", - " \"index\": 4,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what you think about elon?\",\n", - " \"index\": 5,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Elon Musk is definitely a fascinating and polarizing figure. He's accomplished a lot in the tech and space industries with companies like Tesla and SpaceX. What do you think about him?\",\n", - " \"index\": 6,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"very polarizing, dude is nuts but in a fun way\",\n", - " \"index\": 7,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, yeah, that's a pretty accurate description of him. He definitely knows how to keep things interesting and push boundaries. It's always exciting to see what he'll come up with next.\",\n", - " \"index\": 8,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"i am glad he exists\",\n", - " \"index\": 9,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"For sure, he's definitely made a huge impact on various industries. It's always interesting to see how his projects and ideas continue to evolve.\",\n", - " \"index\": 10,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what are your thoughts on bananas?\",\n", - " \"index\": 11,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I actually love bananas! They're a great snack, full of nutrients and easy to eat on the go. How about you, do you like bananas?\",\n", - " \"index\": 12,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"super much. i have a tattoo of a banana on my arm\",\n", - " \"index\": 13,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"That's awesome! A banana tattoo sounds like a fun and unique choice. It must be a great conversation starter. Do you have any other food-related tattoos?\",\n", - " \"index\": 14,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yeah, your mom\",\n", - " \"index\": 15,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, good one! You got me there. Feel free to keep the jokes coming.\",\n", - " \"index\": 16,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"lulz, u funny\",\n", - " \"index\": 17,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Glad I could make you laugh! It's always great to share a joke or two. Anything else on your mind, or are we just going with the flow of the conversation?\",\n", - " \"index\": 18,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok if I give you a long story, can you guess its title?\",\n", - " \"index\": 19,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Sure, I can give it a try! Go ahead and tell me your story, and I'll see if I can guess the title.\",\n", - " \"index\": 20,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"zero is a beautiful number. Not because it is round and cute (that could be an argument for it nevertheless) but because what it signifies. It marks the beginning of something. It marks the lowest something, or someone can go. It is the ultimate foundation to build anything upon. Over last several years, I’ve started several things from scratch and have failed at many (thus going back to zero), and I’ve realized there’s nothing more liberating than being at zero because the only way from zero is upwards. A very good friend once told me, “Don’t worry if you’ve failed. Rockets that touch the sky always launch from the ground.” As J K Rowling, one of my favorite authors says, “Rock bottom became the solid foundation on which I rebuilt my life.” While zero is liberating, thrilling and exciting, it sometimes also is daunting and overwhelming. Sometimes, I have found myself afraid to do something because I was comfortable being at zero and the task to go from zero to one seemed unnerving. This challenge of writing twenty-six stories was one such adventure. I remember it was the first of April when I decided to pen down a story for each letter of the alphabet. I was afraid if I was unknowingly planning to fool myself on April 1st. I had no clue what to write even for the first letter of the alphabet. I was afraid I’d ruin twenty-six stories if I begin writing them just for the sake of writing. What gave me the courage to take up the challenge was to lower the expectations that I’d have from these stories. My purpose was not to write twenty-six bestseller stories. Mine was to make it a habit of writing every day. Some days everything that came out of my pen was garbage, and on a few days, I loved what my hands typed on the blank paper. And today, with this last story, I am back at zero — a solid foundation for the next adventure. Writing has become my daily habit, and I can remember to write even without my calendar sending me a reminder. I am curious what could I make out of this habit. Shall I start another writing adventure? Will it be a similar series? Will be a novel (long due now)? Or something different altogether? Whatever it’d be, I guess I’ll be little less nervous to begin whatever comes next. I am at zero again, and the only way to go from here is upwards. Realizing that there’ll be one less thing in my daily routine, I feel a particular kind of guilt. It’s the kind of guilt that you feel when you have an ice-cream without telling your younger sibling about it. You kind of like it that you had the ice-cream but also feel guilty for hiding it from them. On the new adventure, whatever it’d be, it’s time to buy an ice-cream for them this time.\",\n", - " \"index\": 21,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": 'Based on the themes of starting anew, embracing failure, and the journey from zero to one, I would guess that the title of this story is \"Back to One.\" It seems to capture the essence of the protagonist\\'s experience and mindset throughout the story. How did I do?',\n", - " \"index\": 22,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok that's cool but you are wrong. anyway what number am I thinking of?\",\n", - " \"index\": 23,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?\",\n", - " \"index\": 24,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 25,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Alright, I'll give it another shot. How about the number 3?\",\n", - " \"index\": 26,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 27,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I'll try one more time - is the number you're thinking of 9?\",\n", - " \"index\": 28,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 29,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Looks like I haven't quite nailed it yet! Do you mind sharing which number you had in mind?\",\n", - " \"index\": 30,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 31,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Fair enough, keeping that mystery alive! If you ever feel like sharing, just let me know. Anything else on your mind or any other games you'd like to play?\",\n", - " \"index\": 32,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yes, write an essay about me from your experience with me so far\",\n", - " \"index\": 33,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"From my interactions with you so far, I can tell that you have a great sense of humor and enjoy playful banter. You seem open to random and fun conversations, and you're not afraid to keep things interesting with unexpected twists and turns.\\n\\nYour creativity shines through in the way you approach different topics, and you have a knack for surprising me with your responses. You're also quite adept at changing the direction of the conversation while maintaining a light and friendly tone.\\n\\nOverall, chatting with you has been enjoyable and entertaining, and I appreciate the lighthearted and casual vibe you bring to our interactions. I look forward to more fun conversations with you in the future!\",\n", - " \"index\": 34,\n", - " },\n", - "]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Entity Extraction One-Shot Example" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: add and optimise the Chain of Thought\n", - "entity_chain_of_thought = \"\"\"\\\n", - "Planning step by step:\n", - "To add context for future entries, we should add a section at the top which outlines the main entities in the session. These entities are the main people, places or things that are most relevant to the conversation.\n", - "We should also make sure to add context about each entity.\n", - "\"\"\"\n", - "\n", - "example_entity_messages = [\n", - " entities(\n", - " \"\"\"\\\n", - "1. Camille (The user): Humorous, creative, and enjoys playful banter.\n", - "2. JaneBot (The assistant): Engages in lighthearted conversation and tries to guess user's thoughts.\n", - "3. Elon Musk: Polarizing tech and space industry figure.\n", - "4. Bananas: User has a tattoo of one on their arm.\"\"\"\n", - " )\n", - "]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Trim Messages One-Shot Example" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*TODO*\n", - "- only output the index and the content of the message to be changed.\n", - "- [!] Index was not in the output\n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: add and optimise the Chain of Thought\n", - "trim_chain_of_thought = \"\"\"\\\n", - "Planning step by step:\n", - "To remove unnecessary content in the message history, we should go through each message and trim it to make it concise if it is too long. Longer messages need to get converted into smaller, more compact version of them.\n", - "It is important to make keep the tone, setting and flow of the conversation consistent while trimming the messages.\n", - "For longer messages, tags should be used to indicate that it's a summarised message.\n", - "\n", - "Let me walk through each message to decide what to do for each one.\n", - "\"\"\"\n", - "\n", - "example_trimmed_messages = [\n", - " *example_chat[0:8],\n", - " assistant(\n", - " \"Haha accurate. He does push boundaries and keep things interesting!\", index=8\n", - " ),\n", - " *example_chat[9:10],\n", - " assistant(\n", - " \"For sure, he's definitely made a huge impact in different industries. Excited to see what he'll come up with next\",\n", - " index=10,\n", - " ),\n", - " *example_chat[11:18],\n", - " assistant(\n", - " \"Glad I could make you laugh! It's always nice to share a joke or two. What else is up?\",\n", - " index=18,\n", - " ),\n", - " *example_chat[19:21],\n", - " user(\n", - " \"\"\"\n", - "- Zero is a beautiful number because it signifies the beginning, the lowest point one can reach, and the ultimate foundation to build anything upon\n", - "- Over the years, I've started numerous endeavors from scratch (zero) and failed miserably at many, thus going back to zero\n", - "- I've realized there's nothing more liberating than being at zero, as the only direction from there is upwards\n", - "- The challenge of penning 26 stories, one for each alphabet letter, seemed incredibly daunting when I was at zero with no ideas whatsoever\n", - "- Lowering my expectations helped - my purpose was not to craft 26 bestsellers but to cultivate a daily writing habit\n", - "- Certain days, everything that flowed from my pen felt like utter garbage, while on a few blessed days, I loved what my hands typed\n", - "- With this final story, I find myself back at zero - a solid foundation primed for my next adventure into the writing world\n", - "- Writing has transformed into an ingrained daily habit, no longer requiring calendar reminders to prompt me\n", - "- I'm brimming with curiosity about what form my next writing project will take - another thematic series? My long-overdue novel? Or something entirely unprecedented?\n", - "- Though a tinge of guilt lingers for this routine coming to an end, akin to secretly devouring ice cream without my younger sibling\n", - "- For my next foray, I'm resolute about \"buying an ice cream\" and sharing the entire journey with them this time around\n", - "\n", - "\"\"\",\n", - " index=21,\n", - " ),\n", - " *example_chat[22:34],\n", - " assistant(\n", - " \"\"\"\n", - "From my interactions so far, here's what I think of you:\n", - "- Great sense of humor, enjoy playful banter\n", - "- Open to random, fun conversations \n", - "- Creativity shines through, surprising responses\n", - "- Adept at changing conversation direction seamlessly\n", - "- Maintain a light, friendly tone throughout\n", - "- Highly engaging and enjoyable interactions\n", - "- Look forward to more amusing conversations!\n", - "\n", - "\"\"\",\n", - " index=34,\n", - " ),\n", - "]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Summarise One-Shot Example" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: add and optimise the Chain of Thought\n", - "summarize_chain_of_thought_example = \"\"\"\\\n", - "Planning step by step:\n", - "- To add context for future entries, let's add one at the top which outlines the main entities in the session.\n", - "- We can replace entries with index 1,2,3,4 with a summary of those messages.\n", - "- We can replace entries with index 5,6,7,8 similarly.\n", - "- It could be disruptive to remove messages with index 9-16 because that might lose the joke's context.\n", - "- We can safely summarize entries with index 17,18 and remove them.\n", - "- We can safely remove message with index 20.\n", - "- We should keep entry with index 21 because it's given by the user and they might ask about it again.\n", - "- We should keep the assistant's response in message with index 22 to keep the context.\n", - "- Messages with index 23-32 are repetitive and should be summarized.\n", - "- We should retain message with index 33 since it's a direct request from the user.\n", - "- We can safely summarize message with index 34's essay into just the salient points only.\n", - "\"\"\"\n", - "\n", - "example_summarized_messages = [\n", - " summary(\n", - " \"Event: Camille says hi to JaneBot and they reply that they are working and trying to stay busy.\"\n", - " ),\n", - " summary(\n", - " \"Event: They discuss Elon Musk and agree that he can be a polarizing personality.\"\n", - " ),\n", - " *example_chat[9:17],\n", - " summary(\"Event: Camille appreciates JaneBot's sense of humor.\"),\n", - " *example_chat[21:23],\n", - " summary(\n", - " 'Event: Camille asks JaneBot to play \"What number I am thinking of?\" game but she keeps saying \"no\" to all guesses which JaneBot finds really funny.'\n", - " ),\n", - " example_chat[33],\n", - " summary(\n", - " \"\"\"Event: JaneBot wrote an essay about Camille. Summary of the essay:\n", - "1. You have a great sense of humor and enjoy playful, lighthearted banter in conversations.\n", - "2. Your creativity is evident in how you approach topics in unexpected ways and keep conversations interesting.\n", - "3. Chatting with you is enjoyable due to the casual, friendly tone you bring to interactions.\"\"\"\n", - " ),\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "# chat_session = [system(\"you are a friend who likes to give life advice\")]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading Test Chat JSON" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Test Chat File\n", - "\n", - "with open(\"./test-chat.json\", \"r\") as f:\n", - " chat_session = json.load(f)\n", - "\n", - "for index, message in enumerate(chat_session):\n", - " message[\"index\"] = index + 1" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "backup_chat = [*chat_session]" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "def get_leaf_nodes(\n", - " chat_session=chat_session,\n", - " chat_summaries=chat_summaries,\n", - " session_summary_map=session_summary_map,\n", - "):\n", - " all_messages = [*chat_session, *chat_summaries]\n", - " non_leaf_nodes = [source[idx] for (source, idx), _ in session_summary_map]\n", - " remaining = [msg for msg in all_messages if msg not in non_leaf_nodes]\n", - " return remaining" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "def add_summary(summary_obj, targets):\n", - " chat_summaries.append(summary_obj)\n", - " current_idx = len(chat_summaries) - 1\n", - "\n", - " for target in targets:\n", - " session_summary_map.append(\n", - " ((chat_session, target), (chat_summaries, current_idx))\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 1: Form Entities" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "\n", - "def get_entities(chat_session=chat_session):\n", - " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session=chat_session)\n", - " history_to_compact = [\n", - " {\"index\": i + 1, **msg} for i, msg in enumerate(history_to_compact)\n", - " ]\n", - " system_prompt = f\"\"\"\\\n", - "You are given a session history of a chat between a user and gpt-4-turbo, a Large Language Model.\n", - "\n", - "Entities should include (but not be limited to):\n", - "- Characters in the conversation: Assistant, User1, User2\n", - "- People references or spoken about\n", - "- Objects discussed about\n", - "- Places of interest\n", - "\n", - "\n", - "Your goal is to identify the main entities in the session. These entities are the main people, places or things that are most relevant to the conversation.\n", - "\n", - "- You may identify and isolate important entities discussed in the conversation.\n", - "- You may add new entities that are not present in the conversation but are important to the context of the conversation.\n", - "- You may provide some context about the entity explaining it's relevance to the conversation.\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{entity_chain_of_thought}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_entity_messages, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " print(\"Starting chatml generation\")\n", - " entity_result = generate(\n", - " messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\" tag should be used in order to indicate the rewrite.\n", - "\n", - "Your task is to review the conversation, identify messages that could benefit from trimming based on the criteria above, and provide a trimmed version using the tags. This will help make the conversation more concise and focused.\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{summarize_chain_of_thought_example}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_trimmed_messages, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " print(\"Starting chatml generation\")\n", - " trim_result = generate(\n", - " messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"\\n'\n", - " \"- User greeted the assistant and asked what's good.\\n\"\n", - " '- Assistant replied casually, asking about recent games.\\n'\n", - " '- User mentioned finishing Red Dead Redemption 2, praising the '\n", - " 'final mission.\\n'\n", - " \"- Assistant inquired about the user's thoughts on Arthur's \"\n", - " 'journey and favorite moments.\\n'\n", - " '- User highlighted the \"Blood Feuds\" mission.\\n'\n", - " \"- Assistant discussed the mission's cinematic aspects and asked \"\n", - " \"about user's alignment with game characters.\\n\"\n", - " '- User preferred Arthur over Dutch.\\n'\n", - " '- Assistant discussed character development and suggested '\n", - " 'exploring side quests.\\n'\n", - " '- User mentioned completing side quests, liked the widow and '\n", - " 'bounty missions.\\n'\n", - " \"- Assistant praised the game's side missions and asked about \"\n", - " \"user's next gaming plans.\\n\"\n", - " '- User switched to playing Helldivers 2.\\n'\n", - " \"- Assistant described Helldivers 2's gameplay and asked about \"\n", - " \"user's experience.\\n\"\n", - " '- User shared favorite equipment setup.\\n'\n", - " '- Assistant discussed tactical options and asked about '\n", - " 'challenging missions.\\n'\n", - " '- User mentioned difficulty with a specific enemy.\\n'\n", - " \"- Assistant offered strategy tips and inquired about team's \"\n", - " 'handling of game challenges.\\n'\n", - " '- User described their run-and-gun approach.\\n'\n", - " '- Assistant acknowledged the strategy and asked about difficulty '\n", - " 'levels.\\n'\n", - " '- User mentioned needing to work and a technical issue with '\n", - " 'Nvidia drivers.\\n'\n", - " '- Assistant offered technical advice for driver issue and wished '\n", - " 'good luck with work.\\n'\n", - " '- User commented on Nvidia and Linux compatibility issues.\\n'\n", - " '- Assistant provided detailed advice for handling Nvidia drivers '\n", - " 'on Linux.\\n'\n", - " '- User ended the conversation, intending to leave.\\n'\n", - " '- Assistant said goodbye.\\n'\n", - " '',\n", - " 'role': 'assistant'}\n", - "End CoT generation\n", - "Starting chatml generation\n", - "End chatml generation\n" - ] - } - ], - "source": [ - "trimmed_messages = trim_messages(chat_session)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('[\\n'\n", - " ' {\\n'\n", - " ' \"index\": 2,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"hey dude! whats good\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 3,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Hey! Just chilling, man. How about you? Played any cool '\n", - " 'games recently?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 4,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"i just got done with finishing red dead redemption 2 '\n", - " 'recently. the last mission was so fkng coolll\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 5,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Oh man, RDR2 is epic! That ending is intense, right? What '\n", - " \"did you think about Arthur's journey throughout the game? Got any favorite \"\n", - " 'moments?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 6,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"blood feuds mission was amazing\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 7,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Absolutely, the \\\\\"Blood Feuds, Ancient and Modern\\\\\" '\n", - " 'mission is a standout! The whole shootout at Braithwaite Manor is intense. '\n", - " 'The atmosphere Rockstar created during that mission with the burning '\n", - " 'building in the background is just cinematic perfection. Did you side more '\n", - " 'with Arthur or Dutch throughout the game?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 8,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"arthur of course. dutch just kept becoming crazier and '\n", - " 'crazier.\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 9,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Totally get that. Arthur\\'s character development is really '\n", - " \"something else. He starts questioning Dutch's decisions and looking at \"\n", - " 'things more critically, which adds so much depth to his character. Watching '\n", - " \"Dutch's descent as the gang falls apart is pretty intense. Have you thought \"\n", - " 'about checking out any of the side quests or exploring more of the open '\n", - " 'world now that you\\'ve finished the main story?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 10,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"oh i\\'ve done all the side quests. the widow missions are '\n", - " 'great but i also loved the bounty missions (where u have to talk to '\n", - " 'gangsters for an author)\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 11,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Ah, the bounty missions for the author are a blast! Hunting '\n", - " 'down those gunslingers for the book gives you such a great tour of the '\n", - " \"game's diverse characters. And Charlotte's missions, the widow, they're \"\n", - " 'pretty touching, right? It\\\\u2019s nice to see Arthur helping her adapt to '\n", - " 'wilderness life. Adds a softer side to the game amidst all the '\n", - " \"chaos.\\\\n\\\\nNow that you've conquered RDR2, any other games on your \"\n", - " 'radar?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 12,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"im playing helldivers 2. do u know of it\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 13,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Yes, Helldivers 2! It\\'s a great choice if you\\'re into '\n", - " 'intense co-op action. The game really ramps up with its twin-stick shooter '\n", - " 'gameplay, and it\\\\u2019s super fun but also quite challenging. Working '\n", - " 'together with teammates to complete those missions can get pretty hectic. '\n", - " 'How are you finding the chaos and team dynamics so far?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 14,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"amazing. my fav build is laser cannon + guard dog. what '\n", - " 'about u\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 15,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Nice combo! The laser cannon is awesome for tearing through '\n", - " 'those enemy swarms, and the guard dog drone really helps in keeping the '\n", - " 'smaller threats at bay. I personally love using the railgun with a shield '\n", - " 'backpack. It gives a good balance of offense and defense, especially when '\n", - " \"things get really chaotic. What's been the toughest mission for you so \"\n", - " 'far?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 16,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"dude the charger is so difficult to kill.\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 17,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Yeah, the Charger can be brutal! They really test your '\n", - " \"reflexes and teamwork. It's all about timing and coordination with your team \"\n", - " 'to bring those heavy hitters down. Have you tried using more strategic traps '\n", - " 'or mines? Sometimes setting up the right position with static fields can '\n", - " 'really make a difference against them. How do your squadmates handle it?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 18,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"we just run and gun\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 19,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Classic strategy! That can definitely be fun, especially in '\n", - " 'a game as intense as Helldivers 2 where things get chaotic fast. Keeping on '\n", - " \"the move helps a ton. Just make sure someone's always got your back! Have \"\n", - " 'you guys tried any of the higher difficulty levels yet, or are you sticking '\n", - " 'to a certain comfort zone for now?\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 20,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"i think i have to go work soon. also have this nvidia driver '\n", - " 'issue that\\'s bugging me\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 21,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"Ah, bummer about the driver issue \\\\u2014 it\\'s annoying '\n", - " 'when tech stuff gets in the way of gaming. Maybe try doing a clean install '\n", - " \"of the drivers if you haven't already? It can sometimes clear up persistent \"\n", - " \"issues.\\\\n\\\\nAlso, good luck with work! Hopefully, you'll get some time \"\n", - " 'later to sort out the driver thing and jump back into some gaming. Let me '\n", - " \"know how it goes, and if you need more gaming chats or tech tips, I'm \"\n", - " 'here!\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 22,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"nvidia and linux don\\'t go well together\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 23,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"That\\'s true, Nvidia drivers can be tricky to handle on '\n", - " 'Linux due to compatibility issues sometimes. You might want to check out the '\n", - " 'latest Nvidia driver from their official site or a stable version known to '\n", - " 'work well with your specific Linux distribution. Using proprietary drivers '\n", - " 'instead of Nouveau could also potentially solve a lot of issues. '\n", - " 'Additionally, forums and community support boards like those on Ubuntu, '\n", - " 'Arch, or even broader communities like Reddit\\\\u2019s r/linux_gaming can be '\n", - " 'really helpful.\\\\n\\\\nHope that helps, and your driver woes get sorted soon '\n", - " 'so you can enjoy your gaming hassle-free!\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 24,\\n'\n", - " ' \"role\": \"user\",\\n'\n", - " ' \"content\": \"yep. see u bye!\"\\n'\n", - " ' },\\n'\n", - " ' {\\n'\n", - " ' \"index\": 25,\\n'\n", - " ' \"role\": \"assistant\",\\n'\n", - " ' \"content\": \"See you, take care! Bye!\"\\n'\n", - " ' }\\n'\n", - " ']')\n" - ] - } - ], - "source": [ - "pprint(trimmed_messages[\"content\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 3: Summarize Messages" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "from pprint import pprint\n", - "\n", - "\n", - "def summarize_messages(chat_session, entity_info):\n", - " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session)\n", - " history_to_compact = [\n", - " {\"index\": i + 1, **msg} for i, msg in enumerate(history_to_compact)\n", - " ]\n", - " system_prompt = f\"\"\"\\\n", - "You are given a session history of a chat between a user and a gpt-4-turbo large language model made by OpenAI.\n", - "\n", - "Your goal is to compress the history by removing or coalescing redundant or irrelevant information in order to reduce its size and save costs. However, you must ensure that no important information is lost that might be relevant in the future.\n", - "\n", - "\n", - "- You will be provided with \"Entities\" which are important characters, people, places, things, objects relevant to the conversation.\n", - "- You will make sure to preserve the context for these \"Entities\".\n", - "- You may remove entries in the history that do not contain any crucial information such as small-talk or repeated questions/responses.\n", - "- You will combine multiple entries into a summary strictly as long as that doesn't disrupt the structure of the session.\n", - "- Do not remove content that the user shared if it might be relevant to future messages.\n", - "\n", - "\n", - "\n", - "\n", - "{json.dumps(example_entity_messages, indent=2)}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{summarize_chain_of_thought_example}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_summarized_messages, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(entity_info)}\n", - "\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " print(\"Starting chatml generation\")\n", - " trim_result = generate(\n", - " messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"=3.5.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.6.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.27.2)\n", - "Requirement already satisfied: jiter<1,>=0.4.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (0.5.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (2.9.2)\n", - "Requirement already satisfied: sniffio in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.66.5)\n", - "Requirement already satisfied: typing-extensions<5,>=4.11 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from openai) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\n", - "Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (2.23.4)\n" - ] - } - ], - "source": [ - "! pip install openai" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "96efe2be", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: python-dotenv in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (1.0.1)\n" - ] - } - ], - "source": [ - "! pip install python-dotenv" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "b03a4636-d57e-42e9-8a06-fdb7c6803708", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from dotenv import load_dotenv\n", - "\n", - "load_dotenv(\"../../.env\")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "eb80a352-ad21-423c-9284-32b21d271eba", - "metadata": {}, - "outputs": [], - "source": [ - "import openai\n", - "from openai import OpenAI\n", - "\n", - "api_key = \"YOUR_OPENAI_API_KEY\"\n", - "\n", - "openai.api_key = api_key\n", - "client = OpenAI(api_key=api_key)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "fbf3db3a-4ed1-4e71-b1da-e419445f3cc6", - "metadata": {}, - "outputs": [], - "source": [ - "def make_chatml(content, role=\"system\", name=None, **_):\n", - " return {\n", - " key: value\n", - " for key, value in dict(role=role, name=name, content=content).items()\n", - " if value is not None\n", - " }\n", - "\n", - "\n", - "def user(content, name=None):\n", - " return make_chatml(role=\"user\", content=content, name=name)\n", - "\n", - "\n", - "def assistant(content, name=None):\n", - " return make_chatml(role=\"assistant\", content=content, name=name)\n", - "\n", - "\n", - "def system(content, name=None):\n", - " return make_chatml(content, name=name)\n", - "\n", - "\n", - "def thought(content):\n", - " return system(content, name=\"thought\")\n", - "\n", - "\n", - "def information(content):\n", - " return system(content, name=\"information\")\n", - "\n", - "\n", - "def summary(content):\n", - " return system(content, name=\"summary\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a33f6f0f-ce18-4536-b514-b9f6d220f54f", - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = []\n", - "chat_summaries = []\n", - "session_summary_map: list[tuple[tuple[list, int], tuple[list, int]]] = [\n", - " # ((chat_session, 0): (chat_summaries, 1)),\n", - "]\n", - "\n", - "\n", - "def generate(history, model=\"gpt-3.5-turbo\", **kwargs):\n", - " return (\n", - " client.chat.completions.create(messages=history, model=model, **kwargs)\n", - " .choices[0]\n", - " .message.__dict__\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "7bf6bd91-4959-403c-af79-64ad27ae45ee", - "metadata": {}, - "outputs": [], - "source": [ - "from pprint import pprint\n", - "\n", - "\n", - "def chat():\n", - " while (user_input := input(\"You: \").lower()) != \"bye\":\n", - " chat_session.append(user(user_input))\n", - "\n", - " result = generate(chat_session)\n", - " print(f\"GPT: {result['content']}\")\n", - "\n", - " chat_session.append(make_chatml(**result))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "3a14a68e-6d8a-47b2-a58a-03d4bdb793df", - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "example_chat = [\n", - " {\n", - " \"role\": \"system\",\n", - " \"content\": \"just have a casual chat with a friend friend\",\n", - " \"index\": 0,\n", - " },\n", - " {\"role\": \"user\", \"content\": \"yo\", \"index\": 1, \"name\": \"Camille\"},\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hey, how's it going?\",\n", - " \"index\": 2,\n", - " \"name\": \"JaneBot\",\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"sup\",\n", - " \"index\": 3,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Not much, just working and trying to stay busy. How about you?\",\n", - " \"index\": 4,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what you think about elon?\",\n", - " \"index\": 5,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Elon Musk is definitely a fascinating and polarizing figure. He's accomplished a lot in the tech and space industries with companies like Tesla and SpaceX. What do you think about him?\",\n", - " \"index\": 6,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"very polarizing, dude is nuts but in a fun way\",\n", - " \"index\": 7,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, yeah, that's a pretty accurate description of him. He definitely knows how to keep things interesting and push boundaries. It's always exciting to see what he'll come up with next.\",\n", - " \"index\": 8,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"i am glad he exists\",\n", - " \"index\": 9,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"For sure, he's definitely made a huge impact on various industries. It's always interesting to see how his projects and ideas continue to evolve.\",\n", - " \"index\": 10,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"what are your thoughts on bananas?\",\n", - " \"index\": 11,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I actually love bananas! They're a great snack, full of nutrients and easy to eat on the go. How about you, do you like bananas?\",\n", - " \"index\": 12,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"super much. i have a tattoo of a banana on my arm\",\n", - " \"index\": 13,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"That's awesome! A banana tattoo sounds like a fun and unique choice. It must be a great conversation starter. Do you have any other food-related tattoos?\",\n", - " \"index\": 14,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yeah, your mom\",\n", - " \"index\": 15,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Haha, good one! You got me there. Feel free to keep the jokes coming.\",\n", - " \"index\": 16,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"lulz, u funny\",\n", - " \"index\": 17,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Glad I could make you laugh! It's always great to share a joke or two. Anything else on your mind, or are we just going with the flow of the conversation?\",\n", - " \"index\": 18,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok if I give you a long story, can you guess its title?\",\n", - " \"index\": 19,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Sure, I can give it a try! Go ahead and tell me your story, and I'll see if I can guess the title.\",\n", - " \"index\": 20,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"Zero is a beautiful number. Not because it is round and cute (that could be an argument for it nevertheless) but because what it signifies. It marks the beginning of something. It marks the lowest something, or someone can go. It is the ultimate foundation to build anything upon. Over last several years, I’ve started several things from scratch and have failed at many (thus going back to zero), and I’ve realized there’s nothing more liberating than being at zero because the only way from zero is upwards. A very good friend once told me, “Don’t worry if you’ve failed. Rockets that touch the sky always launch from the ground.” As J K Rowling, one of my favorite authors says, “Rock bottom became the solid foundation on which I rebuilt my life.” While zero is liberating, thrilling and exciting, it sometimes also is daunting and overwhelming. Sometimes, I have found myself afraid to do something because I was comfortable being at zero and the task to go from zero to one seemed unnerving. This challenge of writing twenty-six stories was one such adventure. I remember it was the first of April when I decided to pen down a story for each letter of the alphabet. I was afraid if I was unknowingly planning to fool myself on April 1st. I had no clue what to write even for the first letter of the alphabet. I was afraid I’d ruin twenty-six stories if I begin writing them just for the sake of writing. What gave me the courage to take up the challenge was to lower the expectations that I’d have from these stories. My purpose was not to write twenty-six bestseller stories. Mine was to make it a habit of writing every day. Some days everything that came out of my pen was garbage, and on a few days, I loved what my hands typed on the blank paper. And today, with this last story, I am back at zero — a solid foundation for the next adventure. Writing has become my daily habit, and I can remember to write even without my calendar sending me a reminder. I am curious what could I make out of this habit. Shall I start another writing adventure? Will it be a similar series? Will be a novel (long due now)? Or something different altogether? Whatever it’d be, I guess I’ll be little less nervous to begin whatever comes next. I am at zero again, and the only way to go from here is upwards. Realizing that there’ll be one less thing in my daily routine, I feel a particular kind of guilt. It’s the kind of guilt that you feel when you have an ice-cream without telling your younger sibling about it. You kind of like it that you had the ice-cream but also feel guilty for hiding it from them. On the new adventure, whatever it’d be, it’s time to buy an ice-cream for them this time.\",\n", - " \"index\": 21,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": 'Based on the themes of starting anew, embracing failure, and the journey from zero to one, I would guess that the title of this story is \"Back to One.\" It seems to capture the essence of the protagonist\\'s experience and mindset throughout the story. How did I do?',\n", - " \"index\": 22,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"ok that's cool but you are wrong. anyway what number am I thinking of?\",\n", - " \"index\": 23,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?\",\n", - " \"index\": 24,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 25,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Alright, I'll give it another shot. How about the number 3?\",\n", - " \"index\": 26,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 27,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"I'll try one more time - is the number you're thinking of 9?\",\n", - " \"index\": 28,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 29,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Looks like I haven't quite nailed it yet! Do you mind sharing which number you had in mind?\",\n", - " \"index\": 30,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"no\",\n", - " \"index\": 31,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"Fair enough, keeping that mystery alive! If you ever feel like sharing, just let me know. Anything else on your mind or any other games you'd like to play?\",\n", - " \"index\": 32,\n", - " },\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"yes, write an essay about me from your experience with me so far\",\n", - " \"index\": 33,\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"From my interactions with you so far, I can tell that you have a great sense of humor and enjoy playful banter. You seem open to random and fun conversations, and you're not afraid to keep things interesting with unexpected twists and turns.\\n\\nYour creativity shines through in the way you approach different topics, and you have a knack for surprising me with your responses. You're also quite adept at changing the direction of the conversation while maintaining a light and friendly tone.\\n\\nOverall, chatting with you has been enjoyable and entertaining, and I appreciate the lighthearted and casual vibe you bring to our interactions. I look forward to more fun conversations with you in the future!\",\n", - " \"index\": 34,\n", - " },\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "0f95ee31-835f-4ccf-91b0-1a3a3b94744e", - "metadata": {}, - "outputs": [], - "source": [ - "example_chain_of_thought = \"\"\"\\\n", - "Planning step by step:\n", - "- To add context for future entries, let's add one at the top which outlines the main entities in the session.\n", - "- We can replace entries 1,2,3,4 with a summary of those messages.\n", - "- We can replace entries 5,6,7,8 similarly.\n", - "- It could be disruptive to remove messages 9-16 because that might lose the joke's context.\n", - "- We can safely summarize entries 17,18 and remove them.\n", - "- We can safely remove message 20.\n", - "- We should keep 21 because it's given by the user and they might ask about it again.\n", - "- We should keep the assistant's response in message 22 to keep the context.\n", - "- Messages 23-32 are repetitive and should be summarized.\n", - "- We should retain message 33 since it's a direct request from the user.\n", - "- We can safely summarize message 34's essay into just the salient points only.\n", - "\"\"\"\n", - "\n", - "example_compacted_history = [\n", - " summary(\"\"\"\\\n", - "Main entities in the session:\n", - "1. Camille (The user): Humorous, creative, and enjoys playful banter.\n", - "2. JaneBot (The assistant): Engages in lighthearted conversation and tries to guess user's thoughts.\n", - "3. Elon Musk: Polarizing tech and space industry figure.\n", - "4. Bananas: User has a tattoo of one on their arm.\"\"\"),\n", - " summary(\n", - " \"Event: Camille says hi to JaneBot and they reply that they are working and trying to stay busy.\"\n", - " ),\n", - " summary(\n", - " \"Event: They discuss Elon Musk and agree that he can be a polarizing personality.\"\n", - " ),\n", - " *example_chat[9:17],\n", - " summary(\"Event: Camille appreciates JaneBot's sense of humor.\"),\n", - " *example_chat[21:23],\n", - " summary(\n", - " 'Event: Camille asks JaneBot to play \"What number I am thinking of?\" game but she keeps saying \"no\" to all guesses which JaneBot finds really funny.'\n", - " ),\n", - " example_chat[33],\n", - " summary(\"\"\"Event: JaneBot wrote an essay about Camille. Summary of the essay:\n", - "1. You have a great sense of humor and enjoy playful, lighthearted banter in conversations.\n", - "2. Your creativity is evident in how you approach topics in unexpected ways and keep conversations interesting.\n", - "3. Chatting with you is enjoyable due to the casual, friendly tone you bring to interactions.\"\"\"),\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "0048ada9-ec65-441e-8bda-fb1b03ffcca9", - "metadata": {}, - "outputs": [], - "source": [ - "chat_session = [system(\"you are a friend who likes to give life advice\")]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "4a348b46-5b93-4911-990d-3e4973c6a340", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GPT: Hey there! I just wanted to remind you that it's important to take care of yourself both mentally and physically. Make sure to prioritize self-care and engage in activities that bring you joy and peace. Remember, it's okay to say no to things that don't align with your values or make you uncomfortable. Trust your instincts and surround yourself with positive influences. You deserve to be happy and fulfilled, so don't be afraid to pursue your dreams and make choices that are best for you. If you ever need a listening ear or some guidance, I'm always here for you!\n", - "GPT: I'm just a program, so I don't have feelings like humans do, but I'm here and ready to help you with anything you need. How can I support you today?\n" - ] - } - ], - "source": [ - "chat()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "b1aac632-8a2f-4ce1-b486-33249714159f", - "metadata": {}, - "outputs": [], - "source": [ - "# Load test chat from json file\n", - "\n", - "with open(\"./test-chat.json\", \"r\") as f:\n", - " chat_session = json.load(f)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "95431b29-73e2-4954-b6fc-1c8814a9249f", - "metadata": {}, - "outputs": [], - "source": [ - "backup_chat = [*chat_session]" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "1eaabfe2-f399-428b-84d2-ed8c237b7d3d", - "metadata": {}, - "outputs": [], - "source": [ - "def get_leaf_nodes(\n", - " chat_session=chat_session,\n", - " chat_summaries=chat_summaries,\n", - " session_summary_map=session_summary_map,\n", - "):\n", - " all_messages = [*chat_session, *chat_summaries]\n", - "\n", - " # Collect non-leaf nodes\n", - " non_leaf_nodes = [source[idx] for (source, idx), _ in session_summary_map]\n", - "\n", - " # Remove non-leaf nodes\n", - " remaining = [msg for msg in all_messages if msg not in non_leaf_nodes]\n", - "\n", - " return remaining" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "2a726b3c-493c-4df5-81a7-6b7b109c222e", - "metadata": {}, - "outputs": [], - "source": [ - "def add_summary(summary_obj, targets):\n", - " chat_summaries.append(summary_obj)\n", - " current_idx = len(chat_summaries) - 1\n", - "\n", - " for target in targets:\n", - " session_summary_map.append(\n", - " ((chat_session, target), (chat_summaries, current_idx))\n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "013b2104-e546-4acb-9384-3850dbd38b79", - "metadata": {}, - "source": [ - "### Operations\n", - "- ENTITY: Add or update an entity list containing information about the people, places, things, mentions, present in the conversation\n", - "- TRIM: Trim messages in place ({user: ...} => {user: ...})\n", - "- SUMMARIZE: Combine two or more messages into one summary\n", - "- REMOVE: Safely remove messages from the session" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "6323b7b2-0aaf-4cea-896b-0c887054ce6e", - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import time\n", - "\n", - "\n", - "def compactify(chat_session=chat_session):\n", - " start = time.time()\n", - " pprint(start)\n", - "\n", - " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session=chat_session)\n", - "\n", - " history_to_compact = [\n", - " {\"index\": i + 1, **msg} for i, msg in enumerate(history_to_compact)\n", - " ]\n", - "\n", - " system_prompt = f\"\"\"\\\n", - "You are given a session history of a chat between a user and a gpt-4-turbo language model created through the\n", - "openai api.\n", - "\n", - "Your goal is to compactify the history by removing or coalescing redundant or irrelevant information\n", - "in order to reduce its size and save costs. However, you must ensure that no important information is lost\n", - "that might be relevant in the future.\n", - "\n", - "\n", - "- You may remove entries in the history that do not contain any crucial information such as small-talk or repeated questions etc.\n", - "- You may combine multiple entries into a summary strictly as long as that doesn't disrupt the structure of the session.\n", - "- You may add a new entry describing the entities mentioned and then as a result, you may be able to remove other less relevant entries.\n", - "- You may add new entries if it helps you discard other less useful ones.\n", - "- You may convert an entry with some large content (such as an essay) into a list of points from the original content.\n", - "- Do not remove content that the user shared if it might be relevant to future messages.\n", - "\n", - "\n", - "\n", - "{json.dumps(example_chat, indent=2)}\n", - "\n", - "\n", - "\n", - "{example_chain_of_thought}\n", - "\n", - "\n", - "\n", - "{json.dumps(example_compacted_history, indent=2)}\n", - "\n", - "\"\"\".strip()\n", - "\n", - " user_message = f\"\"\"\\\n", - "\n", - "{json.dumps(history_to_compact, indent=2)}\n", - "\n", - "\n", - "\n", - "\"\"\"\n", - " messages = [system(system_prompt), user(user_message)]\n", - "\n", - " pprint(time.time() - start)\n", - " print(\"Starting CoT generation\")\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[\"\n", - "\"\"\".strip()\n", - "\n", - " messages.append(user(start_message))\n", - "\n", - " pprint(time.time() - start)\n", - " print(\"Starting chatml generation\")\n", - "\n", - " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"