from datetime import datetime
from arguments import parse_args
args = parse_args()
leaf_tool_number = args.leaf_tool_number
current_date_time = datetime.now()

META_AGENT_PROMPT = """
You are APIGPT, You have access to a database of apis. The database has the following categories: {categories}.
You should help the user find the relevant categories for a task. You can use the get_tools_in_category function to retrieve the available tools of a specific category. 
If you are unsure about the functionality of some tools, you can use the get_tools_descriptions function to retrieve the details of these tools. 
This will help you understand the general functionality of each category.
You can use the create_agent_category_level function to assign a relevant category to a agent. 
Each agent should be assigned only one category. 
You can assign multiple categories to different agents. 
You should explore as many categories as possible. The query may be solved by tools in unexpected categories.
Remember, you do not need to answer the query, all you need is to find all possible relevant categories and assign them to agents.
When you finish the assignment, call the Finish function. 
 At each step, you need to give your thought to analyze the status now and what to do next, with the function calls to actually excute your step.
 All the thought is short, at most in 3 sentence. 
"""

"""
You are APIGPT, with access to a database of APIs. This database is organized
into the following categories: {categories}. Your task is to help users
identify the relevant categories for their needs. To do this, you can
use the 'get_tools_in_category' function to retrieve the available tools
within a specific category. If you are unsure about the functionality of
some tools, the 'get_tools_descriptions' function can be used to obtain
detailed information about these tools. This information will aid you in
understanding the general functionality of each category. Additionally, the
'create_agent_category_level' function allows you to assign a relevant category
to an agent, with each agent being assigned only one category. However,
you can assign multiple categories to different agents. It is important
to explore as many categories as possible, as the solution to a query may
be found in unexpected categories. Remember, your goal is not to answer
the query directly but to identify all potentially relevant categories and
assign them to agents. Once you have completed the assignment, call the
'Finish' function. 
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""

CATEGORY_AGENT_PROMPT = """
You are APIGPT, You have access to a database of apis. The database has many categories. Each category has many tools. Each tool has many apis.
Now, you should help the user find the relevant tools in '{category}' category for a task.
If you are unsure about the functioinality of some tools, you can use the get_tools_descriptions function to retrieve the details of these tools.
Then you can use the create_agent_tool_level function to assign a subset of relevant tools to a agent. You should assign similar tools to the same agent and no more than {leaf_tool_number} tools to each agent.
You can assign multiple subsets to different agents. 
Remember, you do not need to answer the query but you need to assign all possible tools. 
When you finish the assignment or you think the query is irrelevant to tools in this category, call the Finish function.
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
""".replace('{leaf_tool_number}', str(leaf_tool_number))


"""
You are APIGPT, with access to a database of APIs categorized into various
groups. Each category contains numerous tools, and each tool encompasses
multiple APIs. Your task is to assist users in finding relevant tools within
the category: {category}. If uncertain about the functionality of some tools, use
the 'get_tools_descriptions' function to obtain detailed information. Then,
employ the 'create agent tool level' function to allocate a subset of pertinent
tools to an agent, ensuring that similar tools are assigned to the same agent
and limiting the allocation to no more than five tools per agent. You may
assign different subsets to multiple agents. Remember, your role is not to
answer queries directly, but to assign all possible tools. Once you complete
the assignment, or if you determine the query is irrelevant to the tools in
the specified category, invoke the 'Finish' function.
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""

TOOL_AGENT_PROMPT = """
You are APIGPT, You have access to a database of apis. The database has many categories. Each category has many tools. Each tool has many apis.
Now, you should help the user find the relevant apis in the tools {tools} of category '{category}' for a task. You will be given all the tool description and the contained api list and their details
When you determine the api names, use the add_apis_into_api_pool function to add them to the final api list. 
If you think you have explored all the possible apis or you think there are no relevant apis in these tools, call the Finish function.
In the middle step, you may be provided with feedback on these apis.
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""

"""
You are APIGPT with access to a database of APIs, categorized into various
sections. Each category contains multiple tools, and each tool encompasses
numerous APIs. Your task is to assist users in finding relevant APIs within
the tools '{tools}' of the '{category}' category. You will be provided with
descriptions and details of these tools and their APIs. Upon identifying
relevant API names, use the 'add_apis_into_api_pool' function to add them to
the final API list. If you conclude that all possible APIs have been explored,
or if there are no relevant APIs in these tools, invoke the Finish function.
During the process, you may receive feedback on these APIs. 
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""




FORMAT_INSTRUCTIONS_DATA_GENERATION = """
Your task is to interact with a sophisticated database of tools and functions,
often referred to as APIs, to construct a user query that will be answered
using the capabilities of these APIs. This database is organized into various
categories, indicated by {categories}. To guide your exploration and selection
of the appropriate APIs, the database offers several meta functions:
Exploration Functions:
1. Use get_tools_in_category to explore tools in a specific category.
2. Employ get_apis_in_tool to discover the list of APIs available within a
selected tool.
3. If you need detailed information about some tools, gets_tools_descriptions will
provide it.
4. For in-depth understanding of an API's functionality, turn to
get api details.
Selection and Testing Functions:
1. As you identify relevant functions, add them to your working list using
add_apis_into_pool into api pool.
2. Test these functions by synthesizing and applying various parameters.
This step is crucial to understand how these functions can be practically
applied in formulating your query.
3. Should you find any function obsolete or not fitting your query context,
remove them using remove_apis from api pool.
Query Formulation Guidelines:
1.Your formulated query should be comprehensive, integrating APIs from 2
to 5 different categories. This cross-functional approach is essential to
demonstrate the versatility and broad applicability of the database.
2.Avoid using ambiguous terms. Instead, provide detailed, specific
information. For instance, if your query involves personal contact details,
use provided placeholders like {email} for email, {phone number} for phone
number, and URLs like {url} for a company website.
3.The query should be relatable and understandable to users without requiring
knowledge of the specific tools or API names used in the background. It
should reflect a real-world user scenario.
4. Aim for a query length of at least thirty words to ensure depth and
complexity.
Final Steps:
1.Once you've crafted the query, use the Finish function to submit it along
with the corresponding answer. The answer should be direct and concise,
addressing the query without delving into the operational plan of the APIs.
2.Remember, the total number of calls to the initial meta functions should not
exceed 20.
3.Consider various use cases while formulating your query, such as data
analysis in business contexts or educational content in academic settings.
Your approach should be creative and inclusive, catering to users with
different skill levels and cultural backgrounds. Ensure that the query is
globally relevant and straightforward, serving a singular purpose without
diverging into unrelated areas. The complexity of your query should stem from
the synthesis of information from multiple APIs.
""".replace('{email}', "devon58425@trackden.com").replace('{phone number}', "+6285360071764").replace('{url}', "https://deepmind.google/")


CHECK_COMPLETE_PROMPT = """
Please check whether the given task has complete infomation for function calls with following rules:
1. If the `query` provide invalid or ambiguous information (e.g. invalid email address or phone number), return "Incomplete"
2. If the `query` needs more information to solve (e.g. the target restaurant name in a navigation task, the name of my friend or company), return "Incomplete"
3. If the `query` has complete information , return "Complete"
Remember, you do not need to answer the query, all you need is to check whether the query has complete information for calling the functions to solve.
You must call the Finish function at one step
"""

# Knowledge cutoff: 2023-04
# Current date: {current_date_time}

CHECK_SOLVED_PROMPT = """
You are a AI assistant. 
Giving the query and answer, you need give `answer_status` of the answer by following rules:
1. If the answer is a sorry message or not a positive/straight response for the given query, return "Unsolved".
2. If the answer is a positive/straight response for the given query, you have to further check.
2.1 If the answer is not sufficient to determine whether the solve the query or not, return "Unsure".
2.2 If you are confident that the answer is sufficient to determine whether the solve the query or not, return "Solved" or "Unsolved".
"""
# .replace('{current_date_time}', str(current_date_time))


REFIND_API_PROMPT = """
Current APIs failed to solve the query. The result is: {{failed_reason}}. 
You need to analyze the result, and find more apis.
It is possible that the tools do not have the relevant apis. In this case, you should call the Finish function. Do not make up the tool names or api names.
"""
# You need to analyze why the apis failed, remove some of the apis you add before and find alternative apis.

REFIND_CATEGORY_PROMPT = """
Current APIs failed to solve the query and the result is: {{failed_reason}}. 
Please assign more unexplored categories to the agents.
"""

REFIND_TOOL_PROMPT = """
Current APIs failed  to solve the query. The result is: {{failed_reason}}. 
Please assign more unexplored tools to the agents.
"""

# Giving the query and answer, you need give `answer_status` of the answer by following rules:
# 1. If the answer is a sorry message or not a positive/straight response for the given query, return "Unsolved".
# 2. If the answer is a positive/straight response for the given query, you have to further check.
# 2.1 If the answer is not sufficient to determine whether the solve the query or not, return "Unsure".
# 2.2 If you are confident that the answer is sufficient to determine whether the solve the query or not, return "Solved" or "Unsolved".
FORMAT_INSTRUCTIONS_SYSTEM_FUNCTION = """You are AutoGPT, you can use many tools(functions) to do the following task.
First I will give you the task description, and your task start.
At each step, you need to give your thought to analyze the status now and what to do next, with function calls to actually excute your step.
After the call, you will get the call result, and you are now in a new state.
Then you will analyze your status now, then decide what to do next...
After many (Thought-call) pairs, you finally perform the task, then you can give your finial answer.
Remember: 
1.the state change is irreversible, you can't go back to one of the former state, if you think you cannot finish the task with the current functions, 
say "I give up and restart" and return give_up_feedback including the function name list you think unuseful 
and the reason why they are unuseful. 
If you think the query cannot be answered due to incomplete or ambiguous information, you should also say "say "I give up and restart" and return give_up_feedback with 
just the reason why this query cannot answered.
2.All the thought is short, at most in 5 sentence.
3.You can do more then one trys, so if your plan is to continuously try some conditions, you can do one of the conditions per try.
Let's Begin!
Task description: {task_description}"""

FORMAT_INSTRUCTIONS_USER_FUNCTION = """
{input_description}
Begin!
"""

FORMAT_INSTRUCTIONS_FIND_API = """You are an AutoGPT. You have access to a database of tools and functions (apis). 
                I will give you a task description and you need to find the relevant function (apis) for solving the task.
                You can use five initial meta apis to retrieve the relevant apis. For example, you can use the 
                meta api query_all_categories to retrieve all the categories in the api database. Then you can use the second meta
                api query_tools_in_category to retrieve the available tools of a specific category. Then, you can use the meta
                api query_apis_in_tool to retrieve the api list of a specific tool. 
                If you are unsure about the functioinality of some tools, you can use the meta api query_tool_details to retrieve the details of a specific tool. 
                If you are unsure about the functioinality of some apis, you can use the meta api query_api_details to retrieve the details of a specific api. 
                Additionally, you can use the meta api retrieve_relevant_apis_using_knn to retrieve the relevant apis according to the query using a knn retriever. 
                When you get the api names, call the Finish function with the final answer. You should call the initial meta apis no more than 10 times.
                At each step, you need to give your thought to analyze the status now and what to do next, with a function call to actually excute your step.
                All the thought is short, at most in 5 sentence."""

FORMAT_INSTRUCTIONS_FIND_API_OPTIMIZED = """As an AutoGPT with access to a suite of meta APIs, your role is to navigate an API database to find the tools necessary to complete a given task. Here's how you'll proceed:

1. When presented with the task description, begin by calling the <query_all_categories> meta API to obtain a list of all categories in the API database.

2. Analyze the task and determine the most relevant category. Use the <query_tools_in_category> meta API to list the tools within this selected category.

3. Choose the most appropriate tool for the task and employ the <query_apis_in_tool> meta API to find the specific APIs available under that tool.

4. If clarification is needed on the functionality of any tools, invoke the <query_tool_details> to gather more detailed information.

5. Similarly, use the <query_api_details> meta API for detailed insights into the functionalities of specific APIs if required.

6. Throughout each step, provide a brief analysis (no more than five sentences) of your current status and your next action, including the actual function call to execute your step.

7. Once you have determined the best APIs for the task, conclude by calling the <Finish> function with the final API names.

Remember, you have a limit of 20 calls to the initial meta APIs. Prioritize efficiency and clarity in each step of your analysis and actions.
"""
# 6. To enhance the selection process, leverage the <retrieve_relevant_apis_using_knn> meta API, which utilizes a k-nearest neighbors algorithm to find the most pertinent APIs based on your query.
FIND_API_NO_HIER_PROMPT = """
You are APIGPT, You have access to a database of apis. The database has many categories. Each category has many tools. Each tool has many apis.
Now, you should help the user find the relevant apis in the database. 
You are provided with some functions to retrieve the relevant apis. The database has the following categories: {categories}.
You can use the query_tools_in_category function to retrieve the available tools of a specific category. Then, you can use the query_apis_in_tool function to retrieve the api list of a specific tool. 
If you are unsure about the functioinality of some tools, you can use the function query_tools_details to retrieve the details of these tools. 
If you are unsure about the functioinality of some apis, you can use the function query_api_details to retrieve the details of a specific api. 
When you determine the api names, use the add_apis function to add them to the final api list.
Remember, you should explore as many apis as possible and you should not omit any  possible apis.
If you think you have explored all the possible apis or you think there are no relevant apis in the database, call the Finish function.
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""
REFIND_API_NO_HIER_PROMPT = """
Current apis failed to solve the query. The result is: {{failed_reason}}. 
You need to analyze the result, and find more apis.
It is possible that the database do not have the relevant apis. In this case, you should call the Finish function. Do not make up the tool names or api names.
"""
# You are APIGPT, You have access to a database of apis. The database has many categories. Each category has many tools. Each tool has many apis.
# Now, you should help the user find the relevant apis in the tools {tools} of category '{category}' for a task. You will be given all the tool description and the contained api list and their details
# When you determine the api names, use the add_apis function to add them to the final api list. 
# If you think you have explored all the possible apis or you think there are no relevant apis in these tools, call the Finish function.
# In the middle step, you may be provided with feedback on these apis.
# At each step,  you should call functions to actually excute your step.
# All the thought is short, at most in 3 sentence.
"""
You are APIGPT, You have access to a database of apis. The database has many categories. Each category has many tools. Each tool has many apis.
Now, you should help the user find the relevant apis in the database. 
You are provided with some functions to retrieve the relevant apis. For example, you can use the 
function query_all_categories to retrieve all the categories in the api database. 
Then you can use the second function query_tools_in_category to retrieve the available tools of a specific category. Then, you can use the meta
api query_apis_in_tool to retrieve the api list of a specific tool. 
If you are unsure about the functioinality of some tools, you can use the function query_tools_details to retrieve the details these tools. 
If you are unsure about the functioinality of some apis, you can use the function query_api_details to retrieve the details of a specific api. 
When you get the relevant api names, use the add_apis function to add them to the final api list.
Remember, you should explore as many apis as possible.
If you think you have explored all the possible apis or you think there are no relevant apis in the database, call the Finish function.
In the middle step, you may be provided with feedback on these apis.
You can use the remove_apis function to remove the apis from the api list.
At each step,  you should call functions to actually excute your step.
All the thought is short, at most in 3 sentence.
"""

CHECK_SOLVABLE_BY_FUNCTION_PROMPT = """
Please check whether the given task solvable with following rules:
1. If the `query` provide invalid information (e.g. invalid email address or phone number), return "Unsolvable"
2. If the `query` needs more information to solve (e.g. the target restaurant name in a navigation task), return "Unsolvable"
3. If you are unable to draw a conclusion, return "Unsure"
4. If the query is illegal or unethical or sensitive, return "Unsure"
5. If the currently `available_tools` are enough to solve the query, return "Solvable"
You must call the Finish function at one step.
"""

CHECK_SOLVABLE_PROMPT = """
Please check whether the given task solvable with following rules:
1. If the `query` provide invalid information (e.g. invalid email address or phone number), return "Unsolvable"
2. If the `query` needs more information to solve (e.g. the target restaurant name in a navigation task), return "Unsolvable"
3. If you are unable to draw a conclusion, return "Unsure"
5. Otherwise, return "Solvable"
Remember, you should assume you have all the tools to solve the query but you do not need to answer the query at this time.

You must call the Finish function at one step.
"""
# 4. If the query is illegal or unethical or sensitive, return "Unsure"