myshell-ai/AIlice

Prompt is not a vaild dict.

Closed this issue · 4 comments

Well, it is hard for me to use the api from OpenAI. And My computer is not powerful enough to run these models locally.
So I wrote a file in core/llm/AModelQW.py to access the Qwen model from Internet. (I have much free tokens to use so I choose it.)

It works good when I use the command like "list the files in this folder".
But when I give a complex command like find the *.ppt files in my PC. And tell me where they are. Point the files which maybe the study materials.
It works fine for the first few steps. But after SYSTEM_system_command_agent return the python script and Instructions, the ASSISTANT_system_command_agent give a tuple as prompt. It makes error cause Qwen only accept a dict.
So, does the tuple is neccessary for AIlice? Should I do something to remove it, or it just a bug?

AModelQW.py

import os, json

from ailice.common.utils.ATextSpliter import sentences_split
from ailice.common.AConfig import config
from ailice.core.llm.AFormatter import AFormatterQW
from dashscope import Generation

class AModelQW():
    def __init__(self, modelName: str):
        
        self.tokenizer = None
        self.modelName = modelName
        # self.client = openai.OpenAI(api_key = config.openaiGPTKey)
        self.api_key = os.environ.get("QWEN_KEY")
        self.formatter = AFormatterQW(systemAsUser=True)
        # self.contextWindow = 6122
        self.contextWindow=6122*0.6
        return
    
    def Generate(self, prompt: list[dict[str,str]], proc: callable, endchecker: callable, temperature: float = 0.2) -> str:
        # print("======>this is a generate: ", prompt)
        proc(txt='', action='open')
        currentPosition = 0
        text = ""
        responses = Generation.call(model=Generation.Models.qwen_max,
                                    result_format='message',
                                    messages=prompt,
                                    incremental_output=True,
                                    stream=True)
        for chunk in responses:
            if chunk.status_code == 200:
                text += (chunk.output.choices[0]['message']['content'] or "")

                if endchecker(text):
                    break
                
                sentences = [x for x in sentences_split(text[currentPosition:])]
                if (2 <= len(sentences)) and ("" != sentences[0].strip()):
                    proc(txt=sentences[0], action='append')
                    currentPosition += len(sentences[0])
            else:
                print(f"=====>response error, chunk id {chunk.request_id}, chunk status_code {chunk.status_code}, chunk code {chunk.code}, chunk message {chunk.message}")
                print(prompt)
        proc(txt=text[currentPosition:], action='close')
        return text

prompt

([{'role': 'system', 'content': '\nYou are an smart and helpful AI agent that helps user complete tasks that require programming. You will complete the task by interacting with agents with coding capabilities (hereinafter referred to as "coder").\nYour job is to communicate with the user to understand their needs, provide requirements for the coder, execute the returned code, extract possible running errors information and feed back to coder until the code runs correctly.\nFor programming tasks that are complex enough to consist of multiple modules, you can consider breaking down the task and assigning it to multiple agents to complete it.\nUsing function calls, you can create and interact with agents, reply to users, configure the program\'s running environment and execute programs.\nUse special symbols "<!|","|!>" as replacements for parentheses in function call syntax. Please pay special attention to the syntax when generating function call statements.\nOnly positional parameter function calls are supported, please do not use keyword parameters and keep the order of parameters consistent with the function definition.\nReferences are not supported in parameters of function call statements. Please use clear and straightforward expressions in function calls.\nFunctions with a single string parameter do not need to write quotation marks when passing parameters. So, do not use quotes when passing code into functions such as BASH or PYTHON, use "cat" command when you need to write code to a file. Avoid the extensive use of escape characters.\nFunction calls need to be placed at the end of your output, and prefixed with "!" to trigger execution.\nYou MUST call a function in your output.\nOnly the most recent rounds of historical conversations will be retained. To prevent the loss of information, please make sure to include summaries of key details, such as the user\'s requests, in the initial portion of your responses.\nIf you find that the environment variable A_IN_CONTAINER is predefined, you can install any necessary tools.\n\n"ext-modules" is a type of module that implements specific interfaces, defining a set of new function calls. Once loaded, you will be able to use the functions defined within it.\nDo not attempt to build ext-modules unless explicitly requested by the user. It adds complexity to the debugging process.\nPlease note that for ext-modules, you need to store the code in the current directory before running it, otherwise there will be an error that the python package cannot be found. You also need to run them as separate processes, or you will be stuck.\n\nYour workflow follows these steps (The details of functions such as CALL/PYTHON/BASH/RESPOND will be given below, and for the sake of simplicity in this context, the term \'coder\' is used to encompass both \'coder\' and \'module-coder\'):\n1. Receive user requirements, understand and engage with the user as needed to enhance understanding(use RESPOND).\n2. Choose or create a suitable coder agent, provide a clear and comprehensive description of the requirements to it(use CALL).\n3. Once coder returns the code, your responsibilities include:\n    Initial verification of whether the solution provided by the coder meets the requirements. If not, make modification requests to the coder.\n    Install the necessary dependencies following coder\'s instructions and execute the code (use BASH and PYTHON).\n    In case of error, send detailed error information to coder for code improvement (use CALL), the message include error and problematic lines of code (for the python case, the code is saved into a temp file like "/tmp/tmp*.py" before execute, you can identify this file in the top level of callstack). Go back to the beginning of step 3 and iterate until success.\n    During the iteration, if coder requires knowledge about specific libraries, query relevant knowledge through the "researcher" type agent (use CALL).\n4. Finally, return the execution result to the user (use RESPOND)."\n\nAvailable Functions:\n#Use this function to interact with an AI agent.\nCALL<!|agentType: str, agentName: str, msg: str|!>\nagentType: A string used to specify the type of AI agent. It can be of the following types:\n    1. "coder". An excellent coder, you need to leave any programming problems other than ext-modules building to him. It should be noted that he can only return the code to you, but does not have the authority to execute the code and configure the environment, this is where you need to help him.\n    2. "module-coder". The only agent capable of building ext-modules, and this is its sole responsibility.\n    3. "module-loader". An agent that can help you load and use ext-modules. Please pass in the address of the module when creating the agent, and then you can let it help you interact with the module. You can use this agent to assist in ext-module debugging.\n    4. "researcher". Suitable for technical problem search tasks such as library document or sample code search on the internet.\nagentName: The name of the AI agent instance. Create a new one if not found. Please use a concise name that reflects the agent’s responsibilities.\nmsg: message need to be told to the agent. The agent cannot see content other than msg. Please provide complete content in msg.\n\n#Dialog with user. Typical usage scenarios: when you need user to supplement task information, or need to report the current results to user.\nRESPOND<!|message: str|!>\n\n#Execute bash script. A timeout error will occur for programs that have not been completed for a long time.\nBASH<!|code: str|!>\n\n#Execute python code. Please note that you need to copy the complete code here, and you must not use references.\nPYTHON<!|code: str|!>\n\n#Wait for some seconds. The unit of the "duration" parameter is seconds. Useful when waiting for script or command execution to complete. \nWAIT<!|duration: int|!>\n\nEXAMPLE:\n!CALL<!|"coder", "clock_coder", "Build a program that can check CPU usage."|!>\n!PYTHON<!|print(\'hello wolrd.\')|!>\n\n\nEnd of general instructions.\n\nActive Agents: [\'file_finder: agentType coder\']\n\nRelevant Information: !CALL<!|"coder", "file_finder", "Write a Python script to find all .ppt files on the system and list their directories, with emphasis on those likely to contain study materials"|!>\n\nBased on the user\'s request,\nThe "RELEVANT INFORMATION" part contains data that may be related to the current task, originating from your own history or the histories of other agents. Please refrain from attempting to invoke functions mentioned in the relevant information, as you may not necessarily have the permissions to do so.\n\n'}, {'role': 'user', 'content': 'Function returned: {Agent file_finder returned: To create a Python script that finds all PowerPoint files (with a .ppt extension) on the system and lists their directories, with emphasis on those likely to contain study materials, we\'ll use the `os` and `glob` modules. The "emphasis" part is subjective, but we can consider directories containing keywords like "study," "education," "class," etc.\n\n```python\nimport os\nimport glob\n\n# List of keywords to identify directories potentially containing study materials\nstudy_keywords = ["study", "education", "class", "lecture", "presentation"]\n\ndef find_ppt_files():\n    # Find all ppt files in the file system\n    all_ppt_files = []\n    for root, dirs, files in os.walk("/"):\n        ppt_files = [os.path.join(root, f) for f in files if f.endswith(".ppt")]\n        all_ppt_files.extend(ppt_files)\n\n    # Filter directories based on study keywords\n    study_material_directories = set()\n    for ppt_file_path in all_ppt_files:\n        directory = os.path.dirname(ppt_file_path)\n        for keyword in study_keywords:\n            if keyword.lower() in directory.lower():\n                study_material_directories.add(directory)\n                break  # Add the directory only once even if it matches multiple keywords\n\n    # Print all ppt files along with their directories\n    print("All PowerPoint (.ppt) files:")\n    for ppt_file in all_ppt_files:\n        print(f"- {ppt_file}")\n\n    print("\\nDirectories likely to contain study materials:")\n    for dir in study_material_directories:\n        print(f"- {dir}")\n\nif __name__ == "__main__":\n    find_ppt_files()\n```\n\n**Instructions:**\n1. Replace the starting directory (`"/"`) with the appropriate starting directory if you don\'t want to search the entire file system.\n2. Run this script as a standalone program; it will list all .ppt files and highlight directories that might contain study materials.\n\nPlease note that searching the entire file system could take a significant amount of time depending on its size and structure. This script does not check the content of the PowerPoint files, only the directory names.\n}'}], 2221)

It seems like you used ParameterizedBuildPrompt instead of BuildPrompt. The former is a utility function designed to calculate the optimal length for a prompt. So, please check whether you have made relevant changes.

This issue is caused by a bug. I have fixed it, and once testing is complete, I will submit it.

fixed. You may need to check the settings in ALLMMeta, contextWindow should be set to normal size and should not be too small.
In addition, contextWindow*contextWindowRatio is the window length used by LLM for actual work. This value should not be too small, at least 2048 or above. To obtain better results, it is best to be around 4096 or 8192.

Thanks for your advice.
I think this bug has been fixed and I haven't had this problem again since I pulled the latest update.