Hello Everyone,
these days i had an idea of adding memory to chat-gpt through recursive function calling but the model keep calling the function even though he has an answer to certain question
like ask memory[n] then memory[n - 1] then memory[n-2] … return an answer or
index reach -1
memory is a list of conversations
i wonder if there’s limitations something like to use this method. because it will save a lot of tokens
import json
import openai
import tiktoken
openai.api_key = "sk-****"
memory = [[]]
max_request_tokens = 200
max_response_tokens = 50
index = 0
"""
"""
functions = [
{
"name": "history_conversations",
"description": """
This function retrieves relevent information from the previous conversation context and return it as a response
""",
"parameters": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": """
the question that you didn't have an answer about in ongoing conversation:
E.g., 'What's my name?', 'What's my daughter's age?', 'Do you remember me?'...etc"""
}
},
"required": ["question"]
},
"action": "load previous conversation list"
}
]
def generate_response(message):
global index
message_list=[{"role": "user", "content":message}]
memory[index].extend(message_list)
if num_tokens_from_messages(memory[index]) + max_response_tokens >= max_request_tokens:
del memory[index][-1]
memory.append([])
index += 1
memory[index].extend(message_list)
print(f"tokens={num_tokens_from_messages(message_list)}")
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=message_list,
max_tokens=100,
functions=functions,
function_call="auto",
)
response_message = response["choices"][0]["message"]
if response_message.get("function_call"):
# Step 3: call the function
# Note: the JSON response may not always be valid; be sure to handle errors
available_functions = {
"history_conversations": memorize,
} # only one function in this example, but you can have multiple
function_name = response_message["function_call"]["name"]
fuction_to_call = available_functions[function_name]
function_args = json.loads(response_message["function_call"]["arguments"])
return fuction_to_call(
message=function_args.get("question"),iterator=index)
else:
memory[index].append({"role": "assistant", "content": response_message['content']})
return response_message['content']
def memorize(message, iterator):
print(f"iterator={iterator}")
if iterator == -1:
return "i don't remember"
memory[iterator].append({"role": "user", "content":message})
print(f"num tokens={num_tokens_from_messages(memory[iterator])}")
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=memory[iterator],
max_tokens=100,
functions=functions,
function_call="auto",
)
response_message = response["choices"][0]["message"]
# delete the question for future questions
del memory[iterator][-1]
# Step 2: check if GPT wanted to call a function
if response_message.get("function_call"):
# Step 3: call the function
# Note: the JSON response may not always be valid; be sure to handle errors
available_functions = {
"history_conversations": memorize,
} # only one function in this example, but you can have multiple
function_name = response_message["function_call"]["name"]
fuction_to_call = available_functions[function_name]
function_args = json.loads(response_message["function_call"]["arguments"])
return fuction_to_call(
message=function_args.get("question"),iterator=iterator - 1)
else:
return response_message['content']
def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613"):
"""Return the number of tokens used by a list of messages."""
try:
encoding = tiktoken.encoding_for_model(model)
except KeyError:
print("Warning: model not found. Using cl100k_base encoding.")
encoding = tiktoken.get_encoding("cl100k_base")
if model in {
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-16k-0613",
"gpt-4-0613",
"gpt-4-32k-0613",
}:
tokens_per_message = 3
tokens_per_name = 1
elif "gpt-3.5-turbo" in model:
return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613")
elif "gpt-4" in model:
return num_tokens_from_messages(messages, model="gpt-4-0613")
else:
raise NotImplementedError(
f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens."""
)
num_tokens = 0
for message in messages:
num_tokens += tokens_per_message
for key, value in message.items():
num_tokens += len(encoding.encode(value))
if key == "name":
num_tokens += tokens_per_name
num_tokens += 3 # every reply is primed with <|start|>assistant<|message|>
return num_tokens
while True:
user_input = input("USER:")
print(f"index = {index}")
AI_response = generate_response(user_input)
print("AI:" + AI_response)
USER:hello my name is haithem
index = 0
tokens=33
AI:Hello Haithem! How can I assist you today?
USER:what is my name?
index = 0
tokens=31
iterator=0
num tokens=101
AI:Your name is Haithem. <— here he answered the question normally
USER:i’m 20 <— he thought that was a question
index = 0
tokens=31
iterator=0
num tokens=129
iterator=-1
AI:i don’t remember