fix bug, remove affect to originally functionality

This commit is contained in:
kevin666aa 2023-10-17 15:43:11 -04:00
parent ffb314cb08
commit ec9ff7fa14
3 changed files with 144 additions and 91 deletions

View File

@ -1,7 +1,7 @@
from typing import Callable, Dict, Optional, Union, Tuple, List, Any
from autogen import oai
from autogen import Agent, ConversableAgent
import copy
from autogen.token_count_utils import count_token
try:
@ -91,7 +91,11 @@ Rules:
# 1. use passed-in config and messages
# in function on_oai_limit of conversable agent, we will pass in llm_config from "config" parameter.
llm_config = self.llm_config if config is None else config
llm_config = copy.deepcopy(self.llm_config) if config is None else copy.deepcopy(config)
# remove functions from llm_config
if "functions" in llm_config:
del llm_config["functions"]
if llm_config is False:
return False, None
if messages is None:

View File

@ -99,12 +99,15 @@ class ConversableAgent(Agent):
Please refer to [Completion.create](/docs/reference/oai/completion#create)
for available options.
To disable llm-based auto reply, set to False.
compress_config (dict or False): config for compression before oai_reply. Default to None, meaning no compression will be used and the conversation will terminate when the token count exceeds the limit.
You should contain the following keys:
"agent" (Optional, "Agent", default to CompressionAgent): the agent to call before oai_reply. the `generate_reply` method from this Agent will be called.
"trigger_count" (Optional, float, int, default to 0.7): the threshold to trigger compression. If a float between (0, 1], it is the percentage of token used. if a int, it is the number of tokens used.
"async" (Optional, bool, default to False): whether to compress asynchronously.
"broadcast" (Optional, bool, default to True): whether to update the compressed message history to sender.
compress_config (dict or False): config for compression before oai_reply. Default to None, meaning no compression will be used and
the conversation will terminate when the token count exceeds the limit. You should contain the following keys:
- "mode" (Optional, str, default to "COMPRESS"): Choose from ["COMPRESS", "TERMINATE"]. "COMPRESS": enable the compression agent.
"TERMINATE": terminate the conversation when the token count exceeds the limit.
- "agent" (Optional, "Agent", default CompressionAgent): the agent to call before oai_reply. the `generate_reply` method from this Agent will be called.
- "trigger_count" (Optional, float, int, default to 0.7): the threshold to trigger compression.
If a float between (0, 1], it is the percentage of token used. if a int, it is the number of tokens used.
- "async" (Optional, bool, default to False): whether to compress asynchronously.
- "broadcast" (Optional, bool, default to True): whether to update the compressed message history to sender.
default_auto_reply (str or dict or None): default auto reply when no code execution or llm-based reply is generated.
"""
super().__init__(name)
@ -137,7 +140,7 @@ class ConversableAgent(Agent):
if compress_config is True:
self.compress_config = {}
if not isinstance(compress_config, dict):
raise ValueError("compress_config must be a dict or False.")
raise ValueError("compress_config must be a dict or 'False'.")
# convert trigger_count to int, default to 0.7
trigger_count = compress_config.get("trigger_count", 0.7)
@ -146,16 +149,24 @@ class ConversableAgent(Agent):
else:
trigger_count = int(trigger_count)
from .contrib.compression_agent import CompressionAgent
assert compress_config.get("mode", "COMPRESS") in [
"COMPRESS",
"TERMINATE",
], "compress_config['mode'] must be 'COMPRESS' or 'TERMINATE'"
if compress_config.get("mode", "COMPRESS") == "TERMINATE":
self.compress_config = compress_config
else:
from .contrib.compression_agent import CompressionAgent
self.compress_config = {
"agent": compress_config.get(
"agent", CompressionAgent(llm_config=llm_config)
), # TODO: llm_config to pass in here?
"trigger_count": trigger_count,
"async": compress_config.get("async", False), # TODO: support async compression
"broadcast": compress_config.get("broadcast", True),
}
self.compress_config = {
"mode": "COMPRESS",
"agent": compress_config.get(
"agent", CompressionAgent(llm_config=llm_config)
), # TODO: llm_config to pass in here?
"trigger_count": trigger_count,
"async": compress_config.get("async", False), # TODO: support async compression
"broadcast": compress_config.get("broadcast", True),
}
else:
self.compress_config = False
@ -664,16 +675,16 @@ class ConversableAgent(Agent):
) -> Tuple[bool, Union[str, Dict, None]]:
"""(Experimental) Compress previous messages when a threshold of tokens is reached."""
llm_config = self.llm_config if config is None else config
if llm_config is False:
# Only apply when this is a LLM-based agent (has llm_config)
if llm_config is False or self.compress_config is False:
# Only apply when this is a LLM-based agent (has llm_config), and compression is enabled.
return False, None
if messages is None:
messages = self._oai_messages[sender]
# if compress_config is None, no compression will be used and the conversation will terminate when the token count exceeds the limit.
# if mode is TERMINATE, terminate the agent if no token left.
token_used = self.compute_init_token_count() + count_token(messages, llm_config["model"])
max_token = get_max_token_limit(llm_config["model"])
if not self.compress_config:
max_token = max(get_max_token_limit(llm_config["model"]), llm_config.get("max_token", 0))
if self.compress_config["mode"] == "TERMINATE":
if max_token - token_used <= 0:
# Teminate if no token left.
print(

View File

@ -13,24 +13,25 @@
"source": [
"# Auto Generated Agent Chat: Convesations with Chat History Compression Enabled (Experimental)\n",
"\n",
"AutoGen offers conversable agents powered by LLM, tools, or humans, which can be used to perform tasks collectively via automated chat. This framwork allows tool use and human participance through multi-agent conversation. Please find documentation about this feature [here](https://microsoft.github.io/autogen/docs/Use-Cases/agent_chat).\n",
"AutoGen offers conversable agents powered by LLM, tools, or humans, which can be used to perform tasks collectively via automated chat. This framework allows tool use and human participance through multi-agent conversation. Please find documentation about this feature [here](https://microsoft.github.io/autogen/docs/Use-Cases/agent_chat).\n",
"\n",
"In this notebook, we demonstrate how to enable compression of history messages for `AssistantAgent`. By setting `compress_config=True/False` when initializing an `AssistantAgent`, you can turn on/off the compression feature. We will count token usages before sending requests to the OpenAI model. By default, the conversation will be terminated directly if the total token usage exceeds the maximum token usage allowed by the model, to avoid the token limit error from OpenAI API. If compression is enabled, we will compress the history messages if the total token usage exceeds a pre-set threshold. \n",
"In this notebook, we demonstrate how to enable compression of history messages for `AssistantAgent`. By setting `compress_config` when initializing an `AssistantAgent`, you can turn on/off the compression feature. By default (`compress_config=False`), compression is disabled and the originally functionality of `AssistantAgent` is preserved. Several cases with compression:\n",
"- Case 1: Initialize with `compress_config=True`, compression is enabled with default settings.\n",
"- Case 2: Initialize with dict `compress_config={\"mode\": \"COMPRESS\", \"trigger_count\": <your pre-set number>}`: compression is enabled, with trigger_count set to your pre-set number.\n",
"- Case 3: Initialize with dict `compress_config={\"mode\": \"TERMINATE\"}`: no compression will be performed. However, we will count token usages before sending requests to the OpenAI model. The conversation will be terminated directly if the total token usage exceeds the maximum token usage allowed by the model (to avoid the token limit error from OpenAI API).\n",
"- Case 4: Initialize with dict `compress_config={\"mode\": \"COMPRESS\", \"agent\": <A customized agent for compression>, \"trigger_count\" : <your pre-set amount>}`: the `generate_reply` function from your customized agent will be called on trigger count and the return is assumed to new set of messages after compression.\n",
"\n",
"By adjusting `trigger_count`, you can decide when to compress the history messages based on existing tokens. (Default: 0.7):\n",
"```Python\n",
"# If all history messages have more than 600 tokens, compress them\n",
"compress_config = {\"trigger_count\": 600}\n",
"1. If all history messages have more than 600 tokens, compress them: {\"mode\": \"COMPRESS\", \"trigger_count\": 600}\n",
"2. If this is a float number between 0 and 1, it is interpreted as ratio of max tokens allowed by the model. For example the AssistantAgent uses gpt-4 with max tokens 8192, the trigger_count = 0.7 * 8192 = 5734.4: `compress_config = {\"mode\": \"COMPRESS\", \"trigger_count\": 0.7}`.\n",
"\n",
"# If this is a float number between 0 and 1, it is interpreted as ratio of max tokens allowed by the model. For example the AssistantAgent uses gpt-4 with max tokens 8192, the trigger_count = 0.7 * 8192 = 5734.4\n",
"compress_config = {\"trigger_count\": 0.7}\n",
"```\n",
"\n",
"Currently, our compression logic is as follows:\n",
"Currently, our compression logic (from Case 1 and 2) is as follows:\n",
"1. We will leave the first user message (as well as system prompts) and compress the rest of the history messages.\n",
"2. The summary is performed in a per-message basis, with the role of the messages (See compressed content in example below).\n",
"\n",
"Note: **For now, the compression feature is not well supported for groupchat**. If you initialize an `AssistantAgent` in a groupchat with compression, the compressed cannot be broadcast to all other agents in the groupchat. This will be addressed in a future release.\n",
"## Limitations\n",
"- **For now, the compression feature is not well supported for groupchat**. If you initialize an `AssistantAgent` in a groupchat with compression, the compressed cannot be broadcast to all other agents in the groupchat. If you will to use this feature in groupchat, extra cost will be incurred since compression will be performed at per-agent basis.\n",
"- We do not support async compression for now.\n",
"\n",
"## Requirements\n",
"\n",
@ -118,7 +119,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [
{
@ -151,7 +152,13 @@
"Problem:\n",
"Find all $x$ that satisfy the inequality $(2x+10)(x+3)<(3x+9)(x+8)$. Express your answer in interval notation.\n",
"\n",
"--------------------------------------------------------------------------------\n",
"--------------------------------------------------------------------------------\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33massistant\u001b[0m (to mathproxyagent):\n",
"\n",
"The key idea to solve the problem is to simplify the inequality expressions, find out when the inequality is equal to zero, check the sign of the inequality, and finally state the solution in an interval notation. \n",
@ -249,45 +256,52 @@
"\n",
"##USER## The simplified function is $(-x - 14)*(x + 3)$ and its roots are [-14, -3]. \u001b[35m\n",
"********************************************************************************\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 324 After: 211 | Total prompt token count after compression: 525\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 324 After: 209 | Total prompt token count after compression: 523\u001b[0m\n",
"--------------------------------------------------------------------------------\n",
"\u001b[33massistant\u001b[0m (to mathproxyagent):\n",
"\n",
"Good. Now, let's divide the x-axis into three intervals using the roots [-14, -3], which are (-∞, -14), (-14, -3), and (-3, +∞). We will choose a test point from each interval and substitute it into the inequality to determine whether the inequality holds. If it holds, that interval is part of the solution.\n",
"Great, now we have the roots -14 and -3.\n",
"\n",
"Given these roots, we have divided the x-axis into three intervals: (-inf, -14), (-14, -3), (-3, inf). \n",
"\n",
"We will select one value from each interval and check whether the inequality (-x - 14)*(x + 3) < 0 holds true. \n",
"\n",
"As we are working with inequalities, remember:\n",
"1. If the inequality is strictly < or >, then we should not include the points at which the inequality equals zero (i.e., roots) in the solution. These points should be shown with parentheses.\n",
"\n",
"2. If the inequality is ≤ or ≥, then we do include the points where it equals zero, which should be denoted with square brackets.\n",
"\n",
"Let's calculate:\n",
"\n",
"```python\n",
"from sympy import *\n",
"from sympy import oo\n",
"\n",
"# define the variable\n",
"x = Symbol('x')\n",
"# Define intervals\n",
"intervals = [(-oo, -14), (-14, -3), (-3, oo)]\n",
"\n",
"# define the simplified function\n",
"func = (-x - 14)*(x + 3)\n",
"solutions = []\n",
"\n",
"# define the test points\n",
"test_points = [-15, -10, 0]\n",
"# Check within each interval\n",
"for interval in intervals:\n",
" # Get a test point in this interval \n",
" test_point = sum(interval) / 2\n",
"\n",
"# check if inequality holds for each test point\n",
"for point in test_points:\n",
" if func.subs(x, point) < 0:\n",
" print(point, 'satisfies the inequality.')\n",
" else:\n",
" print(point, 'does not satisfy the inequality.')\n",
" # Check whether the inequality holds true for this test point\n",
" if f_simplified.subs(x, test_point) < 0:\n",
" solutions.append(interval)\n",
"\n",
"# Print solutions\n",
"print('Solution intervals:', solutions)\n",
"```\n",
"\n",
"The intervals for which the test points satisfy the inequality are a part of the solution.\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[33mmathproxyagent\u001b[0m (to assistant):\n",
"\n",
"-15 satisfies the inequality.\n",
"-10 does not satisfy the inequality.\n",
"0 satisfies the inequality.\n",
"Solution intervals: [(-oo, -14), (-3, oo)]\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[35m******************************Start compressing the following content:******************************\u001b[0m\n",
"To be compressed:\n",
"##SYSTEM## Below is the compressed content from the previous conversation, evaluate the process and continue/terminate if necessary:\n",
"##ASSISTANT## To solve the inequality, we need to simplify the inequality, identify when it equals zero, verify the sign of the inequality, and write the solution in interval notation using sympy in Python. \n",
"Steps involve: \n",
"1. Rewriting the inequality in a form \n",
@ -300,46 +314,61 @@
"##CODE## Sympy is used to simplify the inequality and find the roots of the inequality $(2x + 10)(x + 3) - (3x + 9)(x + 8) < 0$.\n",
"\n",
"##USER## The simplified function is $(-x - 14)*(x + 3)$ and its roots are [-14, -3].\n",
"##ASSISTANT## Good. Now, let's divide the x-axis into three intervals using the roots [-14, -3], which are (-∞, -14), (-14, -3), and (-3, +∞). We will choose a test point from each interval and substitute it into the inequality to determine whether the inequality holds. If it holds, that interval is part of the solution.\n",
"##ASSISTANT## Great, now we have the roots -14 and -3.\n",
"\n",
"Given these roots, we have divided the x-axis into three intervals: (-inf, -14), (-14, -3), (-3, inf). \n",
"\n",
"We will select one value from each interval and check whether the inequality (-x - 14)*(x + 3) < 0 holds true. \n",
"\n",
"As we are working with inequalities, remember:\n",
"1. If the inequality is strictly < or >, then we should not include the points at which the inequality equals zero (i.e., roots) in the solution. These points should be shown with parentheses.\n",
"\n",
"2. If the inequality is ≤ or ≥, then we do include the points where it equals zero, which should be denoted with square brackets.\n",
"\n",
"Let's calculate:\n",
"\n",
"```python\n",
"from sympy import *\n",
"from sympy import oo\n",
"\n",
"# define the variable\n",
"x = Symbol('x')\n",
"# Define intervals\n",
"intervals = [(-oo, -14), (-14, -3), (-3, oo)]\n",
"\n",
"# define the simplified function\n",
"func = (-x - 14)*(x + 3)\n",
"solutions = []\n",
"\n",
"# define the test points\n",
"test_points = [-15, -10, 0]\n",
"# Check within each interval\n",
"for interval in intervals:\n",
" # Get a test point in this interval \n",
" test_point = sum(interval) / 2\n",
"\n",
"# check if inequality holds for each test point\n",
"for point in test_points:\n",
" if func.subs(x, point) < 0:\n",
" print(point, 'satisfies the inequality.')\n",
" else:\n",
" print(point, 'does not satisfy the inequality.')\n",
" # Check whether the inequality holds true for this test point\n",
" if f_simplified.subs(x, test_point) < 0:\n",
" solutions.append(interval)\n",
"\n",
"# Print solutions\n",
"print('Solution intervals:', solutions)\n",
"```\n",
"\n",
"The intervals for which the test points satisfy the inequality are a part of the solution.\n",
"##USER## -15 satisfies the inequality.\n",
"-10 does not satisfy the inequality.\n",
"0 satisfies the inequality.\n",
"##USER## Solution intervals: [(-oo, -14), (-3, oo)]\n",
"\n",
"\u001b[35m******************************Content after compressing: (type=<class 'str'>)******************************\u001b[0m\n",
"##SYSTEM## The assistant provided instructions on solving an inequality using sympy in Python: simplifying the impression, identifying roots and checking if the inequality holds true for certain intervals. \n",
"##ASSISTANT## Explained the next steps and wrote Python code to check if the test points -15, -10, 0 satisfy the inequality using the function and roots provided by the user.\n",
"##CODE## Sympy finds the intervals in which the inequality for the function $(-x - 14)*(x + 3)$ holds true.\n",
"##USER## Tested points -15, -10, 0 with inequality: -15 and 0 satisfied but -10 did not. \u001b[35m\n",
"##ASSISTANT## Outlined steps to solve the given inequality: simplifying the equation, finding its roots, dividing the x-axis into intervals using the roots, and checking each interval's validity for the inequality.\n",
"##CODE## Sympy was used to simplify the inequality $(2x + 10)(x + 3) - (3x + 9)(x + 8) < 0$.\n",
"##USER## Identified simplified function as $(-x - 14)*(x + 3)$ with roots as [-14, -3].\n",
"##ASSISTANT## Divided x-axis into three intervals by the roots [-14,-3]. Explained concept of not including inequality's roots while testing the truth value of each interval using sympy. \n",
"##CODE## Implemented checking the truth value of each interval using sympy, found the solution intervals.\n",
"##USER## Reported solution intervals as [(-oo, -14), (-3, oo)]. \u001b[35m\n",
"********************************************************************************\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 446 After: 163 | Total prompt token count after compression: 477\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 509 After: 219 | Total prompt token count after compression: 533\u001b[0m\n",
"--------------------------------------------------------------------------------\n",
"\u001b[33massistant\u001b[0m (to mathproxyagent):\n",
"\n",
"The Python test results suggested that the function $(-x - 14)*(x + 3)$ is less than zero for $x$ in $(-\\infty, -14)$ or $(-3, \\infty)$. The test points confirm that the intervals (-infinity, -14) and (-3, infinity) fully satisfy the inequality. Please note that the x values -14 and -3 are the roots, and they do not satisfy the inequality themselves so they are not included in the interval.\n",
"Excellent! \n",
"\n",
"Therefore, the solution of the inequality $(2x+10)(x+3)<(3x+9)(x+8)$ can be expressed in interval notation is $x \\in \\boxed{(-\\infty, -14) \\cup (-3, \\infty)}$.\n",
"Therefore, the complete solution to the inequality is $x \\in (-\\infty, -14) \\cup (-3, \\infty)$.\n",
"\n",
"So, all x that satisfy the inequality are those x in $(-\\infty, -14)$ and $(-3, \\infty)$.\n",
"\n",
"So, we have our answer as:\n",
"\\[ \\boxed{x \\in (-\\infty, -14) \\cup (-3, \\infty)} \\].\n",
"\n",
"--------------------------------------------------------------------------------\n"
]
@ -356,10 +385,11 @@
" system_message=\"You are a helpful assistant.\",\n",
" llm_config={\n",
" \"request_timeout\": 600,\n",
" \"seed\": 42,\n",
" \"seed\": 43,\n",
" \"config_list\": config_list,\n",
" },\n",
" compress_config={\n",
" \"mode\": \"COMPRESS\",\n",
" \"trigger_count\": 600, # set this to a large number for less frequent compression\n",
" }\n",
")\n",
@ -385,7 +415,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [
{
@ -396,7 +426,13 @@
"\n",
"Draw two agents chatting with each other with an example dialog. Don't add plt.show().\n",
"\n",
"--------------------------------------------------------------------------------\n",
"--------------------------------------------------------------------------------\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mchatbot\u001b[0m (to user_proxy):\n",
"\n",
"\u001b[32m***** Suggested function Call: python *****\u001b[0m\n",
@ -432,7 +468,7 @@
"(0.27999999999999997, 0.72, 0.39, 0.61)"
]
},
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
@ -484,12 +520,13 @@
"\n",
"\u001b[35m******************************Content after compressing: (type=<class 'str'>)******************************\u001b[0m\n",
"##FUNCTION_CALL##\n",
"Function: python\n",
"Args: Executing a matplotlib Python script to create a visual representing dialouge between 'Agent 1' and 'Agent 2' with dialog lines and texts.\n",
"Name: python\n",
"Args: A code cell creating a plot representing a dialogue between two agents, Agent 1 and Agent 2, using matplotlib. Dialog lines and text are included with axes hidden.\n",
"\n",
"##FUNCTION_RETURN##\n",
"Function 'python' returns plot axis edges (0.28, 0.72, 0.39, 0.61). \u001b[35m\n",
"The python function results in a plot area of (0.28, 0.72, 0.39, 0.61). \u001b[35m\n",
"********************************************************************************\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 312 After: 101 | Total prompt token count after compression: 230\u001b[0m\n",
"\u001b[35mToken Count (of msgs after first prompt): Before compression: 312 After: 102 | Total prompt token count after compression: 231\u001b[0m\n",
"--------------------------------------------------------------------------------\n",
"\u001b[33mchatbot\u001b[0m (to user_proxy):\n",
"\n",
@ -539,6 +576,7 @@
" system_message=\"For coding tasks, only use the functions you have been provided with. Reply TERMINATE when the task is done.\",\n",
" llm_config=llm_config,\n",
" compress_config={\n",
" \"mode\": \"COMPRESS\",\n",
" \"trigger_count\": 300, # set this to a large number for less frequent compression\n",
" }\n",
"\n",