Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation History Trimming with max_tokens and max_history_length #8

Merged
merged 4 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions agentai/conversation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import threading
from typing import List, Optional

import tiktoken
from pydantic import BaseModel
from termcolor import colored

Expand All @@ -11,7 +13,7 @@ class Message(BaseModel):


class Conversation:
def __init__(self, history: List[Message] = [], id: Optional[str] = None):
def __init__(self, history: List[Message] = [], id: Optional[str] = None, max_history_length: int = 20):
NirantK marked this conversation as resolved.
Show resolved Hide resolved
self.history: List[Message] = history
self.role_to_color = {
"system": "red",
Expand All @@ -20,19 +22,55 @@ def __init__(self, history: List[Message] = [], id: Optional[str] = None):
"function": "magenta",
}
self.id = id
self.max_history_length = max_history_length

def add_message(self, role: str, content: str, name: Optional[str] = None):
def add_message(self, role: str, content: str, name: Optional[str] = None) -> None:
message_dict = {"role": role, "content": content}
if name is not None:
if name:
message_dict["name"] = name
message = Message(**message_dict)
self.history.append(message)
self.trim_history()

def display_conversation(self):
def display_conversation(self) -> None:
for message in self.history:
print(
colored(
f"{message.role}: {message.content}\n\n",
self.role_to_color[message.role],
self.role_to_color[message.role.lower()],
)
)

def trim_history(self) -> None:
"Function to keep the message history from growing too large"
if len(self.history) > self.max_history_length:
self.history = self.history[-self.max_history_length :]

def trim_history_by_tokens(self, max_tokens: int) -> None:
"""Function to keep the message history based on the number of tokens
This is important to keep the message history crisp to not flood over the
max_tokens limit of the AI models and give lee-way to the user prompt
"""
local = threading.local()
try:
enc = local.gpt2enc
except AttributeError:
enc = tiktoken.get_encoding("gpt2")
local.gpt2enc = enc
Comment on lines +45 to +50
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check and confirm if the GPT4 tokeniser is same as gpt2? From what I recall, this is wrong. The tokeniser depends on the LLM.


total_tokens = 0
for i in range(len(self.history) - 1, -1, -1):
# Iterate over the messages in reverse order - from the latest to the oldest messages
message = self.history[i] # Message(role='User', content='I appreciate that. Take care too!', name=None)
content = message.content
tokens = len(enc.encode(content))
total_tokens += tokens
if total_tokens > max_tokens:
# Trim the history inplace to keep the total tokens under max_tokens
self.history = self.history[i + 1 :]
break

def get_history(self, max_tokens=100) -> List[Message]:
"""Function to get the conversation history based on the number of tokens"""
self.trim_history_by_tokens(max_tokens=max_tokens)
return self.history
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a utility wrapper. Would prefer to remove this and rename self.trim_history_by_tokens(max_tokens=max_tokens) to get_history instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done.

138 changes: 138 additions & 0 deletions docs/05_Conversation_History.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
{
NirantK marked this conversation as resolved.
Show resolved Hide resolved
NirantK marked this conversation as resolved.
Show resolved Hide resolved
"cells": [
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"\n",
"parent1_path = os.path.abspath('..') # Go one level up from the current notebook\n",
"sys.path.append(parent1_path)\n",
"\n",
"from agentai.conversation import Conversation"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "Conversation.__init__() got an unexpected keyword argument 'max_history_length'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[45], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[39m# Create a conversation object with a maximum history length of 20 messages\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m conversation \u001b[39m=\u001b[39m Conversation(max_history_length\u001b[39m=\u001b[39;49m\u001b[39m20\u001b[39;49m)\n\u001b[1;32m 4\u001b[0m \u001b[39m# Chatgpt Simulated conversations of different length\u001b[39;00m\n\u001b[1;32m 5\u001b[0m conversation\u001b[39m.\u001b[39madd_message(\u001b[39m\"\u001b[39m\u001b[39mUser\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mHello!\u001b[39m\u001b[39m\"\u001b[39m)\n",
"\u001b[0;31mTypeError\u001b[0m: Conversation.__init__() got an unexpected keyword argument 'max_history_length'"
]
}
],
"source": [
"# Create a conversation object with a maximum history length of 20 messages\n",
"conversation = Conversation(max_history_length=20)\n",
"\n",
"# Chatgpt Simulated conversations of different length\n",
"conversation.add_message(\"User\", \"Hello!\")\n",
"conversation.add_message(\"Assistant\", \"Hi there!\")\n",
"conversation.add_message(\"User\", \"How are you?\")\n",
"conversation.add_message(\"Assistant\", \"I'm doing well, thank you!\")\n",
"conversation.add_message(\"User\", \"That's great to hear!\")\n",
"conversation.add_message(\"Assistant\", \"Thank you! How can I assist you today?\")\n",
"conversation.add_message(\"User\", \"I have a recipe conundrum. I want to make something special for dinner.\")\n",
"conversation.add_message(\"Assistant\", \"That sounds fun! What type of cuisine are you interested in?\")\n",
"conversation.add_message(\"User\", \"I'd like to try making a Thai dish.\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"Excellent choice! How about trying to make Pad Thai? It's a popular Thai noodle dish.\",\n",
")\n",
"conversation.add_message(\"User\", \"Pad Thai sounds delicious! Do you have a recipe?\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"Certainly! Here's a simple Pad Thai recipe for you:\\n\\nIngredients:\\n- Rice noodles\\n- Tofu or your choice of protein\\n- Eggs\\n- Bean sprouts\\n- Chopped green onions\\n- Chopped peanuts\\n- Lime wedges\\n- Pad Thai sauce (made from tamarind paste, fish sauce, sugar, and chili flakes)\\n\\nInstructions:\\n1. Soak the rice noodles in warm water until they soften. Drain and set aside.\\n2. In a wok or large pan, stir-fry the tofu or protein until cooked. Push it to one side of the pan.\\n3. Crack the eggs into the pan and scramble them until they're nearly cooked.\\n4. Add the softened rice noodles to the pan and pour the Pad Thai sauce over them.\\n5. Toss everything together until the noodles are coated in the sauce.\\n6. Add bean sprouts and chopped green onions, continuing to stir-fry until they're tender.\\n7. Serve hot, garnished with chopped peanuts and lime wedges.\\n\\nEnjoy your Pad Thai!\",\n",
")\n",
"conversation.add_message(\"User\", \"Wow, thank you! I can't wait to try making it.\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"You're welcome! Cooking can be a delightful experience. If you have any more questions or need assistance with anything else, feel free to ask.\",\n",
")\n",
"conversation.add_message(\"User\", \"Sure thing! By the way, what's the weather like today?\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"I apologize, but as an AI language model, I don't have access to real-time data, including weather updates. You can check the weather forecast on a reliable website or a weather app for accurate information.\",\n",
")\n",
"conversation.add_message(\"User\", \"No problem. I have another question then. Can you tell me a joke?\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"Of course! Here's one for you: Why don't scientists trust atoms? Because they make up everything!\",\n",
")\n",
"conversation.add_message(\"User\", \"Haha, that's a good one! I needed that laugh. Thanks!\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"You're welcome! Laughter is the best medicine. If you ever need more jokes or anything else, I'm here to brighten your day!\",\n",
")\n",
"conversation.add_message(\n",
" \"User\",\n",
" \"That's very kind of you. Actually, I've been feeling a bit stressed lately.\",\n",
")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"I'm sorry to hear that. Stress can be challenging to deal with. Is there something specific bothering you, or do you need some general tips to manage stress?\",\n",
")\n",
"conversation.add_message(\"User\", \"I'd appreciate some tips on how to manage stress.\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"Of course! Here are some helpful tips:\\n1. Practice deep breathing or meditation to relax your mind and body.\\n2. Engage in physical activities like walking, jogging, or yoga to release endorphins.\\n3. Take breaks and do something you enjoy, like reading, listening to music, or spending time in nature.\\n4. Prioritize your tasks and break them into smaller, manageable steps.\\n5. Reach out to friends or family for support and talk about what's on your mind.\\n6. Get enough sleep to allow your body to recover and rejuvenate.\\n7. Consider trying relaxation techniques like progressive muscle relaxation or visualization.\\n8. Limit caffeine and alcohol consumption, as they can increase stress levels.\\n9. Learn to say no to tasks or commitments when you feel overwhelmed.\\n10. Seek professional help if you find that stress is significantly affecting your daily life.\\n\\nRemember, it's essential to take care of yourself, and don't hesitate to seek support when needed.\",\n",
")\n",
"conversation.add_message(\"User\", \"Thank you for the wonderful advice. I'll definitely give these tips a try.\")\n",
"conversation.add_message(\n",
" \"Assistant\",\n",
" \"You're welcome! I hope these tips help you find some relief from stress. If you have any more questions or need further assistance, don't hesitate to ask. Take care!\",\n",
")\n",
"conversation.add_message(\"User\", \"I appreciate that. Take care too!\")\n",
"conversation.add_message(\"Assistant\", \"Thank you! Have a fantastic day!\")\n",
"\n",
"# Get the current conversation history with a maximum token limit of 500\n",
"history = conversation.get_history(max_tokens=500)\n",
"conversation.display_conversation()\n",
"print(history)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "aditya",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
75 changes: 75 additions & 0 deletions docs/test_conversation_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import os
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks identical to the notebook? Let's keep only one copy of the logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The notebook didn't work. Was picking agentai library version and not the folder. So, had to use the python file to test things out

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pip install -e . might be worth looking into for local development

import sys

parent1_path = os.path.abspath('..') # Go one level up from the current notebook
sys.path.append(parent1_path)

from agentai.conversation import Conversation

# Create a conversation object with a maximum history length of 20 messages
conversation = Conversation(max_history_length=20)

# Chatgpt Simulated conversations of different length
conversation.add_message("User", "Hello!")
conversation.add_message("Assistant", "Hi there!")
conversation.add_message("User", "How are you?")
conversation.add_message("Assistant", "I'm doing well, thank you!")
conversation.add_message("User", "That's great to hear!")
conversation.add_message("Assistant", "Thank you! How can I assist you today?")
conversation.add_message("User", "I have a recipe conundrum. I want to make something special for dinner.")
conversation.add_message("Assistant", "That sounds fun! What type of cuisine are you interested in?")
conversation.add_message("User", "I'd like to try making a Thai dish.")
conversation.add_message(
"Assistant",
"Excellent choice! How about trying to make Pad Thai? It's a popular Thai noodle dish.",
)
conversation.add_message("User", "Pad Thai sounds delicious! Do you have a recipe?")
conversation.add_message(
"Assistant",
"Certainly! Here's a simple Pad Thai recipe for you:\n\nIngredients:\n- Rice noodles\n- Tofu or your choice of protein\n- Eggs\n- Bean sprouts\n- Chopped green onions\n- Chopped peanuts\n- Lime wedges\n- Pad Thai sauce (made from tamarind paste, fish sauce, sugar, and chili flakes)\n\nInstructions:\n1. Soak the rice noodles in warm water until they soften. Drain and set aside.\n2. In a wok or large pan, stir-fry the tofu or protein until cooked. Push it to one side of the pan.\n3. Crack the eggs into the pan and scramble them until they're nearly cooked.\n4. Add the softened rice noodles to the pan and pour the Pad Thai sauce over them.\n5. Toss everything together until the noodles are coated in the sauce.\n6. Add bean sprouts and chopped green onions, continuing to stir-fry until they're tender.\n7. Serve hot, garnished with chopped peanuts and lime wedges.\n\nEnjoy your Pad Thai!",
)
conversation.add_message("User", "Wow, thank you! I can't wait to try making it.")
conversation.add_message(
"Assistant",
"You're welcome! Cooking can be a delightful experience. If you have any more questions or need assistance with anything else, feel free to ask.",
)
conversation.add_message("User", "Sure thing! By the way, what's the weather like today?")
conversation.add_message(
"Assistant",
"I apologize, but as an AI language model, I don't have access to real-time data, including weather updates. You can check the weather forecast on a reliable website or a weather app for accurate information.",
)
conversation.add_message("User", "No problem. I have another question then. Can you tell me a joke?")
conversation.add_message(
"Assistant",
"Of course! Here's one for you: Why don't scientists trust atoms? Because they make up everything!",
)
conversation.add_message("User", "Haha, that's a good one! I needed that laugh. Thanks!")
conversation.add_message(
"Assistant",
"You're welcome! Laughter is the best medicine. If you ever need more jokes or anything else, I'm here to brighten your day!",
)
conversation.add_message(
"User",
"That's very kind of you. Actually, I've been feeling a bit stressed lately.",
)
conversation.add_message(
"Assistant",
"I'm sorry to hear that. Stress can be challenging to deal with. Is there something specific bothering you, or do you need some general tips to manage stress?",
)
conversation.add_message("User", "I'd appreciate some tips on how to manage stress.")
conversation.add_message(
"Assistant",
"Of course! Here are some helpful tips:\n1. Practice deep breathing or meditation to relax your mind and body.\n2. Engage in physical activities like walking, jogging, or yoga to release endorphins.\n3. Take breaks and do something you enjoy, like reading, listening to music, or spending time in nature.\n4. Prioritize your tasks and break them into smaller, manageable steps.\n5. Reach out to friends or family for support and talk about what's on your mind.\n6. Get enough sleep to allow your body to recover and rejuvenate.\n7. Consider trying relaxation techniques like progressive muscle relaxation or visualization.\n8. Limit caffeine and alcohol consumption, as they can increase stress levels.\n9. Learn to say no to tasks or commitments when you feel overwhelmed.\n10. Seek professional help if you find that stress is significantly affecting your daily life.\n\nRemember, it's essential to take care of yourself, and don't hesitate to seek support when needed.",
)
conversation.add_message("User", "Thank you for the wonderful advice. I'll definitely give these tips a try.")
conversation.add_message(
"Assistant",
"You're welcome! I hope these tips help you find some relief from stress. If you have any more questions or need further assistance, don't hesitate to ask. Take care!",
)
conversation.add_message("User", "I appreciate that. Take care too!")
conversation.add_message("Assistant", "Thank you! Have a fantastic day!")

# Get the current conversation history with a maximum token limit of 500
history = conversation.get_history(max_tokens=500)
conversation.display_conversation()
print(history)