From 997b6960b757f940e010af5af5ffab938644c9e5 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Wed, 1 May 2024 20:42:00 +0530 Subject: [PATCH 01/43] research: Recursive summarization experiments Signed-off-by: Diwank Singh Tomer --- agents-api/notebooks/RecSum-experiments.ipynb | 719 +++++++++ agents-api/poetry.lock | 1295 +++++++++++++++-- agents-api/pyproject.toml | 2 + 3 files changed, 1921 insertions(+), 95 deletions(-) create mode 100644 agents-api/notebooks/RecSum-experiments.ipynb diff --git a/agents-api/notebooks/RecSum-experiments.ipynb b/agents-api/notebooks/RecSum-experiments.ipynb new file mode 100644 index 000000000..b1b98cb7f --- /dev/null +++ b/agents-api/notebooks/RecSum-experiments.ipynb @@ -0,0 +1,719 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "b03a4636-d57e-42e9-8a06-fdb7c6803708", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from dotenv import load_dotenv\n", + "load_dotenv(\"../.env\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "eb80a352-ad21-423c-9284-32b21d271eba", + "metadata": {}, + "outputs": [], + "source": [ + "from openai import Client" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4619f484-55f6-4122-8e26-27ec9e3506d5", + "metadata": {}, + "outputs": [], + "source": [ + "client = Client()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fbf3db3a-4ed1-4e71-b1da-e419445f3cc6", + "metadata": {}, + "outputs": [], + "source": [ + "make_chatml = lambda content, role=\"system\", name=None, **_: {\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", + "user = lambda content, name=None: make_chatml(role=\"user\", content=content, name=name)\n", + "assistant = lambda content, name=None: make_chatml(role=\"assistant\", content=content, name=name)\n", + "system = lambda content, name=None: make_chatml(content, name=name)\n", + "thought = lambda content: system(content, name=\"thought\")\n", + "information = lambda content: system(content, name=\"information\")\n", + "summary = lambda content: system(content, name=\"summary\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "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", + "generate = lambda history, model=\"gpt-3.5-turbo\", **kwargs: client.chat.completions.create(messages=history, model=model, **kwargs).choices[0].message.__dict__" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7bf6bd91-4959-403c-af79-64ad27ae45ee", + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "def chat():\n", + " while (user_input := input('You: ')) != \"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": 19, + "id": "3a14a68e-6d8a-47b2-a58a-03d4bdb793df", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "example_chat = [\n", + " {\n", + " \"role\": \"system\",\n", + " \"content\": \"just have a casual chat with a friend friend\",\n", + " \"index\": 0,\n", + " },\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": \"yo\",\n", + " \"index\": 1,\n", + " \"name\": \"Camille\"\n", + " },\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\": \"ero 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": 13, + "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(\"Event: Camille says hi to JaneBot and they reply that they are working and trying to stay busy.\"),\n", + " summary(\"Event: They discuss Elon Musk and agree that he can be a polarizing personality.\"),\n", + " *example_chat[9:17],\n", + " summary(\"Event: Camille appreciates JaneBot's sense of humor.\"),\n", + " *example_chat[21:23],\n", + " summary('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", + " 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": 14, + "id": "0048ada9-ec65-441e-8bda-fb1b03ffcca9", + "metadata": {}, + "outputs": [], + "source": [ + "chat_session = [system(\"give relationship advice to the user\")]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "4a348b46-5b93-4911-990d-3e4973c6a340", + "metadata": {}, + "outputs": [ + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: hi\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: Hello! How can I help you today?\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: I am feeling like my wife thinks I am ugly\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: I'm sorry to hear that you're feeling that way. It's important to open up the lines of communication with your wife and share how you're feeling. Try to have an honest and respectful conversation with her about your concerns. It's possible that there could be a misunderstanding or miscommunication that can be cleared up by discussing it openly. It's important to remember that physical appearance is just one aspect of a relationship, and true beauty comes from within. Focus on the love and connection you share with your wife, and work together to understand and support each other.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: yeah but that's just vague. do you have a wife?\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: I'm an AI assistant, so I don't have a personal life or relationships. However, I can still offer guidance and support based on my knowledge and experience in providing relationship advice. Communication, understanding, and empathy are key components of any healthy relationship. If you're feeling insecure about how your wife perceives your appearance, have an open and honest conversation with her to address your concerns and work towards a resolution together. Remember, it's important to value yourself and your worth, regardless of how others may perceive you physically.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: ok, do you talk to other people with these problems?\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: Yes, I interact with many people who seek advice and support on a variety of topics, including relationship issues. I'm here to provide guidance, offer perspective, and assist you in navigating through your concerns. If you have specific questions or need advice on how to approach a situation, feel free to share, and I'll do my best to help you. Remember, it's common for individuals to experience challenges in their relationships, and seeking support and guidance is a positive step towards finding solutions and improving communication.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: ok, can you tell me about an incident that turned out for the better?\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: Certainly! One common example I can share is a couple facing a communication breakdown in their relationship. They were struggling to express their needs and understand each other's perspectives, leading to frequent misunderstandings and arguments. However, they decided to attend couples therapy to work on their communication skills and learn effective ways to express their feelings and listen to each other.\n", + "\n", + "Through therapy, they were able to uncover underlying issues, address past resentments, and develop healthier communication patterns. They learned to communicate openly and honestly, empathize with each other's feelings, and work together as a team to resolve conflicts. Over time, their relationship strengthened, and they felt more connected, understood, and supported by each other.\n", + "\n", + "By taking proactive steps to improve their communication and seek professional guidance, this couple was able to overcome their challenges and ultimately strengthen their relationship. It's a reminder that with effort, patience, and willingness to work on the relationship, positive outcomes and growth are possible.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: why am I like this? ugly i mean\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: It's important to remember that beauty is subjective and comes in many forms. It's natural to have insecurities and doubts about our appearances, as we often compare ourselves to societal standards or feel pressure to look a certain way. However, it's essential to focus on self-acceptance, self-love, and recognizing your inherent worth beyond physical appearance.\n", + "\n", + "It may be helpful to explore where these feelings of being \"ugly\" are coming from and work on building self-confidence and self-esteem. Remember that beauty is not just about external features but also about qualities such as kindness, empathy, resilience, and authenticity.\n", + "\n", + "Consider practicing self-care, engaging in activities that bring you joy and boost your self-esteem, and surrounding yourself with supportive and loving people who appreciate you for who you are. If these feelings persist and significantly impact your well-being, consider reaching out to a therapist or counselor for additional support and guidance in building a positive self-image. You deserve to feel confident and valued in your own skin.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: hmm, can you think of a song about this?\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GPT: One song that comes to mind is \"Scars to Your Beautiful\" by Alessia Cara. The song's powerful lyrics speak to the message of self-acceptance, embracing uniqueness, and recognizing inner beauty beyond physical appearances. It conveys a message of empowerment, self-love, and resilience, encouraging listeners to embrace their imperfections and recognize their worth.\n", + "\n", + "The lyrics highlight the idea that everyone is beautiful in their own way, regardless of society's standards or expectations. The song serves as a reminder that true beauty comes from within and that we should celebrate our differences and embrace who we are, scars and all. It's an uplifting and inspirational anthem that encourages self-acceptance and self-love. I hope you find comfort and empowerment in the message of this song.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "You: bye\n" + ] + } + ], + "source": [ + "chat()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "95431b29-73e2-4954-b6fc-1c8814a9249f", + "metadata": {}, + "outputs": [], + "source": [ + "backup_chat = [*chat_session]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "1eaabfe2-f399-428b-84d2-ed8c237b7d3d", + "metadata": {}, + "outputs": [], + "source": [ + "def get_leaf_nodes(chat_session=chat_session, chat_summaries=chat_summaries, session_summary_map=session_summary_map):\n", + " all_messages = [*chat_session, *chat_summaries]\n", + "\n", + " # Collect non-leaf nodes\n", + " non_leaf_nodes = [\n", + " source[idx]\n", + " for (source, idx), _ in session_summary_map\n", + " ]\n", + " \n", + " # Remove non-leaf nodes\n", + " remaining = [\n", + " msg for msg in all_messages if msg not in non_leaf_nodes\n", + " ]\n", + "\n", + " return remaining" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "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": "code", + "execution_count": 32, + "id": "6323b7b2-0aaf-4cea-896b-0c887054ce6e", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pprint import pprint\n", + "\n", + "def compactify(chat_session=chat_session):\n", + " _sys_msg, *history_to_compact = get_leaf_nodes(chat_session=chat_session)\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", + " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=['\n", + "\"\"\".strip()\n", + "\n", + " messages.append(user(start_message))\n", + "\n", + " # import pdb; pdb.set_trace()\n", + " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.2, stop=['=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] +[[package]] +name = "appnope" +version = "0.1.4" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = ">=3.6" +files = [ + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, +] + [[package]] name = "argcomplete" version = "3.3.0" @@ -157,6 +168,63 @@ files = [ [package.extras] test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] +[[package]] +name = "argon2-cffi" +version = "23.1.0" +description = "Argon2 for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, +] + +[package.dependencies] +argon2-cffi-bindings = "*" + +[package.extras] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] + +[[package]] +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" +optional = false +python-versions = ">=3.6" +files = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["cogapp", "pre-commit", "pytest", "wheel"] +tests = ["pytest"] + [[package]] name = "arrow" version = "1.3.0" @@ -238,6 +306,20 @@ tests = ["attrs[tests-no-zope]", "zope-interface"] tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +[[package]] +name = "babel" +version = "2.15.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + [[package]] name = "beartype" version = "0.18.5" @@ -256,6 +338,27 @@ doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2. test-tox = ["equinox", "mypy (>=0.800)", "numpy", "pandera", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] test-tox-coverage = ["coverage (>=5.5)"] +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "black" version = "24.4.2" @@ -302,6 +405,24 @@ d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] + [[package]] name = "cachetools" version = "5.3.3" @@ -324,6 +445,70 @@ files = [ {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -481,6 +666,23 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "comm" +version = "0.2.2" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.8" +files = [ + {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, + {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +test = ["pytest"] + [[package]] name = "cozo-embedded" version = "0.7.6" @@ -558,6 +760,37 @@ graphql = ["graphql-core (>=3.2.3,<4.0.0)"] http = ["httpx"] validation = ["openapi-spec-validator (>=0.2.8,<0.7.0)", "prance (>=0.18.2)"] +[[package]] +name = "debugpy" +version = "1.8.1" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, +] + [[package]] name = "decorator" version = "5.1.1" @@ -569,6 +802,17 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "distro" version = "1.9.0" @@ -694,6 +938,20 @@ typing-extensions = ">=4.8.0" [package.extras] all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +[[package]] +name = "fastjsonschema" +version = "2.19.1" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = "*" +files = [ + {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, + {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "filelock" version = "3.14.0" @@ -724,6 +982,17 @@ files = [ six = "*" termcolor = "*" +[[package]] +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +files = [ + {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, + {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, +] + [[package]] name = "frozenlist" version = "1.4.1" @@ -1409,6 +1678,39 @@ files = [ docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] testing = ["pygments", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +[[package]] +name = "ipykernel" +version = "6.29.4" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.29.4-py3-none-any.whl", hash = "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da"}, + {file = "ipykernel-6.29.4.tar.gz", hash = "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=24" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] + [[package]] name = "ipython" version = "8.24.0" @@ -1447,6 +1749,41 @@ qtconsole = ["qtconsole"] test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] +[[package]] +name = "ipywidgets" +version = "8.1.3" +description = "Jupyter interactive widgets" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ipywidgets-8.1.3-py3-none-any.whl", hash = "sha256:efafd18f7a142248f7cb0ba890a68b96abd4d6e88ddbda483c9130d12667eaf2"}, + {file = "ipywidgets-8.1.3.tar.gz", hash = "sha256:f5f9eeaae082b1823ce9eac2575272952f40d748893972956dc09700a6392d9c"}, +] + +[package.dependencies] +comm = ">=0.1.3" +ipython = ">=6.1.0" +jupyterlab-widgets = ">=3.0.11,<3.1.0" +traitlets = ">=4.3.1" +widgetsnbextension = ">=4.0.11,<4.1.0" + +[package.extras] +test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] + +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, + {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, +] + +[package.dependencies] +arrow = ">=0.15.0" + [[package]] name = "isort" version = "5.13.2" @@ -1510,6 +1847,28 @@ files = [ [package.dependencies] Jinja2 = ">=2.2" +[[package]] +name = "json5" +version = "0.9.25" +description = "A Python implementation of the JSON5 data format." +optional = false +python-versions = ">=3.8" +files = [ + {file = "json5-0.9.25-py3-none-any.whl", hash = "sha256:34ed7d834b1341a86987ed52f3f76cd8ee184394906b6e22a1e0deb9ab294e8f"}, + {file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"}, +] + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + [[package]] name = "jsonschema" version = "4.22.0" @@ -1523,9 +1882,17 @@ files = [ [package.dependencies] attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -1564,6 +1931,222 @@ openai = ">=1.0.1,<2.0.0" pydantic = ">=2.0.1,<3.0.0" typing-extensions = ">=4.0.0,<5.0.0" +[[package]] +name = "jupyter-client" +version = "8.6.2" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.6.2-py3-none-any.whl", hash = "sha256:50cbc5c66fd1b8f65ecb66bc490ab73217993632809b6e505687de18e9dea39f"}, + {file = "jupyter_client-8.6.2.tar.gz", hash = "sha256:2bda14d55ee5ba58552a8c53ae43d215ad9868853489213f37da060ced54d8df"}, +] + +[package.dependencies] +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.7.2" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, + {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyter-events" +version = "0.10.0" +description = "Jupyter Event System library" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_events-0.10.0-py3-none-any.whl", hash = "sha256:4b72130875e59d57716d327ea70d3ebc3af1944d3717e5a498b8a06c6c159960"}, + {file = "jupyter_events-0.10.0.tar.gz", hash = "sha256:670b8229d3cc882ec782144ed22e0d29e1c2d639263f92ca8383e66682845e22"}, +] + +[package.dependencies] +jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} +python-json-logger = ">=2.0.4" +pyyaml = ">=5.3" +referencing = "*" +rfc3339-validator = "*" +rfc3986-validator = ">=0.1.1" +traitlets = ">=5.3" + +[package.extras] +cli = ["click", "rich"] +docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] +test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] + +[[package]] +name = "jupyter-lsp" +version = "2.2.5" +description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter-lsp-2.2.5.tar.gz", hash = "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001"}, + {file = "jupyter_lsp-2.2.5-py3-none-any.whl", hash = "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da"}, +] + +[package.dependencies] +jupyter-server = ">=1.1.2" + +[[package]] +name = "jupyter-server" +version = "2.14.0" +description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server-2.14.0-py3-none-any.whl", hash = "sha256:fb6be52c713e80e004fac34b35a0990d6d36ba06fd0a2b2ed82b899143a64210"}, + {file = "jupyter_server-2.14.0.tar.gz", hash = "sha256:659154cea512083434fd7c93b7fe0897af7a2fd0b9dd4749282b42eaac4ae677"}, +] + +[package.dependencies] +anyio = ">=3.1.0" +argon2-cffi = ">=21.1" +jinja2 = ">=3.0.3" +jupyter-client = ">=7.4.4" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-events = ">=0.9.0" +jupyter-server-terminals = ">=0.4.4" +nbconvert = ">=6.4.4" +nbformat = ">=5.3.0" +overrides = ">=5.0" +packaging = ">=22.0" +prometheus-client = ">=0.9" +pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} +pyzmq = ">=24" +send2trash = ">=1.8.2" +terminado = ">=0.8.3" +tornado = ">=6.2.0" +traitlets = ">=5.6.0" +websocket-client = ">=1.7" + +[package.extras] +docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.3" +description = "A Jupyter Server Extension Providing Terminals." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa"}, + {file = "jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269"}, +] + +[package.dependencies] +pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} +terminado = ">=0.8.3" + +[package.extras] +docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] + +[[package]] +name = "jupyterlab" +version = "4.2.1" +description = "JupyterLab computational environment" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab-4.2.1-py3-none-any.whl", hash = "sha256:6ac6e3827b3c890e6e549800e8a4f4aaea6a69321e2240007902aa7a0c56a8e4"}, + {file = "jupyterlab-4.2.1.tar.gz", hash = "sha256:a10fb71085a6900820c62d43324005046402ffc8f0fde696103e37238a839507"}, +] + +[package.dependencies] +async-lru = ">=1.0.0" +httpx = ">=0.25.0" +ipykernel = ">=6.5.0" +jinja2 = ">=3.0.3" +jupyter-core = "*" +jupyter-lsp = ">=2.0.0" +jupyter-server = ">=2.4.0,<3" +jupyterlab-server = ">=2.27.1,<3" +notebook-shim = ">=0.2" +packaging = "*" +tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} +tornado = ">=6.2.0" +traitlets = "*" + +[package.extras] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.3.5)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.3.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.2)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.1.post2)", "matplotlib (==3.8.3)", "nbconvert (>=7.0.0)", "pandas (==2.2.1)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] +test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] +upgrade-extension = ["copier (>=8,<10)", "jinja2-time (<0.3)", "pydantic (<2.0)", "pyyaml-include (<2.0)", "tomli-w (<2.0)"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, +] + +[[package]] +name = "jupyterlab-server" +version = "2.27.2" +description = "A set of server components for JupyterLab and JupyterLab like applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_server-2.27.2-py3-none-any.whl", hash = "sha256:54aa2d64fd86383b5438d9f0c032f043c4d8c0264b8af9f60bd061157466ea43"}, + {file = "jupyterlab_server-2.27.2.tar.gz", hash = "sha256:15cbb349dc45e954e09bacf81b9f9bcb10815ff660fb2034ecd7417db3a7ea27"}, +] + +[package.dependencies] +babel = ">=2.10" +jinja2 = ">=3.0.3" +json5 = ">=0.9.0" +jsonschema = ">=4.18.0" +jupyter-server = ">=1.21,<3" +packaging = ">=21.3" +requests = ">=2.31" + +[package.extras] +docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] +openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0,<8)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.11" +description = "Jupyter interactive widgets for JupyterLab" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyterlab_widgets-3.0.11-py3-none-any.whl", hash = "sha256:78287fd86d20744ace330a61625024cf5521e1c012a352ddc0a3cdc2348becd0"}, + {file = "jupyterlab_widgets-3.0.11.tar.gz", hash = "sha256:dd5ac679593c969af29c9bed054c24f26842baa51352114736756bc035deee27"}, +] + [[package]] name = "libcst" version = "1.4.0" @@ -1606,13 +2189,13 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.12.1)", "build (>=0.10.0)", "coverage (> [[package]] name = "litellm" -version = "1.38.10" +version = "1.39.2" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.38.10-py3-none-any.whl", hash = "sha256:4d33465eacde566832b9d7aa7677476e61aa7ba4ec26631fb1c8411c87219ed1"}, - {file = "litellm-1.38.10.tar.gz", hash = "sha256:1a0b3088fe4b072f367343a7d7d25e4c5f9990975d9ee7dbf21f3b25ff046bb0"}, + {file = "litellm-1.39.2-py3-none-any.whl", hash = "sha256:843cb9a4d45c89ba6da95529815ec83ee7e4b7fe07aa0ed633102f600fddd9ad"}, + {file = "litellm-1.39.2.tar.gz", hash = "sha256:96c4f3d522ccf32817357b1e9f5f63fa36a4a884f336314e1f6d66c0576d689e"}, ] [package.dependencies] @@ -1767,6 +2350,17 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] + [[package]] name = "msgspec" version = "0.18.6" @@ -1929,6 +2523,97 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nbclient" +version = "0.10.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "nbclient-0.10.0-py3-none-any.whl", hash = "sha256:f13e3529332a1f1f81d82a53210322476a168bb7090a0289c795fe9cc11c9d3f"}, + {file = "nbclient-0.10.0.tar.gz", hash = "sha256:4b3f1b7dba531e498449c4db4f53da339c91d449dc11e9af3a43b4eb5c5abb09"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.16.4" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"}, + {file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" + +[package.extras] +all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.10.4" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, + {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, +] + +[package.dependencies] +fastjsonschema = ">=2.15" +jsonschema = ">=2.6" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, +] + [[package]] name = "networkx" version = "3.1" @@ -1974,6 +2659,23 @@ files = [ [package.extras] test = ["codecov (>=2.0.5)", "coverage (>=4.2)", "flake8 (>=3.0.4)", "pytest (>=4.5.0)", "pytest-cov (>=2.7.1)", "pytest-runner (>=5.1)", "pytest-virtualenv (>=1.7.0)", "virtualenv (>=15.0.3)"] +[[package]] +name = "notebook-shim" +version = "0.2.4" +description = "A shim layer for notebook traits and config" +optional = false +python-versions = ">=3.7" +files = [ + {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, + {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, +] + +[package.dependencies] +jupyter-server = ">=1.8,<3" + +[package.extras] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] + [[package]] name = "numpy" version = "1.26.4" @@ -2021,13 +2723,13 @@ files = [ [[package]] name = "openai" -version = "1.30.3" +version = "1.30.4" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.30.3-py3-none-any.whl", hash = "sha256:f88119c8a848998be533c71ab8aa832446fa72b7ddbc70917c3f5886dc132051"}, - {file = "openai-1.30.3.tar.gz", hash = "sha256:8e1bcdca2b96fe3636ab522fa153d88efde1b702d12ec32f1c73e9553ff93f45"}, + {file = "openai-1.30.4-py3-none-any.whl", hash = "sha256:fb2635efd270efaf9fac2e07558d7948373b940637d3ae3ab624c1a983d4f03f"}, + {file = "openai-1.30.4.tar.gz", hash = "sha256:f3488d9a1c4e0d332b019377d27d7cb4b3d6103fd5d0a416c7ceac780d1d9b88"}, ] [package.dependencies] @@ -2042,6 +2744,17 @@ typing-extensions = ">=4.7,<5" [package.extras] datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +[[package]] +name = "overrides" +version = "7.7.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = false +python-versions = ">=3.6" +files = [ + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, +] + [[package]] name = "packaging" version = "24.0" @@ -2122,6 +2835,17 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, +] + [[package]] name = "parso" version = "0.8.4" @@ -2233,15 +2957,29 @@ files = [ {file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"}, ] +[[package]] +name = "prometheus-client" +version = "0.20.0" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.8" +files = [ + {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, + {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, +] + +[package.extras] +twisted = ["twisted"] + [[package]] name = "prompt-toolkit" -version = "3.0.44" +version = "3.0.45" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.44-py3-none-any.whl", hash = "sha256:205a20669633d042d3722a528b8e7cd3f4dbd9e1450935f596c2cc61166762dd"}, - {file = "prompt_toolkit-3.0.44.tar.gz", hash = "sha256:c1dfd082c4259964bc8bcce1f8460d9dbeb5d4a37bfc25b8082bc02cd41c8af6"}, + {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, + {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, ] [package.dependencies] @@ -2284,6 +3022,34 @@ files = [ {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] +[[package]] +name = "psutil" +version = "5.9.8" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, + {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, + {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, + {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, + {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, + {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, + {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, + {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, + {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, + {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + [[package]] name = "ptyprocess" version = "0.7.0" @@ -2364,21 +3130,32 @@ client = ["requests"] embedded = ["cozo-embedded (==0.7.6)"] pandas = ["ipython", "pandas"] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pydantic" -version = "2.7.1" +version = "2.7.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, - {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, + {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, + {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, ] [package.dependencies] annotated-types = ">=0.4.0" email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""} -pydantic-core = "2.18.2" +pydantic-core = "2.18.3" typing-extensions = ">=4.6.1" [package.extras] @@ -2386,90 +3163,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.2" +version = "2.18.3" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, - {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, - {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, - {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, - {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, - {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, - {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, - {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, - {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, - {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, - {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, - {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, - {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, - {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, + {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, + {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, + {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, + {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, + {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, + {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, + {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, + {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, + {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, + {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, + {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, ] [package.dependencies] @@ -2567,6 +3344,17 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-json-logger" +version = "2.0.7" +description = "A python library adding a json log formatter" +optional = false +python-versions = ">=3.6" +files = [ + {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, + {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, +] + [[package]] name = "pytype" version = "2024.4.11" @@ -2615,6 +3403,44 @@ files = [ {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pywinpty" +version = "2.0.13" +description = "Pseudo terminal support for Windows from Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pywinpty-2.0.13-cp310-none-win_amd64.whl", hash = "sha256:697bff211fb5a6508fee2dc6ff174ce03f34a9a233df9d8b5fe9c8ce4d5eaf56"}, + {file = "pywinpty-2.0.13-cp311-none-win_amd64.whl", hash = "sha256:b96fb14698db1284db84ca38c79f15b4cfdc3172065b5137383910567591fa99"}, + {file = "pywinpty-2.0.13-cp312-none-win_amd64.whl", hash = "sha256:2fd876b82ca750bb1333236ce98488c1be96b08f4f7647cfdf4129dfad83c2d4"}, + {file = "pywinpty-2.0.13-cp38-none-win_amd64.whl", hash = "sha256:61d420c2116c0212808d31625611b51caf621fe67f8a6377e2e8b617ea1c1f7d"}, + {file = "pywinpty-2.0.13-cp39-none-win_amd64.whl", hash = "sha256:71cb613a9ee24174730ac7ae439fd179ca34ccb8c5349e8d7b72ab5dea2c6f4b"}, + {file = "pywinpty-2.0.13.tar.gz", hash = "sha256:c34e32351a3313ddd0d7da23d27f835c860d32fe4ac814d372a3ea9594f41dde"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -2640,6 +3466,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2674,6 +3501,106 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyzmq" +version = "26.0.3" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:44dd6fc3034f1eaa72ece33588867df9e006a7303725a12d64c3dff92330f625"}, + {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acb704195a71ac5ea5ecf2811c9ee19ecdc62b91878528302dd0be1b9451cc90"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbb9c997932473a27afa93954bb77a9f9b786b4ccf718d903f35da3232317de"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bcb34f869d431799c3ee7d516554797f7760cb2198ecaa89c3f176f72d062be"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ece17ec5f20d7d9b442e5174ae9f020365d01ba7c112205a4d59cf19dc38ee"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ba6e5e6588e49139a0979d03a7deb9c734bde647b9a8808f26acf9c547cab1bf"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3bf8b000a4e2967e6dfdd8656cd0757d18c7e5ce3d16339e550bd462f4857e59"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2136f64fbb86451dbbf70223635a468272dd20075f988a102bf8a3f194a411dc"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e8918973fbd34e7814f59143c5f600ecd38b8038161239fd1a3d33d5817a38b8"}, + {file = "pyzmq-26.0.3-cp310-cp310-win32.whl", hash = "sha256:0aaf982e68a7ac284377d051c742610220fd06d330dcd4c4dbb4cdd77c22a537"}, + {file = "pyzmq-26.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:f1a9b7d00fdf60b4039f4455afd031fe85ee8305b019334b72dcf73c567edc47"}, + {file = "pyzmq-26.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:80b12f25d805a919d53efc0a5ad7c0c0326f13b4eae981a5d7b7cc343318ebb7"}, + {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32"}, + {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ca684ee649b55fd8f378127ac8462fb6c85f251c2fb027eb3c887e8ee347bcd"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f17cde1db0754c35a91ac00b22b25c11da6eec5746431d6e5092f0cd31a3fea9"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7c0c0b3244bb2275abe255d4a30c050d541c6cb18b870975553f1fb6f37527"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b88282e55fa39dd556d7fc04160bcf39dea015f78e0cecec8ff4f06c1fc2b5"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:72b67f966b57dbd18dcc7efbc1c7fc9f5f983e572db1877081f075004614fcdd"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4b6cecbbf3b7380f3b61de3a7b93cb721125dc125c854c14ddc91225ba52f83"}, + {file = "pyzmq-26.0.3-cp311-cp311-win32.whl", hash = "sha256:eed56b6a39216d31ff8cd2f1d048b5bf1700e4b32a01b14379c3b6dde9ce3aa3"}, + {file = "pyzmq-26.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500"}, + {file = "pyzmq-26.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:b6907da3017ef55139cf0e417c5123a84c7332520e73a6902ff1f79046cd3b94"}, + {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:068ca17214038ae986d68f4a7021f97e187ed278ab6dccb79f837d765a54d753"}, + {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7821d44fe07335bea256b9f1f41474a642ca55fa671dfd9f00af8d68a920c2d4"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb438a26d87c123bb318e5f2b3d86a36060b01f22fbdffd8cf247d52f7c9a2b"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69ea9d6d9baa25a4dc9cef5e2b77b8537827b122214f210dd925132e34ae9b12"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7daa3e1369355766dea11f1d8ef829905c3b9da886ea3152788dc25ee6079e02"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6ca7a9a06b52d0e38ccf6bca1aeff7be178917893f3883f37b75589d42c4ac20"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1b7d0e124948daa4d9686d421ef5087c0516bc6179fdcf8828b8444f8e461a77"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e746524418b70f38550f2190eeee834db8850088c834d4c8406fbb9bc1ae10b2"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6b3146f9ae6af82c47a5282ac8803523d381b3b21caeae0327ed2f7ecb718798"}, + {file = "pyzmq-26.0.3-cp312-cp312-win32.whl", hash = "sha256:2b291d1230845871c00c8462c50565a9cd6026fe1228e77ca934470bb7d70ea0"}, + {file = "pyzmq-26.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:926838a535c2c1ea21c903f909a9a54e675c2126728c21381a94ddf37c3cbddf"}, + {file = "pyzmq-26.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:5bf6c237f8c681dfb91b17f8435b2735951f0d1fad10cc5dfd96db110243370b"}, + {file = "pyzmq-26.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c0991f5a96a8e620f7691e61178cd8f457b49e17b7d9cfa2067e2a0a89fc1d5"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dbf012d8fcb9f2cf0643b65df3b355fdd74fc0035d70bb5c845e9e30a3a4654b"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:01fbfbeb8249a68d257f601deb50c70c929dc2dfe683b754659569e502fbd3aa"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c8eb19abe87029c18f226d42b8a2c9efdd139d08f8bf6e085dd9075446db450"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5344b896e79800af86ad643408ca9aa303a017f6ebff8cee5a3163c1e9aec987"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:204e0f176fd1d067671157d049466869b3ae1fc51e354708b0dc41cf94e23a3a"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a42db008d58530efa3b881eeee4991146de0b790e095f7ae43ba5cc612decbc5"}, + {file = "pyzmq-26.0.3-cp37-cp37m-win32.whl", hash = "sha256:8d7a498671ca87e32b54cb47c82a92b40130a26c5197d392720a1bce1b3c77cf"}, + {file = "pyzmq-26.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3b4032a96410bdc760061b14ed6a33613ffb7f702181ba999df5d16fb96ba16a"}, + {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2cc4e280098c1b192c42a849de8de2c8e0f3a84086a76ec5b07bfee29bda7d18"}, + {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bde86a2ed3ce587fa2b207424ce15b9a83a9fa14422dcc1c5356a13aed3df9d"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34106f68e20e6ff253c9f596ea50397dbd8699828d55e8fa18bd4323d8d966e6"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ebbbd0e728af5db9b04e56389e2299a57ea8b9dd15c9759153ee2455b32be6ad"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6b1d1c631e5940cac5a0b22c5379c86e8df6a4ec277c7a856b714021ab6cfad"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e891ce81edd463b3b4c3b885c5603c00141151dd9c6936d98a680c8c72fe5c67"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9b273ecfbc590a1b98f014ae41e5cf723932f3b53ba9367cfb676f838038b32c"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b32bff85fb02a75ea0b68f21e2412255b5731f3f389ed9aecc13a6752f58ac97"}, + {file = "pyzmq-26.0.3-cp38-cp38-win32.whl", hash = "sha256:f6c21c00478a7bea93caaaef9e7629145d4153b15a8653e8bb4609d4bc70dbfc"}, + {file = "pyzmq-26.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:3401613148d93ef0fd9aabdbddb212de3db7a4475367f49f590c837355343972"}, + {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:2ed8357f4c6e0daa4f3baf31832df8a33334e0fe5b020a61bc8b345a3db7a606"}, + {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1c8f2a2ca45292084c75bb6d3a25545cff0ed931ed228d3a1810ae3758f975f"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b63731993cdddcc8e087c64e9cf003f909262b359110070183d7f3025d1c56b5"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3cd31f859b662ac5d7f4226ec7d8bd60384fa037fc02aee6ff0b53ba29a3ba8"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115f8359402fa527cf47708d6f8a0f8234f0e9ca0cab7c18c9c189c194dbf620"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:715bdf952b9533ba13dfcf1f431a8f49e63cecc31d91d007bc1deb914f47d0e4"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e1258c639e00bf5e8a522fec6c3eaa3e30cf1c23a2f21a586be7e04d50c9acab"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:15c59e780be8f30a60816a9adab900c12a58d79c1ac742b4a8df044ab2a6d920"}, + {file = "pyzmq-26.0.3-cp39-cp39-win32.whl", hash = "sha256:d0cdde3c78d8ab5b46595054e5def32a755fc028685add5ddc7403e9f6de9879"}, + {file = "pyzmq-26.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:ce828058d482ef860746bf532822842e0ff484e27f540ef5c813d516dd8896d2"}, + {file = "pyzmq-26.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:788f15721c64109cf720791714dc14afd0f449d63f3a5487724f024345067381"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c18645ef6294d99b256806e34653e86236eb266278c8ec8112622b61db255de"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e6bc96ebe49604df3ec2c6389cc3876cabe475e6bfc84ced1bf4e630662cb35"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:971e8990c5cc4ddcff26e149398fc7b0f6a042306e82500f5e8db3b10ce69f84"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8416c23161abd94cc7da80c734ad7c9f5dbebdadfdaa77dad78244457448223"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:082a2988364b60bb5de809373098361cf1dbb239623e39e46cb18bc035ed9c0c"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d57dfbf9737763b3a60d26e6800e02e04284926329aee8fb01049635e957fe81"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:77a85dca4c2430ac04dc2a2185c2deb3858a34fe7f403d0a946fa56970cf60a1"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c82a6d952a1d555bf4be42b6532927d2a5686dd3c3e280e5f63225ab47ac1f5"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4496b1282c70c442809fc1b151977c3d967bfb33e4e17cedbf226d97de18f709"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e4946d6bdb7ba972dfda282f9127e5756d4f299028b1566d1245fa0d438847e6"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03c0ae165e700364b266876d712acb1ac02693acd920afa67da2ebb91a0b3c09"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3e3070e680f79887d60feeda051a58d0ac36622e1759f305a41059eff62c6da7"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6ca08b840fe95d1c2bd9ab92dac5685f949fc6f9ae820ec16193e5ddf603c3b2"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e76654e9dbfb835b3518f9938e565c7806976c07b37c33526b574cc1a1050480"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:871587bdadd1075b112e697173e946a07d722459d20716ceb3d1bd6c64bd08ce"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d0a2d1bd63a4ad79483049b26514e70fa618ce6115220da9efdff63688808b17"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0270b49b6847f0d106d64b5086e9ad5dc8a902413b5dbbb15d12b60f9c1747a4"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:703c60b9910488d3d0954ca585c34f541e506a091a41930e663a098d3b794c67"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74423631b6be371edfbf7eabb02ab995c2563fee60a80a30829176842e71722a"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4adfbb5451196842a88fda3612e2c0414134874bffb1c2ce83ab4242ec9e027d"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3516119f4f9b8671083a70b6afaa0a070f5683e431ab3dc26e9215620d7ca1ad"}, + {file = "pyzmq-26.0.3.tar.gz", hash = "sha256:dba7d9f2e047dfa2bca3b01f4f84aa5246725203d6284e3790f2ca15fba6b40a"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + [[package]] name = "referencing" version = "0.35.1" @@ -2798,6 +3725,31 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +description = "Pure python rfc3986 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, + {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, +] + [[package]] name = "rich" version = "13.7.1" @@ -3086,6 +4038,22 @@ tensorflow = ["safetensors[numpy]", "tensorflow (>=2.11.0)"] testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"] torch = ["safetensors[numpy]", "torch (>=1.10)"] +[[package]] +name = "send2trash" +version = "1.8.3" +description = "Send file to trash natively under Mac OS X, Windows and Linux" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, + {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, +] + +[package.extras] +nativelib = ["pyobjc-framework-Cocoa", "pywin32"] +objc = ["pyobjc-framework-Cocoa"] +win32 = ["pywin32"] + [[package]] name = "sentry-sdk" version = "1.45.0" @@ -3224,6 +4192,17 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "stack-data" version = "0.6.3" @@ -3313,6 +4292,27 @@ files = [ [package.extras] tests = ["pytest", "pytest-cov"] +[[package]] +name = "terminado" +version = "0.18.1" +description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0"}, + {file = "terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e"}, +] + +[package.dependencies] +ptyprocess = {version = "*", markers = "os_name != \"nt\""} +pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} +tornado = ">=6.1.0" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] + [[package]] name = "tiktoken" version = "0.6.0" @@ -3365,6 +4365,24 @@ requests = ">=2.26.0" [package.extras] blobfile = ["blobfile (>=2)"] +[[package]] +name = "tinycss2" +version = "1.3.0" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, + {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["pytest", "ruff"] + [[package]] name = "tokenizers" version = "0.19.1" @@ -3504,6 +4522,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + [[package]] name = "tqdm" version = "4.66.4" @@ -3666,6 +4704,20 @@ files = [ {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] +[[package]] +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, +] + +[package.extras] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] + [[package]] name = "urllib3" version = "2.2.1" @@ -3734,6 +4786,59 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] +[[package]] +name = "webcolors" +version = "1.13" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.7" +files = [ + {file = "webcolors-1.13-py3-none-any.whl", hash = "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf"}, + {file = "webcolors-1.13.tar.gz", hash = "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a"}, +] + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "widgetsnbextension" +version = "4.0.11" +description = "Jupyter interactive widgets for Jupyter Notebook" +optional = false +python-versions = ">=3.7" +files = [ + {file = "widgetsnbextension-4.0.11-py3-none-any.whl", hash = "sha256:55d4d6949d100e0d08b94948a42efc3ed6dfdc0e9468b2c4b128c9a2ce3a7a36"}, + {file = "widgetsnbextension-4.0.11.tar.gz", hash = "sha256:8b22a8f1910bfd188e596fe7fc05dcbd87e810c8a4ba010bdb3da86637398474"}, +] + [[package]] name = "xxhash" version = "3.4.1" @@ -3972,4 +5077,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "3342e4723ae2e448074da082ab6d9db5dea78ede813d1ad8241f39ee97e96b12" +content-hash = "f8a02f17d792c9823d581de52fec20fffbb6bf61c15923d890676ef9c1426d24" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index 82545c3c4..ba43887ee 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -44,6 +44,8 @@ pytype = ">=2024.4.11" julep = "^0.2.4" pyjwt = "^2.8.0" ward = "^0.68.0b0" +jupyterlab = "^4.1.8" +ipywidgets = "^8.1.2" [build-system] requires = ["poetry-core"] From ccf7bae35070816741b499912e4df88d447bf6b0 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Wed, 1 May 2024 20:54:36 +0530 Subject: [PATCH 02/43] fix: Minor fix to rec-sum notebook Signed-off-by: Diwank Singh Tomer --- agents-api/notebooks/RecSum-experiments.ipynb | 194 ++++++++++++------ 1 file changed, 130 insertions(+), 64 deletions(-) diff --git a/agents-api/notebooks/RecSum-experiments.ipynb b/agents-api/notebooks/RecSum-experiments.ipynb index b1b98cb7f..90e282203 100644 --- a/agents-api/notebooks/RecSum-experiments.ipynb +++ b/agents-api/notebooks/RecSum-experiments.ipynb @@ -519,7 +519,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 38, "id": "6323b7b2-0aaf-4cea-896b-0c887054ce6e", "metadata": {}, "outputs": [], @@ -529,6 +529,10 @@ "\n", "def compactify(chat_session=chat_session):\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", @@ -568,7 +572,7 @@ "\n", "\"\"\"\n", " messages = [system(system_prompt), user(user_message)]\n", - " cot_result = generate(messages, model=\"gpt-4-turbo\", stop=[' Date: Thu, 2 May 2024 15:45:42 +0530 Subject: [PATCH 03/43] wip: Rec-sum notebook Signed-off-by: Diwank Singh Tomer --- agents-api/notebooks/RecSum-experiments.ipynb | 319 ++++++------------ agents-api/notebooks/test-chat.json | 1 + 2 files changed, 111 insertions(+), 209 deletions(-) create mode 100644 agents-api/notebooks/test-chat.json diff --git a/agents-api/notebooks/RecSum-experiments.ipynb b/agents-api/notebooks/RecSum-experiments.ipynb index 90e282203..b767d2494 100644 --- a/agents-api/notebooks/RecSum-experiments.ipynb +++ b/agents-api/notebooks/RecSum-experiments.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "b03a4636-d57e-42e9-8a06-fdb7c6803708", "metadata": {}, "outputs": [ @@ -12,19 +12,19 @@ "True" ] }, - "execution_count": 1, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from dotenv import load_dotenv\n", - "load_dotenv(\"../.env\")" + "load_dotenv(\"../../.env\")" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "eb80a352-ad21-423c-9284-32b21d271eba", "metadata": {}, "outputs": [], @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "4619f484-55f6-4122-8e26-27ec9e3506d5", "metadata": {}, "outputs": [], @@ -44,7 +44,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "fbf3db3a-4ed1-4e71-b1da-e419445f3cc6", "metadata": {}, "outputs": [], @@ -65,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "a33f6f0f-ce18-4536-b514-b9f6d220f54f", "metadata": {}, "outputs": [], @@ -81,7 +81,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "7bf6bd91-4959-403c-af79-64ad27ae45ee", "metadata": {}, "outputs": [], @@ -100,7 +100,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 8, "id": "3a14a68e-6d8a-47b2-a58a-03d4bdb793df", "metadata": {}, "outputs": [], @@ -289,7 +289,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "id": "0f95ee31-835f-4ccf-91b0-1a3a3b94744e", "metadata": {}, "outputs": [], @@ -332,17 +332,17 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "id": "0048ada9-ec65-441e-8bda-fb1b03ffcca9", "metadata": {}, "outputs": [], "source": [ - "chat_session = [system(\"give relationship advice to the user\")]" + "chat_session = [system(\"you are a friend who likes to give life advice\")]" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 11, "id": "4a348b46-5b93-4911-990d-3e4973c6a340", "metadata": {}, "outputs": [ @@ -350,108 +350,56 @@ "name": "stdin", "output_type": "stream", "text": [ - "You: hi\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GPT: Hello! How can I help you today?\n" - ] - }, - { - "name": "stdin", - "output_type": "stream", - "text": [ - "You: I am feeling like my wife thinks I am ugly\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GPT: I'm sorry to hear that you're feeling that way. It's important to open up the lines of communication with your wife and share how you're feeling. Try to have an honest and respectful conversation with her about your concerns. It's possible that there could be a misunderstanding or miscommunication that can be cleared up by discussing it openly. It's important to remember that physical appearance is just one aspect of a relationship, and true beauty comes from within. Focus on the love and connection you share with your wife, and work together to understand and support each other.\n" - ] - }, - { - "name": "stdin", - "output_type": "stream", - "text": [ - "You: yeah but that's just vague. do you have a wife?\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GPT: I'm an AI assistant, so I don't have a personal life or relationships. However, I can still offer guidance and support based on my knowledge and experience in providing relationship advice. Communication, understanding, and empathy are key components of any healthy relationship. If you're feeling insecure about how your wife perceives your appearance, have an open and honest conversation with her to address your concerns and work towards a resolution together. Remember, it's important to value yourself and your worth, regardless of how others may perceive you physically.\n" - ] - }, - { - "name": "stdin", - "output_type": "stream", - "text": [ - "You: ok, do you talk to other people with these problems?\n" + "You: hey\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "GPT: Yes, I interact with many people who seek advice and support on a variety of topics, including relationship issues. I'm here to provide guidance, offer perspective, and assist you in navigating through your concerns. If you have specific questions or need advice on how to approach a situation, feel free to share, and I'll do my best to help you. Remember, it's common for individuals to experience challenges in their relationships, and seeking support and guidance is a positive step towards finding solutions and improving communication.\n" + "GPT: Hey! How are you doing?\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ - "You: ok, can you tell me about an incident that turned out for the better?\n" + "You: good, how about you?\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "GPT: Certainly! One common example I can share is a couple facing a communication breakdown in their relationship. They were struggling to express their needs and understand each other's perspectives, leading to frequent misunderstandings and arguments. However, they decided to attend couples therapy to work on their communication skills and learn effective ways to express their feelings and listen to each other.\n", - "\n", - "Through therapy, they were able to uncover underlying issues, address past resentments, and develop healthier communication patterns. They learned to communicate openly and honestly, empathize with each other's feelings, and work together as a team to resolve conflicts. Over time, their relationship strengthened, and they felt more connected, understood, and supported by each other.\n", - "\n", - "By taking proactive steps to improve their communication and seek professional guidance, this couple was able to overcome their challenges and ultimately strengthen their relationship. It's a reminder that with effort, patience, and willingness to work on the relationship, positive outcomes and growth are possible.\n" + "GPT: I'm doing well, thank you for asking. Is there anything on your mind that you'd like to talk about or get some advice on?\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ - "You: why am I like this? ugly i mean\n" + "You: no why do you say that? did I sound troubled?\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "GPT: It's important to remember that beauty is subjective and comes in many forms. It's natural to have insecurities and doubts about our appearances, as we often compare ourselves to societal standards or feel pressure to look a certain way. However, it's essential to focus on self-acceptance, self-love, and recognizing your inherent worth beyond physical appearance.\n", - "\n", - "It may be helpful to explore where these feelings of being \"ugly\" are coming from and work on building self-confidence and self-esteem. Remember that beauty is not just about external features but also about qualities such as kindness, empathy, resilience, and authenticity.\n", - "\n", - "Consider practicing self-care, engaging in activities that bring you joy and boost your self-esteem, and surrounding yourself with supportive and loving people who appreciate you for who you are. If these feelings persist and significantly impact your well-being, consider reaching out to a therapist or counselor for additional support and guidance in building a positive self-image. You deserve to feel confident and valued in your own skin.\n" + "GPT: Not at all! I just thought I'd check in and see if there's anything on your mind that you might need some advice or someone to talk to about. But if you're doing well, that's great to hear!\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ - "You: hmm, can you think of a song about this?\n" + "You: no I didnt say I was ok just that I hadnt thought of asking for advice yet\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "GPT: One song that comes to mind is \"Scars to Your Beautiful\" by Alessia Cara. The song's powerful lyrics speak to the message of self-acceptance, embracing uniqueness, and recognizing inner beauty beyond physical appearances. It conveys a message of empowerment, self-love, and resilience, encouraging listeners to embrace their imperfections and recognize their worth.\n", - "\n", - "The lyrics highlight the idea that everyone is beautiful in their own way, regardless of society's standards or expectations. The song serves as a reminder that true beauty comes from within and that we should celebrate our differences and embrace who we are, scars and all. It's an uplifting and inspirational anthem that encourages self-acceptance and self-love. I hope you find comfort and empowerment in the message of this song.\n" + "GPT: Ah, I see. Well, I'm here whenever you need a listening ear or some advice. Just let me know how I can help!\n" ] }, { @@ -466,6 +414,19 @@ "chat()" ] }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b1aac632-8a2f-4ce1-b486-33249714159f", + "metadata": {}, + "outputs": [], + "source": [ + "# Load test chat from json file\n", + "import json\n", + "with open(\"./test-chat.json\", 'r') as f:\n", + " chat_session = json.load(f)" + ] + }, { "cell_type": "code", "execution_count": 16, @@ -478,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 13, "id": "1eaabfe2-f399-428b-84d2-ed8c237b7d3d", "metadata": {}, "outputs": [], @@ -502,7 +463,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 14, "id": "2a726b3c-493c-4df5-81a7-6b7b109c222e", "metadata": {}, "outputs": [], @@ -517,17 +478,33 @@ " )" ] }, + { + "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": 38, + "execution_count": 19, "id": "6323b7b2-0aaf-4cea-896b-0c887054ce6e", "metadata": {}, "outputs": [], "source": [ "import json\n", "from pprint import pprint\n", + "import time\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", @@ -572,11 +549,17 @@ "\n", "\"\"\"\n", " messages = [system(system_prompt), user(user_message)]\n", - " cot_result = generate(messages, model=\"gpt-4\", stop=[' Date: Fri, 3 May 2024 10:21:25 +0530 Subject: [PATCH 04/43] entity and trim step prompt + notebook. summarise setup. --- agents-api/notebooks/01-revise-entities.ipynb | 539 +++++++++++++ agents-api/notebooks/02-trim-messages.ipynb | 727 ++++++++++++++++++ agents-api/notebooks/03-summarise.ipynb | 665 ++++++++++++++++ agents-api/notebooks/04-remove-messages.ipynb | 0 agents-api/notebooks/RecSum-experiments.ipynb | 14 +- 5 files changed, 1938 insertions(+), 7 deletions(-) create mode 100644 agents-api/notebooks/01-revise-entities.ipynb create mode 100644 agents-api/notebooks/02-trim-messages.ipynb create mode 100644 agents-api/notebooks/03-summarise.ipynb create mode 100644 agents-api/notebooks/04-remove-messages.ipynb diff --git a/agents-api/notebooks/01-revise-entities.ipynb b/agents-api/notebooks/01-revise-entities.ipynb new file mode 100644 index 000000000..00667cb82 --- /dev/null +++ b/agents-api/notebooks/01-revise-entities.ipynb @@ -0,0 +1,539 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "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": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from openai import Client\n", + "\n", + "client = Client()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "make_chatml = lambda content, role=\"system\", name=None, **_: {\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", + "user = lambda content, name=None: make_chatml(role=\"user\", content=content, name=name)\n", + "assistant = lambda content, name=None: make_chatml(\n", + " role=\"assistant\", content=content, name=name\n", + ")\n", + "system = lambda content, name=None: make_chatml(content, name=name)\n", + "thought = lambda content, name=None: make_chatml(content, name=\"thought\")\n", + "information = lambda content: system(content, name=\"information\")\n", + "summary = lambda content: system(content, name=\"summary\")\n", + "entities = lambda content: system(content, name=\"entity\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "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", + "generate = (\n", + " lambda history, model=\"gpt-4-turbo\", **kwargs: client.chat.completions.create(\n", + " model=model, messages=history, **kwargs\n", + " )\n", + " .choices[0]\n", + " .message.__dict__\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "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": 11, + "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": 29, + "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": 13, + "metadata": {}, + "outputs": [], + "source": [ + "chat_session = [system(\"you are a friend who likes to give life advice\")]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# Load test chat from json file\n", + "import json\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": 15, + "metadata": {}, + "outputs": [], + "source": [ + "backup_chat = [*chat_session]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "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": 17, + "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": 32, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pprint import pprint\n", + "import time\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=[\" {user: ...})\n", + "- SUMMARIZE: Combine two or more messages into one summary\n", + "- REMOVE: Safely remove messages from the session" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from openai import Client\n", + "\n", + "client = Client()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "make_chatml = lambda content, role=\"system\", name=None, **_: {\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", + "user = lambda content, name=None: make_chatml(role=\"user\", content=content, name=name)\n", + "assistant = lambda content, name=None: make_chatml(\n", + " role=\"assistant\", content=content, name=name\n", + ")\n", + "system = lambda content, name=None: make_chatml(content, name=name)\n", + "thought = lambda content, name=None: make_chatml(content, name=\"thought\")\n", + "information = lambda content: system(content, name=\"information\")\n", + "summary = lambda content: system(content, name=\"summary\")\n", + "entities = lambda content: system(content, name=\"entity\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "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", + "generate = (\n", + " lambda history, model=\"gpt-4-turbo\", **kwargs: client.chat.completions.create(\n", + " model=model, messages=history, **kwargs\n", + " )\n", + " .choices[0]\n", + " .message.__dict__\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "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": 6, + "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": 7, + "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": null, + "metadata": {}, + "outputs": [], + "source": [ + "chat_session = [system(\"you are a friend who likes to give life advice\")]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# Load test chat from json file\n", + "import json\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": 9, + "metadata": {}, + "outputs": [], + "source": [ + "backup_chat = [*chat_session]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "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": 11, + "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": 13, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pprint import pprint\n", + "import time\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=[\" {user: ...})\n", + "- SUMMARIZE: Combine two or more messages into one summary\n", + "- REMOVE: Safely remove messages from the session" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from openai import Client\n", + "\n", + "client = Client()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "make_chatml = lambda content, role=\"system\", name=None, **_: {\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", + "user = lambda content, name=None: make_chatml(role=\"user\", content=content, name=name)\n", + "assistant = lambda content, name=None: make_chatml(\n", + " role=\"assistant\", content=content, name=name\n", + ")\n", + "system = lambda content, name=None: make_chatml(content, name=name)\n", + "thought = lambda content, name=None: make_chatml(content, name=\"thought\")\n", + "information = lambda content: system(content, name=\"information\")\n", + "summary = lambda content: system(content, name=\"summary\")\n", + "entities = lambda content: system(content, name=\"entity\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "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", + "generate = (\n", + " lambda history, model=\"gpt-4-turbo\", **kwargs: client.chat.completions.create(\n", + " model=model, messages=history, **kwargs\n", + " )\n", + " .choices[0]\n", + " .message.__dict__\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "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": 6, + "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 CoT" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "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 CoT" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "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(\"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": "markdown", + "metadata": {}, + "source": [ + "## Summarise CoT" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# TODO:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "chat_session = [system(\"you are a friend who likes to give life advice\")]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load test chat from json file\n", + "import json\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": null, + "metadata": {}, + "outputs": [], + "source": [ + "backup_chat = [*chat_session]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "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": null, + "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": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pprint import pprint\n", + "import time\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", + " result = generate(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", + "{entity_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=[\" Date: Fri, 3 May 2024 14:35:07 +0530 Subject: [PATCH 05/43] summarization step added. --- agents-api/notebooks/03-summarise.ipynb | 762 ++++++++++++++++++++++-- 1 file changed, 724 insertions(+), 38 deletions(-) diff --git a/agents-api/notebooks/03-summarise.ipynb b/agents-api/notebooks/03-summarise.ipynb index 88357151d..a934fd1b9 100644 --- a/agents-api/notebooks/03-summarise.ipynb +++ b/agents-api/notebooks/03-summarise.ipynb @@ -33,6 +33,13 @@ "- REMOVE: Safely remove messages from the session" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper functions and Setup" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -50,20 +57,24 @@ "metadata": {}, "outputs": [], "source": [ - "make_chatml = lambda content, role=\"system\", name=None, **_: {\n", + "make_chatml = lambda content, role=\"system\", name=None, index=None, **_: {\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", - "user = lambda content, name=None: make_chatml(role=\"user\", content=content, name=name)\n", - "assistant = lambda content, name=None: make_chatml(\n", - " role=\"assistant\", content=content, name=name\n", + "user = lambda content, name=None, index=None: make_chatml(\n", + " role=\"user\", content=content, name=name, index=index\n", + ")\n", + "assistant = lambda content, name=None, index=None: make_chatml(\n", + " role=\"assistant\", content=content, name=name, index=index\n", + ")\n", + "system = lambda content, name=None, index=None: make_chatml(\n", + " content, name=name, index=index\n", ")\n", - "system = lambda content, name=None: make_chatml(content, name=name)\n", "thought = lambda content, name=None: make_chatml(content, name=\"thought\")\n", "information = lambda content: system(content, name=\"information\")\n", - "summary = lambda content: system(content, name=\"summary\")\n", + "summary = lambda content, index=None: system(content, name=\"summary\", index=index)\n", "entities = lambda content: system(content, name=\"entity\")" ] }, @@ -89,7 +100,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -104,9 +115,16 @@ " chat_session.append(make_chatml(**result))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## One-Shot Example Chat" + ] + }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -292,12 +310,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Entity CoT" + "## Entity Extraction One-Shot Example" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -323,12 +341,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Trim CoT" + "## 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": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -344,14 +371,18 @@ "\n", "example_trimmed_messages = [\n", " *example_chat[0:8],\n", - " assistant(\"Haha accurate. He does push boundaries and keep things interesting!\"),\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", + " \"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", + " \"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", @@ -368,7 +399,8 @@ "- 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", + " index=21,\n", " ),\n", " *example_chat[22:34],\n", " assistant(\n", @@ -382,7 +414,8 @@ "- Highly engaging and enjoyable interactions\n", "- Look forward to more amusing conversations!\n", "\n", - "\"\"\"\n", + "\"\"\",\n", + " index=34,\n", " ),\n", "]" ] @@ -391,16 +424,52 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Summarise CoT" + "## Summarise One-Shot Example" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "metadata": {}, "outputs": [], "source": [ - "# TODO:" + "# 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", + "]" ] }, { @@ -409,28 +478,35 @@ "metadata": {}, "outputs": [], "source": [ - "chat_session = [system(\"you are a friend who likes to give life advice\")]" + "# 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": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ - "# Load test chat from json file\n", + "# Test Chat File\n", "import json\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" + "for index, message in enumerate(chat_session):\n", + " message[\"index\"] = index + 1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -439,7 +515,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -456,7 +532,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -479,7 +555,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": {}, "outputs": [], "source": [ @@ -541,7 +617,6 @@ "\n", " messages.append(cot_result)\n", " start_message = \"\"\"\\\n", - "\n", "Begin! Directly write the entities as a Markdown formatted list, don't write any thoughts or delimiters.\n", "\n", "\n", @@ -550,11 +625,69 @@ " messages.append(user(start_message))\n", "\n", " print(\"Starting chatml generation\")\n", - " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"\n", "\n", "\n", - "{entity_chain_of_thought}\n", + "{summarize_chain_of_thought_example}\n", "\n", "\n", "\n", @@ -633,11 +766,564 @@ " messages.append(user(start_message))\n", "\n", " print(\"Starting chatml generation\")\n", - " result = generate(messages, model=\"gpt-4-turbo\", temperature=0.1, stop=[\"\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=[\"\\n'\n", + " '[\\n'\n", + " ' {\\n'\n", + " ' \"role\": \"system\",\\n'\n", + " ' \"name\": \"summary\",\\n'\n", + " ' \"content\": \"Event: The user discussed finishing \\'Red Dead '\n", + " \"Redemption 2' and particularly enjoyed the last mission. They \"\n", + " 'also talked about favorite missions and characters, specifically '\n", + " 'Arthur over Dutch.\"\\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 '\n", + " \"you're into intense co-op action. The game really ramps up with \"\n", + " 'its twin-stick shooter gameplay, and it\\\\u2019s super fun but '\n", + " 'also quite challenging. Working together with teammates to '\n", + " 'complete those missions can get pretty hectic. How are you '\n", + " '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 '\n", + " 'dog. what 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 '\n", + " 'tearing through those enemy swarms, and the guard dog drone '\n", + " 'really helps in keeping the smaller threats at bay. I personally '\n", + " 'love using the railgun with a shield backpack. It gives a good '\n", + " 'balance of offense and defense, especially when things get really '\n", + " 'chaotic. What\\'s been the toughest mission for you so 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 '\n", + " \"your reflexes and teamwork. It's all about timing and \"\n", + " 'coordination with your team to bring those heavy hitters down. '\n", + " 'Have you tried using more strategic traps or mines? Sometimes '\n", + " 'setting up the right position with static fields can really make '\n", + " '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, '\n", + " 'especially in a game as intense as Helldivers 2 where things get '\n", + " 'chaotic fast. Keeping on the move helps a ton. Just make sure '\n", + " \"someone's always got your back! Have you guys tried any of the \"\n", + " 'higher difficulty levels yet, or are you sticking to a certain '\n", + " 'comfort zone for now?\"\\n'\n", + " ' },\\n'\n", + " ' {\\n'\n", + " ' \"role\": \"system\",\\n'\n", + " ' \"name\": \"summary\",\\n'\n", + " ' \"content\": \"Event: The user discussed an Nvidia driver issue, '\n", + " 'particularly its incompatibility with Linux, and the assistant '\n", + " 'provided potential solutions and resources for assistance.\"\\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',\n", + " 'role': 'assistant'}\n", + "End CoT generation\n", + "Starting chatml generation\n", + "End chatml generation\n" + ] + } + ], + "source": [ + "trimmed_session = json.loads(trimmed_messages[\"content\"])\n", + "entity_info = entities(entity_info[\"content\"])\n", + "\n", + "\n", + "summarized_messages = summarize_messages(\n", + " entity_info=entity_info, chat_session=trimmed_session\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'content': '[\\n'\n", + " ' {\\n'\n", + " ' \"role\": \"system\",\\n'\n", + " ' \"name\": \"summary\",\\n'\n", + " ' \"content\": \"Event: The user discussed finishing \\'Red Dead '\n", + " \"Redemption 2' and particularly enjoyed the last mission. They \"\n", + " 'also talked about favorite missions and characters, specifically '\n", + " 'Arthur over Dutch.\"\\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 '\n", + " \"you're into intense co-op action. The game really ramps up with \"\n", + " 'its twin-stick shooter gameplay, and it\\\\u2019s super fun but '\n", + " 'also quite challenging. Working together with teammates to '\n", + " 'complete those missions can get pretty hectic. How are you '\n", + " '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 '\n", + " 'dog. what 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 '\n", + " 'tearing through those enemy swarms, and the guard dog drone '\n", + " 'really helps in keeping the smaller threats at bay. I personally '\n", + " 'love using the railgun with a shield backpack. It gives a good '\n", + " 'balance of offense and defense, especially when things get really '\n", + " 'chaotic. What\\'s been the toughest mission for you so 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 '\n", + " \"your reflexes and teamwork. It's all about timing and \"\n", + " 'coordination with your team to bring those heavy hitters down. '\n", + " 'Have you tried using more strategic traps or mines? Sometimes '\n", + " 'setting up the right position with static fields can really make '\n", + " '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, '\n", + " 'especially in a game as intense as Helldivers 2 where things get '\n", + " 'chaotic fast. Keeping on the move helps a ton. Just make sure '\n", + " \"someone's always got your back! Have you guys tried any of the \"\n", + " 'higher difficulty levels yet, or are you sticking to a certain '\n", + " 'comfort zone for now?\"\\n'\n", + " ' },\\n'\n", + " ' {\\n'\n", + " ' \"role\": \"system\",\\n'\n", + " ' \"name\": \"summary\",\\n'\n", + " ' \"content\": \"Event: The user discussed an Nvidia driver issue, '\n", + " 'particularly its incompatibility with Linux, and the assistant '\n", + " 'provided potential solutions and resources for assistance.\"\\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", + " 'role': 'assistant'}\n" + ] + } + ], + "source": [ + "pprint(summarized_messages)" ] } ], From a6ce7b979537369e2e19bea610ac40e5eaf8f691 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Tue, 7 May 2024 21:28:23 +0530 Subject: [PATCH 06/43] wip Signed-off-by: Diwank Singh Tomer --- agents-api/notebooks/rec_sum/__init__.py | 3 + agents-api/notebooks/rec_sum/data.py | 32 + agents-api/notebooks/rec_sum/entities.py | 104 +++ .../rec_sum/entities_example_chat.json | 68 ++ agents-api/notebooks/rec_sum/generate.py | 22 + agents-api/notebooks/rec_sum/summarize.py | 111 +++ .../rec_sum/summarize_example_chat.json | 144 ++++ .../rec_sum/summarize_example_result.json | 58 ++ agents-api/notebooks/rec_sum/trim.py | 108 +++ .../notebooks/rec_sum/trim_example_chat.json | 34 + .../rec_sum/trim_example_result.json | 17 + agents-api/notebooks/rec_sum/utils.py | 37 + agents-api/poetry.lock | 768 +++++++++++++++++- agents-api/pyproject.toml | 2 + 14 files changed, 1504 insertions(+), 4 deletions(-) create mode 100644 agents-api/notebooks/rec_sum/__init__.py create mode 100644 agents-api/notebooks/rec_sum/data.py create mode 100644 agents-api/notebooks/rec_sum/entities.py create mode 100644 agents-api/notebooks/rec_sum/entities_example_chat.json create mode 100644 agents-api/notebooks/rec_sum/generate.py create mode 100644 agents-api/notebooks/rec_sum/summarize.py create mode 100644 agents-api/notebooks/rec_sum/summarize_example_chat.json create mode 100644 agents-api/notebooks/rec_sum/summarize_example_result.json create mode 100644 agents-api/notebooks/rec_sum/trim.py create mode 100644 agents-api/notebooks/rec_sum/trim_example_chat.json create mode 100644 agents-api/notebooks/rec_sum/trim_example_result.json create mode 100644 agents-api/notebooks/rec_sum/utils.py diff --git a/agents-api/notebooks/rec_sum/__init__.py b/agents-api/notebooks/rec_sum/__init__.py new file mode 100644 index 000000000..c2b9d406e --- /dev/null +++ b/agents-api/notebooks/rec_sum/__init__.py @@ -0,0 +1,3 @@ +from .entities import get_entities +from .summarize import summarize_messages +from .trim import trim_messages diff --git a/agents-api/notebooks/rec_sum/data.py b/agents-api/notebooks/rec_sum/data.py new file mode 100644 index 000000000..2caa7231d --- /dev/null +++ b/agents-api/notebooks/rec_sum/data.py @@ -0,0 +1,32 @@ +import json +from pathlib import Path + + +module_directory = Path(__file__).parent + + + +with open(f"{module_directory}/entities_example_chat.json", 'r') as _f: + entities_example_chat = json.load(_f) + + + +with open(f"{module_directory}/trim_example_chat.json", 'r') as _f: + trim_example_chat = json.load(_f) + + + +with open(f"{module_directory}/trim_example_result.json", 'r') as _f: + trim_example_result = json.load(_f) + + + +with open(f"{module_directory}/summarize_example_chat.json", 'r') as _f: + summarize_example_chat = json.load(_f) + + + +with open(f"{module_directory}/summarize_example_result.json", 'r') as _f: + summarize_example_result = json.load(_f) + + diff --git a/agents-api/notebooks/rec_sum/entities.py b/agents-api/notebooks/rec_sum/entities.py new file mode 100644 index 000000000..baf702597 --- /dev/null +++ b/agents-api/notebooks/rec_sum/entities.py @@ -0,0 +1,104 @@ +import json + +from tenacity import retry, stop_after_attempt, wait_fixed + +from .data import entities_example_chat +from .generate import generate +from .utils import chatml, get_names_from_session + + +############## +## Entities ## +############## + +entities_example_plan = """\ +Thinking step by step: +- To add context for future entries, let's outline the main entities in the session above. +- In this session, as mentioned in the first message metadata, the user's name is Camille and the assistant's name is JaneBot. +- They talk about Elon Musk and the banana tattoo on Camille's arm briefly.""" + + +entities_example_result = """\ +1. Camille (The user): Humorous, creative, and enjoys playful banter. +2. JaneBot (The assistant): Engages in lighthearted conversation and tries to guess user's thoughts. +3. Elon Musk: Camille and JaneBot discuss the polarizing tech and space industry figure. +4. Banana Tattoo: Camille has a tattoo of a banana on their arm.""" + + +entities_instructions = """\ +Your goal is to identify the main entities in the session. Entities should include: +- Characters in the conversation: Assistant, User1, User2 +- People references or spoken about +- Objects discussed about +- Places of interest +- ...etc + +Instructions: +- Identify and extract important entities discussed. +- You can add entities that, while not directly mentioned, are important in the context of the conversation. +- Write a brief line to provide context about each entity explaining it's relevance to the conversation. +- Enclose your answer inside XML tags. +- See the example to get a better idea of the task.""" + + +make_entities_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ +You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). + +{entities_instructions} + + +{json.dumps(entities_example_chat, indent=2)} + + + +{entities_example_plan} + + + +{entities_example_result} +""", + +f"""\ +Begin! Write the entities as a Markdown formatted list. First write your plan inside and then the extracted entities between . + + +{json.dumps(session, indent=2)} + +"""] + + + +@retry(stop=stop_after_attempt(2)) +async def get_entities( + chat_session, + model="gpt-4-turbo", + stop=[" 2, "Session is too short" + + # Remove the system prompt if present + if ( + chat_session[0]["role"] == "system" + and chat_session[0].get("name") != "entities" + ): + chat_session = chat_session[1:] + + names = get_names_from_session(chat_session) + system_prompt, user_message = make_entities_prompt(chat_session, **names) + messages = [chatml.system(system_prompt), chatml.user(user_message)] + result = await generate( + messages, + model=model, + stop=stop, + temperature=temperature, + **kwargs, + ) + + assert "" in result["content"] + result["content"] = result["content"].split("")[-1].strip() + result["role"] = "system" + result["name"] = "entities" + + return chatml.make(**result) diff --git a/agents-api/notebooks/rec_sum/entities_example_chat.json b/agents-api/notebooks/rec_sum/entities_example_chat.json new file mode 100644 index 000000000..32d994877 --- /dev/null +++ b/agents-api/notebooks/rec_sum/entities_example_chat.json @@ -0,0 +1,68 @@ +[ + { + "role": "system", + "content": "just have a casual chat with a friend friend" + }, + { + "role": "user", + "name": "Camille", + "content": "yo" + }, + { + "role": "assistant", + "name": "JaneBot", + "content": "Hey, how's it going?" + }, + { + "role": "user", + "content": "what you think about elon?" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "very polarizing, dude is nuts but in a fun way" + }, + { + "role": "assistant", + "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." + }, + { + "role": "user", + "content": "i am glad he exists" + }, + { + "role": "assistant", + "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." + }, + { + "role": "user", + "content": "what are your thoughts on bananas?" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "super much. i have a tattoo of a banana on my arm" + }, + { + "role": "assistant", + "content": "That's awesome! A banana tattoo sounds like a fun and unique choice. It must be a great conversation starter." + }, + { + "role": "user", + "content": "anyway what number am I thinking of?" + }, + { + "role": "assistant", + "content": "Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?" + }, + { + "role": "user", + "content": "no" + } +] \ No newline at end of file diff --git a/agents-api/notebooks/rec_sum/generate.py b/agents-api/notebooks/rec_sum/generate.py new file mode 100644 index 000000000..99c0a5e79 --- /dev/null +++ b/agents-api/notebooks/rec_sum/generate.py @@ -0,0 +1,22 @@ +from openai import AsyncClient +from tenacity import retry, stop_after_attempt, wait_fixed + + +client = AsyncClient() + + +@retry(wait=wait_fixed(2), stop=stop_after_attempt(5)) +async def generate( + messages: list[dict], + client: AsyncClient=client, + model: str="gpt-4-turbo", + **kwargs +) -> dict: + result = await client.chat.completions.create( + model=model, messages=messages, **kwargs + ) + + result = result.choices[0].message.__dict__ + + return result + diff --git a/agents-api/notebooks/rec_sum/summarize.py b/agents-api/notebooks/rec_sum/summarize.py new file mode 100644 index 000000000..9793be702 --- /dev/null +++ b/agents-api/notebooks/rec_sum/summarize.py @@ -0,0 +1,111 @@ +import json + +from tenacity import retry, stop_after_attempt, wait_fixed + +from .data import summarize_example_chat, summarize_example_result +from .generate import generate +from .utils import chatml, add_indices, get_names_from_session + + +########## +## summarize ## +########## + +summarize_example_plan = """\ +Planning step by step: +- We can replace entries 1,2,3,4 with a summary of those messages. +- We can replace entries 5,6,7,8 similarly. +- It could be disruptive to remove messages 9-16 because that might lose the joke's context. +- We can safely summarize entries 17,18 without losing context. +- We should keep 21 because it's given by the user and they might ask about it again. +- We should keep the assistant's response in message 22 to keep the context. +- Messages 23-32 are repetitive and can be summarized. +- We should retain message 33 since it's a direct request from the user. +- We can safely summarize message 34's essay into just the salient points only.""" + + + +summarize_instructions = """\ +Your goal is to compactify the history by coalescing redundant information in messages into their summary in order to reduce its size and save costs. + +Instructions: +- Combine multiple messages into summaries when possible as long as that doesn't disrupt the structure of the session. +- You can convert large messages (such as an essay) into a list of points. +- Do not summarize content that the user shared since it might be relevant to future messages. +- Make sure to preserve the tone of the conversation and its flow. Refer to the example and do EXACTLY as shown. +- VERY IMPORTANT: Add the indices of messages that are being summarized so that those messages can then be removed from the session otherwise, there'll be no way to identify which messages to remove. See example for more details.""" + + + +make_summarize_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ +You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). + +{summarize_instructions} + + +{json.dumps(add_indices(summarize_example_chat), indent=2)} + + + +{summarize_example_plan} + + + +{json.dumps(summarize_example_result, indent=2)} +""", + +f"""\ +Begin! Write the summarized messages as a json list just like the example above. First write your plan inside and then your answer between . Don't forget to add the indices of the messages being summarized alongside each summary. + + +{json.dumps(add_indices(session), indent=2)} + +"""] + + + +@retry(stop=stop_after_attempt(2)) +async def summarize_messages( + chat_session, + model="gpt-4-turbo", + stop=[" 2, "Session is too short" + + offset = 0 + + # Remove the system prompt if present + if ( + chat_session[0]["role"] == "system" + and chat_session[0].get("name") != "entities" + ): + chat_session = chat_session[1:] + + # The indices are not matched up correctly + offset = 1 + + names = get_names_from_session(chat_session) + system_prompt, user_message = make_summarize_prompt(chat_session, **names) + messages = [chatml.system(system_prompt), chatml.user(user_message)] + result = await generate( + messages, + model=model, + stop=stop, + temperature=temperature, + **kwargs, + ) + + assert "" in result["content"] + summarized_messages = json.loads(result["content"].split("")[-1].strip()) + + assert all((msg.get("summarizes") is not None for msg in summarized_messages)) + + # Correct offset + summarized_messages = [ + {**msg, "summarizes": [i + offset for i in msg["summarizes"]]} + for msg in summarized_messages + ] + + return summarized_messages diff --git a/agents-api/notebooks/rec_sum/summarize_example_chat.json b/agents-api/notebooks/rec_sum/summarize_example_chat.json new file mode 100644 index 000000000..f7897cc36 --- /dev/null +++ b/agents-api/notebooks/rec_sum/summarize_example_chat.json @@ -0,0 +1,144 @@ +[ + { + "role": "system", + "content": "just have a casual chat with a friend friend" + }, + { + "role": "user", + "content": "yo", + "name": "Camille" + }, + { + "role": "assistant", + "content": "Hey, how's it going?", + "name": "JaneBot" + }, + { + "role": "user", + "content": "sup" + }, + { + "role": "assistant", + "content": "Not much, just working and trying to stay busy. How about you?" + }, + { + "role": "user", + "content": "what you think about elon?" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "very polarizing, dude is nuts but in a fun way" + }, + { + "role": "assistant", + "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." + }, + { + "role": "user", + "content": "i am glad he exists" + }, + { + "role": "assistant", + "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." + }, + { + "role": "user", + "content": "what are your thoughts on bananas?" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "super much. i have a tattoo of a banana on my arm" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "yeah, your mom" + }, + { + "role": "assistant", + "content": "Haha, good one! You got me there. Feel free to keep the jokes coming." + }, + { + "role": "user", + "content": "lulz, u funny" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "ok if I give you a long story, can you guess its title?" + }, + { + "role": "assistant", + "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." + }, + { + "role": "user", + "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." + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "ok that's cool but you are wrong. anyway what number am I thinking of?" + }, + { + "role": "assistant", + "content": "Hmm, I'll take a wild guess and say you're thinking of the number 7. Did I get it right?" + }, + { + "role": "user", + "content": "no" + }, + { + "role": "assistant", + "content": "Alright, I'll give it another shot. How about the number 3?" + }, + { + "role": "user", + "content": "no" + }, + { + "role": "assistant", + "content": "I'll try one more time - is the number you're thinking of 9?" + }, + { + "role": "user", + "content": "no" + }, + { + "role": "assistant", + "content": "Looks like I haven't quite nailed it yet! Do you mind sharing which number you had in mind?" + }, + { + "role": "user", + "content": "no" + }, + { + "role": "assistant", + "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?" + }, + { + "role": "user", + "content": "yes, write an essay about me from your experience with me so far" + }, + { + "role": "assistant", + "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!" + } +] \ No newline at end of file diff --git a/agents-api/notebooks/rec_sum/summarize_example_result.json b/agents-api/notebooks/rec_sum/summarize_example_result.json new file mode 100644 index 000000000..a3a361546 --- /dev/null +++ b/agents-api/notebooks/rec_sum/summarize_example_result.json @@ -0,0 +1,58 @@ +[ + { + "role": "system", + "name": "summary", + "content": "Event: Camille says hi to JaneBot and they reply that they are working and trying to stay busy.", + "summarizes": [ + 1, + 2, + 3, + 4 + ] + }, + { + "role": "system", + "name": "summary", + "content": "Event: They discuss Elon Musk and agree that he can be a polarizing personality.", + "summarizes": [ + 5, + 6, + 7, + 8 + ] + }, + { + "role": "system", + "name": "summary", + "content": "Event: Camille appreciates JaneBot's sense of humor.", + "summarizes": [ + 17, + 18 + ] + }, + { + "role": "system", + "name": "summary", + "content": "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.", + "summarizes": [ + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ] + }, + { + "role": "system", + "name": "summary", + "content": "Event: JaneBot wrote an essay about Camille. Summary of the essay:\n1. You have a great sense of humor and enjoy playful, lighthearted banter in conversations.\n2. Your creativity is evident in how you approach topics in unexpected ways and keep conversations interesting.\n3. Chatting with you is enjoyable due to the casual, friendly tone you bring to interactions.", + "summarizes": [ + 34 + ] + } +] \ No newline at end of file diff --git a/agents-api/notebooks/rec_sum/trim.py b/agents-api/notebooks/rec_sum/trim.py new file mode 100644 index 000000000..b2af0b64c --- /dev/null +++ b/agents-api/notebooks/rec_sum/trim.py @@ -0,0 +1,108 @@ +import json + +from tenacity import retry, stop_after_attempt, wait_fixed + +from .data import trim_example_chat, trim_example_result +from .generate import generate +from .utils import chatml, add_indices, get_names_from_session + + +########## +## Trim ## +########## + +trim_example_plan = """\ +Thinking step by step: +- To trim the context, let's examine the messages in the session above. +- Messages 1, 2, and 3 are succinct and do not need trimming. +- However, messages 4, 5, and 6 are all rather verbose and can be safely trimmed. +- Message 7 is short enough and doesn't need any edits.""" + + + +trim_instructions = """\ +Your goal is to identify messages in the session that are needlessly verbose and then trim them in length without losing any meaning or changing the tone of the message. + +Instructions: +- Identify messages that are long and repetitive. +- Longer messages need to be converted into smaller, more compact version of them. +- Make sure to only trim out content that is not important to the context. +- Write down the trimmed messages as a json list along with their indices. +- Enclose your answer inside XML tags. +- See the example to get a better idea of the task.""" + +# It is important to make keep the tone, setting and flow of the conversation consistent while trimming the messages. + + +make_trim_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ +You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). + +{trim_instructions} + + +{json.dumps(add_indices(trim_example_chat), indent=2)} + + + +{trim_example_plan} + + + +{json.dumps(trim_example_result, indent=2)} +""", + +f"""\ +Begin! Write the trimmed messages as a json list. First write your plan inside and then your answer between . + + +{json.dumps(add_indices(session), indent=2)} + +"""] + + + +@retry(stop=stop_after_attempt(2)) +async def trim_messages( + chat_session, + model="gpt-4-turbo", + stop=[" 2, "Session is too short" + + offset = 0 + + # Remove the system prompt if present + if ( + chat_session[0]["role"] == "system" + and chat_session[0].get("name") != "entities" + ): + chat_session = chat_session[1:] + + # The indices are not matched up correctly + offset = 1 + + names = get_names_from_session(chat_session) + system_prompt, user_message = make_trim_prompt(chat_session, **names) + messages = [chatml.system(system_prompt), chatml.user(user_message)] + result = await generate( + messages, + model=model, + stop=stop, + temperature=temperature, + **kwargs, + ) + + assert "" in result["content"] + trimmed_messages = json.loads(result["content"].split("")[-1].strip()) + + assert all((msg.get("index") is not None for msg in trimmed_messages)) + + # Correct offset + trimmed_messages = [ + {**msg, "index": msg["index"] + offset} + for msg in trimmed_messages + ] + + return trimmed_messages diff --git a/agents-api/notebooks/rec_sum/trim_example_chat.json b/agents-api/notebooks/rec_sum/trim_example_chat.json new file mode 100644 index 000000000..63d51586e --- /dev/null +++ b/agents-api/notebooks/rec_sum/trim_example_chat.json @@ -0,0 +1,34 @@ +[ + { + "role": "system", + "content": "You are a Large Language Model" + }, + { + "role": "user", + "content": "hi" + }, + { + "role": "assistant", + "content": "Hello! How can I assist you today?" + }, + { + "role": "user", + "content": "I wanted to discuss consciousness with you" + }, + { + "role": "assistant", + "content": "Absolutely, I'd be glad to discuss consciousness with you! It's a fascinating and very complex topic. Consciousness involves awareness of one's internal and external environments, personal thoughts, feelings, and experiences. It's often discussed in various contexts, including philosophy, psychology, and neuroscience. What specific aspects of consciousness are you interested in exploring?" + }, + { + "role": "user", + "content": "well, I am an AGI researcher and I think about consciousness a lot. The most interesting part of it is actually the potential that possibly I am currently talking to a proto-conscious system (you) since we do not really have a concrete definition of consciousness anyway yet. What do you think?" + }, + { + "role": "assistant", + "content": "That's a compelling aspect of the discussion around artificial intelligence. The idea of whether AI, like myself, can possess consciousness, or something akin to it, is a topic of debate among philosophers, computer scientists, and cognitive scientists.\n\nAs it stands, AI, including this system, operates without consciousness. AI systems process data and generate responses based on patterns and instructions in their programming, but they do not experience awareness or subjective experiences. Although AI can simulate aspects of human conversation and behavior, these actions are not accompanied by personal consciousness or an internal life.\n\nThat said, discussions about the potential for artificial general intelligence (AGI) to exhibit features similar to consciousness are ongoing and raise questions about what consciousness fundamentally is, how it can be recognized, and whether it can exist independently of the biological processes that underpin human consciousness.\n\nWhat are your thoughts on the matter, both personally and as an AGI researcher?" + }, + { + "role": "user", + "content": "I am working on Julep AI -- an \"AGI infrastructure lab\" and we are trying to contribute to this space." + } +] \ No newline at end of file diff --git a/agents-api/notebooks/rec_sum/trim_example_result.json b/agents-api/notebooks/rec_sum/trim_example_result.json new file mode 100644 index 000000000..85ef9e997 --- /dev/null +++ b/agents-api/notebooks/rec_sum/trim_example_result.json @@ -0,0 +1,17 @@ +[ + { + "index": 4, + "role": "assistant", + "content": "I'd be glad to discuss consciousness with you! Consciousness involves awareness of one's internal and external environments, thoughts, feelings, and experiences. It's discussed in philosophy, psychology, and neuroscience. What aspects are you interested in?" + }, + { + "index": 5, + "role": "user", + "content": "well, I am an AGI researcher and I think about consciousness. The interesting part is that I may be talking to a proto-conscious system (you) since we do not have a concrete definition of consciousness yet. What do you think?" + }, + { + "index": 6, + "role": "assistant", + "content": "The idea of whether AI, like myself, can possess consciousness, is a topic of debate among scientists.\n\nAI systems process data and generate responses based on patterns in their programming, but they do not experience awareness. Although AI can simulate human conversation and behavior, they are not accompanied by consciousness.\n\nThat said, discussions about AGI to exhibit consciousness are ongoing and raise questions about what consciousness is, how it can be recognized, and whether it can exist independently of the biological processes that underpin human consciousness.\n\nWhat are your thoughts, both personally and as an AGI researcher?" + } +] \ No newline at end of file diff --git a/agents-api/notebooks/rec_sum/utils.py b/agents-api/notebooks/rec_sum/utils.py new file mode 100644 index 000000000..512bfff9f --- /dev/null +++ b/agents-api/notebooks/rec_sum/utils.py @@ -0,0 +1,37 @@ +########### +## Utils ## +########### + +class chatml: + make = lambda content, role="system", name=None, **_: { + key: value + for key, value in dict(role=role, name=name, content=content).items() + if value is not None + } + + user = lambda content, name=None: chatml.make(role="user", content=content, name=name) + assistant = lambda content, name=None: chatml.make( + role="assistant", content=content, name=name + ) + system = lambda content, name=None: chatml.make(content, name=name) + thought = lambda content, name=None: chatml.make(content, name="thought") + information = lambda content: chatml.system(content, name="information") + summary = lambda content: chatml.system(content, name="summary") + entities = lambda content: chatml.system(content, name="entity") + + + +add_indices = lambda list_of_dicts, idx_name="index": [ + {idx_name: i, **msg} for i, msg in enumerate(list_of_dicts) +] + + + +get_names_from_session = lambda session: { + role: next(( + msg.get("name", None) + for msg in session + if msg["role"] == role + ), None) + for role in {"user", "assistant", "system"} +} diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 1e17705f8..7d184f5f0 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -110,6 +110,24 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "aiosqlite" +version = "0.20.0" +description = "asyncio bridge to the standard sqlite3 module" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"}, + {file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"}, +] + +[package.dependencies] +typing_extensions = ">=4.0" + +[package.extras] +dev = ["attribution (==1.7.0)", "black (==24.2.0)", "coverage[toml] (==7.4.1)", "flake8 (==7.0.0)", "flake8-bugbear (==24.2.6)", "flit (==3.9.0)", "mypy (==1.8.0)", "ufmt (==2.3.0)", "usort (==1.0.8.post1)"] +docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"] + [[package]] name = "annotated-types" version = "0.7.0" @@ -655,6 +673,17 @@ click = "*" [package.extras] test = ["pytest"] +[[package]] +name = "cloudpickle" +version = "3.0.0" +description = "Pickler class to extend the standard pickle.Pickler functionality" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cloudpickle-3.0.0-py3-none-any.whl", hash = "sha256:246ee7d0c295602a036e86369c77fecda4ab17b506496730f2f576d9016fd9c7"}, + {file = "cloudpickle-3.0.0.tar.gz", hash = "sha256:996d9a482c6fb4f33c1a35335cf8afd065d2a56e973270364840712d9131a882"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -731,6 +760,51 @@ files = [ [package.extras] develop = ["coverage", "invoke", "path.py", "pylint", "pytest (>=3.2)", "pytest-html (>=1.19.0)", "tox (>=2.9)"] +[[package]] +name = "dask" +version = "2024.5.1" +description = "Parallel PyData with Task Scheduling" +optional = false +python-versions = ">=3.9" +files = [ + {file = "dask-2024.5.1-py3-none-any.whl", hash = "sha256:af1cadd1fd1d1d44600ff5de43dd029e5668fdf87422131f4e3e3aa2a6a63555"}, + {file = "dask-2024.5.1.tar.gz", hash = "sha256:e071fda67031c314569e37ca70b3e88bb30f1d91ff8ee4122b541845847cc264"}, +] + +[package.dependencies] +click = ">=8.1" +cloudpickle = ">=1.5.0" +distributed = {version = "2024.5.1", optional = true, markers = "extra == \"distributed\""} +fsspec = ">=2021.09.0" +importlib-metadata = {version = ">=4.13.0", markers = "python_version < \"3.12\""} +packaging = ">=20.0" +partd = ">=1.2.0" +pyyaml = ">=5.3.1" +toolz = ">=0.10.0" + +[package.extras] +array = ["numpy (>=1.21)"] +complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)", "pyarrow-hotfix"] +dataframe = ["dask-expr (>=1.1,<1.2)", "dask[array]", "pandas (>=1.3)"] +diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] +distributed = ["distributed (==2024.5.1)"] +test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytest-xdist"] + +[[package]] +name = "dataclasses-json" +version = "0.6.6" +description = "Easily serialize dataclasses to and from JSON." +optional = false +python-versions = "<4.0,>=3.7" +files = [ + {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"}, + {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"}, +] + +[package.dependencies] +marshmallow = ">=3.18.0,<4.0.0" +typing-inspect = ">=0.4.0,<1" + [[package]] name = "datamodel-code-generator" version = "0.25.6" @@ -802,6 +876,17 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deepmerge" +version = "1.1.1" +description = "a toolset to deeply merge python dictionaries." +optional = false +python-versions = "*" +files = [ + {file = "deepmerge-1.1.1-py3-none-any.whl", hash = "sha256:7219dad9763f15be9dcd4bcb53e00f48e4eed6f5ed8f15824223eb934bb35977"}, + {file = "deepmerge-1.1.1.tar.gz", hash = "sha256:53a489dc9449636e480a784359ae2aab3191748c920649551c8e378622f0eca4"}, +] + [[package]] name = "defusedxml" version = "0.7.1" @@ -813,6 +898,34 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +[[package]] +name = "distributed" +version = "2024.5.1" +description = "Distributed scheduler for Dask" +optional = false +python-versions = ">=3.9" +files = [ + {file = "distributed-2024.5.1-py3-none-any.whl", hash = "sha256:cf77583ce67f6696aa716c30f1cba3403ac866241c00d6e9a0bc1500c6818b40"}, + {file = "distributed-2024.5.1.tar.gz", hash = "sha256:c4e641e5fc014de3b43c584c70f703a7d44557b51b1143db812b8bc861aa84e2"}, +] + +[package.dependencies] +click = ">=8.0" +cloudpickle = ">=1.5.0" +dask = "2024.5.1" +jinja2 = ">=2.10.3" +locket = ">=1.0.0" +msgpack = ">=1.0.0" +packaging = ">=20.0" +psutil = ">=5.7.2" +pyyaml = ">=5.3.1" +sortedcontainers = ">=2.0.5" +tblib = ">=1.6.0" +toolz = ">=0.10.0" +tornado = ">=6.0.4" +urllib3 = ">=1.24.3" +zict = ">=3.0.0" + [[package]] name = "distro" version = "1.9.0" @@ -919,6 +1032,44 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +[[package]] +name = "faiss-cpu" +version = "1.8.0" +description = "A library for efficient similarity search and clustering of dense vectors." +optional = false +python-versions = ">=3.8" +files = [ + {file = "faiss-cpu-1.8.0.tar.gz", hash = "sha256:3ee1549491728f37b65267c192a94661a907154a8ae0546ad50a564b8be0d82e"}, + {file = "faiss_cpu-1.8.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:134a064c7411acf7d1d863173a9d2605c5a59bd573639ab39a5ded5ca983b1b2"}, + {file = "faiss_cpu-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba8e6202d561ac57394c9d691ff17f8fa6eb9a077913a993fce0a154ec0176f1"}, + {file = "faiss_cpu-1.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66e9fa7b70556a39681f06e0652f4124c8ddb0a1924afe4f0e40b6924dc845b"}, + {file = "faiss_cpu-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51aaef5a1255d0ea88ea7e52a2415f98c5dd2dd9cec10348d55136541eeec99f"}, + {file = "faiss_cpu-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:38152761242870ec7019e0397cbd0ed0b0716562029ce41a71bb38448bd6d5bc"}, + {file = "faiss_cpu-1.8.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c9e6ad94b86626be1a0faff3e53c4ca169eba88aa156d7e90c5a2e9ba30558fb"}, + {file = "faiss_cpu-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4601dbd81733bf1bc3bff690aac981289fb386dc8e60d0c4eec8a37ba6856d20"}, + {file = "faiss_cpu-1.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa943d3b5e8c5c77cdd629d9c3c6f78d7da616e586fdd1b94aecbf2e5fa9ba06"}, + {file = "faiss_cpu-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b644b366c3b239b34fa3e08bf65bfc78a24eda1e1ea5b2b6d9be3e8fc73d8179"}, + {file = "faiss_cpu-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:f85ecf3514850f93985be238351f5a70736133cfae784b372640aa17c6343a1b"}, + {file = "faiss_cpu-1.8.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:61abc0129a357ac00f17f5167f14dff41480de2cc852f306c3d4cd36b893ccbd"}, + {file = "faiss_cpu-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b788186d6eb94e6333e1aa8bb6c84b66e967458ecdd1cee22e16f04c43ee674c"}, + {file = "faiss_cpu-1.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5658d90a202c62e4a69c5b065785e9ddcaf6986cb395c16afed8dbe4c58c31a2"}, + {file = "faiss_cpu-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d460a372efce547e53d3c47d2c2a8a90b186ad245969048c10c1d7a1e5cf21b"}, + {file = "faiss_cpu-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:9e6520324f0a6764dd267b3c32c76958bf2b1ec36752950f6fab31a7295980a0"}, + {file = "faiss_cpu-1.8.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:fc44be179d5b7f690484ef0d0caf817fea2698a5275a0c7fb6cbf406e5b2e4d1"}, + {file = "faiss_cpu-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbd6f0bc2e1424a12dc7e19d2cc95b53124867966b21110d26f909227e7ed1f1"}, + {file = "faiss_cpu-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06e7add0c8a06ce8fb0443c38fcaf49c45fb74527ea633b819e56452608e64f5"}, + {file = "faiss_cpu-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b864e23c1817fa6cfe9bbec096fd7140d596002934f71aa89b196ffb1b9cd846"}, + {file = "faiss_cpu-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:655433755845adbb6f0961e2f8980703640cb9faa96f1cd1ea190252149e0d0a"}, + {file = "faiss_cpu-1.8.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:e81fc376a3bcda213ffb395dda1018c953ce927c587731ad582f4e6c2b225363"}, + {file = "faiss_cpu-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c6fa6b7eaf558307b4ab118a236e8d1da79a8685222928e4dd52e277dba144a"}, + {file = "faiss_cpu-1.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:652f6812ef2e8b0f9b18209828c590bc618aca82e7f1c1b1888f52928258e406"}, + {file = "faiss_cpu-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:304da4e0d19044374b63a5b6467028572eac4bd3f32bc9e8783d800a03fb1f02"}, + {file = "faiss_cpu-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:cb475d3f25f08c97ac64dfe026f113e2aeb9829b206b3b046256c3b40dd7eb62"}, +] + +[package.dependencies] +numpy = "*" + [[package]] name = "fastapi" version = "0.110.3" @@ -1428,6 +1579,77 @@ protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4 [package.extras] grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] +[[package]] +name = "greenlet" +version = "3.0.3" +description = "Lightweight in-process concurrent programming" +optional = false +python-versions = ">=3.7" +files = [ + {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, + {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, + {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, + {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, + {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, + {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, + {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, + {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, + {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, + {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, + {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, + {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, + {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, + {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, + {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, + {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, +] + +[package.extras] +docs = ["Sphinx", "furo"] +test = ["objgraph", "psutil"] + [[package]] name = "grpc-google-iam-v1" version = "0.13.0" @@ -1858,6 +2080,34 @@ files = [ {file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"}, ] +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, +] + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpath-ng" +version = "1.6.1" +description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." +optional = false +python-versions = "*" +files = [ + {file = "jsonpath-ng-1.6.1.tar.gz", hash = "sha256:086c37ba4917304850bd837aeab806670224d3f038fe2833ff593a672ef0a5fa"}, + {file = "jsonpath_ng-1.6.1-py3-none-any.whl", hash = "sha256:8f22cd8273d7772eea9aaa84d922e0841aa36fdb8a2c6b7f6c3791a16a9bc0be"}, +] + +[package.dependencies] +ply = "*" + [[package]] name = "jsonpointer" version = "2.4" @@ -1931,6 +2181,58 @@ openai = ">=1.0.1,<2.0.0" pydantic = ">=2.0.1,<3.0.0" typing-extensions = ">=4.0.0,<5.0.0" +[[package]] +name = "jupyter-ai" +version = "2.16.0" +description = "A generative AI extension for JupyterLab" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_ai-2.16.0-py3-none-any.whl", hash = "sha256:7f428a4a01c050bfa0722dd81688e43416ff1e5b15339f00e8efa544fd0b7fc9"}, + {file = "jupyter_ai-2.16.0.tar.gz", hash = "sha256:6fb78ee82ea6c0174f26142615d427a038f19ed1fc16a5779dc81715f8d2a5b1"}, +] + +[package.dependencies] +aiosqlite = ">=0.18" +dask = {version = "*", extras = ["distributed"]} +deepmerge = ">=1.0" +faiss-cpu = "*" +importlib-metadata = ">=5.2.0" +jupyter-ai-magics = ">=2.13.0" +jupyter-server = ">=1.6,<3" +jupyterlab = ">=4.0,<5.0" +traitlets = ">=5.0" +typing-extensions = ">=4.5.0" + +[package.extras] +all = ["arxiv", "jupyter-ai-magics[all]", "pypdf"] +dev = ["jupyter-ai-magics[dev]"] +test = ["coverage", "jupyter-server[test] (>=1.6,<3)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-jupyter", "pytest-tornasync", "syrupy (>=4.0.8,<4.1.0)"] + +[[package]] +name = "jupyter-ai-magics" +version = "2.16.0" +description = "Jupyter AI magics Python package. Not published on NPM." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_ai_magics-2.16.0-py3-none-any.whl", hash = "sha256:9c231a12350ca5c8a3db2ea8dae0517bc046bb7d2351b66a26e3ede946edf895"}, + {file = "jupyter_ai_magics-2.16.0.tar.gz", hash = "sha256:f35cce92814ccf63ac2b900275f7470f459e4857376a3575c4c25f13707923da"}, +] + +[package.dependencies] +click = ">=8.0,<9.0" +importlib-metadata = ">=5.2.0" +ipython = "*" +jsonpath-ng = ">=1.5.3,<2" +langchain = ">=0.1.0,<0.2.0" +typing-extensions = ">=4.5.0" + +[package.extras] +all = ["ai21", "boto3", "cohere (>4.40,<5)", "gpt4all", "huggingface-hub", "ipywidgets", "langchain-anthropic", "langchain-google-genai", "langchain-nvidia-ai-endpoints", "langchain-openai", "pillow", "qianfan", "together"] +dev = ["pre-commit (>=3.3.3,<4)"] +test = ["coverage", "pytest", "pytest-asyncio", "pytest-cov"] + [[package]] name = "jupyter-client" version = "8.6.2" @@ -2147,6 +2449,143 @@ files = [ {file = "jupyterlab_widgets-3.0.11.tar.gz", hash = "sha256:dd5ac679593c969af29c9bed054c24f26842baa51352114736756bc035deee27"}, ] +[[package]] +name = "langchain" +version = "0.1.20" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain-0.1.20-py3-none-any.whl", hash = "sha256:09991999fbd6c3421a12db3c7d1f52d55601fc41d9b2a3ef51aab2e0e9c38da9"}, + {file = "langchain-0.1.20.tar.gz", hash = "sha256:f35c95eed8c8375e02dce95a34f2fd4856a4c98269d6dc34547a23dba5beab7e"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} +dataclasses-json = ">=0.5.7,<0.7" +langchain-community = ">=0.0.38,<0.1" +langchain-core = ">=0.1.52,<0.2.0" +langchain-text-splitters = ">=0.0.1,<0.1" +langsmith = ">=0.1.17,<0.2.0" +numpy = ">=1,<2" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] +clarifai = ["clarifai (>=9.1.0)"] +cli = ["typer (>=0.9.0,<0.10.0)"] +cohere = ["cohere (>=4,<6)"] +docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] +embeddings = ["sentence-transformers (>=2,<3)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +javascript = ["esprima (>=4.0.1,<5.0.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] +qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] +text-helpers = ["chardet (>=5.1.0,<6.0.0)"] + +[[package]] +name = "langchain-community" +version = "0.0.38" +description = "Community contributed LangChain integrations." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_community-0.0.38-py3-none-any.whl", hash = "sha256:ecb48660a70a08c90229be46b0cc5f6bc9f38f2833ee44c57dfab9bf3a2c121a"}, + {file = "langchain_community-0.0.38.tar.gz", hash = "sha256:127fc4b75bc67b62fe827c66c02e715a730fef8fe69bd2023d466bab06b5810d"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +dataclasses-json = ">=0.5.7,<0.7" +langchain-core = ">=0.1.52,<0.2.0" +langsmith = ">=0.1.0,<0.2.0" +numpy = ">=1,<2" +PyYAML = ">=5.3" +requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +cli = ["typer (>=0.9.0,<0.10.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] + +[[package]] +name = "langchain-core" +version = "0.1.52" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_core-0.1.52-py3-none-any.whl", hash = "sha256:62566749c92e8a1181c255c788548dc16dbc319d896cd6b9c95dc17af9b2a6db"}, + {file = "langchain_core-0.1.52.tar.gz", hash = "sha256:084c3fc452f5a6966c28ab3ec5dbc8b8d26fc3f63378073928f4e29d90b6393f"}, +] + +[package.dependencies] +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.1.0,<0.2.0" +packaging = ">=23.2,<24.0" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +extended-testing = ["jinja2 (>=3,<4)"] + +[[package]] +name = "langchain-openai" +version = "0.1.6" +description = "An integration package connecting OpenAI and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_openai-0.1.6-py3-none-any.whl", hash = "sha256:7f62ecb12d3cdd0d96679abea00e4e3ceb1f829f6d1f127a5f7b97c1315d157f"}, + {file = "langchain_openai-0.1.6.tar.gz", hash = "sha256:7d2e838e57ef231cb7689fd58ac5fa8a6e9e504174f8c5698c837739786e2030"}, +] + +[package.dependencies] +langchain-core = ">=0.1.46,<0.2.0" +openai = ">=1.24.0,<2.0.0" +tiktoken = ">=0.5.2,<1" + +[[package]] +name = "langchain-text-splitters" +version = "0.0.2" +description = "LangChain text splitting utilities" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_text_splitters-0.0.2-py3-none-any.whl", hash = "sha256:13887f32705862c1e1454213cb7834a63aae57c26fcd80346703a1d09c46168d"}, + {file = "langchain_text_splitters-0.0.2.tar.gz", hash = "sha256:ac8927dc0ba08eba702f6961c9ed7df7cead8de19a9f7101ab2b5ea34201b3c1"}, +] + +[package.dependencies] +langchain-core = ">=0.1.28,<0.3" + +[package.extras] +extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] + +[[package]] +name = "langsmith" +version = "0.1.63" +description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langsmith-0.1.63-py3-none-any.whl", hash = "sha256:7810afdf5e3f3b472fc581a29371fb96cd843dde2149e048d1b9610325159d1e"}, + {file = "langsmith-0.1.63.tar.gz", hash = "sha256:a609405b52f6f54df442a142cbf19ab38662d54e532f96028b4c546434d4afdf"}, +] + +[package.dependencies] +orjson = ">=3.9.14,<4.0.0" +pydantic = ">=1,<3" +requests = ">=2,<3" + [[package]] name = "libcst" version = "1.4.0" @@ -2213,6 +2652,17 @@ tokenizers = "*" extra-proxy = ["azure-identity (>=1.15.0,<2.0.0)", "azure-keyvault-secrets (>=4.8.0,<5.0.0)", "google-cloud-kms (>=2.21.3,<3.0.0)", "prisma (==0.11.0)", "resend (>=0.8.0,<0.9.0)"] proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "cryptography (>=42.0.5,<43.0.0)", "fastapi (>=0.111.0,<0.112.0)", "fastapi-sso (>=0.10.0,<0.11.0)", "gunicorn (>=22.0.0,<23.0.0)", "orjson (>=3.9.7,<4.0.0)", "python-multipart (>=0.0.9,<0.0.10)", "pyyaml (>=6.0.1,<7.0.0)", "rq", "uvicorn (>=0.22.0,<0.23.0)"] +[[package]] +name = "locket" +version = "1.0.0" +description = "File-based locks for Python on Linux and Windows" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "locket-1.0.0-py2.py3-none-any.whl", hash = "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3"}, + {file = "locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632"}, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -2361,6 +2811,71 @@ files = [ {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] +[[package]] +name = "msgpack" +version = "1.0.8" +description = "MessagePack serializer" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, + {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, + {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, + {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, + {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, + {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, + {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, + {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, + {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, + {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, + {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, +] + [[package]] name = "msgspec" version = "0.18.6" @@ -2744,6 +3259,61 @@ typing-extensions = ">=4.7,<5" [package.extras] datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, +] + [[package]] name = "overrides" version = "7.7.0" @@ -2757,13 +3327,13 @@ files = [ [[package]] name = "packaging" -version = "24.0" +version = "23.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] @@ -2861,6 +3431,24 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] +[[package]] +name = "partd" +version = "1.4.2" +description = "Appendable key-value storage" +optional = false +python-versions = ">=3.9" +files = [ + {file = "partd-1.4.2-py3-none-any.whl", hash = "sha256:978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f"}, + {file = "partd-1.4.2.tar.gz", hash = "sha256:d022c33afbdc8405c226621b015e8067888173d85f7f5ecebb3cafed9a20f02c"}, +] + +[package.dependencies] +locket = "*" +toolz = "*" + +[package.extras] +complete = ["blosc", "numpy (>=1.20.0)", "pandas (>=1.3)", "pyzmq"] + [[package]] name = "pastel" version = "0.2.1" @@ -2928,6 +3516,17 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "ply" +version = "3.11" +description = "Python Lex & Yacc" +optional = false +python-versions = "*" +files = [ + {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, + {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, +] + [[package]] name = "poethepoet" version = "0.25.1" @@ -4192,6 +4791,17 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "soupsieve" version = "2.5" @@ -4203,6 +4813,93 @@ files = [ {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, ] +[[package]] +name = "sqlalchemy" +version = "2.0.30" +description = "Database Abstraction Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"}, + {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"}, + {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +typing-extensions = ">=4.6.0" + +[package.extras] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx_oracle (>=8)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +sqlcipher = ["sqlcipher3_binary"] + [[package]] name = "stack-data" version = "0.6.3" @@ -4253,6 +4950,17 @@ files = [ [package.extras] widechars = ["wcwidth"] +[[package]] +name = "tblib" +version = "3.0.0" +description = "Traceback serialization library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "tblib-3.0.0-py3-none-any.whl", hash = "sha256:80a6c77e59b55e83911e1e607c649836a69c103963c5f28a46cbeef44acf8129"}, + {file = "tblib-3.0.0.tar.gz", hash = "sha256:93622790a0a29e04f0346458face1e144dc4d32f493714c6c3dff82a4adb77e6"}, +] + [[package]] name = "temporalio" version = "1.6.0" @@ -4278,6 +4986,21 @@ typing-extensions = ">=4.2.0,<5.0.0" grpc = ["grpcio (>=1.59.0,<2.0.0)"] opentelemetry = ["opentelemetry-api (>=1.11.1,<2.0.0)", "opentelemetry-sdk (>=1.11.1,<2.0.0)"] +[[package]] +name = "tenacity" +version = "8.3.0" +description = "Retry code until it succeeds" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, +] + +[package.extras] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + [[package]] name = "termcolor" version = "2.4.0" @@ -4522,6 +5245,17 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "toolz" +version = "0.12.1" +description = "List processing tools and functional utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "toolz-0.12.1-py3-none-any.whl", hash = "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85"}, + {file = "toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d"}, +] + [[package]] name = "tornado" version = "6.4" @@ -4693,6 +5427,21 @@ files = [ {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] +[[package]] +name = "typing-inspect" +version = "0.9.0" +description = "Runtime inspection utilities for typing module." +optional = false +python-versions = "*" +files = [ + {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, + {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, +] + +[package.dependencies] +mypy-extensions = ">=0.3.0" +typing-extensions = ">=3.7.4" + [[package]] name = "tzdata" version = "2024.1" @@ -5059,6 +5808,17 @@ files = [ idna = ">=2.0" multidict = ">=4.0" +[[package]] +name = "zict" +version = "3.0.0" +description = "Mutable mapping tools" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zict-3.0.0-py2.py3-none-any.whl", hash = "sha256:5796e36bd0e0cc8cf0fbc1ace6a68912611c1dbd74750a3f3026b9b9d6a327ae"}, + {file = "zict-3.0.0.tar.gz", hash = "sha256:e321e263b6a97aafc0790c3cfb3c04656b7066e6738c37fffcca95d803c9fba5"}, +] + [[package]] name = "zipp" version = "3.19.0" @@ -5077,4 +5837,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "f8a02f17d792c9823d581de52fec20fffbb6bf61c15923d890676ef9c1426d24" +content-hash = "1d3bbaa8e939f41b1a9b582b2091c186373f10f55e3cd23ee976cfea7c865a89" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index ba43887ee..df063e62b 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -46,6 +46,8 @@ pyjwt = "^2.8.0" ward = "^0.68.0b0" jupyterlab = "^4.1.8" ipywidgets = "^8.1.2" +jupyter-ai = "^2.14.1" +langchain-openai = "^0.1.6" [build-system] requires = ["poetry-core"] From 086366d2f6d44f098e77658f2a29978d8eeb91b0 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Tue, 21 May 2024 15:43:26 +0300 Subject: [PATCH 07/43] chore: Move rec_sum subpackage --- agents-api/{notebooks => agents_api}/rec_sum/__init__.py | 0 agents-api/{notebooks => agents_api}/rec_sum/data.py | 0 agents-api/{notebooks => agents_api}/rec_sum/entities.py | 0 .../{notebooks => agents_api}/rec_sum/entities_example_chat.json | 0 agents-api/{notebooks => agents_api}/rec_sum/generate.py | 0 agents-api/{notebooks => agents_api}/rec_sum/summarize.py | 0 .../{notebooks => agents_api}/rec_sum/summarize_example_chat.json | 0 .../rec_sum/summarize_example_result.json | 0 agents-api/{notebooks => agents_api}/rec_sum/trim.py | 0 .../{notebooks => agents_api}/rec_sum/trim_example_chat.json | 0 .../{notebooks => agents_api}/rec_sum/trim_example_result.json | 0 agents-api/{notebooks => agents_api}/rec_sum/utils.py | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename agents-api/{notebooks => agents_api}/rec_sum/__init__.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/data.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/entities.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/entities_example_chat.json (100%) rename agents-api/{notebooks => agents_api}/rec_sum/generate.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/summarize.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/summarize_example_chat.json (100%) rename agents-api/{notebooks => agents_api}/rec_sum/summarize_example_result.json (100%) rename agents-api/{notebooks => agents_api}/rec_sum/trim.py (100%) rename agents-api/{notebooks => agents_api}/rec_sum/trim_example_chat.json (100%) rename agents-api/{notebooks => agents_api}/rec_sum/trim_example_result.json (100%) rename agents-api/{notebooks => agents_api}/rec_sum/utils.py (100%) diff --git a/agents-api/notebooks/rec_sum/__init__.py b/agents-api/agents_api/rec_sum/__init__.py similarity index 100% rename from agents-api/notebooks/rec_sum/__init__.py rename to agents-api/agents_api/rec_sum/__init__.py diff --git a/agents-api/notebooks/rec_sum/data.py b/agents-api/agents_api/rec_sum/data.py similarity index 100% rename from agents-api/notebooks/rec_sum/data.py rename to agents-api/agents_api/rec_sum/data.py diff --git a/agents-api/notebooks/rec_sum/entities.py b/agents-api/agents_api/rec_sum/entities.py similarity index 100% rename from agents-api/notebooks/rec_sum/entities.py rename to agents-api/agents_api/rec_sum/entities.py diff --git a/agents-api/notebooks/rec_sum/entities_example_chat.json b/agents-api/agents_api/rec_sum/entities_example_chat.json similarity index 100% rename from agents-api/notebooks/rec_sum/entities_example_chat.json rename to agents-api/agents_api/rec_sum/entities_example_chat.json diff --git a/agents-api/notebooks/rec_sum/generate.py b/agents-api/agents_api/rec_sum/generate.py similarity index 100% rename from agents-api/notebooks/rec_sum/generate.py rename to agents-api/agents_api/rec_sum/generate.py diff --git a/agents-api/notebooks/rec_sum/summarize.py b/agents-api/agents_api/rec_sum/summarize.py similarity index 100% rename from agents-api/notebooks/rec_sum/summarize.py rename to agents-api/agents_api/rec_sum/summarize.py diff --git a/agents-api/notebooks/rec_sum/summarize_example_chat.json b/agents-api/agents_api/rec_sum/summarize_example_chat.json similarity index 100% rename from agents-api/notebooks/rec_sum/summarize_example_chat.json rename to agents-api/agents_api/rec_sum/summarize_example_chat.json diff --git a/agents-api/notebooks/rec_sum/summarize_example_result.json b/agents-api/agents_api/rec_sum/summarize_example_result.json similarity index 100% rename from agents-api/notebooks/rec_sum/summarize_example_result.json rename to agents-api/agents_api/rec_sum/summarize_example_result.json diff --git a/agents-api/notebooks/rec_sum/trim.py b/agents-api/agents_api/rec_sum/trim.py similarity index 100% rename from agents-api/notebooks/rec_sum/trim.py rename to agents-api/agents_api/rec_sum/trim.py diff --git a/agents-api/notebooks/rec_sum/trim_example_chat.json b/agents-api/agents_api/rec_sum/trim_example_chat.json similarity index 100% rename from agents-api/notebooks/rec_sum/trim_example_chat.json rename to agents-api/agents_api/rec_sum/trim_example_chat.json diff --git a/agents-api/notebooks/rec_sum/trim_example_result.json b/agents-api/agents_api/rec_sum/trim_example_result.json similarity index 100% rename from agents-api/notebooks/rec_sum/trim_example_result.json rename to agents-api/agents_api/rec_sum/trim_example_result.json diff --git a/agents-api/notebooks/rec_sum/utils.py b/agents-api/agents_api/rec_sum/utils.py similarity index 100% rename from agents-api/notebooks/rec_sum/utils.py rename to agents-api/agents_api/rec_sum/utils.py From 39985ea0936467532c3a6c257e69d76a4dc97c93 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 22 May 2024 22:28:27 +0300 Subject: [PATCH 08/43] feat: Summarize messages recursively --- agents-api/agents_api/activities/logger.py | 8 ++ .../agents_api/activities/summarization.py | 102 ++++++++++++++---- .../agents_api/models/entry/delete_entries.py | 47 ++++++++ agents-api/agents_api/rec_sum/__init__.py | 3 - agents-api/agents_api/rec_sum/data.py | 17 +-- agents-api/agents_api/rec_sum/entities.py | 45 ++------ agents-api/agents_api/rec_sum/generate.py | 9 +- agents-api/agents_api/rec_sum/summarize.py | 48 +++------ agents-api/agents_api/rec_sum/trim.py | 56 ++-------- agents-api/agents_api/rec_sum/utils.py | 69 +++++++----- 10 files changed, 222 insertions(+), 182 deletions(-) create mode 100644 agents-api/agents_api/activities/logger.py diff --git a/agents-api/agents_api/activities/logger.py b/agents-api/agents_api/activities/logger.py new file mode 100644 index 000000000..4880d0652 --- /dev/null +++ b/agents-api/agents_api/activities/logger.py @@ -0,0 +1,8 @@ +import logging + + +logger = logging.getLogger(__name__) +h = logging.StreamHandler() +fmt = logging.Formatter("[%(asctime)s/%(levelname)s] - %(message)s") +h.setFormatter(fmt) +logger.addHandler(h) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index 85a8a9ae5..1eaa2003d 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -1,17 +1,25 @@ #!/usr/bin/env python3 +import asyncio +from pycozo.client import QueryException from uuid import UUID from typing import Callable from textwrap import dedent from temporalio import activity from litellm import acompletion +from agents_api.models.entry.add_entries import add_entries_query +from agents_api.models.entry.delete_entries import delete_entries_by_ids_query from agents_api.models.entry.entries_summarization import ( get_toplevel_entries_query, entries_summarization_query, ) from agents_api.common.protocol.entries import Entry from ..model_registry import JULEP_MODELS -from ..env import summarization_model_name, model_inference_url, model_api_key +from ..env import model_inference_url, model_api_key +from agents_api.rec_sum.entities import get_entities +from agents_api.rec_sum.summarize import summarize_messages +from agents_api.rec_sum.trim import trim_messages +from agents_api.activities.logger import logger example_previous_memory = """ @@ -157,31 +165,85 @@ async def run_prompt( return parser(content.strip() if content is not None else "") +# @activity.defn +# async def summarization(session_id: str) -> None: +# session_id = UUID(session_id) +# entries = [ +# Entry(**row) +# for _, row in get_toplevel_entries_query(session_id=session_id).iterrows() +# ] + +# assert len(entries) > 0, "no need to summarize on empty entries list" + +# response = await run_prompt( +# dialog=entries, previous_memories=[], model=summarization_model_name +# ) + +# new_entry = Entry( +# session_id=session_id, +# source="summarizer", +# role="system", +# name="information", +# content=response, +# timestamp=entries[-1].timestamp + 0.01, +# ) + +# entries_summarization_query( +# session_id=session_id, +# new_entry=new_entry, +# old_entry_ids=[e.id for e in entries], +# ) + + @activity.defn async def summarization(session_id: str) -> None: session_id = UUID(session_id) - entries = [ - Entry(**row) - for _, row in get_toplevel_entries_query(session_id=session_id).iterrows() - ] + entries = [] + entities_entry_ids = [] + for _, row in get_toplevel_entries_query(session_id=session_id).iterrows(): + if row["role"] == "system" and row.get("name") == "entities": + entities_entry_ids.append(row["entry_id"]) + else: + entries.append(row) assert len(entries) > 0, "no need to summarize on empty entries list" - response = await run_prompt( - dialog=entries, previous_memories=[], model=f"openai/{summarization_model_name}" + trimmed_messages, entities = await asyncio.gather( + trim_messages(entries), + get_entities(entries), ) - - new_entry = Entry( - session_id=session_id, - source="summarizer", - role="system", - name="information", - content=response, - timestamp=entries[-1].timestamp + 0.01, + summarized = await summarize_messages(trimmed_messages) + + ts_delta = (entries[1]["timestamp"] - entries[0]["timestamp"]) / 2 + + add_entries_query( + Entry( + session_id=session_id, + source="summarizer", + role="system", + name="entities", + content=entities["content"], + timestamp=entries[0]["timestamp"] + ts_delta, + ) ) - entries_summarization_query( - session_id=session_id, - new_entry=new_entry, - old_entry_ids=[e.id for e in entries], - ) + try: + delete_entries_by_ids_query(entry_ids=entities_entry_ids) + except QueryException as e: + logger.exception(e) + + for msg in summarized: + new_entry = Entry( + session_id=session_id, + source="summarizer", + role="system", + name="information", + content=msg["content"], + timestamp=entries[-1]["timestamp"] + 0.01, + ) + + entries_summarization_query( + session_id=session_id, + new_entry=new_entry, + old_entry_ids=[entries[idx]["entry_id"] for idx in msg["summarizes"]], + ) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 2affa321d..8fdb9ee72 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -61,3 +61,50 @@ def delete_entries_query(session_id: UUID) -> tuple[str, dict]: }""" return (query, {"session_id": str(session_id)}) + + +@cozo_query +def delete_entries_by_ids_query(entry_ids: list[UUID]) -> tuple[str, dict]: + entry_ids = [f'to_uuid("{id}")' for id in entry_ids] + + query = """ + { + input[entry_id] <- $entry_ids + + ?[ + session_id, + entry_id, + role, + name, + content, + source, + token_count, + created_at, + timestamp, + ] := input[entry_id], + *entries{ + session_id, + entry_id, + role, + name, + content, + source, + token_count, + created_at, + timestamp, + } + + :delete entries { + session_id, + entry_id, + role, + name, + content, + source, + token_count, + created_at, + timestamp, + } + }""" + + return (query, {"entry_ids": entry_ids}) diff --git a/agents-api/agents_api/rec_sum/__init__.py b/agents-api/agents_api/rec_sum/__init__.py index c2b9d406e..e69de29bb 100644 --- a/agents-api/agents_api/rec_sum/__init__.py +++ b/agents-api/agents_api/rec_sum/__init__.py @@ -1,3 +0,0 @@ -from .entities import get_entities -from .summarize import summarize_messages -from .trim import trim_messages diff --git a/agents-api/agents_api/rec_sum/data.py b/agents-api/agents_api/rec_sum/data.py index 2caa7231d..93e78851c 100644 --- a/agents-api/agents_api/rec_sum/data.py +++ b/agents-api/agents_api/rec_sum/data.py @@ -5,28 +5,21 @@ module_directory = Path(__file__).parent - -with open(f"{module_directory}/entities_example_chat.json", 'r') as _f: +with open(f"{module_directory}/entities_example_chat.json", "r") as _f: entities_example_chat = json.load(_f) - -with open(f"{module_directory}/trim_example_chat.json", 'r') as _f: +with open(f"{module_directory}/trim_example_chat.json", "r") as _f: trim_example_chat = json.load(_f) - -with open(f"{module_directory}/trim_example_result.json", 'r') as _f: +with open(f"{module_directory}/trim_example_result.json", "r") as _f: trim_example_result = json.load(_f) - -with open(f"{module_directory}/summarize_example_chat.json", 'r') as _f: +with open(f"{module_directory}/summarize_example_chat.json", "r") as _f: summarize_example_chat = json.load(_f) - -with open(f"{module_directory}/summarize_example_result.json", 'r') as _f: +with open(f"{module_directory}/summarize_example_result.json", "r") as _f: summarize_example_result = json.load(_f) - - diff --git a/agents-api/agents_api/rec_sum/entities.py b/agents-api/agents_api/rec_sum/entities.py index baf702597..2a853e337 100644 --- a/agents-api/agents_api/rec_sum/entities.py +++ b/agents-api/agents_api/rec_sum/entities.py @@ -1,6 +1,6 @@ import json -from tenacity import retry, stop_after_attempt, wait_fixed +from tenacity import retry, stop_after_attempt from .data import entities_example_chat from .generate import generate @@ -41,50 +41,23 @@ - See the example to get a better idea of the task.""" -make_entities_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ -You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). - -{entities_instructions} - - -{json.dumps(entities_example_chat, indent=2)} - - - -{entities_example_plan} - - - -{entities_example_result} -""", - -f"""\ -Begin! Write the entities as a Markdown formatted list. First write your plan inside and then the extracted entities between . - - -{json.dumps(session, indent=2)} - -"""] - +def make_entities_prompt(session, user="a user", assistant="gpt-4-turbo", **_): + return [ + f"You are given a session history of a chat between {user or 'a user'} and {assistant or 'gpt-4-turbo'}. The session is formatted in the ChatML JSON format (from OpenAI).\n\n{entities_instructions}\n\n\n{json.dumps(entities_example_chat, indent=2)}\n\n\n\n{entities_example_plan}\n\n\n\n{entities_example_result}\n", + f"Begin! Write the entities as a Markdown formatted list. First write your plan inside and then the extracted entities between .\n\n\n{json.dumps(session, indent=2)}\n\n", + ] @retry(stop=stop_after_attempt(2)) async def get_entities( chat_session, - model="gpt-4-turbo", - stop=[" 2, "Session is too short" - # Remove the system prompt if present - if ( - chat_session[0]["role"] == "system" - and chat_session[0].get("name") != "entities" - ): - chat_session = chat_session[1:] - names = get_names_from_session(chat_session) system_prompt, user_message = make_entities_prompt(chat_session, **names) messages = [chatml.system(system_prompt), chatml.user(user_message)] @@ -100,5 +73,5 @@ async def get_entities( result["content"] = result["content"].split("")[-1].strip() result["role"] = "system" result["name"] = "entities" - + return chatml.make(**result) diff --git a/agents-api/agents_api/rec_sum/generate.py b/agents-api/agents_api/rec_sum/generate.py index 99c0a5e79..d8a280d36 100644 --- a/agents-api/agents_api/rec_sum/generate.py +++ b/agents-api/agents_api/rec_sum/generate.py @@ -7,16 +7,15 @@ @retry(wait=wait_fixed(2), stop=stop_after_attempt(5)) async def generate( - messages: list[dict], - client: AsyncClient=client, - model: str="gpt-4-turbo", + messages: list[dict], + client: AsyncClient = client, + model: str = "gpt-4-turbo", **kwargs ) -> dict: result = await client.chat.completions.create( model=model, messages=messages, **kwargs ) - + result = result.choices[0].message.__dict__ return result - diff --git a/agents-api/agents_api/rec_sum/summarize.py b/agents-api/agents_api/rec_sum/summarize.py index 9793be702..f0146210e 100644 --- a/agents-api/agents_api/rec_sum/summarize.py +++ b/agents-api/agents_api/rec_sum/summarize.py @@ -1,6 +1,6 @@ import json -from tenacity import retry, stop_after_attempt, wait_fixed +from tenacity import retry, stop_after_attempt from .data import summarize_example_chat, summarize_example_result from .generate import generate @@ -24,7 +24,6 @@ - We can safely summarize message 34's essay into just the salient points only.""" - summarize_instructions = """\ Your goal is to compactify the history by coalescing redundant information in messages into their summary in order to reduce its size and save costs. @@ -36,53 +35,32 @@ - VERY IMPORTANT: Add the indices of messages that are being summarized so that those messages can then be removed from the session otherwise, there'll be no way to identify which messages to remove. See example for more details.""" - -make_summarize_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ -You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). - -{summarize_instructions} - - -{json.dumps(add_indices(summarize_example_chat), indent=2)} - - - -{summarize_example_plan} - - - -{json.dumps(summarize_example_result, indent=2)} -""", - -f"""\ -Begin! Write the summarized messages as a json list just like the example above. First write your plan inside and then your answer between . Don't forget to add the indices of the messages being summarized alongside each summary. - - -{json.dumps(add_indices(session), indent=2)} - -"""] - +def make_summarize_prompt(session, user="a user", assistant="gpt-4-turbo", **_): + return [ + f"You are given a session history of a chat between {user or 'a user'} and {assistant or 'gpt-4-turbo'}. The session is formatted in the ChatML JSON format (from OpenAI).\n\n{summarize_instructions}\n\n\n{json.dumps(add_indices(summarize_example_chat), indent=2)}\n\n\n\n{summarize_example_plan}\n\n\n\n{json.dumps(summarize_example_result, indent=2)}\n", + f"Begin! Write the summarized messages as a json list just like the example above. First write your plan inside and then your answer between . Don't forget to add the indices of the messages being summarized alongside each summary.\n\n\n{json.dumps(add_indices(session), indent=2)}\n\n", + ] @retry(stop=stop_after_attempt(2)) async def summarize_messages( chat_session, - model="gpt-4-turbo", - stop=[" 2, "Session is too short" offset = 0 - + # Remove the system prompt if present if ( chat_session[0]["role"] == "system" and chat_session[0].get("name") != "entities" ): chat_session = chat_session[1:] - + # The indices are not matched up correctly offset = 1 @@ -98,7 +76,9 @@ async def summarize_messages( ) assert "" in result["content"] - summarized_messages = json.loads(result["content"].split("")[-1].strip()) + summarized_messages = json.loads( + result["content"].split("")[-1].strip() + ) assert all((msg.get("summarizes") is not None for msg in summarized_messages)) @@ -107,5 +87,5 @@ async def summarize_messages( {**msg, "summarizes": [i + offset for i in msg["summarizes"]]} for msg in summarized_messages ] - + return summarized_messages diff --git a/agents-api/agents_api/rec_sum/trim.py b/agents-api/agents_api/rec_sum/trim.py index b2af0b64c..eeb05719c 100644 --- a/agents-api/agents_api/rec_sum/trim.py +++ b/agents-api/agents_api/rec_sum/trim.py @@ -1,6 +1,6 @@ import json -from tenacity import retry, stop_after_attempt, wait_fixed +from tenacity import retry, stop_after_attempt from .data import trim_example_chat, trim_example_result from .generate import generate @@ -19,7 +19,6 @@ - Message 7 is short enough and doesn't need any edits.""" - trim_instructions = """\ Your goal is to identify messages in the session that are needlessly verbose and then trim them in length without losing any meaning or changing the tone of the message. @@ -34,55 +33,23 @@ # It is important to make keep the tone, setting and flow of the conversation consistent while trimming the messages. -make_trim_prompt = lambda session, user="a user", assistant="gpt-4-turbo", **_: [f"""\ -You are given a session history of a chat between {user or "a user"} and {assistant or "gpt-4-turbo"}. The session is formatted in the ChatML JSON format (from OpenAI). - -{trim_instructions} - - -{json.dumps(add_indices(trim_example_chat), indent=2)} - - - -{trim_example_plan} - - - -{json.dumps(trim_example_result, indent=2)} -""", - -f"""\ -Begin! Write the trimmed messages as a json list. First write your plan inside and then your answer between . - - -{json.dumps(add_indices(session), indent=2)} - -"""] - +def make_trim_prompt(session, user="a user", assistant="gpt-4-turbo", **_): + return [ + f"You are given a session history of a chat between {user or 'a user'} and {assistant or 'gpt-4-turbo'}. The session is formatted in the ChatML JSON format (from OpenAI).\n\n{trim_instructions}\n\n\n{json.dumps(add_indices(trim_example_chat), indent=2)}\n\n\n\n{trim_example_plan}\n\n\n\n{json.dumps(trim_example_result, indent=2)}\n", + f"Begin! Write the trimmed messages as a json list. First write your plan inside and then your answer between .\n\n\n{json.dumps(add_indices(session), indent=2)}\n\n", + ] @retry(stop=stop_after_attempt(2)) async def trim_messages( chat_session, - model="gpt-4-turbo", - stop=[" 2, "Session is too short" - offset = 0 - - # Remove the system prompt if present - if ( - chat_session[0]["role"] == "system" - and chat_session[0].get("name") != "entities" - ): - chat_session = chat_session[1:] - - # The indices are not matched up correctly - offset = 1 - names = get_names_from_session(chat_session) system_prompt, user_message = make_trim_prompt(chat_session, **names) messages = [chatml.system(system_prompt), chatml.user(user_message)] @@ -100,9 +67,6 @@ async def trim_messages( assert all((msg.get("index") is not None for msg in trimmed_messages)) # Correct offset - trimmed_messages = [ - {**msg, "index": msg["index"] + offset} - for msg in trimmed_messages - ] - + trimmed_messages = [{**msg, "index": msg["index"]} for msg in trimmed_messages] + return trimmed_messages diff --git a/agents-api/agents_api/rec_sum/utils.py b/agents-api/agents_api/rec_sum/utils.py index 512bfff9f..596174e08 100644 --- a/agents-api/agents_api/rec_sum/utils.py +++ b/agents-api/agents_api/rec_sum/utils.py @@ -2,36 +2,53 @@ ## Utils ## ########### + class chatml: - make = lambda content, role="system", name=None, **_: { - key: value - for key, value in dict(role=role, name=name, content=content).items() - if value is not None - } - - user = lambda content, name=None: chatml.make(role="user", content=content, name=name) - assistant = lambda content, name=None: chatml.make( - role="assistant", content=content, name=name - ) - system = lambda content, name=None: chatml.make(content, name=name) - thought = lambda content, name=None: chatml.make(content, name="thought") - information = lambda content: chatml.system(content, name="information") - summary = lambda content: chatml.system(content, name="summary") - entities = lambda content: chatml.system(content, name="entity") + @staticmethod + def make(content, role="system", name=None, **_): + return { + key: value + for key, value in dict(role=role, name=name, content=content).items() + if value is not None + } + + @staticmethod + def user(content, name=None): + return chatml.make(role="user", content=content, name=name) + + @staticmethod + def assistant(content, name=None): + return chatml.make(role="assistant", content=content, name=name) + @staticmethod + def system(content, name=None): + return chatml.make(content, name=name) + @staticmethod + def thought(content, name=None): + return chatml.make(content, name="thought") -add_indices = lambda list_of_dicts, idx_name="index": [ - {idx_name: i, **msg} for i, msg in enumerate(list_of_dicts) -] + @staticmethod + def information(content): + return chatml.system(content, name="information") + @staticmethod + def summary(content): + return chatml.system(content, name="summary") + @staticmethod + def entities(content): + return chatml.system(content, name="entity") -get_names_from_session = lambda session: { - role: next(( - msg.get("name", None) - for msg in session - if msg["role"] == role - ), None) - for role in {"user", "assistant", "system"} -} + +def add_indices(list_of_dicts, idx_name="index"): + return [{idx_name: i, **msg} for i, msg in enumerate(list_of_dicts)] + + +def get_names_from_session(session): + return { + role: next( + (msg.get("name", None) for msg in session if msg["role"] == role), None + ) + for role in {"user", "assistant", "system"} + } From 94199d30528a0e92a8e6c10e4ee744f93fcd2c16 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Fri, 24 May 2024 14:59:59 +0300 Subject: [PATCH 09/43] feat: Use custom model for summarization --- agents-api/agents_api/activities/summarization.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index 1eaa2003d..f2ebd387b 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -15,7 +15,7 @@ ) from agents_api.common.protocol.entries import Entry from ..model_registry import JULEP_MODELS -from ..env import model_inference_url, model_api_key +from ..env import model_inference_url, model_api_key, summarization_model_name from agents_api.rec_sum.entities import get_entities from agents_api.rec_sum.summarize import summarize_messages from agents_api.rec_sum.trim import trim_messages @@ -209,8 +209,8 @@ async def summarization(session_id: str) -> None: assert len(entries) > 0, "no need to summarize on empty entries list" trimmed_messages, entities = await asyncio.gather( - trim_messages(entries), - get_entities(entries), + trim_messages(entries, model=summarization_model_name), + get_entities(entries, model=summarization_model_name), ) summarized = await summarize_messages(trimmed_messages) From dd301d9f762923d427c795b572f41fb4bf08c03f Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Fri, 24 May 2024 15:01:39 +0300 Subject: [PATCH 10/43] chore: Remove commented out code --- .../agents_api/activities/summarization.py | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index f2ebd387b..c8c4215c1 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -165,36 +165,6 @@ async def run_prompt( return parser(content.strip() if content is not None else "") -# @activity.defn -# async def summarization(session_id: str) -> None: -# session_id = UUID(session_id) -# entries = [ -# Entry(**row) -# for _, row in get_toplevel_entries_query(session_id=session_id).iterrows() -# ] - -# assert len(entries) > 0, "no need to summarize on empty entries list" - -# response = await run_prompt( -# dialog=entries, previous_memories=[], model=summarization_model_name -# ) - -# new_entry = Entry( -# session_id=session_id, -# source="summarizer", -# role="system", -# name="information", -# content=response, -# timestamp=entries[-1].timestamp + 0.01, -# ) - -# entries_summarization_query( -# session_id=session_id, -# new_entry=new_entry, -# old_entry_ids=[e.id for e in entries], -# ) - - @activity.defn async def summarization(session_id: str) -> None: session_id = UUID(session_id) From 97fbd706e672d466c1250c012b4f315f02cfea34 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Fri, 24 May 2024 15:55:07 +0300 Subject: [PATCH 11/43] fix: Serialize pandas series objects --- agents-api/agents_api/rec_sum/entities.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/agents-api/agents_api/rec_sum/entities.py b/agents-api/agents_api/rec_sum/entities.py index 2a853e337..649ef3f91 100644 --- a/agents-api/agents_api/rec_sum/entities.py +++ b/agents-api/agents_api/rec_sum/entities.py @@ -1,5 +1,7 @@ import json +import pandas as pd +from typing import Any from tenacity import retry, stop_after_attempt from .data import entities_example_chat @@ -41,10 +43,15 @@ - See the example to get a better idea of the task.""" -def make_entities_prompt(session, user="a user", assistant="gpt-4-turbo", **_): +def make_entities_prompt( + session: list[pd.Series] | list[Any], user="a user", assistant="gpt-4-turbo", **_ +): + session = [m.to_dict() if isinstance(m, pd.Series) else m for m in session] + session_json_str = json.dumps(session, indent=2) + return [ f"You are given a session history of a chat between {user or 'a user'} and {assistant or 'gpt-4-turbo'}. The session is formatted in the ChatML JSON format (from OpenAI).\n\n{entities_instructions}\n\n\n{json.dumps(entities_example_chat, indent=2)}\n\n\n\n{entities_example_plan}\n\n\n\n{entities_example_result}\n", - f"Begin! Write the entities as a Markdown formatted list. First write your plan inside and then the extracted entities between .\n\n\n{json.dumps(session, indent=2)}\n\n", + f"Begin! Write the entities as a Markdown formatted list. First write your plan inside and then the extracted entities between .\n\n\n{session_json_str}\n\n", ] From 373f0034a4ba73c9fe6d49af4db26b27c5a327e1 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Fri, 24 May 2024 15:55:54 +0300 Subject: [PATCH 12/43] fix: Choose correct way to generate based on model name --- agents-api/agents_api/rec_sum/generate.py | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/agents-api/agents_api/rec_sum/generate.py b/agents-api/agents_api/rec_sum/generate.py index d8a280d36..e05111faa 100644 --- a/agents-api/agents_api/rec_sum/generate.py +++ b/agents-api/agents_api/rec_sum/generate.py @@ -1,21 +1,25 @@ -from openai import AsyncClient from tenacity import retry, stop_after_attempt, wait_fixed - - -client = AsyncClient() +from agents_api.env import model_inference_url, model_api_key +from agents_api.model_registry import JULEP_MODELS +from litellm import acompletion @retry(wait=wait_fixed(2), stop=stop_after_attempt(5)) async def generate( messages: list[dict], - client: AsyncClient = client, model: str = "gpt-4-turbo", - **kwargs + **kwargs, ) -> dict: - result = await client.chat.completions.create( - model=model, messages=messages, **kwargs - ) + base_url, api_key = None, None + if model in JULEP_MODELS: + base_url, api_key = model_inference_url, model_api_key + model = f"openai/{model}" - result = result.choices[0].message.__dict__ + result = await acompletion( + model=model, + messages=messages, + base_url=base_url, + api_key=api_key, + ) - return result + return result.choices[0].message.json() From 395646c326e3df5434010aed61c3713d43a90111 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Mon, 27 May 2024 16:36:00 +0300 Subject: [PATCH 13/43] fix: Add old entities message as a child for the new one instead of deleting it --- .../agents_api/activities/summarization.py | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index c8c4215c1..50292f7e6 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 import asyncio -from pycozo.client import QueryException from uuid import UUID from typing import Callable from textwrap import dedent from temporalio import activity from litellm import acompletion from agents_api.models.entry.add_entries import add_entries_query -from agents_api.models.entry.delete_entries import delete_entries_by_ids_query from agents_api.models.entry.entries_summarization import ( get_toplevel_entries_query, entries_summarization_query, @@ -19,7 +17,6 @@ from agents_api.rec_sum.entities import get_entities from agents_api.rec_sum.summarize import summarize_messages from agents_api.rec_sum.trim import trim_messages -from agents_api.activities.logger import logger example_previous_memory = """ @@ -183,24 +180,22 @@ async def summarization(session_id: str) -> None: get_entities(entries, model=summarization_model_name), ) summarized = await summarize_messages(trimmed_messages) - ts_delta = (entries[1]["timestamp"] - entries[0]["timestamp"]) / 2 - - add_entries_query( - Entry( - session_id=session_id, - source="summarizer", - role="system", - name="entities", - content=entities["content"], - timestamp=entries[0]["timestamp"] + ts_delta, - ) + new_entities_entry = Entry( + session_id=session_id, + source="summarizer", + role="system", + name="entities", + content=entities["content"], + timestamp=entries[0]["timestamp"] + ts_delta, ) - try: - delete_entries_by_ids_query(entry_ids=entities_entry_ids) - except QueryException as e: - logger.exception(e) + add_entries_query(new_entities_entry) + entries_summarization_query( + session_id=session_id, + new_entry=new_entities_entry, + old_entry_ids=entities_entry_ids, + ) for msg in summarized: new_entry = Entry( From dcbeafa43b8aed8b7b6f341334ea21d00067ffbd Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Tue, 28 May 2024 09:51:03 +0300 Subject: [PATCH 14/43] chore: Add tenacity dependency --- agents-api/poetry.lock | 2 +- agents-api/pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 7d184f5f0..1790ab54d 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -5837,4 +5837,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "1d3bbaa8e939f41b1a9b582b2091c186373f10f55e3cd23ee976cfea7c865a89" +content-hash = "32799f56a3e625e2ae5291f88e4225d30bc878c29e5cf4d40d04c346b75381e9" diff --git a/agents-api/pyproject.toml b/agents-api/pyproject.toml index df063e62b..51c62df55 100644 --- a/agents-api/pyproject.toml +++ b/agents-api/pyproject.toml @@ -30,6 +30,7 @@ numpy = "^1.26.4" transformers = "^4.40.1" tiktoken = "^0.6.0" xxhash = "^3.4.1" +tenacity = "^8.3.0" beartype = "^0.18.5" From 3011c5dbb63f430b01a2b2572e1677a9f768782b Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Tue, 28 May 2024 10:13:04 +0300 Subject: [PATCH 15/43] fix: Strip closing ct:trimmed tag --- agents-api/agents_api/rec_sum/trim.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/rec_sum/trim.py b/agents-api/agents_api/rec_sum/trim.py index eeb05719c..ea611a9f2 100644 --- a/agents-api/agents_api/rec_sum/trim.py +++ b/agents-api/agents_api/rec_sum/trim.py @@ -62,7 +62,9 @@ async def trim_messages( ) assert "" in result["content"] - trimmed_messages = json.loads(result["content"].split("")[-1].strip()) + trimmed_messages = json.loads( + result["content"].split("")[-1].replace("", "").strip() + ) assert all((msg.get("index") is not None for msg in trimmed_messages)) From 83d63f6132aec60b73d0251f4d9eb9d224ff1b75 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Tue, 28 May 2024 11:14:43 +0300 Subject: [PATCH 16/43] fix: Strip closing ct:summarized-messages tag --- agents-api/agents_api/rec_sum/summarize.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/rec_sum/summarize.py b/agents-api/agents_api/rec_sum/summarize.py index f0146210e..e103addfe 100644 --- a/agents-api/agents_api/rec_sum/summarize.py +++ b/agents-api/agents_api/rec_sum/summarize.py @@ -77,7 +77,10 @@ async def summarize_messages( assert "" in result["content"] summarized_messages = json.loads( - result["content"].split("")[-1].strip() + result["content"] + .split("")[-1] + .replace("", "") + .strip() ) assert all((msg.get("summarizes") is not None for msg in summarized_messages)) From c1e4404312aa703567c263dfcf5e036b497fd860 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Tue, 28 May 2024 12:04:25 +0300 Subject: [PATCH 17/43] fix: Add a list of entries instead of only one --- agents-api/agents_api/activities/summarization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index 50292f7e6..f10a64e38 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -190,7 +190,7 @@ async def summarization(session_id: str) -> None: timestamp=entries[0]["timestamp"] + ts_delta, ) - add_entries_query(new_entities_entry) + add_entries_query([new_entities_entry]) entries_summarization_query( session_id=session_id, new_entry=new_entities_entry, From f777c4ece30ed24822a19275f5e4e1f5905b93fa Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 29 May 2024 21:13:06 +0300 Subject: [PATCH 18/43] fix: Convert strings to UUID --- agents-api/agents_api/activities/summarization.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index f10a64e38..d074e8285 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -169,7 +169,7 @@ async def summarization(session_id: str) -> None: entities_entry_ids = [] for _, row in get_toplevel_entries_query(session_id=session_id).iterrows(): if row["role"] == "system" and row.get("name") == "entities": - entities_entry_ids.append(row["entry_id"]) + entities_entry_ids.append(UUID(row["entry_id"], version=4)) else: entries.append(row) @@ -210,5 +210,7 @@ async def summarization(session_id: str) -> None: entries_summarization_query( session_id=session_id, new_entry=new_entry, - old_entry_ids=[entries[idx]["entry_id"] for idx in msg["summarizes"]], + old_entry_ids=[ + UUID(entries[idx]["entry_id"], version=4) for idx in msg["summarizes"] + ], ) From 1346bb66ba2dcb9ccdafddf3f60ae7b1f35a3166 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 29 May 2024 21:33:11 +0300 Subject: [PATCH 19/43] fix: Stringify message content --- agents-api/agents_api/common/utils/messages.py | 15 +++++++++++++++ agents-api/agents_api/routers/sessions/session.py | 15 +++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/agents-api/agents_api/common/utils/messages.py b/agents-api/agents_api/common/utils/messages.py index c59d751c0..14fe817cc 100644 --- a/agents-api/agents_api/common/utils/messages.py +++ b/agents-api/agents_api/common/utils/messages.py @@ -1,4 +1,5 @@ import json +from typing import cast from agents_api.autogen.openapi_model import ( ChatMLTextContentPart, ChatMLImageContentPart, @@ -23,3 +24,17 @@ def content_to_json( result = [{"type": "text", "text": json.dumps(content, indent=4)}] return result + + +def stringify_content( + msg: str | list[ChatMLTextContentPart] | list[ChatMLImageContentPart] | dict, +) -> str: + content = "" + if isinstance(msg, list): + content = " ".join([part.text for part in msg if part.type == "text"]) + elif isinstance(msg, str): + content = msg + elif isinstance(msg, dict) and msg["type"] == "text": + content = cast(str, msg["text"]) + + return content diff --git a/agents-api/agents_api/routers/sessions/session.py b/agents-api/agents_api/routers/sessions/session.py index a743f4bf6..e6f5e2f48 100644 --- a/agents-api/agents_api/routers/sessions/session.py +++ b/agents-api/agents_api/routers/sessions/session.py @@ -2,7 +2,7 @@ import xxhash from functools import reduce from json import JSONDecodeError -from typing import Callable, cast +from typing import Callable from uuid import uuid4 from dataclasses import dataclass @@ -21,6 +21,7 @@ from ...common.protocol.sessions import SessionData from ...common.utils.template import render_template from ...common.utils.json import CustomJSONEncoder +from ...common.utils.messages import stringify_content from ...env import ( summarization_tokens_threshold, docs_embedding_service_url, @@ -220,21 +221,11 @@ async def forward( ) -> tuple[list[ChatML], Settings, DocIds]: stringified_input = [] for msg in new_input: - content = "" - if isinstance(msg.content, list): - content = " ".join( - [part.text for part in msg.content if part.type == "text"] - ) - elif isinstance(msg.content, str): - content = msg.content - elif isinstance(msg.content, dict) and msg.content["type"] == "text": - content = cast(str, msg.content["text"]) - stringified_input.append( ( msg.role, msg.name, - content, + stringify_content(msg.content), ) ) From 0e207bf641466957fb76fd55f3b9a08b6cf3cac8 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 29 May 2024 21:57:14 +0300 Subject: [PATCH 20/43] fix: Convert new entry content to a list of JSON --- .../agents_api/models/entry/entries_summarization.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/agents-api/agents_api/models/entry/entries_summarization.py b/agents-api/agents_api/models/entry/entries_summarization.py index 30b8ea9bc..536f99e52 100644 --- a/agents-api/agents_api/models/entry/entries_summarization.py +++ b/agents-api/agents_api/models/entry/entries_summarization.py @@ -88,6 +88,14 @@ def entries_summarization_query( # Convert the new entry's source information into JSON format for storage. + content = [] + if isinstance(new_entry.content, str): + content = [{"type": "text", "text": new_entry.content}] + elif isinstance(new_entry.content, list): + content = [m.model_dump() for m in new_entry.content] + elif isinstance(new_entry.content, dict): + content = [new_entry.content] + entries = [ [ str(new_entry.id), From 55bc9d699cce7d5d53d82e75abae232df2270acc Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 29 May 2024 22:25:10 +0300 Subject: [PATCH 21/43] fix: Strip ct:entities tag --- agents-api/agents_api/rec_sum/entities.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/rec_sum/entities.py b/agents-api/agents_api/rec_sum/entities.py index 649ef3f91..ca3d4b1f2 100644 --- a/agents-api/agents_api/rec_sum/entities.py +++ b/agents-api/agents_api/rec_sum/entities.py @@ -77,7 +77,12 @@ async def get_entities( ) assert "" in result["content"] - result["content"] = result["content"].split("")[-1].strip() + result["content"] = ( + result["content"] + .split("")[-1] + .replace("", "") + .strip() + ) result["role"] = "system" result["name"] = "entities" From d7cf69038622da087140145673bb38c79db12e20 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 29 May 2024 22:52:16 +0300 Subject: [PATCH 22/43] fix: Do not add new entry explicitly --- agents-api/agents_api/activities/summarization.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index d074e8285..d54c440cb 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -6,7 +6,6 @@ from textwrap import dedent from temporalio import activity from litellm import acompletion -from agents_api.models.entry.add_entries import add_entries_query from agents_api.models.entry.entries_summarization import ( get_toplevel_entries_query, entries_summarization_query, @@ -190,7 +189,6 @@ async def summarization(session_id: str) -> None: timestamp=entries[0]["timestamp"] + ts_delta, ) - add_entries_query([new_entities_entry]) entries_summarization_query( session_id=session_id, new_entry=new_entities_entry, From e9de8db55cd861c002f0df73687e05e4e732db67 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 30 May 2024 10:20:27 +0300 Subject: [PATCH 23/43] fix: Update assertion --- .../agents_api/models/entry/entries_summarization.py | 8 -------- agents-api/agents_api/rec_sum/entities.py | 2 +- agents-api/agents_api/rec_sum/summarize.py | 2 +- agents-api/agents_api/rec_sum/trim.py | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/agents-api/agents_api/models/entry/entries_summarization.py b/agents-api/agents_api/models/entry/entries_summarization.py index 536f99e52..30b8ea9bc 100644 --- a/agents-api/agents_api/models/entry/entries_summarization.py +++ b/agents-api/agents_api/models/entry/entries_summarization.py @@ -88,14 +88,6 @@ def entries_summarization_query( # Convert the new entry's source information into JSON format for storage. - content = [] - if isinstance(new_entry.content, str): - content = [{"type": "text", "text": new_entry.content}] - elif isinstance(new_entry.content, list): - content = [m.model_dump() for m in new_entry.content] - elif isinstance(new_entry.content, dict): - content = [new_entry.content] - entries = [ [ str(new_entry.id), diff --git a/agents-api/agents_api/rec_sum/entities.py b/agents-api/agents_api/rec_sum/entities.py index ca3d4b1f2..db6cba826 100644 --- a/agents-api/agents_api/rec_sum/entities.py +++ b/agents-api/agents_api/rec_sum/entities.py @@ -63,7 +63,7 @@ async def get_entities( temperature=0.7, **kwargs, ): - assert len(chat_session) > 2, "Session is too short" + assert len(chat_session) >= 2, "Session is too short" names = get_names_from_session(chat_session) system_prompt, user_message = make_entities_prompt(chat_session, **names) diff --git a/agents-api/agents_api/rec_sum/summarize.py b/agents-api/agents_api/rec_sum/summarize.py index e103addfe..4ae546e8b 100644 --- a/agents-api/agents_api/rec_sum/summarize.py +++ b/agents-api/agents_api/rec_sum/summarize.py @@ -50,7 +50,7 @@ async def summarize_messages( temperature=0.8, **kwargs, ): - assert len(chat_session) > 2, "Session is too short" + assert len(chat_session) >= 2, "Session is too short" offset = 0 diff --git a/agents-api/agents_api/rec_sum/trim.py b/agents-api/agents_api/rec_sum/trim.py index ea611a9f2..ef8ae4b73 100644 --- a/agents-api/agents_api/rec_sum/trim.py +++ b/agents-api/agents_api/rec_sum/trim.py @@ -48,7 +48,7 @@ async def trim_messages( temperature=0.7, **kwargs, ): - assert len(chat_session) > 2, "Session is too short" + assert len(chat_session) >= 2, "Session is too short" names = get_names_from_session(chat_session) system_prompt, user_message = make_trim_prompt(chat_session, **names) From 9998986fcbce61d0bab1fb9179890b0f4413a3d0 Mon Sep 17 00:00:00 2001 From: whiterabbit1983 Date: Sat, 1 Jun 2024 19:01:38 +0300 Subject: [PATCH 24/43] feat: Truncate context window based on session settings (#381) --- .../agents_api/autogen/openapi_model.py | 34 +++++++++- .../agents_api/common/protocol/sessions.py | 2 + agents-api/agents_api/env.py | 8 --- .../models/session/create_session.py | 12 +++- .../agents_api/models/session/get_session.py | 4 ++ .../models/session/list_sessions.py | 4 ++ .../agents_api/models/session/session_data.py | 8 +++ agents-api/agents_api/models/utils.py | 7 +- .../agents_api/routers/sessions/protocol.py | 2 + .../agents_api/routers/sessions/routers.py | 6 ++ .../agents_api/routers/sessions/session.py | 56 ++++++++++++++-- .../migrate_1717239610_token_budget.py | 67 +++++++++++++++++++ openapi.yaml | 24 +++++++ 13 files changed, 215 insertions(+), 19 deletions(-) create mode 100644 agents-api/migrations/migrate_1717239610_token_budget.py diff --git a/agents-api/agents_api/autogen/openapi_model.py b/agents-api/agents_api/autogen/openapi_model.py index 33a8b3422..95efb2025 100644 --- a/agents-api/agents_api/autogen/openapi_model.py +++ b/agents-api/agents_api/autogen/openapi_model.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-05-28T03:07:50+00:00 +# timestamp: 2024-06-01T12:26:54+00:00 from __future__ import annotations @@ -124,6 +124,14 @@ class Session(BaseModel): """ Render system and assistant message content as jinja templates """ + token_budget: int | None = None + """ + Threshold value for the adaptive context functionality + """ + context_overflow: str | None = None + """ + Action to start on context window overflow + """ class CreateSessionRequest(BaseModel): @@ -151,6 +159,14 @@ class CreateSessionRequest(BaseModel): """ Render system and assistant message content as jinja templates """ + token_budget: int | None = None + """ + Threshold value for the adaptive context functionality + """ + context_overflow: str | None = None + """ + Action to start on context window overflow + """ class UpdateSessionRequest(BaseModel): @@ -166,6 +182,14 @@ class UpdateSessionRequest(BaseModel): """ Optional metadata """ + token_budget: int | None = None + """ + Threshold value for the adaptive context functionality + """ + context_overflow: str | None = None + """ + Action to start on context window overflow + """ class UpdateUserRequest(BaseModel): @@ -753,6 +777,14 @@ class PatchSessionRequest(BaseModel): """ Optional metadata """ + token_budget: int | None = None + """ + Threshold value for the adaptive context functionality + """ + context_overflow: str | None = None + """ + Action to start on context window overflow + """ class PartialFunctionDef(BaseModel): diff --git a/agents-api/agents_api/common/protocol/sessions.py b/agents-api/agents_api/common/protocol/sessions.py index c9fa81075..683b36aaf 100644 --- a/agents-api/agents_api/common/protocol/sessions.py +++ b/agents-api/agents_api/common/protocol/sessions.py @@ -44,3 +44,5 @@ class SessionData(BaseModel): metadata: Dict = {} user_metadata: Optional[Dict] = None agent_metadata: Dict = {} + token_budget: int | None = None + context_overflow: str | None = None diff --git a/agents-api/agents_api/env.py b/agents-api/agents_api/env.py index b4524004c..2825aba27 100644 --- a/agents-api/agents_api/env.py +++ b/agents-api/agents_api/env.py @@ -26,12 +26,6 @@ model_api_key: str = env.str("MODEL_API_KEY", default=None) model_inference_url: str = env.str("MODEL_INFERENCE_URL", default=None) openai_api_key: str = env.str("OPENAI_API_KEY", default="") -summarization_ratio_threshold: float = env.float( - "MAX_TOKENS_RATIO_TO_SUMMARIZE", default=0.5 -) -summarization_tokens_threshold: int = env.int( - "SUMMARIZATION_TOKENS_THRESHOLD", default=2048 -) summarization_model_name: str = env.str( "SUMMARIZATION_MODEL_NAME", default="gpt-4-turbo" ) @@ -78,8 +72,6 @@ debug=debug, cozo_host=cozo_host, cozo_auth=cozo_auth, - summarization_ratio_threshold=summarization_ratio_threshold, - summarization_tokens_threshold=summarization_tokens_threshold, worker_url=worker_url, sentry_dsn=sentry_dsn, temporal_endpoint=temporal_endpoint, diff --git a/agents-api/agents_api/models/session/create_session.py b/agents-api/agents_api/models/session/create_session.py index 6cf149bce..8eebd5280 100644 --- a/agents-api/agents_api/models/session/create_session.py +++ b/agents-api/agents_api/models/session/create_session.py @@ -21,6 +21,8 @@ def create_session_query( situation: str | None, metadata: dict = {}, render_templates: bool = False, + token_budget: int | None = None, + context_overflow: str | None = None, ) -> tuple[str, dict]: """ Constructs and executes a datalog query to create a new session in the database. @@ -33,6 +35,8 @@ def create_session_query( - situation (str | None): The situation/context of the session. - metadata (dict): Additional metadata for the session. - render_templates (bool): Specifies whether to render templates. + - token_budget (int | None): Token count threshold to consider it as a context window overflow + - context_overflow (str | None): Action to take on context window overflow Returns: - pd.DataFrame: The result of the query execution. @@ -57,12 +61,14 @@ def create_session_query( } } { # Insert the new session data into the 'session' table with the specified columns. - ?[session_id, developer_id, situation, metadata, render_templates] <- [[ + ?[session_id, developer_id, situation, metadata, render_templates, token_budget, context_overflow] <- [[ $session_id, $developer_id, $situation, $metadata, $render_templates, + $token_budget, + $context_overflow, ]] :insert sessions { @@ -71,6 +77,8 @@ def create_session_query( situation, metadata, render_templates, + token_budget, + context_overflow, } # Specify the data to return after the query execution, typically the newly created session's ID. :returning @@ -87,5 +95,7 @@ def create_session_query( "situation": situation, "metadata": metadata, "render_templates": render_templates, + "token_budget": token_budget, + "context_overflow": context_overflow, }, ) diff --git a/agents-api/agents_api/models/session/get_session.py b/agents-api/agents_api/models/session/get_session.py index a47c09495..09b763489 100644 --- a/agents-api/agents_api/models/session/get_session.py +++ b/agents-api/agents_api/models/session/get_session.py @@ -44,6 +44,8 @@ def get_session_query( created_at, metadata, render_templates, + token_budget, + context_overflow, ] := input[developer_id, id], *sessions{ developer_id, @@ -54,6 +56,8 @@ def get_session_query( updated_at: validity, metadata, render_templates, + token_budget, + context_overflow, @ "NOW" }, *session_lookup{ diff --git a/agents-api/agents_api/models/session/list_sessions.py b/agents-api/agents_api/models/session/list_sessions.py index e0cf4a59e..ec5c40310 100644 --- a/agents-api/agents_api/models/session/list_sessions.py +++ b/agents-api/agents_api/models/session/list_sessions.py @@ -50,6 +50,8 @@ def list_sessions_query( updated_at, created_at, metadata, + token_budget, + context_overflow, ] := input[developer_id], *sessions{{ @@ -60,6 +62,8 @@ def list_sessions_query( created_at, updated_at: validity, metadata, + token_budget, + context_overflow, @ "NOW" }}, *session_lookup{{ diff --git a/agents-api/agents_api/models/session/session_data.py b/agents-api/agents_api/models/session/session_data.py index d3a5bafc3..5d2c13996 100644 --- a/agents-api/agents_api/models/session/session_data.py +++ b/agents-api/agents_api/models/session/session_data.py @@ -47,6 +47,8 @@ def session_data_query( default_settings, metadata, render_templates, + token_budget, + context_overflow, user_metadata, agent_metadata, ] := input[developer_id, session_id], @@ -59,6 +61,8 @@ def session_data_query( updated_at: validity, metadata, render_templates, + token_budget, + context_overflow, @ "NOW" }, *session_lookup{ @@ -116,6 +120,8 @@ def session_data_query( default_settings, metadata, render_templates, + token_budget, + context_overflow, user_metadata, agent_metadata, ] := input[developer_id, session_id], @@ -128,6 +134,8 @@ def session_data_query( updated_at: validity, metadata, render_templates, + token_budget, + context_overflow, @ "NOW" }, *session_lookup{ diff --git a/agents-api/agents_api/models/utils.py b/agents-api/agents_api/models/utils.py index a6fb71c86..fe269b17c 100644 --- a/agents-api/agents_api/models/utils.py +++ b/agents-api/agents_api/models/utils.py @@ -1,12 +1,15 @@ from functools import wraps -from typing import Callable +from typing import Callable, ParamSpec import pandas as pd from ..clients.cozo import client as cozo_client -def cozo_query(func: Callable[..., tuple[str, dict]]): +P = ParamSpec("P") + + +def cozo_query(func: Callable[P, tuple[str, dict]]): """ Decorator that wraps a function that takes arbitrary arguments, and returns a (query string, variables) tuple. diff --git a/agents-api/agents_api/routers/sessions/protocol.py b/agents-api/agents_api/routers/sessions/protocol.py index d630762db..2350afeb3 100644 --- a/agents-api/agents_api/routers/sessions/protocol.py +++ b/agents-api/agents_api/routers/sessions/protocol.py @@ -23,6 +23,8 @@ class Settings(BaseModel): min_p: float | None = Field(default=0.01) preset: Preset | None = Field(default=None) tools: list[Tool] | None = Field(default=None) + token_budget: int | None = Field(default=None) + context_overflow: str | None = Field(default=None) @field_validator("max_tokens") def set_max_tokens(cls, max_tokens): diff --git a/agents-api/agents_api/routers/sessions/routers.py b/agents-api/agents_api/routers/sessions/routers.py index caa9fcefc..ad87d3aaa 100644 --- a/agents-api/agents_api/routers/sessions/routers.py +++ b/agents-api/agents_api/routers/sessions/routers.py @@ -90,6 +90,8 @@ async def create_session( situation=request.situation, metadata=request.metadata or {}, render_templates=request.render_templates or False, + token_budget=request.token_budget, + context_overflow=request.context_overflow, ) return ResourceCreatedResponse( @@ -151,6 +153,8 @@ async def update_session( developer_id=x_developer_id, situation=request.situation, metadata=request.metadata, + token_budget=request.token_budget, + context_overflow=request.context_overflow, ) return ResourceUpdatedResponse( @@ -182,6 +186,8 @@ async def patch_session( developer_id=x_developer_id, situation=request.situation, metadata=request.metadata, + token_budget=request.token_budget, + context_overflow=request.context_overflow, ) return ResourceUpdatedResponse( diff --git a/agents-api/agents_api/routers/sessions/session.py b/agents-api/agents_api/routers/sessions/session.py index e6f5e2f48..c2940d4fc 100644 --- a/agents-api/agents_api/routers/sessions/session.py +++ b/agents-api/agents_api/routers/sessions/session.py @@ -12,7 +12,7 @@ import litellm from litellm import acompletion -from ...autogen.openapi_model import InputChatMLMessage, Tool, DocIds +from ...autogen.openapi_model import InputChatMLMessage, Tool, DocIds, Role from ...clients.embed import embed from ...clients.temporal import run_summarization_task from ...clients.worker.types import ChatML @@ -23,7 +23,6 @@ from ...common.utils.json import CustomJSONEncoder from ...common.utils.messages import stringify_content from ...env import ( - summarization_tokens_threshold, docs_embedding_service_url, docs_embedding_model_id, ) @@ -116,8 +115,8 @@ def _remove_messages( return result, token_count - def truncate( - self, messages: list[Entry], summarization_tokens_threshold: int + def _truncate_context( + self, messages: list[Entry], summarization_tokens_threshold: int | None ) -> list[Entry]: def rm_thoughts(m): return m.role == "system" and m.name == "thought" @@ -125,6 +124,9 @@ def rm_thoughts(m): def rm_user_assistant(m): return m.role in ("user", "assistant") + if summarization_tokens_threshold is None: + return messages + token_count = reduce(lambda c, e: (e.token_count or 0) + c, messages, 0) if token_count <= summarization_tokens_threshold: @@ -153,6 +155,31 @@ def rm_user_assistant(m): raise InputTooBigError(token_count, summarization_tokens_threshold) + def _truncate_entries( + self, messages: list[Entry], token_count_threshold: int + ) -> list[Entry]: + if not len(messages): + return messages + + result: list[Entry] = [] + token_cnt, offset = 0, 0 + if messages[0].role == Role.system: + result: list[Entry] = messages[0] + token_cnt, offset = messages[0].token_count, 1 + + for m in reversed(messages[offset:]): + if token_cnt < token_count_threshold: + result.append(m) + else: + break + + token_cnt += m.token_count + + if offset: + result.append(messages[0]) + + return list(reversed(result)) + async def run( self, new_input, settings: Settings ) -> tuple[ChatCompletion, Entry, Callable | None, DocIds]: @@ -170,7 +197,8 @@ async def run( # Generate response response = await self.generate( - self.truncate(init_context, summarization_tokens_threshold), final_settings + self._truncate_context(init_context, final_settings.token_budget), + final_settings, ) # Save response to session @@ -219,6 +247,10 @@ async def forward( new_input: list[Entry], settings: Settings, ) -> tuple[list[ChatML], Settings, DocIds]: + if session_data is not None: + settings.token_budget = session_data.token_budget + settings.context_overflow = session_data.context_overflow + stringified_input = [] for msg in new_input: stringified_input.append( @@ -452,10 +484,20 @@ async def backward( ) entries.append(new_entry) + summarization_task = None + + if ( + final_settings.token_budget is not None + and total_tokens >= final_settings.token_budget + ): + if final_settings.context_overflow == "truncate": + entries = self._truncate_entries(entries, final_settings.token_budget) + elif final_settings.context_overflow == "adaptive": + summarization_task = run_summarization_task + add_entries_query(entries) - if total_tokens >= summarization_tokens_threshold: - return run_summarization_task + return summarization_task class PlainCompletionSession(BaseSession): diff --git a/agents-api/migrations/migrate_1717239610_token_budget.py b/agents-api/migrations/migrate_1717239610_token_budget.py new file mode 100644 index 000000000..c042c56e5 --- /dev/null +++ b/agents-api/migrations/migrate_1717239610_token_budget.py @@ -0,0 +1,67 @@ +# /usr/bin/env python3 + +MIGRATION_ID = "token_budget" +CREATED_AT = 1717239610.622555 + +update_sessions = { + "up": """ + ?[developer_id, session_id, updated_at, situation, summary, created_at, metadata, render_templates, token_budget, context_overflow] := *sessions{ + developer_id, + session_id, + updated_at, + situation, + summary, + created_at, + metadata, + render_templates, + }, + token_budget = null, + context_overflow = null, + + :replace sessions { + developer_id: Uuid, + session_id: Uuid, + updated_at: Validity default [floor(now()), true], + => + situation: String, + summary: String? default null, + created_at: Float default now(), + metadata: Json default {}, + render_templates: Bool default false, + token_budget: Int? default null, + context_overflow: String? default null, + } + """, + "down": """ + ?[developer_id, session_id, updated_at, situation, summary, created_at, metadata, render_templates] := *sessions{ + developer_id, + session_id, + updated_at, + situation, + summary, + created_at, + metadata, + render_templates, + } + + :replace sessions { + developer_id: Uuid, + session_id: Uuid, + updated_at: Validity default [floor(now()), true], + => + situation: String, + summary: String? default null, + created_at: Float default now(), + metadata: Json default {}, + render_templates: Bool default false, + } + """, +} + + +def up(client): + client.run(update_sessions["up"]) + + +def down(client): + client.run(update_sessions["down"]) diff --git a/openapi.yaml b/openapi.yaml index f675b82dc..72f532fd9 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1298,6 +1298,12 @@ components: type: boolean description: Render system and assistant message content as jinja templates default: false + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow required: - id - agent_id @@ -1346,6 +1352,12 @@ components: type: boolean description: Render system and assistant message content as jinja templates default: false + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow required: - agent_id description: A valid request payload for creating a session @@ -1407,6 +1419,12 @@ components: type: object properties: {} description: Optional metadata + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow description: A valid request payload for updating a session required: - situation @@ -2322,6 +2340,12 @@ components: type: object properties: {} description: Optional metadata + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow description: A request for patching a session PatchToolRequest: type: object From e4da1d3a8c9185b9848af4731e289cc38f737da6 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Mon, 3 Jun 2024 12:21:27 +0300 Subject: [PATCH 25/43] feat: Calculate tokens for image content --- agents-api/agents_api/common/protocol/entries.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/agents-api/agents_api/common/protocol/entries.py b/agents-api/agents_api/common/protocol/entries.py index 25c1bde3c..e6ff945fb 100644 --- a/agents-api/agents_api/common/protocol/entries.py +++ b/agents-api/agents_api/common/protocol/entries.py @@ -7,6 +7,7 @@ Role, ChatMLImageContentPart, ChatMLTextContentPart, + Detail, ) from agents_api.common.utils.datetime import utcnow @@ -14,6 +15,10 @@ Tokenizer = Literal["character_count"] +LOW_IMAGE_TOKEN_COUNT = 85 +HIGH_IMAGE_TOKEN_COUNT = 85 + 4 * 170 + + class Entry(BaseModel): """Represents an entry in the system, encapsulating all necessary details such as ID, session ID, source, role, and content among others.""" @@ -44,12 +49,15 @@ def token_count(self) -> int: elif isinstance(self.content, dict): content_length = len(json.dumps(self.content)) elif isinstance(self.content, list): - text = "" for part in self.content: - # TODO: how to calc token count for images? if isinstance(part, ChatMLTextContentPart): - text += part.text - content_length = len(text) + content_length += len(part.text) + elif isinstance(part, ChatMLImageContentPart): + content_length += ( + LOW_IMAGE_TOKEN_COUNT + if part.image_url.detail == Detail.low + else HIGH_IMAGE_TOKEN_COUNT + ) # Divide the content length by 3.5 to estimate token count based on character count. return int(content_length // 3.5) From 7a6be6fdf5709de5f3f187e9c2bf0c0e9d3469be Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Mon, 3 Jun 2024 15:25:38 +0300 Subject: [PATCH 26/43] feat: Update SDKs to support adaptive context options --- .../agents_api/autogen/openapi_model.py | 2 +- agents-api/poetry.lock | 92 +++--- mock_openapi.yaml | 24 ++ sdks/postman/collection.json | 4 +- sdks/python/julep/api/client.py | 60 ++++ sdks/python/julep/api/types/session.py | 6 + sdks/python/julep/managers/session.py | 12 + sdks/python/poetry.lock | 273 +++++++----------- sdks/ts/package-lock.json | 4 +- .../ts/src/api/models/CreateSessionRequest.ts | 8 + sdks/ts/src/api/models/PatchSessionRequest.ts | 8 + sdks/ts/src/api/models/Session.ts | 8 + .../ts/src/api/models/UpdateSessionRequest.ts | 8 + .../src/api/schemas/$CreateSessionRequest.ts | 8 + .../src/api/schemas/$PatchSessionRequest.ts | 8 + sdks/ts/src/api/schemas/$Session.ts | 8 + .../src/api/schemas/$UpdateSessionRequest.ts | 8 + 17 files changed, 316 insertions(+), 225 deletions(-) diff --git a/agents-api/agents_api/autogen/openapi_model.py b/agents-api/agents_api/autogen/openapi_model.py index 95efb2025..beee3c003 100644 --- a/agents-api/agents_api/autogen/openapi_model.py +++ b/agents-api/agents_api/autogen/openapi_model.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.yaml -# timestamp: 2024-06-01T12:26:54+00:00 +# timestamp: 2024-06-03T12:10:34+00:00 from __future__ import annotations diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 1790ab54d..0c755c0f7 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -454,13 +454,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -762,19 +762,19 @@ develop = ["coverage", "invoke", "path.py", "pylint", "pytest (>=3.2)", "pytest- [[package]] name = "dask" -version = "2024.5.1" +version = "2024.5.2" description = "Parallel PyData with Task Scheduling" optional = false python-versions = ">=3.9" files = [ - {file = "dask-2024.5.1-py3-none-any.whl", hash = "sha256:af1cadd1fd1d1d44600ff5de43dd029e5668fdf87422131f4e3e3aa2a6a63555"}, - {file = "dask-2024.5.1.tar.gz", hash = "sha256:e071fda67031c314569e37ca70b3e88bb30f1d91ff8ee4122b541845847cc264"}, + {file = "dask-2024.5.2-py3-none-any.whl", hash = "sha256:acc2cfe41d9e0151c216ac40396dbe34df13bc3d8c51dfece190349e4f2243af"}, + {file = "dask-2024.5.2.tar.gz", hash = "sha256:5c9722c44d0195e78b6e54197aa3302e6fcaaac2310fd3014560bcb86253dcb3"}, ] [package.dependencies] click = ">=8.1" cloudpickle = ">=1.5.0" -distributed = {version = "2024.5.1", optional = true, markers = "extra == \"distributed\""} +distributed = {version = "2024.5.2", optional = true, markers = "extra == \"distributed\""} fsspec = ">=2021.09.0" importlib-metadata = {version = ">=4.13.0", markers = "python_version < \"3.12\""} packaging = ">=20.0" @@ -787,7 +787,7 @@ array = ["numpy (>=1.21)"] complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)", "pyarrow-hotfix"] dataframe = ["dask-expr (>=1.1,<1.2)", "dask[array]", "pandas (>=1.3)"] diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] -distributed = ["distributed (==2024.5.1)"] +distributed = ["distributed (==2024.5.2)"] test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytest-xdist"] [[package]] @@ -900,19 +900,19 @@ files = [ [[package]] name = "distributed" -version = "2024.5.1" +version = "2024.5.2" description = "Distributed scheduler for Dask" optional = false python-versions = ">=3.9" files = [ - {file = "distributed-2024.5.1-py3-none-any.whl", hash = "sha256:cf77583ce67f6696aa716c30f1cba3403ac866241c00d6e9a0bc1500c6818b40"}, - {file = "distributed-2024.5.1.tar.gz", hash = "sha256:c4e641e5fc014de3b43c584c70f703a7d44557b51b1143db812b8bc861aa84e2"}, + {file = "distributed-2024.5.2-py3-none-any.whl", hash = "sha256:c0fd59d5c34179d9c9b5dc5acb42a00a06d163107b79f66c2dc73e9479a92286"}, + {file = "distributed-2024.5.2.tar.gz", hash = "sha256:4cee41093e98340d04d9254012c7d521065f64b3f33546dd0b02b00becb41e21"}, ] [package.dependencies] click = ">=8.0" cloudpickle = ">=1.5.0" -dask = "2024.5.1" +dask = "2024.5.2" jinja2 = ">=2.10.3" locket = ">=1.0.0" msgpack = ">=1.0.0" @@ -1329,13 +1329,13 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] [[package]] name = "google-cloud-aiplatform" -version = "1.52.0" +version = "1.53.0" description = "Vertex AI API client library" optional = false python-versions = ">=3.8" files = [ - {file = "google-cloud-aiplatform-1.52.0.tar.gz", hash = "sha256:932a56e3050b4bc9a2c0630e6af3c0bd52f0bcf72b5dc01c059874231099edd3"}, - {file = "google_cloud_aiplatform-1.52.0-py2.py3-none-any.whl", hash = "sha256:8c62f5d0ec39e008737ebba4875105ed7563dd0958f591f95dc7816e4b30f92a"}, + {file = "google-cloud-aiplatform-1.53.0.tar.gz", hash = "sha256:574cfad8ac5fa5d57ef717f5335ce05636a5fa9b8aeea0f5c325b46b9448e6b1"}, + {file = "google_cloud_aiplatform-1.53.0-py2.py3-none-any.whl", hash = "sha256:9dfb1f110e6d4795b45afcfab79108fc5c8ed9aa4eaf899e433bc2ca1b76c778"}, ] [package.dependencies] @@ -1935,13 +1935,13 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.24.0" +version = "8.25.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.24.0-py3-none-any.whl", hash = "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3"}, - {file = "ipython-8.24.0.tar.gz", hash = "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501"}, + {file = "ipython-8.25.0-py3-none-any.whl", hash = "sha256:53eee7ad44df903a06655871cbab66d156a051fd86f3ec6750470ac9604ac1ab"}, + {file = "ipython-8.25.0.tar.gz", hash = "sha256:c6ed726a140b6e725b911528f80439c534fac915246af3efc39440a6b0f9d716"}, ] [package.dependencies] @@ -1960,7 +1960,7 @@ typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"] kernel = ["ipykernel"] matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] @@ -2316,13 +2316,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.14.0" +version = "2.14.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.14.0-py3-none-any.whl", hash = "sha256:fb6be52c713e80e004fac34b35a0990d6d36ba06fd0a2b2ed82b899143a64210"}, - {file = "jupyter_server-2.14.0.tar.gz", hash = "sha256:659154cea512083434fd7c93b7fe0897af7a2fd0b9dd4749282b42eaac4ae677"}, + {file = "jupyter_server-2.14.1-py3-none-any.whl", hash = "sha256:16f7177c3a4ea8fe37784e2d31271981a812f0b2874af17339031dc3510cc2a5"}, + {file = "jupyter_server-2.14.1.tar.gz", hash = "sha256:12558d158ec7a0653bf96cc272bc7ad79e0127d503b982ed144399346694f726"}, ] [package.dependencies] @@ -2347,7 +2347,7 @@ traitlets = ">=5.6.0" websocket-client = ">=1.7" [package.extras] -docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] [[package]] @@ -2572,13 +2572,13 @@ extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] [[package]] name = "langsmith" -version = "0.1.63" +version = "0.1.67" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.63-py3-none-any.whl", hash = "sha256:7810afdf5e3f3b472fc581a29371fb96cd843dde2149e048d1b9610325159d1e"}, - {file = "langsmith-0.1.63.tar.gz", hash = "sha256:a609405b52f6f54df442a142cbf19ab38662d54e532f96028b4c546434d4afdf"}, + {file = "langsmith-0.1.67-py3-none-any.whl", hash = "sha256:7eb2e1c1b375925ff47700ed8071e10c15e942e9d1d634b4a449a9060364071a"}, + {file = "langsmith-0.1.67.tar.gz", hash = "sha256:149558669a2ac4f21471cd964e61072687bba23b7c1ccb51f190a8f59b595b39"}, ] [package.dependencies] @@ -2628,13 +2628,13 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.12.1)", "build (>=0.10.0)", "coverage (> [[package]] name = "litellm" -version = "1.39.2" +version = "1.40.0" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.39.2-py3-none-any.whl", hash = "sha256:843cb9a4d45c89ba6da95529815ec83ee7e4b7fe07aa0ed633102f600fddd9ad"}, - {file = "litellm-1.39.2.tar.gz", hash = "sha256:96c4f3d522ccf32817357b1e9f5f63fa36a4a884f336314e1f6d66c0576d689e"}, + {file = "litellm-1.40.0-py3-none-any.whl", hash = "sha256:c3055767ae144585699fdb07b3ad678e66738c2eff19abd7761c8fe22d6e636f"}, + {file = "litellm-1.40.0.tar.gz", hash = "sha256:12b4c0ad850ede5aebdb2f48e3a8e898efb25df5bc915ff89929ad963cb92f54"}, ] [package.dependencies] @@ -3238,13 +3238,13 @@ files = [ [[package]] name = "openai" -version = "1.30.4" +version = "1.30.5" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.30.4-py3-none-any.whl", hash = "sha256:fb2635efd270efaf9fac2e07558d7948373b940637d3ae3ab624c1a983d4f03f"}, - {file = "openai-1.30.4.tar.gz", hash = "sha256:f3488d9a1c4e0d332b019377d27d7cb4b3d6103fd5d0a416c7ceac780d1d9b88"}, + {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, + {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, ] [package.dependencies] @@ -4305,13 +4305,13 @@ files = [ [[package]] name = "requests" -version = "2.32.2" +version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ - {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, - {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -5313,13 +5313,13 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.41.1" +version = "4.41.2" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = false python-versions = ">=3.8.0" files = [ - {file = "transformers-4.41.1-py3-none-any.whl", hash = "sha256:f0680e0b1a01067eccd11f62f0522409422c7d6f91d532fe0f50b136a406129d"}, - {file = "transformers-4.41.1.tar.gz", hash = "sha256:fa859e4c66f0896633a3bf534e0d9a29a9a88478a49f94c5d8270537dc61cc42"}, + {file = "transformers-4.41.2-py3-none-any.whl", hash = "sha256:05555d20e43f808de1ef211ab64803cdb513170cef70d29a888b589caebefc67"}, + {file = "transformers-4.41.2.tar.gz", hash = "sha256:80a4db216533d573e9cc7388646c31ed9480918feb7c55eb211249cb23567f87"}, ] [package.dependencies] @@ -5418,13 +5418,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.1" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, + {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, ] [[package]] @@ -5821,18 +5821,18 @@ files = [ [[package]] name = "zipp" -version = "3.19.0" +version = "3.19.1" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, - {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, + {file = "zipp-3.19.1-py3-none-any.whl", hash = "sha256:2828e64edb5386ea6a52e7ba7cdb17bb30a73a858f5eb6eb93d8d36f5ea26091"}, + {file = "zipp-3.19.1.tar.gz", hash = "sha256:35427f6d5594f4acf82d25541438348c26736fa9b3afa2754bcd63cdb99d8e8f"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" diff --git a/mock_openapi.yaml b/mock_openapi.yaml index 763e4fbf8..a83e167d0 100644 --- a/mock_openapi.yaml +++ b/mock_openapi.yaml @@ -1298,6 +1298,12 @@ components: type: boolean description: Render system and assistant message content as jinja templates default: false + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow required: - id - agent_id @@ -1346,6 +1352,12 @@ components: type: boolean description: Render system and assistant message content as jinja templates default: false + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow required: - agent_id description: A valid request payload for creating a session @@ -1407,6 +1419,12 @@ components: type: object properties: {} description: Optional metadata + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow description: A valid request payload for updating a session required: - situation @@ -2322,6 +2340,12 @@ components: type: object properties: {} description: Optional metadata + token_budget: + type: integer + description: Threshold value for the adaptive context functionality + context_overflow: + type: string + description: Action to start on context window overflow description: A request for patching a session PatchToolRequest: type: object diff --git a/sdks/postman/collection.json b/sdks/postman/collection.json index 16eed0839..07e71271e 100644 --- a/sdks/postman/collection.json +++ b/sdks/postman/collection.json @@ -106,7 +106,7 @@ "body": null }, "description": "List of sessions (sorted created_at descending order) with limit+offset pagination", - "body": "{\n \"items\": [\n {\n \"id\": \"id\",\n \"user_id\": \"user_id\",\n \"agent_id\": \"agent_id\",\n \"situation\": \"situation\",\n \"summary\": \"summary\",\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\",\n \"render_templates\": true\n }\n ]\n}", + "body": "{\n \"items\": [\n {\n \"id\": \"id\",\n \"user_id\": \"user_id\",\n \"agent_id\": \"agent_id\",\n \"situation\": \"situation\",\n \"summary\": \"summary\",\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\",\n \"render_templates\": true,\n \"token_budget\": 1,\n \"context_overflow\": \"context_overflow\"\n }\n ]\n}", "_postman_previewlanguage": "json" } ] @@ -612,7 +612,7 @@ "body": null }, "description": null, - "body": "{\n \"id\": \"id\",\n \"user_id\": \"user_id\",\n \"agent_id\": \"agent_id\",\n \"situation\": \"situation\",\n \"summary\": \"summary\",\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\",\n \"render_templates\": true\n}", + "body": "{\n \"id\": \"id\",\n \"user_id\": \"user_id\",\n \"agent_id\": \"agent_id\",\n \"situation\": \"situation\",\n \"summary\": \"summary\",\n \"created_at\": \"2024-01-15T09:30:00Z\",\n \"updated_at\": \"2024-01-15T09:30:00Z\",\n \"render_templates\": true,\n \"token_budget\": 1,\n \"context_overflow\": \"context_overflow\"\n}", "_postman_previewlanguage": "json" } ] diff --git a/sdks/python/julep/api/client.py b/sdks/python/julep/api/client.py index 0ac307a05..afc148aaf 100644 --- a/sdks/python/julep/api/client.py +++ b/sdks/python/julep/api/client.py @@ -149,6 +149,8 @@ def create_session( situation: typing.Optional[str] = OMIT, metadata: typing.Optional[CreateSessionRequestMetadata] = OMIT, render_templates: typing.Optional[bool] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceCreatedResponse: """ Create a session between an agent and a user @@ -163,6 +165,10 @@ def create_session( - metadata: typing.Optional[CreateSessionRequestMetadata]. Optional metadata - render_templates: typing.Optional[bool]. Render system and assistant message content as jinja templates + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import JulepApi @@ -182,6 +188,10 @@ def create_session( _request["metadata"] = metadata if render_templates is not OMIT: _request["render_templates"] = render_templates + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = self._client_wrapper.httpx_client.request( "POST", urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"), @@ -463,6 +473,8 @@ def update_session( *, situation: str, metadata: typing.Optional[UpdateSessionRequestMetadata] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceUpdatedResponse: """ @@ -473,6 +485,10 @@ def update_session( - situation: str. Updated situation for this session - metadata: typing.Optional[UpdateSessionRequestMetadata]. Optional metadata + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import JulepApi @@ -487,6 +503,10 @@ def update_session( _request: typing.Dict[str, typing.Any] = {"situation": situation} if metadata is not OMIT: _request["metadata"] = metadata + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = self._client_wrapper.httpx_client.request( "PUT", urllib.parse.urljoin( @@ -542,6 +562,8 @@ def patch_session( *, situation: typing.Optional[str] = OMIT, metadata: typing.Optional[PatchSessionRequestMetadata] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceUpdatedResponse: """ @@ -552,6 +574,10 @@ def patch_session( - situation: typing.Optional[str]. Updated situation for this session - metadata: typing.Optional[PatchSessionRequestMetadata]. Optional metadata + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import JulepApi @@ -567,6 +593,10 @@ def patch_session( _request["situation"] = situation if metadata is not OMIT: _request["metadata"] = metadata + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = self._client_wrapper.httpx_client.request( "PATCH", urllib.parse.urljoin( @@ -1910,6 +1940,8 @@ async def create_session( situation: typing.Optional[str] = OMIT, metadata: typing.Optional[CreateSessionRequestMetadata] = OMIT, render_templates: typing.Optional[bool] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceCreatedResponse: """ Create a session between an agent and a user @@ -1924,6 +1956,10 @@ async def create_session( - metadata: typing.Optional[CreateSessionRequestMetadata]. Optional metadata - render_templates: typing.Optional[bool]. Render system and assistant message content as jinja templates + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import AsyncJulepApi @@ -1943,6 +1979,10 @@ async def create_session( _request["metadata"] = metadata if render_templates is not OMIT: _request["render_templates"] = render_templates + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = await self._client_wrapper.httpx_client.request( "POST", urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sessions"), @@ -2224,6 +2264,8 @@ async def update_session( *, situation: str, metadata: typing.Optional[UpdateSessionRequestMetadata] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceUpdatedResponse: """ @@ -2234,6 +2276,10 @@ async def update_session( - situation: str. Updated situation for this session - metadata: typing.Optional[UpdateSessionRequestMetadata]. Optional metadata + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import AsyncJulepApi @@ -2248,6 +2294,10 @@ async def update_session( _request: typing.Dict[str, typing.Any] = {"situation": situation} if metadata is not OMIT: _request["metadata"] = metadata + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = await self._client_wrapper.httpx_client.request( "PUT", urllib.parse.urljoin( @@ -2303,6 +2353,8 @@ async def patch_session( *, situation: typing.Optional[str] = OMIT, metadata: typing.Optional[PatchSessionRequestMetadata] = OMIT, + token_budget: typing.Optional[int] = OMIT, + context_overflow: typing.Optional[str] = OMIT, ) -> ResourceUpdatedResponse: """ @@ -2313,6 +2365,10 @@ async def patch_session( - situation: typing.Optional[str]. Updated situation for this session - metadata: typing.Optional[PatchSessionRequestMetadata]. Optional metadata + + - token_budget: typing.Optional[int]. Threshold value for the adaptive context functionality + + - context_overflow: typing.Optional[str]. Action to start on context window overflow --- from julep.client import AsyncJulepApi @@ -2328,6 +2384,10 @@ async def patch_session( _request["situation"] = situation if metadata is not OMIT: _request["metadata"] = metadata + if token_budget is not OMIT: + _request["token_budget"] = token_budget + if context_overflow is not OMIT: + _request["context_overflow"] = context_overflow _response = await self._client_wrapper.httpx_client.request( "PATCH", urllib.parse.urljoin( diff --git a/sdks/python/julep/api/types/session.py b/sdks/python/julep/api/types/session.py index 97c442cd5..e5b6aafe2 100644 --- a/sdks/python/julep/api/types/session.py +++ b/sdks/python/julep/api/types/session.py @@ -38,6 +38,12 @@ class Session(pydantic.BaseModel): render_templates: typing.Optional[bool] = pydantic.Field( description="Render system and assistant message content as jinja templates" ) + token_budget: typing.Optional[int] = pydantic.Field( + description="Threshold value for the adaptive context functionality" + ) + context_overflow: typing.Optional[str] = pydantic.Field( + description="Action to start on context window overflow" + ) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = { diff --git a/sdks/python/julep/managers/session.py b/sdks/python/julep/managers/session.py index a61436b6b..a083c4f29 100644 --- a/sdks/python/julep/managers/session.py +++ b/sdks/python/julep/managers/session.py @@ -40,6 +40,8 @@ class SessionCreateArgs(TypedDict): situation: Optional[str] = None metadata: Dict[str, Any] = {} render_templates: bool = False + token_budget: Optional[int] = None + context_overflow: Optional[str] = None class SessionUpdateArgs(TypedDict): @@ -48,6 +50,8 @@ class SessionUpdateArgs(TypedDict): metadata: Optional[Dict[str, Any]] = None overwrite: bool = False render_templates: bool = False + token_budget: Optional[int] = None + context_overflow: Optional[str] = None class BaseSessionsManager(BaseManager): @@ -182,6 +186,8 @@ def _create( situation: Optional[str] = None, metadata: Dict[str, Any] = {}, render_templates: bool = False, + token_budget: Optional[int] = None, + context_overflow: Optional[str] = None, ) -> Union[ResourceCreatedResponse, Awaitable[ResourceCreatedResponse]]: # Cast instructions to a list of Instruction objects """ @@ -213,6 +219,8 @@ def _create( situation=situation, metadata=metadata, render_templates=render_templates, + token_budget=token_budget, + context_overflow=context_overflow, ) def _list_items( @@ -267,6 +275,8 @@ def _update( situation: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None, overwrite: bool = False, + token_budget: Optional[int] = None, + context_overflow: Optional[str] = None, ) -> Union[ResourceUpdatedResponse, Awaitable[ResourceUpdatedResponse]]: """ Update a session with a given situation. @@ -293,6 +303,8 @@ def _update( session_id=session_id, situation=situation, metadata=metadata, + token_budget=token_budget, + context_overflow=context_overflow, ) def _chat( diff --git a/sdks/python/poetry.lock b/sdks/python/poetry.lock index be501a9a5..d141296e3 100644 --- a/sdks/python/poetry.lock +++ b/sdks/python/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -11,9 +11,6 @@ files = [ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "anyio" version = "4.4.0" @@ -185,9 +182,6 @@ files = [ {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -307,13 +301,13 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -1014,11 +1008,9 @@ files = [ attrs = ">=22.2.0" fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} jsonschema-specifications = ">=2023.03.6" -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} @@ -1042,7 +1034,6 @@ files = [ ] [package.dependencies] -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} referencing = ">=0.31.0" [[package]] @@ -1198,7 +1189,6 @@ files = [ async-lru = ">=1.0.0" httpx = ">=0.25.0" importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -importlib-resources = {version = ">=1.4", markers = "python_version < \"3.9\""} ipykernel = ">=6.5.0" jinja2 = ">=3.0.3" jupyter-core = "*" @@ -1257,51 +1247,43 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v [[package]] name = "libcst" -version = "1.1.0" -description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." +version = "1.4.0" +description = "A concrete syntax tree with AST-like properties for Python 3.0 through 3.12 programs." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "libcst-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:63f75656fd733dc20354c46253fde3cf155613e37643c3eaf6f8818e95b7a3d1"}, - {file = "libcst-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ae11eb1ea55a16dc0cdc61b41b29ac347da70fec14cc4381248e141ee2fbe6c"}, - {file = "libcst-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bc745d0c06420fe2644c28d6ddccea9474fb68a2135904043676deb4fa1e6bc"}, - {file = "libcst-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c1f2da45f1c45634090fd8672c15e0159fdc46853336686959b2d093b6e10fa"}, - {file = "libcst-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:003e5e83a12eed23542c4ea20fdc8de830887cc03662432bb36f84f8c4841b81"}, - {file = "libcst-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:3ebbb9732ae3cc4ae7a0e97890bed0a57c11d6df28790c2b9c869f7da653c7c7"}, - {file = "libcst-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d68c34e3038d3d1d6324eb47744cbf13f2c65e1214cf49db6ff2a6603c1cd838"}, - {file = "libcst-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9dffa1795c2804d183efb01c0f1efd20a7831db6a21a0311edf90b4100d67436"}, - {file = "libcst-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc9b6ac36d7ec9db2f053014ea488086ca2ed9c322be104fbe2c71ca759da4bb"}, - {file = "libcst-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b7a38ec4c1c009ac39027d51558b52851fb9234669ba5ba62283185963a31c"}, - {file = "libcst-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5297a16e575be8173185e936b7765c89a3ca69d4ae217a4af161814a0f9745a7"}, - {file = "libcst-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:7ccaf53925f81118aeaadb068a911fac8abaff608817d7343da280616a5ca9c1"}, - {file = "libcst-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:75816647736f7e09c6120bdbf408456f99b248d6272277eed9a58cf50fb8bc7d"}, - {file = "libcst-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c8f26250f87ca849a7303ed7a4fd6b2c7ac4dec16b7d7e68ca6a476d7c9bfcdb"}, - {file = "libcst-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d37326bd6f379c64190a28947a586b949de3a76be00176b0732c8ee87d67ebe"}, - {file = "libcst-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d8cf974cfa2487b28f23f56c4bff90d550ef16505e58b0dca0493d5293784b"}, - {file = "libcst-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d1271403509b0a4ee6ff7917c2d33b5a015f44d1e208abb1da06ba93b2a378"}, - {file = "libcst-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bca1841693941fdd18371824bb19a9702d5784cd347cb8231317dbdc7062c5bc"}, - {file = "libcst-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f36f592e035ef84f312a12b75989dde6a5f6767fe99146cdae6a9ee9aff40dd0"}, - {file = "libcst-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f561c9a84eca18be92f4ad90aa9bd873111efbea995449301719a1a7805dbc5c"}, - {file = "libcst-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97fbc73c87e9040e148881041fd5ffa2a6ebf11f64b4ccb5b52e574b95df1a15"}, - {file = "libcst-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99fdc1929703fd9e7408aed2e03f58701c5280b05c8911753a8d8619f7dfdda5"}, - {file = "libcst-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bf69cbbab5016d938aac4d3ae70ba9ccb3f90363c588b3b97be434e6ba95403"}, - {file = "libcst-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fe41b33aa73635b1651f64633f429f7aa21f86d2db5748659a99d9b7b1ed2a90"}, - {file = "libcst-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73c086705ed34dbad16c62c9adca4249a556c1b022993d511da70ea85feaf669"}, - {file = "libcst-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a07ecfabbbb8b93209f952a365549e65e658831e9231649f4f4e4263cad24b1"}, - {file = "libcst-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c653d9121d6572d8b7f8abf20f88b0a41aab77ff5a6a36e5a0ec0f19af0072e8"}, - {file = "libcst-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f1cd308a4c2f71d5e4eec6ee693819933a03b78edb2e4cc5e3ad1afd5fb3f07"}, - {file = "libcst-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8afb6101b8b3c86c5f9cec6b90ab4da16c3c236fe7396f88e8b93542bb341f7c"}, - {file = "libcst-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:d22d1abfe49aa60fc61fa867e10875a9b3024ba5a801112f4d7ba42d8d53242e"}, - {file = "libcst-1.1.0.tar.gz", hash = "sha256:0acbacb9a170455701845b7e940e2d7b9519db35a86768d86330a0b0deae1086"}, + {file = "libcst-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:279b54568ea1f25add50ea4ba3d76d4f5835500c82f24d54daae4c5095b986aa"}, + {file = "libcst-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3401dae41fe24565387a65baee3887e31a44e3e58066b0250bc3f3ccf85b1b5a"}, + {file = "libcst-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1989fa12d3cd79118ebd29ebe2a6976d23d509b1a4226bc3d66fcb7cb50bd5d"}, + {file = "libcst-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:addc6d585141a7677591868886f6bda0577529401a59d210aa8112114340e129"}, + {file = "libcst-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17d71001cb25e94cfe8c3d997095741a8c4aa7a6d234c0f972bc42818c88dfaf"}, + {file = "libcst-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:2d47de16d105e7dd5f4e01a428d9f4dc1e71efd74f79766daf54528ce37f23c3"}, + {file = "libcst-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e6227562fc5c9c1efd15dfe90b0971ae254461b8b6b23c1b617139b6003de1c1"}, + {file = "libcst-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3399e6c95df89921511b44d8c5bf6a75bcbc2d51f1f6429763609ba005c10f6b"}, + {file = "libcst-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48601e3e590e2d6a7ab8c019cf3937c70511a78d778ab3333764531253acdb33"}, + {file = "libcst-1.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f42797309bb725f0f000510d5463175ccd7155395f09b5e7723971b0007a976d"}, + {file = "libcst-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb4e42ea107a37bff7f9fdbee9532d39f9ea77b89caa5c5112b37057b12e0838"}, + {file = "libcst-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:9d0cc3c5a2a51fa7e1d579a828c0a2e46b2170024fd8b1a0691c8a52f3abb2d9"}, + {file = "libcst-1.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7ece51d935bc9bf60b528473d2e5cc67cbb88e2f8146297e40ee2c7d80be6f13"}, + {file = "libcst-1.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:81653dea1cdfa4c6520a7c5ffb95fa4d220cbd242e446c7a06d42d8636bfcbba"}, + {file = "libcst-1.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6abce0e66bba2babfadc20530fd3688f672d565674336595b4623cd800b91ef"}, + {file = "libcst-1.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5da9d7dc83801aba3b8d911f82dc1a375db0d508318bad79d9fb245374afe068"}, + {file = "libcst-1.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c54aa66c86d8ece9c93156a2cf5ca512b0dce40142fe9e072c86af2bf892411"}, + {file = "libcst-1.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:62e2682ee1567b6a89c91853865372bf34f178bfd237853d84df2b87b446e654"}, + {file = "libcst-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b8ecdba8934632b4dadacb666cd3816627a6ead831b806336972ccc4ba7ca0e9"}, + {file = "libcst-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8e54c777b8d27339b70f304d16fc8bc8674ef1bd34ed05ea874bf4921eb5a313"}, + {file = "libcst-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:061d6855ef30efe38b8a292b7e5d57c8e820e71fc9ec9846678b60a934b53bbb"}, + {file = "libcst-1.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb0abf627ee14903d05d0ad9b2c6865f1b21eb4081e2c7bea1033f85db2b8bae"}, + {file = "libcst-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d024f44059a853b4b852cfc04fec33e346659d851371e46fc8e7c19de24d3da9"}, + {file = "libcst-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3c6a8faab9da48c5b371557d0999b4ca51f4f2cbd37ee8c2c4df0ac01c781465"}, + {file = "libcst-1.4.0.tar.gz", hash = "sha256:449e0b16604f054fa7f27c3ffe86ea7ef6c409836fe68fe4e752a1894175db00"}, ] [package.dependencies] pyyaml = ">=5.2" -typing-extensions = ">=3.7.4.2" -typing-inspect = ">=0.4.0" [package.extras] -dev = ["Sphinx (>=5.1.1)", "black (==23.9.1)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==2.0.0.post1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.16)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.18)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.2.0)", "usort (==1.0.7)"] +dev = ["Sphinx (>=5.1.1)", "black (==23.12.1)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==2.1.0)", "flake8 (==7.0.0)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.4)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<1.6)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.18)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.6.0)", "usort (==1.0.8.post1)"] [[package]] name = "markdown-it-py" @@ -1627,43 +1609,6 @@ jupyter-server = ">=1.8,<3" [package.extras] test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] -[[package]] -name = "numpy" -version = "1.24.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, - {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, - {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, - {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, - {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, - {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, - {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, - {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, - {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, - {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, - {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, -] - [[package]] name = "numpy" version = "1.26.4" @@ -1756,70 +1701,76 @@ files = [ [[package]] name = "pandas" -version = "2.0.3" +version = "2.2.2" description = "Powerful data structures for data analysis, time series, and statistics" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, - {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, - {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, - {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, - {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, - {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, - {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, - {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, - {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, - {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, - {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, - {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, - {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, - {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, - {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, - {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, - {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, - {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, - {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, - {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, - {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, - {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, - {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, - {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, - {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, + {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, + {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, + {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, + {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, + {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, ] [package.dependencies] numpy = [ - {version = ">=1.20.3", markers = "python_version < \"3.10\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, - {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" -tzdata = ">=2022.1" - -[package.extras] -all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] -aws = ["s3fs (>=2021.08.0)"] -clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] -compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] -computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] -feather = ["pyarrow (>=7.0.0)"] -fss = ["fsspec (>=2021.07.0)"] -gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] -hdf5 = ["tables (>=3.6.1)"] -html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] -mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] -parquet = ["pyarrow (>=7.0.0)"] -performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] -plot = ["matplotlib (>=3.6.1)"] -postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] -spss = ["pyreadstat (>=1.1.2)"] -sql-other = ["SQLAlchemy (>=1.4.16)"] -test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.6.3)"] +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] [[package]] name = "pandocfilters" @@ -1905,17 +1856,6 @@ files = [ {file = "pip-24.0.tar.gz", hash = "sha256:ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2"}, ] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" version = "4.2.2" @@ -2422,6 +2362,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2631,7 +2572,6 @@ files = [ [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] @@ -3042,30 +2982,15 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.1" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, + {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, ] -[[package]] -name = "typing-inspect" -version = "0.9.0" -description = "Runtime inspection utilities for typing module." -optional = false -python-versions = "*" -files = [ - {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, - {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, -] - -[package.dependencies] -mypy-extensions = ">=0.3.0" -typing-extensions = ">=3.7.4" - [[package]] name = "tzdata" version = "2024.1" @@ -3199,5 +3124,5 @@ test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-it [metadata] lock-version = "2.0" -python-versions = ">=3.8,<3.14" -content-hash = "d1814da9089d0b4027a2f2e3e1487af13962467b4beb49841fc168118be9930d" +python-versions = ">=3.9,<3.14" +content-hash = "9c33d3e428386f3e2c6c4bd703808ef01df6791b5779725ca4426e33f9a54751" diff --git a/sdks/ts/package-lock.json b/sdks/ts/package-lock.json index 25daa1d2c..366599308 100644 --- a/sdks/ts/package-lock.json +++ b/sdks/ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@julep/sdk", - "version": "0.3.3", + "version": "0.3.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@julep/sdk", - "version": "0.3.3", + "version": "0.3.4", "license": "ISC", "dependencies": { "@rollup/plugin-typescript": "^11.1.6", diff --git a/sdks/ts/src/api/models/CreateSessionRequest.ts b/sdks/ts/src/api/models/CreateSessionRequest.ts index bdb4e699f..47cc2bf0f 100644 --- a/sdks/ts/src/api/models/CreateSessionRequest.ts +++ b/sdks/ts/src/api/models/CreateSessionRequest.ts @@ -26,4 +26,12 @@ export type CreateSessionRequest = { * Render system and assistant message content as jinja templates */ render_templates?: boolean; + /** + * Threshold value for the adaptive context functionality + */ + token_budget?: number; + /** + * Action to start on context window overflow + */ + context_overflow?: string; }; diff --git a/sdks/ts/src/api/models/PatchSessionRequest.ts b/sdks/ts/src/api/models/PatchSessionRequest.ts index 5d1d43650..4a109cfee 100644 --- a/sdks/ts/src/api/models/PatchSessionRequest.ts +++ b/sdks/ts/src/api/models/PatchSessionRequest.ts @@ -14,4 +14,12 @@ export type PatchSessionRequest = { * Optional metadata */ metadata?: any; + /** + * Threshold value for the adaptive context functionality + */ + token_budget?: number; + /** + * Action to start on context window overflow + */ + context_overflow?: string; }; diff --git a/sdks/ts/src/api/models/Session.ts b/sdks/ts/src/api/models/Session.ts index 2312a7a4b..27ed7f7f1 100644 --- a/sdks/ts/src/api/models/Session.ts +++ b/sdks/ts/src/api/models/Session.ts @@ -39,4 +39,12 @@ export type Session = { * Render system and assistant message content as jinja templates */ render_templates?: boolean; + /** + * Threshold value for the adaptive context functionality + */ + token_budget?: number; + /** + * Action to start on context window overflow + */ + context_overflow?: string; }; diff --git a/sdks/ts/src/api/models/UpdateSessionRequest.ts b/sdks/ts/src/api/models/UpdateSessionRequest.ts index b26b2e944..50e3bd14f 100644 --- a/sdks/ts/src/api/models/UpdateSessionRequest.ts +++ b/sdks/ts/src/api/models/UpdateSessionRequest.ts @@ -14,4 +14,12 @@ export type UpdateSessionRequest = { * Optional metadata */ metadata?: any; + /** + * Threshold value for the adaptive context functionality + */ + token_budget?: number; + /** + * Action to start on context window overflow + */ + context_overflow?: string; }; diff --git a/sdks/ts/src/api/schemas/$CreateSessionRequest.ts b/sdks/ts/src/api/schemas/$CreateSessionRequest.ts index 647a066b3..79d56647e 100644 --- a/sdks/ts/src/api/schemas/$CreateSessionRequest.ts +++ b/sdks/ts/src/api/schemas/$CreateSessionRequest.ts @@ -28,5 +28,13 @@ export const $CreateSessionRequest = { type: "boolean", description: `Render system and assistant message content as jinja templates`, }, + token_budget: { + type: "number", + description: `Threshold value for the adaptive context functionality`, + }, + context_overflow: { + type: "string", + description: `Action to start on context window overflow`, + }, }, } as const; diff --git a/sdks/ts/src/api/schemas/$PatchSessionRequest.ts b/sdks/ts/src/api/schemas/$PatchSessionRequest.ts index fb64543d6..f6c0b4d75 100644 --- a/sdks/ts/src/api/schemas/$PatchSessionRequest.ts +++ b/sdks/ts/src/api/schemas/$PatchSessionRequest.ts @@ -13,5 +13,13 @@ export const $PatchSessionRequest = { description: `Optional metadata`, properties: {}, }, + token_budget: { + type: "number", + description: `Threshold value for the adaptive context functionality`, + }, + context_overflow: { + type: "string", + description: `Action to start on context window overflow`, + }, }, } as const; diff --git a/sdks/ts/src/api/schemas/$Session.ts b/sdks/ts/src/api/schemas/$Session.ts index ccbbff296..24354f4f4 100644 --- a/sdks/ts/src/api/schemas/$Session.ts +++ b/sdks/ts/src/api/schemas/$Session.ts @@ -47,5 +47,13 @@ export const $Session = { type: "boolean", description: `Render system and assistant message content as jinja templates`, }, + token_budget: { + type: "number", + description: `Threshold value for the adaptive context functionality`, + }, + context_overflow: { + type: "string", + description: `Action to start on context window overflow`, + }, }, } as const; diff --git a/sdks/ts/src/api/schemas/$UpdateSessionRequest.ts b/sdks/ts/src/api/schemas/$UpdateSessionRequest.ts index 95180ec84..9b415c138 100644 --- a/sdks/ts/src/api/schemas/$UpdateSessionRequest.ts +++ b/sdks/ts/src/api/schemas/$UpdateSessionRequest.ts @@ -14,5 +14,13 @@ export const $UpdateSessionRequest = { description: `Optional metadata`, properties: {}, }, + token_budget: { + type: "number", + description: `Threshold value for the adaptive context functionality`, + }, + context_overflow: { + type: "string", + description: `Action to start on context window overflow`, + }, }, } as const; From e8be05b096dbf8f1bba3dbf93f8d4678f2b7c354 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 14:25:37 +0300 Subject: [PATCH 27/43] fix: Truncate entries --- .../agents_api/routers/sessions/session.py | 7 +- agents-api/tests/__init__.py | 0 agents-api/tests/test_sessions_context.py | 126 ++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 agents-api/tests/__init__.py create mode 100644 agents-api/tests/test_sessions_context.py diff --git a/agents-api/agents_api/routers/sessions/session.py b/agents-api/agents_api/routers/sessions/session.py index c2940d4fc..bf72ff677 100644 --- a/agents-api/agents_api/routers/sessions/session.py +++ b/agents-api/agents_api/routers/sessions/session.py @@ -36,6 +36,7 @@ from ...models.session.session_data import get_session_data from ...models.session.get_cached_response import get_cached_response from ...models.session.set_cached_response import set_cached_response +from ...exceptions import PromptTooBigError from .exceptions import InputTooBigError from .protocol import Settings @@ -164,17 +165,15 @@ def _truncate_entries( result: list[Entry] = [] token_cnt, offset = 0, 0 if messages[0].role == Role.system: - result: list[Entry] = messages[0] token_cnt, offset = messages[0].token_count, 1 for m in reversed(messages[offset:]): + token_cnt += m.token_count if token_cnt < token_count_threshold: result.append(m) else: break - token_cnt += m.token_count - if offset: result.append(messages[0]) @@ -494,6 +493,8 @@ async def backward( entries = self._truncate_entries(entries, final_settings.token_budget) elif final_settings.context_overflow == "adaptive": summarization_task = run_summarization_task + else: + raise PromptTooBigError(total_tokens, final_settings.token_budget) add_entries_query(entries) diff --git a/agents-api/tests/__init__.py b/agents-api/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/agents-api/tests/test_sessions_context.py b/agents-api/tests/test_sessions_context.py new file mode 100644 index 000000000..0c4280dcb --- /dev/null +++ b/agents-api/tests/test_sessions_context.py @@ -0,0 +1,126 @@ +import time +import uuid +from ward import test +from agents_api.common.protocol.entries import Entry +from agents_api.autogen.openapi_model import Role +from tests.fixtures import base_session + + +@test("truncate entries, do not strip system message") +def _(session=base_session): + session_ids = [uuid.uuid4()] * 3 + entry_ids = [uuid.uuid4()] * 3 + now = time.time() + messages = [ + Entry( + entry_id=entry_ids[0], + session_id=session_ids[0], + role=Role.system, + content="content 1", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[1], + session_id=session_ids[1], + role=Role.assistant, + content="content 2", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[2], + session_id=session_ids[2], + role=Role.user, + content="content 3", + created_at=now, + timestamp=now, + ), + ] + + expected_result = [ + Entry( + entry_id=entry_ids[0], + session_id=session_ids[0], + role=Role.system, + content="content 1", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[2], + session_id=session_ids[2], + role=Role.user, + content="content 3", + created_at=now, + timestamp=now, + ), + ] + threshold = sum([m.token_count for m in messages]) - 1 + result = session._truncate_entries(messages, threshold) + + assert result == expected_result + + +@test("truncate entries") +def _(session=base_session): + session_ids = [uuid.uuid4()] * 3 + entry_ids = [uuid.uuid4()] * 3 + now = time.time() + messages = [ + Entry( + entry_id=entry_ids[0], + session_id=session_ids[0], + role=Role.user, + content="content 1", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[1], + session_id=session_ids[1], + role=Role.assistant, + content="content 2", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[2], + session_id=session_ids[2], + role=Role.user, + content="content 3", + created_at=now, + timestamp=now, + ), + ] + + expected_result = [ + Entry( + entry_id=entry_ids[1], + session_id=session_ids[1], + role=Role.assistant, + content="content 2", + created_at=now, + timestamp=now, + ), + Entry( + entry_id=entry_ids[2], + session_id=session_ids[2], + role=Role.user, + content="content 3", + created_at=now, + timestamp=now, + ), + ] + threshold = sum([m.token_count for m in messages]) - 1 + result = session._truncate_entries(messages, threshold) + + assert result == expected_result + + +@test("truncate entries, no change if empty") +def _(session=base_session): + messages = [] + result = session._truncate_entries(messages, 1) + + assert result == [] From 3181fcac32a3f4b2d282e72a007307f9f3d9b0d9 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 17:53:59 +0300 Subject: [PATCH 28/43] fix: Make truncation a background task --- .../agents_api/activities/truncation.py | 55 +++++++++++++++++ agents-api/agents_api/clients/temporal.py | 13 ++++ .../agents_api/routers/sessions/session.py | 35 +++-------- agents-api/agents_api/workflows/truncation.py | 19 ++++++ ...sessions_context.py => test_activities.py} | 60 ++++--------------- 5 files changed, 106 insertions(+), 76 deletions(-) create mode 100644 agents-api/agents_api/activities/truncation.py create mode 100644 agents-api/agents_api/workflows/truncation.py rename agents-api/tests/{test_sessions_context.py => test_activities.py} (56%) diff --git a/agents-api/agents_api/activities/truncation.py b/agents-api/agents_api/activities/truncation.py new file mode 100644 index 000000000..f264a18ee --- /dev/null +++ b/agents-api/agents_api/activities/truncation.py @@ -0,0 +1,55 @@ +from uuid import UUID +from temporalio import activity +from agents_api.models.entry.entries_summarization import get_toplevel_entries_query +from agents_api.models.entry.delete_entries import delete_entries_by_ids_query +from agents_api.autogen.openapi_model import Role +from agents_api.common.protocol.entries import Entry + + +def get_extra_entry_ids( + messages: list[Entry], token_count_threshold: int +) -> set[Entry]: + if not len(messages): + return messages + + result: list[UUID] = [] + token_cnt, offset = 0, 0 + if messages[0].role == Role.system: + token_cnt, offset = messages[0].token_count, 1 + + for m in reversed(messages[offset:]): + token_cnt += m.token_count + if token_cnt < token_count_threshold: + continue + else: + result.append(m.id) + + return set(result) + + +@activity.defn +async def truncation(session_id: str, token_count_threshold: int) -> None: + session_id = UUID(session_id) + + delete_entries_by_ids_query( + list( + get_extra_entry_ids( + [ + Entry( + entry_id=row["entry_id"], + session_id=session_id, + source=row["source"], + role=Role(row["role"]), + name=row["name"], + content=row["content"], + created_at=row["created_at"], + timestamp=row["timestamp"], + ) + for _, row in get_toplevel_entries_query( + session_id=session_id + ).iterrows() + ], + token_count_threshold, + ) + ), + ) diff --git a/agents-api/agents_api/clients/temporal.py b/agents-api/agents_api/clients/temporal.py index e10c97df5..902a75d65 100644 --- a/agents-api/agents_api/clients/temporal.py +++ b/agents-api/agents_api/clients/temporal.py @@ -46,3 +46,16 @@ async def run_embed_docs_task( task_queue="memory-task-queue", id=str(job_id), ) + + +async def run_truncation_task( + token_count_threshold: int, session_id: UUID, job_id: UUID +): + client = await get_client() + + await client.execute_workflow( + "TruncationWorkflow", + args=[str(session_id), token_count_threshold], + task_queue="memory-task-queue", + id=str(job_id), + ) diff --git a/agents-api/agents_api/routers/sessions/session.py b/agents-api/agents_api/routers/sessions/session.py index bf72ff677..da9121366 100644 --- a/agents-api/agents_api/routers/sessions/session.py +++ b/agents-api/agents_api/routers/sessions/session.py @@ -4,6 +4,7 @@ from json import JSONDecodeError from typing import Callable from uuid import uuid4 +from functools import partial from dataclasses import dataclass from openai.types.chat.chat_completion import ChatCompletion @@ -12,9 +13,10 @@ import litellm from litellm import acompletion -from ...autogen.openapi_model import InputChatMLMessage, Tool, DocIds, Role +from ...autogen.openapi_model import InputChatMLMessage, Tool, DocIds from ...clients.embed import embed from ...clients.temporal import run_summarization_task +from ...clients.temporal import run_truncation_task from ...clients.worker.types import ChatML from ...common.exceptions.sessions import SessionNotFoundError from ...common.protocol.entries import Entry @@ -156,29 +158,6 @@ def rm_user_assistant(m): raise InputTooBigError(token_count, summarization_tokens_threshold) - def _truncate_entries( - self, messages: list[Entry], token_count_threshold: int - ) -> list[Entry]: - if not len(messages): - return messages - - result: list[Entry] = [] - token_cnt, offset = 0, 0 - if messages[0].role == Role.system: - token_cnt, offset = messages[0].token_count, 1 - - for m in reversed(messages[offset:]): - token_cnt += m.token_count - if token_cnt < token_count_threshold: - result.append(m) - else: - break - - if offset: - result.append(messages[0]) - - return list(reversed(result)) - async def run( self, new_input, settings: Settings ) -> tuple[ChatCompletion, Entry, Callable | None, DocIds]: @@ -483,22 +462,22 @@ async def backward( ) entries.append(new_entry) - summarization_task = None + bg_task = None if ( final_settings.token_budget is not None and total_tokens >= final_settings.token_budget ): if final_settings.context_overflow == "truncate": - entries = self._truncate_entries(entries, final_settings.token_budget) + bg_task = partial(run_truncation_task, final_settings.token_budget) elif final_settings.context_overflow == "adaptive": - summarization_task = run_summarization_task + bg_task = run_summarization_task else: raise PromptTooBigError(total_tokens, final_settings.token_budget) add_entries_query(entries) - return summarization_task + return bg_task class PlainCompletionSession(BaseSession): diff --git a/agents-api/agents_api/workflows/truncation.py b/agents-api/agents_api/workflows/truncation.py new file mode 100644 index 000000000..6057eec38 --- /dev/null +++ b/agents-api/agents_api/workflows/truncation.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + + +from datetime import timedelta +from temporalio import workflow + +with workflow.unsafe.imports_passed_through(): + from ..activities.truncation import truncation + + +@workflow.defn +class TruncationWorkflow: + @workflow.run + async def run(self, session_id: str, token_count_threshold: int) -> None: + return await workflow.execute_activity( + truncation, + args=[session_id, token_count_threshold], + schedule_to_close_timeout=timedelta(seconds=600), + ) diff --git a/agents-api/tests/test_sessions_context.py b/agents-api/tests/test_activities.py similarity index 56% rename from agents-api/tests/test_sessions_context.py rename to agents-api/tests/test_activities.py index 0c4280dcb..a5cca1d29 100644 --- a/agents-api/tests/test_sessions_context.py +++ b/agents-api/tests/test_activities.py @@ -3,11 +3,11 @@ from ward import test from agents_api.common.protocol.entries import Entry from agents_api.autogen.openapi_model import Role -from tests.fixtures import base_session +from agents_api.activities.truncation import get_extra_entry_ids -@test("truncate entries, do not strip system message") -def _(session=base_session): +@test("get extra entries, do not strip system message") +def _(): session_ids = [uuid.uuid4()] * 3 entry_ids = [uuid.uuid4()] * 3 now = time.time() @@ -38,32 +38,14 @@ def _(session=base_session): ), ] - expected_result = [ - Entry( - entry_id=entry_ids[0], - session_id=session_ids[0], - role=Role.system, - content="content 1", - created_at=now, - timestamp=now, - ), - Entry( - entry_id=entry_ids[2], - session_id=session_ids[2], - role=Role.user, - content="content 3", - created_at=now, - timestamp=now, - ), - ] threshold = sum([m.token_count for m in messages]) - 1 - result = session._truncate_entries(messages, threshold) + result = get_extra_entry_ids(messages, threshold) - assert result == expected_result + assert result == {entry_ids[1]} -@test("truncate entries") -def _(session=base_session): +@test("get extra entries") +def _(): session_ids = [uuid.uuid4()] * 3 entry_ids = [uuid.uuid4()] * 3 now = time.time() @@ -94,33 +76,15 @@ def _(session=base_session): ), ] - expected_result = [ - Entry( - entry_id=entry_ids[1], - session_id=session_ids[1], - role=Role.assistant, - content="content 2", - created_at=now, - timestamp=now, - ), - Entry( - entry_id=entry_ids[2], - session_id=session_ids[2], - role=Role.user, - content="content 3", - created_at=now, - timestamp=now, - ), - ] threshold = sum([m.token_count for m in messages]) - 1 - result = session._truncate_entries(messages, threshold) + result = get_extra_entry_ids(messages, threshold) - assert result == expected_result + assert result == {entry_ids[0]} -@test("truncate entries, no change if empty") -def _(session=base_session): +@test("get extra entries, no change if empty") +def _(): messages = [] - result = session._truncate_entries(messages, 1) + result = get_extra_entry_ids(messages, 1) assert result == [] From 2e20a4cf1dfbfb23469da2b0a4b6a85418503b4a Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 18:17:05 +0300 Subject: [PATCH 29/43] fix: Add truncation workflow to registry --- agents-api/agents_api/worker/__main__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/agents-api/agents_api/worker/__main__.py b/agents-api/agents_api/worker/__main__.py index 587bab7a1..02a588c1a 100644 --- a/agents-api/agents_api/worker/__main__.py +++ b/agents-api/agents_api/worker/__main__.py @@ -18,6 +18,7 @@ from ..activities.relationship_summary import relationship_summary from ..activities.salient_questions import salient_questions from ..activities.embed_docs import embed_docs +from ..activities.truncation import truncation from ..env import ( temporal_endpoint, temporal_task_queue, @@ -33,6 +34,7 @@ from ..workflows.mem_rating import MemRatingWorkflow from ..workflows.relationship_summary import RelationshipSummaryWorkflow from ..workflows.salient_questions import SalientQuestionsWorkflow +from ..workflows.truncation import TruncationWorkflow async def main(): @@ -72,6 +74,7 @@ async def main(): RelationshipSummaryWorkflow, SalientQuestionsWorkflow, EmbedDocsWorkflow, + TruncationWorkflow, ], activities=[ summarization, @@ -82,6 +85,7 @@ async def main(): relationship_summary, salient_questions, embed_docs, + truncation, ], ) From c824516f8a4f778076ea61307fd2aaa25b70217d Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 18:23:59 +0300 Subject: [PATCH 30/43] fix: Fix deleting query --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 8fdb9ee72..05ab7abdf 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -65,7 +65,7 @@ def delete_entries_query(session_id: UUID) -> tuple[str, dict]: @cozo_query def delete_entries_by_ids_query(entry_ids: list[UUID]) -> tuple[str, dict]: - entry_ids = [f'to_uuid("{id}")' for id in entry_ids] + entry_ids = [[f'to_uuid("{id}")'] for id in entry_ids] query = """ { From 4e7798a8db61991d5d396f0106513c7c36c5fd67 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 19:31:59 +0300 Subject: [PATCH 31/43] fix: Remove truncated entries --- .../agents_api/activities/truncation.py | 50 +++++++++---------- .../agents_api/models/entry/delete_entries.py | 49 ++++++++---------- agents-api/tests/test_activities.py | 12 ++--- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/agents-api/agents_api/activities/truncation.py b/agents-api/agents_api/activities/truncation.py index f264a18ee..961bf96da 100644 --- a/agents-api/agents_api/activities/truncation.py +++ b/agents-api/agents_api/activities/truncation.py @@ -1,18 +1,16 @@ from uuid import UUID from temporalio import activity from agents_api.models.entry.entries_summarization import get_toplevel_entries_query -from agents_api.models.entry.delete_entries import delete_entries_by_ids_query +from agents_api.models.entry.delete_entries import delete_entries from agents_api.autogen.openapi_model import Role from agents_api.common.protocol.entries import Entry -def get_extra_entry_ids( - messages: list[Entry], token_count_threshold: int -) -> set[Entry]: +def get_extra_entries(messages: list[Entry], token_count_threshold: int) -> list[Entry]: if not len(messages): return messages - result: list[UUID] = [] + result: list[Entry] = [] token_cnt, offset = 0, 0 if messages[0].role == Role.system: token_cnt, offset = messages[0].token_count, 1 @@ -22,34 +20,32 @@ def get_extra_entry_ids( if token_cnt < token_count_threshold: continue else: - result.append(m.id) + result.append(m) - return set(result) + return result @activity.defn async def truncation(session_id: str, token_count_threshold: int) -> None: session_id = UUID(session_id) - delete_entries_by_ids_query( - list( - get_extra_entry_ids( - [ - Entry( - entry_id=row["entry_id"], - session_id=session_id, - source=row["source"], - role=Role(row["role"]), - name=row["name"], - content=row["content"], - created_at=row["created_at"], - timestamp=row["timestamp"], - ) - for _, row in get_toplevel_entries_query( - session_id=session_id - ).iterrows() - ], - token_count_threshold, - ) + delete_entries( + get_extra_entries( + [ + Entry( + entry_id=row["entry_id"], + session_id=session_id, + source=row["source"], + role=Role(row["role"]), + name=row["name"], + content=row["content"], + created_at=row["created_at"], + timestamp=row["timestamp"], + ) + for _, row in get_toplevel_entries_query( + session_id=session_id + ).iterrows() + ], + token_count_threshold, ), ) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 05ab7abdf..df5ff0d77 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -4,6 +4,7 @@ from ..utils import cozo_query +from ...common.protocol.entries import Entry @cozo_query @@ -64,47 +65,37 @@ def delete_entries_query(session_id: UUID) -> tuple[str, dict]: @cozo_query -def delete_entries_by_ids_query(entry_ids: list[UUID]) -> tuple[str, dict]: - entry_ids = [[f'to_uuid("{id}")'] for id in entry_ids] +def delete_entries(entries: list[Entry]) -> tuple[str, dict]: + entry_keys = [ + [ + f'to_uuid("{e.id}")', + f'to_uuid("{e.session_id}")', + e.source, + e.role.value, + e.name, + ] + for e in entries + ] query = """ { - input[entry_id] <- $entry_ids - ?[ - session_id, entry_id, + session_id, + source, role, name, - content, - source, - token_count, - created_at, - timestamp, - ] := input[entry_id], - *entries{ - session_id, - entry_id, - role, - name, - content, - source, - token_count, - created_at, - timestamp, - } + ] <- $entry_keys :delete entries { - session_id, entry_id, + session_id, + source, role, name, - content, - source, - token_count, - created_at, - timestamp, } + + :returning }""" - return (query, {"entry_ids": entry_ids}) + return (query, {"entry_keys": entry_keys}) diff --git a/agents-api/tests/test_activities.py b/agents-api/tests/test_activities.py index a5cca1d29..092c1b0a0 100644 --- a/agents-api/tests/test_activities.py +++ b/agents-api/tests/test_activities.py @@ -3,7 +3,7 @@ from ward import test from agents_api.common.protocol.entries import Entry from agents_api.autogen.openapi_model import Role -from agents_api.activities.truncation import get_extra_entry_ids +from agents_api.activities.truncation import get_extra_entries @test("get extra entries, do not strip system message") @@ -39,9 +39,9 @@ def _(): ] threshold = sum([m.token_count for m in messages]) - 1 - result = get_extra_entry_ids(messages, threshold) + result = get_extra_entries(messages, threshold) - assert result == {entry_ids[1]} + assert result == [messages[1]] @test("get extra entries") @@ -77,14 +77,14 @@ def _(): ] threshold = sum([m.token_count for m in messages]) - 1 - result = get_extra_entry_ids(messages, threshold) + result = get_extra_entries(messages, threshold) - assert result == {entry_ids[0]} + assert result == [messages[0]] @test("get extra entries, no change if empty") def _(): messages = [] - result = get_extra_entry_ids(messages, 1) + result = get_extra_entries(messages, 1) assert result == [] From e696951c80c5f47f59a72141abf3aa87598d2455 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 19:38:33 +0300 Subject: [PATCH 32/43] fix: Convert role to string only if needed --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index df5ff0d77..af707f071 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -71,7 +71,7 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: f'to_uuid("{e.id}")', f'to_uuid("{e.session_id}")', e.source, - e.role.value, + e.role.value if hasattr(e.role, "value") else e.role, e.name, ] for e in entries From f38bf3e83d1bd83a62fbd4d11f646271300cfdf7 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 19:45:43 +0300 Subject: [PATCH 33/43] fix: Replace delete by rm --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index af707f071..582a61b09 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -87,7 +87,7 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: name, ] <- $entry_keys - :delete entries { + :rm entries { entry_id, session_id, source, From d313315f72b63ece2f6a7c69f876368fcbdfdc5c Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 19:56:26 +0300 Subject: [PATCH 34/43] fix: Fix entries deleting logic --- .../agents_api/models/entry/delete_entries.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 582a61b09..3030d2c49 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -5,6 +5,7 @@ from ..utils import cozo_query from ...common.protocol.entries import Entry +from ...common.utils.messages import content_to_json @cozo_query @@ -73,6 +74,11 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: e.source, e.role.value if hasattr(e.role, "value") else e.role, e.name, + content_to_json(e.content), + e.token_count, + e.tokenizer, + e.created_at, + e.timestamp, ] for e in entries ] @@ -85,14 +91,24 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: source, role, name, + content, + token_count, + tokenizer, + created_at, + timestamp, ] <- $entry_keys - :rm entries { + :delete entries { entry_id, session_id, source, role, name, + content, + token_count, + tokenizer, + created_at, + timestamp, } :returning From 9b58614af8584c801ea4ada834eb023cba5cdb5b Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Wed, 5 Jun 2024 20:05:23 +0300 Subject: [PATCH 35/43] fix: Set name to None if absent --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 3030d2c49..f530d1573 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -73,7 +73,7 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: f'to_uuid("{e.session_id}")', e.source, e.role.value if hasattr(e.role, "value") else e.role, - e.name, + e.name or None, content_to_json(e.content), e.token_count, e.tokenizer, From 08f6295014ff5107dabbb155b38a612f41524f53 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 08:43:38 +0300 Subject: [PATCH 36/43] fix: Make deleting query accept UUID as a string --- .../agents_api/activities/truncation.py | 6 +-- .../agents_api/models/entry/delete_entries.py | 42 +++++++++---------- agents-api/tests/test_activities.py | 4 +- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/agents-api/agents_api/activities/truncation.py b/agents-api/agents_api/activities/truncation.py index 961bf96da..cbe0ee730 100644 --- a/agents-api/agents_api/activities/truncation.py +++ b/agents-api/agents_api/activities/truncation.py @@ -6,11 +6,11 @@ from agents_api.common.protocol.entries import Entry -def get_extra_entries(messages: list[Entry], token_count_threshold: int) -> list[Entry]: +def get_extra_entries(messages: list[Entry], token_count_threshold: int) -> list[UUID]: if not len(messages): return messages - result: list[Entry] = [] + result: list[UUID] = [] token_cnt, offset = 0, 0 if messages[0].role == Role.system: token_cnt, offset = messages[0].token_count, 1 @@ -20,7 +20,7 @@ def get_extra_entries(messages: list[Entry], token_count_threshold: int) -> list if token_cnt < token_count_threshold: continue else: - result.append(m) + result.append(m.id) return result diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index f530d1573..d57121ed2 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -4,8 +4,6 @@ from ..utils import cozo_query -from ...common.protocol.entries import Entry -from ...common.utils.messages import content_to_json @cozo_query @@ -66,25 +64,11 @@ def delete_entries_query(session_id: UUID) -> tuple[str, dict]: @cozo_query -def delete_entries(entries: list[Entry]) -> tuple[str, dict]: - entry_keys = [ - [ - f'to_uuid("{e.id}")', - f'to_uuid("{e.session_id}")', - e.source, - e.role.value if hasattr(e.role, "value") else e.role, - e.name or None, - content_to_json(e.content), - e.token_count, - e.tokenizer, - e.created_at, - e.timestamp, - ] - for e in entries - ] - +def delete_entries(entry_ids: list[UUID]) -> tuple[str, dict]: query = """ { + input[entry_id_str] <- $entry_keys + ?[ entry_id, session_id, @@ -96,8 +80,22 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: tokenizer, created_at, timestamp, - ] <- $entry_keys - + ] := + input[entry_id_str], + entry_id = to_uuid(entry_id_str), + *entries { + entry_id, + session_id, + source, + role, + name, + content, + token_count, + tokenizer, + created_at, + timestamp, + } + :delete entries { entry_id, session_id, @@ -114,4 +112,4 @@ def delete_entries(entries: list[Entry]) -> tuple[str, dict]: :returning }""" - return (query, {"entry_keys": entry_keys}) + return (query, {"entry_ids": entry_ids}) diff --git a/agents-api/tests/test_activities.py b/agents-api/tests/test_activities.py index 092c1b0a0..70581c378 100644 --- a/agents-api/tests/test_activities.py +++ b/agents-api/tests/test_activities.py @@ -41,7 +41,7 @@ def _(): threshold = sum([m.token_count for m in messages]) - 1 result = get_extra_entries(messages, threshold) - assert result == [messages[1]] + assert result == [messages[1].id] @test("get extra entries") @@ -79,7 +79,7 @@ def _(): threshold = sum([m.token_count for m in messages]) - 1 result = get_extra_entries(messages, threshold) - assert result == [messages[0]] + assert result == [messages[0].id] @test("get extra entries, no change if empty") From 8f8b604a4af2c3fb343fae6e43973aced0984a5d Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 08:51:28 +0300 Subject: [PATCH 37/43] fix: Convert UUIDs to strings --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index d57121ed2..23aabc8a1 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -112,4 +112,4 @@ def delete_entries(entry_ids: list[UUID]) -> tuple[str, dict]: :returning }""" - return (query, {"entry_ids": entry_ids}) + return (query, {"entry_ids": [str(id) for id in entry_ids]}) From 9f74d34d8481da95ce535ae072182c0cdf715953 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 08:55:02 +0300 Subject: [PATCH 38/43] fix: Fix query parameter name --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 23aabc8a1..6aa9b1672 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -67,7 +67,7 @@ def delete_entries_query(session_id: UUID) -> tuple[str, dict]: def delete_entries(entry_ids: list[UUID]) -> tuple[str, dict]: query = """ { - input[entry_id_str] <- $entry_keys + input[entry_id_str] <- $entry_ids ?[ entry_id, From 97d265d86d474a03c0778319b00c4e361c1f1473 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 08:58:08 +0300 Subject: [PATCH 39/43] fix: Convert input to array of arrays --- agents-api/agents_api/models/entry/delete_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents-api/agents_api/models/entry/delete_entries.py b/agents-api/agents_api/models/entry/delete_entries.py index 6aa9b1672..7bdb2dce7 100644 --- a/agents-api/agents_api/models/entry/delete_entries.py +++ b/agents-api/agents_api/models/entry/delete_entries.py @@ -112,4 +112,4 @@ def delete_entries(entry_ids: list[UUID]) -> tuple[str, dict]: :returning }""" - return (query, {"entry_ids": [str(id) for id in entry_ids]}) + return (query, {"entry_ids": [[str(id)] for id in entry_ids]}) From 2c4ceb622fd760c3293435e55a256c39dba95f16 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 10:44:31 +0300 Subject: [PATCH 40/43] fix: Make entries indices zro-based --- agents-api/agents_api/activities/summarization.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index d54c440cb..69bda17df 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -209,6 +209,7 @@ async def summarization(session_id: str) -> None: session_id=session_id, new_entry=new_entry, old_entry_ids=[ - UUID(entries[idx]["entry_id"], version=4) for idx in msg["summarizes"] + UUID(entries[idx - 1]["entry_id"], version=4) + for idx in msg["summarizes"] ], ) From ddbf7d00bce6f733cce559de5dd7a0692f7f4942 Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Thu, 6 Jun 2024 17:02:19 +0300 Subject: [PATCH 41/43] fix: Customize summarization model via environment variable --- agents-api/agents_api/activities/summarization.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index 69bda17df..4740cb43a 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -178,7 +178,9 @@ async def summarization(session_id: str) -> None: trim_messages(entries, model=summarization_model_name), get_entities(entries, model=summarization_model_name), ) - summarized = await summarize_messages(trimmed_messages) + summarized = await summarize_messages( + trimmed_messages, model=summarization_model_name + ) ts_delta = (entries[1]["timestamp"] - entries[0]["timestamp"]) / 2 new_entities_entry = Entry( session_id=session_id, From 9a4935af327e9d843abffede475c90efde465b6d Mon Sep 17 00:00:00 2001 From: Dmitry Paramonov Date: Sat, 8 Jun 2024 14:58:26 +0300 Subject: [PATCH 42/43] chore: Re-arrange operations on dialog entries --- .../agents_api/activities/summarization.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/agents-api/agents_api/activities/summarization.py b/agents-api/agents_api/activities/summarization.py index 4740cb43a..e44fc455d 100644 --- a/agents-api/agents_api/activities/summarization.py +++ b/agents-api/agents_api/activities/summarization.py @@ -174,13 +174,11 @@ async def summarization(session_id: str) -> None: assert len(entries) > 0, "no need to summarize on empty entries list" - trimmed_messages, entities = await asyncio.gather( - trim_messages(entries, model=summarization_model_name), + summarized, entities = await asyncio.gather( + summarize_messages(entries, model=summarization_model_name), get_entities(entries, model=summarization_model_name), ) - summarized = await summarize_messages( - trimmed_messages, model=summarization_model_name - ) + trimmed_messages = await trim_messages(summarized, model=summarization_model_name) ts_delta = (entries[1]["timestamp"] - entries[0]["timestamp"]) / 2 new_entities_entry = Entry( session_id=session_id, @@ -197,13 +195,17 @@ async def summarization(session_id: str) -> None: old_entry_ids=entities_entry_ids, ) - for msg in summarized: + trimmed_map = { + m["index"]: m["content"] for m in trimmed_messages if m.get("index") is not None + } + + for idx, msg in enumerate(summarized): new_entry = Entry( session_id=session_id, source="summarizer", role="system", name="information", - content=msg["content"], + content=trimmed_map.get(idx, msg["content"]), timestamp=entries[-1]["timestamp"] + 0.01, ) From 43990aba0f2e5c41e4f1f0aca35dc6ef0e06ce56 Mon Sep 17 00:00:00 2001 From: Diwank Tomer Date: Mon, 10 Jun 2024 23:38:31 -0700 Subject: [PATCH 43/43] deps: poetry lock on agents-api and python sdk Signed-off-by: Diwank Tomer --- agents-api/poetry.lock | 5 ++--- sdks/python/poetry.lock | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/agents-api/poetry.lock b/agents-api/poetry.lock index 0c755c0f7..8f4784f7c 100644 --- a/agents-api/poetry.lock +++ b/agents-api/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -4065,7 +4065,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -4872,7 +4871,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} typing-extensions = ">=4.6.0" [package.extras] diff --git a/sdks/python/poetry.lock b/sdks/python/poetry.lock index d141296e3..fb946ac85 100644 --- a/sdks/python/poetry.lock +++ b/sdks/python/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -2362,7 +2362,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},