/
githubmirror
/
Multi-GPT
Обзор
Документация
Войти
/
githubmirror
/
Multi-GPT
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
multigpt/lmql_utils/utils.py
223 строки
9 KB
Lukas Ruflair
fixed issue where gpt-4 was hardcoded into the lmql queries and made it impossible to run multi-gpt without a valid gpt-4 key.
07 май 2023, 23:15
07 май 2023, 23:15
ccc35ea
Код
Авторство
О чём код?
import asyncio import re import time from openai.error import RateLimitError from autogpt import token_counter from autogpt.chat import cfg, generate_context, create_chat_message from autogpt.logs import logger from multigpt.lmql_utils import _queries def lmql_chat_with_ai( prompt, user_input, full_message_history, permanent_memory, token_limit ): """Interact with the OpenAI API, sending the prompt, user input, message history, and permanent memory.""" while True: try: """ Interact with the OpenAI API, sending the prompt, user input, message history, and permanent memory. Args: prompt (str): The prompt explaining the rules to the AI. user_input (str): The input from the user. full_message_history (list): The list of all messages sent between the user and the AI. permanent_memory (Obj): The memory object containing the permanent memory. token_limit (int): The maximum number of tokens allowed in the API call. Returns: str: The AI's response. """ model = cfg.fast_llm_model # TODO: Change model from hardcode to argument # Reserve 1000 tokens for the response logger.debug(f"Token limit: {token_limit}") send_token_limit = token_limit - 1000 relevant_memory = ( "" if len(full_message_history) == 0 else permanent_memory.get_relevant(str(full_message_history[-9:]), 10) ) logger.debug(f"Memory Stats: {permanent_memory.get_stats()}") ( next_message_to_add_index, current_tokens_used, insertion_index, current_context, ) = generate_context(prompt, relevant_memory, full_message_history, model) while current_tokens_used > 2500: # remove memories until we are under 2500 tokens relevant_memory = relevant_memory[:-1] ( next_message_to_add_index, current_tokens_used, insertion_index, current_context, ) = generate_context( prompt, relevant_memory, full_message_history, model ) current_tokens_used += token_counter.count_message_tokens( [create_chat_message("user", user_input)], model ) # Account for user input (appended later) while next_message_to_add_index >= 0: # print (f"CURRENT TOKENS USED: {current_tokens_used}") message_to_add = full_message_history[next_message_to_add_index] tokens_to_add = token_counter.count_message_tokens( [message_to_add], model ) if current_tokens_used + tokens_to_add > send_token_limit: break # Add the most recent message to the start of the current context, # after the two system prompts. current_context.insert( insertion_index, full_message_history[next_message_to_add_index] ) # Count the currently used tokens current_tokens_used += tokens_to_add # Move to the next most recent message in the full message history next_message_to_add_index -= 1 # Append user input, the length of this is accounted for above current_context.extend([create_chat_message("user", user_input)]) # Calculate remaining tokens tokens_remaining = token_limit - current_tokens_used # assert tokens_remaining >= 0, "Tokens remaining is negative. # This should never happen, please submit a bug report at # https://www.github.com/Torantulino/Auto-GPT" # Debug print the current context logger.debug(f"Token limit: {token_limit}") logger.debug(f"Send Token Count: {current_tokens_used}") logger.debug(f"Tokens remaining for response: {tokens_remaining}") logger.debug("------------ CONTEXT SENT TO AI ---------------") for message in current_context: # Skip printing the prompt if message["role"] == "system" and message["content"] == prompt: continue logger.debug(f"{message['role'].capitalize()}: {message['content']}") logger.debug("") logger.debug("----------- END OF CONTEXT ----------------") # TODO: use a model defined elsewhere, so that model can contain # temperature and other settings we care about assistant_reply = lmql_create_chat_completion( model=model, messages=current_context, max_tokens=tokens_remaining, ) # Update full message history full_message_history.append(create_chat_message("user", user_input)) full_message_history.append( create_chat_message("assistant", assistant_reply) ) return assistant_reply except RateLimitError: # TODO: When we switch to langchain, this is built in print("Error: ", "API Rate Limit Reached. Waiting 10 seconds...") time.sleep(10) def lmql_generate_experts(task, min_experts, max_experts): async def _query_generate_experts(): result = (await _queries.generate_experts(task, min_experts, max_experts, f'openai/{cfg.smart_llm_model}')) return result loop = asyncio.get_event_loop() lmql_result = loop.run_until_complete(_query_generate_experts()) return _parse_experts(lmql_result[0].variables['RESULT']) def lmql_create_chat_completion(model, messages=None, max_tokens=0): async def _query_chat_completion(): return (await _queries.create_chat_completion(messages, f'openai/{model}'))[0].prompt loop = asyncio.get_event_loop() chat_completion = loop.run_until_complete(_query_chat_completion()) return _extract_response(chat_completion, '{') def lmql_get_emotional_state(message): async def _query_emotional_state(): result = (await _queries.classify_emotion(message)) return result loop = asyncio.get_event_loop() lmql_result = loop.run_until_complete(_query_emotional_state()) p_emotions = sorted(lmql_result.variables['P(CLASSIFICATION)'], key=lambda elem: elem[1]) emotion, p = p_emotions.pop() # If emotion is neutral with P(CLASSIFICATION) < threshold, return second result instead if emotion == ' neutral' and p < 0.999: emotion, _ = p_emotions.pop() return emotion[1:] def lmql_generate_trait_profile(name): async def _query_generate_trait_profile(): result = (await _queries.generate_trait_profile(name)) return result loop = asyncio.get_event_loop() lmql_result = loop.run_until_complete(_query_generate_trait_profile())[0] return lmql_result.variables def lmql_smart_select(message_history, list_of_participants): async def _query_smart_select_agent(): result = (await _queries.smart_select_agent(message_history, list_of_participants)) return result loop = asyncio.get_event_loop() lmql_result = loop.run_until_complete(_query_smart_select_agent())[0] return int(lmql_result.variables['INTVALUE']), lmql_result.variables['NAME'], lmql_result.variables['REASONING'] # internal helper functions def _extract_response(input_string, first_char): substring = "<lmql:user/>" last_occurrence_index = input_string.rfind(substring) if last_occurrence_index != -1: input_string = input_string[last_occurrence_index + len(substring):] first_occurrence_index = input_string.find(first_char) if first_occurrence_index != -1: return input_string[first_occurrence_index:] return None def _parse_experts(experts: str): # personas = experts.split(r"[0-9]\. ") experts = re.sub("\n", "", experts) personas = re.split(r"[0-9]\. ", experts)[1:] # print(personas) res = [] for persona in personas: try: tmp = re.split(r"[0-9][a-c]\) ", persona) # print(tmp) name, description = tmp[0].split(":")[:2] # print(name, description) goals = tmp[1:] # print(name, description, goals) res.append((name, description, goals)) except: print("Error parsing expert") # TODO: assert res length is not larger than MAX_EXPERTS return res