├── LLM.py ├── make_plan_example.py ├── config.py ├── data_demo ├── question_react_11_03.json ├── question_react.json ├── question_react_11_06.json ├── question_complex_react.json └── complex_react_11_07.json ├── cpm_utils.py ├── readme_1.md ├── tools_call.py ├── tool_call_en.py ├── tool_caption_en.py ├── tools_caption.py ├── readme_en.md ├── README.md ├── finetune_tool.py ├── main.py └── config_web.py /LLM.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /make_plan_example.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | with open('/Users/liudan/ai/AutoPlan2/train_plan.json','r',encoding='utf-8') as f: 4 | example_list = json.load(f) 5 | new_example_list = [] 6 | for i in example_list: 7 | key = re.sub('\nassistant\nThought:','',i["conversations"][0]['value'].split('Begin!\n\nQuestion: ')[-1]) 8 | value = re.sub('\nAction:','',i["conversations"][1]['value']) 9 | if len(value.split("\n")) > 2: 10 | new_example_list.append({key:value}) 11 | 12 | with open('/root/ld/ld_project/MiniCPM-CookBook/agent_demo/plan_example.json','w',encoding='utf-8') as f: 13 | json.dump(new_example_list, f, ensure_ascii=False, indent=4) -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | ### 必须设置的项 2 | model_path = "/root/ld/ld_model_pretrain/Qwen2.5-72B-Instruct-GPTQ-Int4" # 教师模型地址 3 | gen_datas_per_tool = 10 # 每个tool生成多少条react数据 4 | params_dict = { # vllm的生成参数 5 | "n": 1, 6 | "best_of": 1, 7 | "presence_penalty": 1, 8 | "frequency_penalty": 1.0, 9 | "temperature": 0.8, 10 | "top_p": 0.8, 11 | "top_k": -1, 12 | "stop": None, 13 | "stop_token_ids": None, 14 | "ignore_eos": False, 15 | "max_tokens": 4096, 16 | "logprobs": None, 17 | "prompt_logprobs": None, 18 | "skip_special_tokens": True, 19 | } 20 | 21 | 22 | ### 调用get_question函数,获取单链条agent的问题 23 | save_question_json = "/root/ld/ld_project/AutoPlan2/data_demo/question_react.json" # 保存query的json地址 24 | 25 | ### 调用get_react_data函数,获取简单Agent的训练数据 26 | input_question_json = "/root/ld/ld_project/AutoPlan2/data_demo/question_react_11_06.json" # 用于作为react数据的输入 27 | save_react_qa_json = "/root/ld/ld_project/AutoPlan2/data_demo/react_qa_react_11_06.json" # 用于保存单链条Agent训练数据 28 | inference_batch_size = 8 # 教师模型生成数据时的batch 29 | 30 | ### 调用get_complex_question函数,获取长链条agent数据 31 | save_complex_question_json = "/root/ld/ld_project/AutoPlan2/data_demo/question_complex_react.json" # 用于保存长链条复杂任务的query 32 | complex_example_json = '/root/ld/ld_project/AutoPlan2/data_demo/plan_example.json' # 用于长链条复杂任务的任务规划示例,请参考示例文件,最少写一个 33 | 34 | ### 调用get_complex_react_data函数,获取长链条agent训练数据 35 | input_complex_question_json = "/root/ld/ld_project/AutoPlan2/data_demo/plan_example.json" # 用于保存长链条复杂任务的query 36 | save_complex_react_qa_json = '/root/ld/ld_project/AutoPlan2/data_demo/complex_react_qa_11_07.json' 37 | inference_batch_size = 8 # 教师模型生成数据时的batch 38 | except_comple_react_json = '/root/ld/ld_project/AutoPlan2/data_demo/except_react_11_07.json' 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /data_demo/question_react_11_03.json: -------------------------------------------------------------------------------- 1 | { 2 | "image_gen_prompt": [ 3 | "请帮我描述一下https://example.com/image.jpg这张图片的内容", 4 | "看看这张图片https://example.com/photo.png里的人在做什么", 5 | "描述一下这张图片中的风景http://example.com/scenery.jpg", 6 | "这个图片https://example.com/image2.jpg中的动物是什么?", 7 | "帮我生成http://example.com/building.png这张图片的详细描述", 8 | "这张图片https://example.com/nature.jpg里有什么特征?", 9 | "描述一下本地图片C:/images/sunset.png的内容", 10 | "看看http://example.com/portrait.jpg这张图片中的人穿什么衣服", 11 | "描述图片https://example.com/car.png中的车辆信息", 12 | "这张图片http://example.com/art.jpg的艺术风格是什么?" 13 | ], 14 | "knowledge_graph": [ 15 | "查询豹2A7坦克的克制武器信息", 16 | "查找黑狐坦克的所有属性", 17 | "获取雷达的最大探测范围", 18 | "请告诉我装甲车的满载人数是多少?", 19 | "我想知道狙击枪的射程", 20 | "查看无人机的飞行高度等相关信息", 21 | "反坦克导弹的重量是多少?", 22 | "所有武器的适应场景是什么?", 23 | "请问步兵的携带武器有哪些?", 24 | "火箭炮的速度是多少?" 25 | ], 26 | "google_search": [ 27 | "帮我搜索一下现在的天气情况", 28 | "我想知道最新的科技新闻", 29 | "帮我查找一下中国的人口数量", 30 | "请查一下如何提高工作效率", 31 | "请问有哪些好的在线学习资源", 32 | "查一下今天的世界新闻", 33 | "帮我找一下最近流行的电影有哪些", 34 | "能帮我查一下2023年的诺贝尔奖获得者吗", 35 | "帮我看一下最受欢迎的编程语言是什么", 36 | "查找一下如何健康饮食" 37 | ], 38 | "military_information_search": [ 39 | "查询最近的军事新闻", 40 | "查找关于新式武器的情报", 41 | "获取某国的军事部署情况", 42 | "搜索当前的军事演习活动", 43 | "查询最新的军事技术发展", 44 | "查找某地区的军事冲突报道", 45 | "获取某国的军事战略分析", 46 | "搜索关于无人机使用的军方报告", 47 | "查询最新的军事合作消息", 48 | "查找关于海军部署的详细信息" 49 | ], 50 | "address_book": [ 51 | "张三的邮箱地址是什么?", 52 | "王五的公司地址在哪里?", 53 | "我方指挥所的电话是多少?", 54 | "侦察部队的邮箱地址是什么?", 55 | "指挥官的公司地址在哪里?", 56 | "李四的邮箱地址是多少?", 57 | "张三的公司地址在哪里?", 58 | "王五的电话是什么?", 59 | "我方指挥所的邮箱地址是什么?", 60 | "侦察部队的公司地址在哪里?" 61 | ], 62 | "QQ_Email": [ 63 | "帮我将‘今天下午三点开会’发到123456xxxyy@qq.com", 64 | "帮我将‘请查收最新的项目报告’发到987654xxxyy@qq.com", 65 | "帮我将‘生日快乐!祝你有个美好的一天’发到happybirthdayxxxyy@qq.com", 66 | "帮我将‘请确认收到上周五发出的邮件’发到confirmxxxyy@qq.com", 67 | "帮我将‘我们的会议时间改到了星期三上午十点’发到meetingtimexxxyy@qq.com", 68 | "帮我将‘请查看附件中的文件并提出意见’发到feedbackneededxxxyy@qq.com", 69 | "帮我将‘请回复您的出差安排’发到tripdetailsxxxyy@qq.com", 70 | "帮我将‘合同已签署,请尽快处理’发到contractsignedxxxyy@qq.com", 71 | "帮我将‘请更新您的联系方式’发到updatecontactxxxyy@qq.com", 72 | "帮我将‘提醒:明天是您的定期体检’发到healthcheckxxxyy@qq.com" 73 | ], 74 | "Situation_display": [ 75 | "请显示我方前线[100,350]处的态势图。", 76 | "我需要查看坐标[250,150]处的战场态势图,显示范围为200km。", 77 | "能否生成敌军营地[320,180]处的态势图?", 78 | "请展示坐标[50,50]的战场态势,默认范围即可。", 79 | "生成一下坐标[150,200]处的当前战场态势图像。", 80 | "我需要查看敌方指挥部[300,400]处的态势图,显示范围设为100km。", 81 | "显示坐标[75,225]处的态势图,范围为400km。", 82 | "请生成我方基地[20,300]的战场态势图。", 83 | "能显示一下坐标[200,100]处,显示范围为250km的战场态势么?", 84 | "帮我查看[370,90]处的态势图,默认范围即可。" 85 | ], 86 | "calendar": [ 87 | "请帮我查询今天的天气情况。", 88 | "我要知道明天的日出时间。", 89 | "昨天的日落时间是什么时候?", 90 | "帮我查看一下今天的月相信息。", 91 | "请告诉我明天有什么节日。", 92 | "昨天的农历日期是什么?", 93 | "今天的公历日期是多少?", 94 | "我需要了解明天的吉时。", 95 | "昨天有发生什么重要事件吗?", 96 | "今天有哪些纪念日?" 97 | ], 98 | "map_search": [ 99 | "请获取敌直升机的坐标和敌坦克的位置。", 100 | "请查询我方火箭炮和敌反坦克导弹的位置信息。", 101 | "请获取敌指挥中心和我方坦克的坐标信息。", 102 | "请查询敌坦克和我方发射阵地2的具体位置。", 103 | "请获得我方直升机和我方发射阵地1的坐标。", 104 | "请获取敌反坦克导弹和敌直升机的位置。", 105 | "请查询我方指挥所和敌指挥中心的坐标。", 106 | "请获得我方发射阵地2和敌坦克的位置信息。", 107 | "请获取我方坦克和我方发射阵地1的具体坐标。", 108 | "请查询敌直升机和敌指挥中心的位置。" 109 | ], 110 | "python_math": [ 111 | "50*5-10/2", 112 | "45+75-30*2", 113 | "20*(3+7)//5", 114 | "88/11+12**2", 115 | "15*4-(6+2)**2", 116 | "144/12-8*2", 117 | "10**3//50-(2+5)", 118 | "25/5+6*(3-1)", 119 | "9*9-(12//4)**2", 120 | "6**2*2-10/2" 121 | ], 122 | "weapon_launch": [ 123 | "启动敌反坦克导弹打击我方直升机[200,150]", 124 | "发射我方坦克攻击敌坦克[50,350]", 125 | "发射敌直升机打击我方指挥所[100,200]", 126 | "启动我方火箭炮打击敌反坦克导弹[300,100]", 127 | "发射敌坦克攻击我方指挥所[400,50]", 128 | "发射我方直升机打击地方直升机[250,250]", 129 | "启动我方指挥所打击敌坦克[120,300]", 130 | "发射敌反坦克导弹打击我方火箭炮[10,200]", 131 | "发射敌坦克攻击我方直升机[80,90]", 132 | "启动我方火箭炮打击敌反坦克导弹[180,230]" 133 | ], 134 | "math_model": [ 135 | "根据汽车的速度和A、B两地的距离100,计算单程时间", 136 | "求解100和30两个数字的平均数", 137 | "已知矩形的长10和宽20,计算矩形的面积", 138 | "求两个数字35和14的最大公约数", 139 | "求解直角三角形的两个直角边为12,21,计算斜边的长度", 140 | "计算一个数16的平方根", 141 | "已知三角形的底10和高5,求三角形的面积", 142 | "求给定一组数据的最大值[12,39,1,24,14]", 143 | "计算两个数15和239的加和", 144 | "求解不同数值35和13的最小公倍数" 145 | ], 146 | "distance_calculation": [ 147 | "计算我方战甲单位A1到敌方前线阵地B1的距离.", 148 | "计算我队狙击手S1到敌军狙击手S2的距离.", 149 | "计算我方坦克T1到敌方指挥中心H1的距离.", 150 | "计算我方运输车V1到中立补给点N1的距离.", 151 | "计算我方无人机U1到对方雷达R1的距离.", 152 | "计算敌方侦察兵R2到我方警戒哨P3的距离.", 153 | "计算我方指挥官C1到前线步兵F2的距离.", 154 | "计算我方机枪手G1到敌方堡垒F3的距离.", 155 | "计算我方前锋部队F1到敌方装甲车A2的距离.", 156 | "计算敌军狙击手S3到我方主基地H2的距离." 157 | ] 158 | } -------------------------------------------------------------------------------- /cpm_utils.py: -------------------------------------------------------------------------------- 1 | import json 2 | def save_cpm3_data(cpm3_data_path, cpm3_data): 3 | # 将列表转换为 JSON 格式的字符串 4 | json_str = json.dumps(cpm3_data, ensure_ascii=False, indent=4) 5 | 6 | # 将 JSON 字符串保存到文件 7 | with open(cpm3_data_path, "w", encoding="utf-8") as json_file: 8 | json_file.write(json_str) 9 | 10 | 11 | def switch_cpm_tool(tools): 12 | format_tool = { 13 | "type": "function", 14 | "function": { 15 | "name": "get_delivery_date", 16 | "description": "Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package'", 17 | "parameters": { 18 | "type": "object", 19 | "properties": { 20 | "order_id": { 21 | "type": "string", 22 | "description": "The customer's order ID.", 23 | } 24 | }, 25 | "required": ["order_id"], 26 | "additionalProperties": False, 27 | }, 28 | }, 29 | } 30 | cpm_tools = [] 31 | for tool in tools: 32 | format_tool["function"]["name"] = tool["name_for_model"] 33 | format_tool["function"]["description"] = tool["description_for_model"] 34 | # format_tool['function']["parameters"]['properties']= 35 | required_list = [] 36 | for param in tool["parameters"]: 37 | """param{ 38 | 'name': 'weapon_query', 39 | 'description': '武器名称', 40 | 'scope':['直升机','坦克','反坦克导弹','直升机','火箭炮','所有武器'], 41 | 'required': True, 42 | 'schema': {'type': 'string'}, 43 | }""" 44 | format_tool["function"]["parameters"]["properties"][param["name"]] = { 45 | "type": param["schema"]["type"], 46 | "description": param["description"], 47 | } 48 | if param["required"]: 49 | required_list.append(param["name"]) 50 | format_tool["function"]["parameters"]["required"] = required_list 51 | format_tool["function"]["parameters"]["additionalProperties"] = False 52 | cpm_tools.append(format_tool) 53 | return cpm_tools 54 | 55 | 56 | def get_cpm_function_call(): 57 | with open(save_react_qa_json, "r", encoding="utf-8") as file: 58 | # 将json文件内容解析为Python对象 59 | react_qa = json.load(file) 60 | cpm_tool = switch_cpm_tool(tools) 61 | tokenizer = AutoTokenizer.from_pretrained(cpm3_path, trust_remote_code=True) 62 | cpm_fc_train_data = [] 63 | for react in react_qa: 64 | messages = [ 65 | { 66 | "role": "system", 67 | "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user.", 68 | } 69 | ] 70 | query = react["input"].split("Question: ")[-1] 71 | print(query) 72 | react_str = list(react.values())[-1] 73 | Thought1, Action, Action_Input, Observation, Thought2, Final_Answer = split_react_data( 74 | react_str 75 | ) 76 | if ( 77 | Thought1 78 | and Action 79 | and Action_Input 80 | and Observation 81 | and Thought2 82 | and Final_Answer 83 | ): 84 | messages.append({"role": "user", "content": query}) 85 | prompt = tokenizer.apply_chat_template( 86 | messages, tools=cpm_tool, tokenize=False, add_generation_prompt=True 87 | ) 88 | cpm_thought1 = "<|thought_start|>\n{}\n<|thought_end|>".format(Thought1) 89 | cpm_function_and_param = "\n<|tool_call_start|>\n```python\n{}({})\n```\n<|tool_call_end|>".format( 90 | Action, re.sub(": ", "=", Action_Input) 91 | ) 92 | 93 | cpm_fc_train_data.append( 94 | [ 95 | {"role": "system", "content": prompt.split("<|im_end|>")[0][19:]}, 96 | {"role": "user", "content": query}, 97 | { 98 | "role": "assistant", 99 | "content": cpm_thought1 + cpm_function_and_param, 100 | }, 101 | ] 102 | ) 103 | 104 | cpm_response = "<|im_end|>\n<|im_start|>tool\n{}<|im_end|>\n<|im_start|>assistant\n".format( 105 | Observation 106 | ) 107 | cpm_thought2 = "<|thought_start|>\n{}\n<|thought_end|>\n".format(Thought2) 108 | cpm_answer = Final_Answer 109 | cpm_fc_train_data.append( 110 | [ 111 | {"role": "system", "content": prompt.split("<|im_end|>")[0][19:]}, 112 | { 113 | "role": "user", 114 | "content": query 115 | + "<|im_start|>assistant\n" 116 | + cpm_function_and_param 117 | + cpm_response, 118 | }, 119 | {"role": "assistant", "content": cpm_thought2 + cpm_answer}, 120 | ] 121 | ) 122 | else: 123 | print(1) 124 | continue 125 | # cpm_fc_train_data.append({"role":"system",'content':prompt+cpm_function_and_param+cpm_response,'role':'assistant','content':cpm_thought2+cpm_answer}) 126 | save_cpm3_data(cpm3_data_save_path, cpm_fc_train_data) 127 | print( 128 | "{}条cpm3 function call数据已经保存到{}".format( 129 | len(cpm_fc_train_data), cpm3_data_save_path 130 | ) 131 | ) -------------------------------------------------------------------------------- /data_demo/question_react.json: -------------------------------------------------------------------------------- 1 | { 2 | "image_gen_prompt": [ 3 | "能否描述一下http://example.com/image1.jpg这张图片中的场景?", 4 | "请告诉我https://sample.com/photo2.png里的动物是什么?", 5 | "我想知道www.imagesite.com/pic3.jpeg中的人物正在做什么。", 6 | "描述下http://picserver.org/img4.bmp这个链接的图片里有什么。", 7 | "请问在https://gallery.net/art5.jpg这幅画中,主要的颜色是什么?", 8 | "帮我分析一下www.photoalbum.com/snap6.gif这张照片的情绪氛围。", 9 | "请描述一下https://example.com/image1.jpg这张图片上的风景是什么样的?", 10 | "能否告诉我http://www.example.com/pic2.png里的动物是什么?", 11 | "我想知道https://example.org/photo3.jpeg中的建筑物名字,能帮我吗?", 12 | "请根据http://sample.com/art4.jpg生成一段文字描述画中的人物。", 13 | "帮我分析一下https://artgallery.net/work5.bmp这幅作品的风格和特点。" 14 | ], 15 | "knowledge_graph": [ 16 | "请告诉我豹2A7坦克的射程是多少?", 17 | "黑狐坦克能够适应哪些场景?", 18 | "装甲车可以携带什么武器?", 19 | "狙击枪的有效射程是多少?", 20 | "反坦克导弹的重量是多少?", 21 | "帮我查一下豹2A7坦克的射程", 22 | "我想知道黑狐坦克的速度是多少?", 23 | "请告诉我雷达的适应场景。", 24 | "反坦克导弹能携带哪些武器?", 25 | "装甲车满载时可以坐多少人?", 26 | "狙击枪的有效射程是多少?" 27 | ], 28 | "google_search": [ 29 | "帮我找一下最近的科技新闻", 30 | "搜索一下如何做蛋糕的方法", 31 | "查询一下巴黎圣母院的历史背景", 32 | "了解最新的医疗健康资讯", 33 | "查找关于人工智能的最新研究进展", 34 | "帮我找一下最近的科技新闻", 35 | "搜索如何制作蛋糕的方法", 36 | "查询一下最近的天气预报", 37 | "查找关于人工智能的最新研究进展", 38 | "了解最新的国际政治动态" 39 | ], 40 | "military_information_search": [ 41 | "最近有哪些重要的军事演习?", 42 | "搜索有关新型战斗机的最新报道。", 43 | "查找关于某国军力部署的最新情报。", 44 | "请查询最新的国际军事动态。", 45 | "最近的军事新闻有哪些?", 46 | "查询一下最新的军事情报网信息。", 47 | "帮我找一下关于航空母舰的技术资料。", 48 | "搜索有关现代战争中无人机的应用的文章。", 49 | "查找有关新型导弹系统的发展动态。", 50 | "了解近期各国的军事演习情况。" 51 | ], 52 | "address_book": [ 53 | "张三的电子邮件地址是什么?", 54 | "王五的公司地址在哪里?", 55 | "我方指挥所的电话号码是多少?", 56 | "侦察部队的邮箱地址是什么?", 57 | "张三的邮箱地址是什么?", 58 | "王五的公司地址在哪里?", 59 | "我方指挥所的电话号码是多少?", 60 | "侦察部队的联系邮箱是什么?", 61 | "指挥官的家庭住址可以提供吗?", 62 | "李四的工作单位地址是哪里?" 63 | ], 64 | "QQ_Email": [ 65 | "请将“会议取消,改期至下周一”发送到123456789@qq.com", 66 | "帮我给2837465912@outlook.com发一封邮件,内容是“项目延期至下月”", 67 | "发送“生日快乐!”到happybirthday@sina.com", 68 | "请帮我把“报告已准备好,请查收附件。”发给reportreviewer@gmail.com", 69 | "将“周末一起吃饭吧?”发送给weekenddinner@foxmail.com。", 70 | "请将‘会议取消,改期通知’发到zhangsan@126.com", 71 | "帮我给lisi@163.com发送邮件,内容是‘项目进展顺利,预计按时完成’", 72 | "请帮我把‘生日快乐!附带礼物清单’发给xiaoming@qq.com", 73 | "将‘合同已审核,请查收附件’发送至contract@example.com.cn", 74 | "给customer_service@sina.com发送一封邮件,内容为‘产品使用反馈及建议’。", 75 | "帮我把“关于下周一的会议安排”发给wangwu@sohu.com。" 76 | ], 77 | "Situation_display": [ 78 | "我需要查看友军基地[200,300]处的态势图,请显示。", 79 | "请为我生成位于坐标[150,150]的战场态势图像,范围设为250km。", 80 | "我想了解敌军驻扎点[350,180]周围的战场情况,请提供态势图。", 81 | "能否给我展示一下在坐标位置[123,456]上的当前战场局势?", 82 | "请显示友军前沿阵地[89,76]周围150公里内的最新战场动态图。", 83 | "对于目标区域[287,349],我需要查看其周边的军事力量分布情况,请生成图片。", 84 | "我想查看位于[150,300]的友军基地周围的战场态势,范围设为200km,请显示。", 85 | "请为我生成一个以坐标[250,180]为中心,半径为150km的战场态势图。", 86 | "想要了解坐标点[345,78]附近的敌情,能给我看下该区域的态势图吗?", 87 | "坐标[123,456]处有异常活动,请提供此位置周围300km内的详细态势图像。", 88 | "需要在地图上查看坐标[99,99]周围123km范围内的情况,请帮助生成图片。", 89 | "能否帮我获取并显示以坐标[278, 146]为中心、半径为87km的当前战场情况?" 90 | ], 91 | "calendar": [ 92 | "请告诉我明天的日期", 93 | "昨天是几号?", 94 | "下周一是什么时候?", 95 | "这个周末具体是哪两天?", 96 | "上周五是哪一天?", 97 | "请告诉我昨天的日期是什么?", 98 | "明天是几号?", 99 | "上周六是哪一天?", 100 | "下周五是几号?", 101 | "本周日的具体日期是什么?", 102 | "上个月的今天是哪一天?" 103 | ], 104 | "map_search": [ 105 | "敌直升机的现在在哪里", 106 | "我方指挥所的现在在哪里", 107 | "敌坦克的现在在哪里", 108 | "我方火箭炮的现在在哪里", 109 | "我方发射阵地1的现在在哪里", 110 | "敌直升机的现在在哪里", 111 | "我方指挥所的位置是什么", 112 | "敌坦克的现在位置在哪", 113 | "我方火箭炮的位置信息是什么", 114 | "我方发射阵地1的具体位置在哪里" 115 | ], 116 | "python_math": [ 117 | "5 + 10 * 2", 118 | "(4 + 6) ** 2 - 3 * 7", 119 | "8 / 4 + 9 - 3 ** 2", 120 | "(15 - 7) * (2 + 3)", 121 | "sqrt(16) + sqrt(9)", 122 | "5 * (10 + 2) - 3**2", 123 | "(15 + 7) * (8 - 3)", 124 | "20 / 4 + 6 * 2 - 9", 125 | "(4 + 6) ** 2 / 5 - 3 * (7 - 4)", 126 | "100 // (5 + 5) * (8 - 2)", 127 | "(9 ** 2) / (3 * (4 + 5))" 128 | ], 129 | "weapon_launch": [ 130 | "使用我方直升机打击敌坦克[200,150]", 131 | "发射我方火箭炮攻击敌反坦克导弹[35,275]", 132 | "我方指挥所对敌直升机发起攻击[300,80]", 133 | "用我方坦克摧毁地方火箭炮[180,195]", 134 | "发射我方反坦克导弹打击敌指挥所[45,45]", 135 | "使用我方直升机打击敌坦克[200, 150]", 136 | "发射我方火箭炮攻击敌反坦克导弹[350, 250]", 137 | "我方指挥所对敌直升机进行攻击[180, 80]", 138 | "调用我方坦克打击敌人指挥所位置[45, 95]", 139 | "指挥我方火箭炮对准敌反坦克导弹坐标[76, 34]", 140 | "使用我方直升机打击位于坐标[321, 78]的敌军目标" 141 | ], 142 | "math_model": [ 143 | "根据给定的两个数,计算它们的乘积。", 144 | "已知一个正方形的边长,求该正方形的面积。", 145 | "给出三个数字,找出其中的最大值。", 146 | "已知一个圆的半径,计算该圆的周长。", 147 | "根据两个数,计算它们相除的结果并保留两位小数。", 148 | "给定一个数值,求它的平方根(结果保留两位小数)。", 149 | "已知一个长方形的长和宽,计算其面积。", 150 | "根据圆的半径,计算其周长。", 151 | "有一批苹果,如果每个篮子装5个苹果,则剩下3个;如果每个篮子装6个,则刚好装完。求这批苹果最少有多少个?", 152 | "计算两个数的最大值:123 和 456。", 153 | "如果一个人每天存10元钱,一年(非闰年)能存多少元?", 154 | "给定三个数字2, 4, 和8,请找出其中最小的一个。" 155 | ], 156 | "distance_calculation": [ 157 | "计算敌方坦克[300,150]和其他所有单位的距离", 158 | "计算友军步兵[120,80]和其他所有单位的距离", 159 | "计算敌方战斗机[450,250]和其他所有单位的距离", 160 | "计算我方装甲车[75,225]和其他所有单位的距离", 161 | "计算敌方直升机[375,360]和其他所有单位的距离", 162 | "计算敌方坦克[100,250]和其他所有单位的距离", 163 | "计算我方步兵[350,450]和其他所有单位的距离", 164 | "计算敌方直升机[150,200]和其他所有单位的距离", 165 | "计算我方坦克[400,600]和其他所有单位的距离", 166 | "计算地方炮兵[75,89]和其他所有单位的距离", 167 | "计算友军侦察车[333,222]和其他所有单位的距离" 168 | ] 169 | } -------------------------------------------------------------------------------- /data_demo/question_react_11_06.json: -------------------------------------------------------------------------------- 1 | { 2 | "image_gen_prompt": [ 3 | "能否描述一下http://example.com/image1.jpg这张图片中的场景?", 4 | "请告诉我https://sample.com/photo2.png里的动物是什么?", 5 | "我想知道www.imagesite.com/pic3.jpeg中的人物正在做什么。", 6 | "描述下http://picserver.org/img4.bmp这个链接的图片里有什么。", 7 | "请问在https://gallery.net/art5.jpg这幅画中,主要的颜色是什么?", 8 | "帮我分析一下www.photoalbum.com/snap6.gif这张照片的情绪氛围。", 9 | "请描述一下https://example.com/image1.jpg这张图片上的风景是什么样的?", 10 | "能否告诉我http://www.example.com/pic2.png里的动物是什么?", 11 | "我想知道https://example.org/photo3.jpeg中的建筑物名字,能帮我吗?", 12 | "请根据http://sample.com/art4.jpg生成一段文字描述画中的人物。", 13 | "帮我分析一下https://artgallery.net/work5.bmp这幅作品的风格和特点。" 14 | ], 15 | "knowledge_graph": [ 16 | "请告诉我豹2A7坦克的射程是多少?", 17 | "黑狐坦克能够适应哪些场景?", 18 | "装甲车可以携带什么武器?", 19 | "狙击枪的有效射程是多少?", 20 | "反坦克导弹的重量是多少?", 21 | "帮我查一下豹2A7坦克的射程", 22 | "我想知道黑狐坦克的速度是多少?", 23 | "请告诉我雷达的适应场景。", 24 | "反坦克导弹能携带哪些武器?", 25 | "装甲车满载时可以坐多少人?", 26 | "狙击枪的有效射程是多少?" 27 | ], 28 | "google_search": [ 29 | "帮我找一下最近的科技新闻", 30 | "搜索一下如何做蛋糕的方法", 31 | "查询一下巴黎圣母院的历史背景", 32 | "了解最新的医疗健康资讯", 33 | "查找关于人工智能的最新研究进展", 34 | "帮我找一下最近的科技新闻", 35 | "搜索如何制作蛋糕的方法", 36 | "查询一下最近的天气预报", 37 | "查找关于人工智能的最新研究进展", 38 | "了解最新的国际政治动态" 39 | ], 40 | "military_information_search": [ 41 | "最近有哪些重要的军事演习?", 42 | "搜索有关新型战斗机的最新报道。", 43 | "查找关于某国军力部署的最新情报。", 44 | "请查询最新的国际军事动态。", 45 | "最近的军事新闻有哪些?", 46 | "查询一下最新的军事情报网信息。", 47 | "帮我找一下关于航空母舰的技术资料。", 48 | "搜索有关现代战争中无人机的应用的文章。", 49 | "查找有关新型导弹系统的发展动态。", 50 | "了解近期各国的军事演习情况。" 51 | ], 52 | "address_book": [ 53 | "张三的电子邮件地址是什么?", 54 | "王五的公司地址在哪里?", 55 | "我方指挥所的电话号码是多少?", 56 | "侦察部队的邮箱地址是什么?", 57 | "张三的邮箱地址是什么?", 58 | "王五的公司地址在哪里?", 59 | "我方指挥所的电话号码是多少?", 60 | "侦察部队的联系邮箱是什么?", 61 | "指挥官的家庭住址可以提供吗?", 62 | "李四的工作单位地址是哪里?" 63 | ], 64 | "QQ_Email": [ 65 | "请将“会议取消,改期至下周一”发送到123456789@qq.com", 66 | "帮我给2837465912@outlook.com发一封邮件,内容是“项目延期至下月”", 67 | "发送“生日快乐!”到happybirthday@sina.com", 68 | "请帮我把“报告已准备好,请查收附件。”发给reportreviewer@gmail.com", 69 | "将“周末一起吃饭吧?”发送给weekenddinner@foxmail.com。", 70 | "请将‘会议取消,改期通知’发到zhangsan@126.com", 71 | "帮我给lisi@163.com发送邮件,内容是‘项目进展顺利,预计按时完成’", 72 | "请帮我把‘生日快乐!附带礼物清单’发给xiaoming@qq.com", 73 | "将‘合同已审核,请查收附件’发送至contract@example.com.cn", 74 | "给customer_service@sina.com发送一封邮件,内容为‘产品使用反馈及建议’。", 75 | "帮我把“关于下周一的会议安排”发给wangwu@sohu.com。" 76 | ], 77 | "Situation_display": [ 78 | "我需要查看友军基地[200,300]处的态势图,请显示。", 79 | "请为我生成位于坐标[150,150]的战场态势图像,范围设为250km。", 80 | "我想了解敌军驻扎点[350,180]周围的战场情况,请提供态势图。", 81 | "能否给我展示一下在坐标位置[123,456]上的当前战场局势?", 82 | "请显示友军前沿阵地[89,76]周围150公里内的最新战场动态图。", 83 | "对于目标区域[287,349],我需要查看其周边的军事力量分布情况,请生成图片。", 84 | "我想查看位于[150,300]的友军基地周围的战场态势,范围设为200km,请显示。", 85 | "请为我生成一个以坐标[250,180]为中心,半径为150km的战场态势图。", 86 | "想要了解坐标点[345,78]附近的敌情,能给我看下该区域的态势图吗?", 87 | "坐标[123,456]处有异常活动,请提供此位置周围300km内的详细态势图像。", 88 | "需要在地图上查看坐标[99,99]周围123km范围内的情况,请帮助生成图片。", 89 | "能否帮我获取并显示以坐标[278, 146]为中心、半径为87km的当前战场情况?" 90 | ], 91 | "calendar": [ 92 | "请告诉我明天的日期", 93 | "昨天是几号?", 94 | "下周一是什么时候?", 95 | "这个周末具体是哪两天?", 96 | "上周五是哪一天?", 97 | "请告诉我昨天的日期是什么?", 98 | "明天是几号?", 99 | "上周六是哪一天?", 100 | "下周五是几号?", 101 | "本周日的具体日期是什么?", 102 | "上个月的今天是哪一天?" 103 | ], 104 | "map_search": [ 105 | "敌直升机的现在在哪里", 106 | "我方指挥所的现在在哪里", 107 | "敌坦克的现在在哪里", 108 | "我方火箭炮的现在在哪里", 109 | "我方发射阵地1的现在在哪里", 110 | "敌直升机的现在在哪里", 111 | "我方指挥所的位置是什么", 112 | "敌坦克的现在位置在哪", 113 | "我方火箭炮的位置信息是什么", 114 | "我方发射阵地1的具体位置在哪里" 115 | ], 116 | "python_math": [ 117 | "5 + 10 * 2", 118 | "(4 + 6) ** 2 - 3 * 7", 119 | "8 / 4 + 9 - 3 ** 2", 120 | "(15 - 7) * (2 + 3)", 121 | "sqrt(16) + sqrt(9)", 122 | "5 * (10 + 2) - 3**2", 123 | "(15 + 7) * (8 - 3)", 124 | "20 / 4 + 6 * 2 - 9", 125 | "(4 + 6) ** 2 / 5 - 3 * (7 - 4)", 126 | "100 // (5 + 5) * (8 - 2)", 127 | "(9 ** 2) / (3 * (4 + 5))" 128 | ], 129 | "weapon_launch": [ 130 | "使用我方直升机打击敌坦克[200,150]", 131 | "发射我方火箭炮攻击敌反坦克导弹[35,275]", 132 | "我方指挥所对敌直升机发起攻击[300,80]", 133 | "用我方坦克摧毁地方火箭炮[180,195]", 134 | "发射我方反坦克导弹打击敌指挥所[45,45]", 135 | "使用我方直升机打击敌坦克[200, 150]", 136 | "发射我方火箭炮攻击敌反坦克导弹[350, 250]", 137 | "我方指挥所对敌直升机进行攻击[180, 80]", 138 | "调用我方坦克打击敌人指挥所位置[45, 95]", 139 | "指挥我方火箭炮对准敌反坦克导弹坐标[76, 34]", 140 | "使用我方直升机打击位于坐标[321, 78]的敌军目标" 141 | ], 142 | "math_model": [ 143 | "根据给定的两个数,计算它们的乘积。", 144 | "已知一个正方形的边长,求该正方形的面积。", 145 | "给出三个数字,找出其中的最大值。", 146 | "已知一个圆的半径,计算该圆的周长。", 147 | "根据两个数,计算它们相除的结果并保留两位小数。", 148 | "给定一个数值,求它的平方根(结果保留两位小数)。", 149 | "已知一个长方形的长和宽,计算其面积。", 150 | "根据圆的半径,计算其周长。", 151 | "有一批苹果,如果每个篮子装5个苹果,则剩下3个;如果每个篮子装6个,则刚好装完。求这批苹果最少有多少个?", 152 | "计算两个数的最大值:123 和 456。", 153 | "如果一个人每天存10元钱,一年(非闰年)能存多少元?", 154 | "给定三个数字2, 4, 和8,请找出其中最小的一个。" 155 | ], 156 | "distance_calculation": [ 157 | "计算敌方坦克[300,150]和其他所有单位的距离", 158 | "计算友军步兵[120,80]和其他所有单位的距离", 159 | "计算敌方战斗机[450,250]和其他所有单位的距离", 160 | "计算我方装甲车[75,225]和其他所有单位的距离", 161 | "计算敌方直升机[375,360]和其他所有单位的距离", 162 | "计算敌方坦克[100,250]和其他所有单位的距离", 163 | "计算我方步兵[350,450]和其他所有单位的距离", 164 | "计算敌方直升机[150,200]和其他所有单位的距离", 165 | "计算我方坦克[400,600]和其他所有单位的距离", 166 | "计算地方炮兵[75,89]和其他所有单位的距离", 167 | "计算友军侦察车[333,222]和其他所有单位的距离" 168 | ] 169 | } -------------------------------------------------------------------------------- /data_demo/question_complex_react.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "在今天的军事演习中,指挥官需要了解我方坦克和敌方坦克之间的距离,并且要将这个信息发送给张三。": "\n1. 使用map_search获取“我方坦克”的坐标A。\n2. 使用map_search获取“敌坦克”的坐标B。\n3. 使用distance_calculation计算A到B的距离C。\n4. 使用address_book查询张三的QQ_Email地址D。\n5. 使用QQ_Email将距离C的信息发送给张三的QQ_Email地址D。\n" 4 | }, 5 | { 6 | "为了确保明天上午8点前能够完成对敌指挥中心的情报收集,侦察部队需确定从当前地点到达目标位置所需的时间。请提供具体时间并通知李四该计划是否可行。": "\n1. 使用calendar设置时间为明天上午8点作为目标时间T1。\n2. 使用map_search获取“侦察部队”当前位置坐标P1以及“敌指挥中心”位置坐标P2。\n3. 使用distance_calculation计算P1到P2的距离D1,并使用knowledge_graph查询侦察部队的速度S1来估算所需时间T2(假设直线路程)。\n4. 计算实际出发时间T3 = T1 - T2 - 剩余缓冲时间(例如:半小时)以确保准时到达并有足够的时间进行情报收集工作准备等事宜安排;\n5. 如果当前时间为今天下午6点,则判断是否满足条件;如果不满足则建议调整行动计划或增加额外资源支持;\n6. 通过address_book查找李四的联系方式E-mail_address;\n7.使用QQ_Email向李四报告上述情况及最终决定方案内容说明等信息以便其做出进一步指示或反馈意见等处理措施落实到位后执行下一步行动指令下达等工作流程推进实施过程顺利开展直至圆满完成各项既定目标任务要求为止.\n" 7 | }, 8 | { 9 | "假设现在是昨天晚上9点钟,我方火箭炮需要在今天中午十二点前打击位于[300, 350]的目标。请问我们需要提前多久开始准备?": "\n1.使用calendar设定当前时间为昨天晚上9点钟为起始时刻time_0;\n2.设定攻击时间为今天中午十二点为结束时刻time_1;\n3.计算从time_0到time_1之间的时间差Δt即为总可用准备时长X小时;\n4.使用weapon_launch参数设置武器名称为\"我方火箭炮\"、被打击单位名称为空(因为直接指定坐标)、被打击目标坐标的x=300,y=350;\n5.利用知识图谱knowledge_graph查询关于\"我方火箭炮\"的相关属性如发射准备时间和飞行至目标地所需时长Y分钟;\n6.根据步骤4得到的数据结合步骤5中的发射准备时间和飞行至目标地所需的总时长Z分钟来评估是否能在规定时间内完成所有准备工作并及时发起攻击,若不能则提出相应的优化建议或者推迟攻击计划直到满足条件为止.\n7.如果一切正常,则通过地图搜索(map_search)确认所有相关单位的位置信息以保证作战指令的有效传达与执行.\n8.(可选)若有必要可通过通讯录(address_book)联系相关人员通报情况并协调行动.\n9.(可选)最后用邮件(QQ_Email)的形式正式通知相关人员作战计划详情.\n" 10 | } 11 | ][ 12 | { 13 | "计算我方坦克从当前位置到达敌指挥中心所需时间,并评估是否可以在此时间内完成对敌反坦克导弹的打击。": "\n1. 使用knowledge_graph查询我方坦克的速度A。\n2. 使用map_search获取我方坦克的位置B和敌指挥中心的位置C。\n3. 使用distance_calculation计算B到C的距离D。\n4. 计算以速度A行驶距离D所需的时间E。\n5. 使用weapon_launch模拟发射武器,输入参数为“我方坦克”作为weapon_query,“敌反坦克导弹”作为target_name及其坐标F,判断在时间E内能否完成攻击G。\n6. 如果步骤5的结果是肯定的,则返回可行;否则返回不可行并给出理由(如:无法在规定时间内到达目标或击毁目标)。\n" 14 | }, 15 | { 16 | "向张三汇报今日凌晨至午夜期间所有单位的动态变化情况,并附带地图上的位置信息和可能的影响分析报告。": "\n1. 使用calendar获取今天的日期H(假设为具体某日)。\n2. 通过military_information_search搜索H日期内0点到24点之间的军事新闻I,重点关注与各单位动态相关的信息J。(注意需要将搜索关键词转化为具体格式)\n3. 利用map_search获取当前时刻所有单位的具体位置K以及历史记录L(如果工具支持的话),并与J中提到的变化进行对比M,确定哪些信息是最新的N、哪些发生了变动O、哪些没有改变P等细节Q;\n4. 对比新旧数据R来推测这些变动S可能导致的影响T;\n5. 将以上收集整理的信息U汇总成一份详细的报告V;\n6. 通过address_book查找张三W的联系邮箱X;\n7. 最后使用QQ_Email功能Y发送邮件Z给张三X包含最终报告V及必要附件AA(如有)。 \n" 17 | }, 18 | { 19 | "请求支援!侦察部队发现敌人正在集结一支由豹2A7坦克组成的车队。请尽快查明该车型的所有属性,并估算出我们至少需要多少架直升机才能摧毁这支部队?": "\n1. 用knowledge_graph查询豹2A7坦克的所有属性列表B,特别是其射程C、重量D、速度E等关键指标F;\n2. 分析这些数据G以确定最佳对抗策略H:比如考虑使用何种武器I(例如直升机携带导弹)最为有效J;\n3.利用python_math根据已知条件K(包括但不限于每枚导弹可造成的伤害L与单个豹2A7被彻底摧毁所需的总损伤值M),计算出理论上击败整个车队所需的最小数量N;\n4.再次运用knowledge_graph查询所选对抗手段(如特定型号的武装直升机)的相关性能指标O,特别关注载弹量P及飞行速度Q等因素R;\n5.结合第3步得出的数量需求S与第4步获得的数据T,进一步细化实际作战方案U,即究竟出动几架飞机V能够确保行动成功W同时又尽可能减少资源浪费X;\n6.最后形成书面建议Y并通过相应渠道传达给决策者Z.\n" 20 | } 21 | ][ 22 | { 23 | "确认我方坦克是否能在我方火箭炮的射程范围内打击敌指挥中心。": "\n1. 使用knowledge_graph获取我方火箭炮的射程A。\n2. 使用map_search获取敌指挥中心的位置B和我方坦克的位置C。\n3. 使用distance_calculation计算我方坦克到敌指挥中心的距离D。\n4. 比较距离D与火箭炮射程A,判断是否在有效攻击范围内。\n5. 如果不在有效攻击范围内,使用knowledge_graph查询我方坦克的最大速度E,并计算将位置调整到射程范围内的所需时间F(如果需要)。\n6. 评估行动可行性并制定进一步计划或报告无法完成的任务原因。\n" 24 | }, 25 | { 26 | "为防止敌反坦克导弹对我装甲车部队造成威胁,需确定所有可能被其发现的目标及其距离,并分析这些目标的安全性等级(根据距离远近)以决定优先保护顺序。": "\n1. 使用knowledge_graph查询敌反坦克导弹的探测范围A和最大射程B。\n2. 使用map_search获取地图上所有单位的位置信息C,包括但不限于友军装甲车、其他重要设施等潜在目标D以及己方可能提供掩护或干扰的单位E位置信息F等G个不同类别的H个具体单位I的位置J列表K。 \n3. 对于每个潜在目标L,使用distance_calculation分别计算它与已知敌人反坦克导弹发射点M之间的直线距离N。 \n4. 根据步骤3中得到的数据O,对所有潜在威胁进行分类P: 将处于探测范围Q内但超出最大射击R限制S外T的目标U定义为低风险V;位于两者之间W区域X内的Y视为中度风险Z;而那些同时满足探测AA和射击BB条件CC的目标DD则属于高危EE级别FF。 GG.\n5. 根据风险级别HH排序II并将结果JJ反馈给指挥部KK以便做出合理LL策略MM决策NN.\n6.(可选)针对最高风险OO目标PP提出具体QQ防御RR建议SS.\n7.(可选)若有必要TT,则考虑UU派遣VV无人机WW或其他XX装备YY执行ZZ侦察[或者]\\监测\\干扰]等工作].\n8.(最终输出)汇总报告AAA供领导审阅BBB并指导后续CCC行动DDD.\n" 27 | } 28 | ][ 29 | { 30 | "如何评估我方坦克在特定区域内的生存能力?": "\n1. 使用map_search获取敌方所有单位的位置信息,包括敌直升机、敌反坦克导弹等。\n2. 使用distance_calculation计算我方坦克与这些敌对单位的距离。\n3. 使用knowledge_graph查询我方坦克的射程、速度和适应场景属性。\n4. 使用knowledge_graph查询敌对单位的射程、速度和克制武器属性。\n5. 根据距离和双方武器性能评估潜在威胁等级。\n6. 使用calendar获取当前时间,结合态势显示工具观察未来一段时间内战场态势变化,判断是否存在对我方坦克不利的情况。\n7. 综合以上信息分析并给出建议:是否需要调整位置或采取其他防御措施以提高生存率。\n" 31 | }, 32 | { 33 | "如果敌人试图用无人机攻击我方指挥所,我们能否及时发现并做出反应?": "\n1. 使用knowledge_graph查询无人机的飞行高度A及探测范围B。\n2. 通过map_search定位我方指挥所的确切位置C,并确定其周边地形特征D(例如山地可能阻碍信号)。\n3. 利用知识图谱中的雷达参数E(如探测范围),评估从不同方向接近时雷达能提前多久发现无人机F = (C - B) / E.\n4. 同样使用knowledge_graph获得雷达的工作频率G以及可能存在的干扰因素H,确认是否有办法减少误报率I = G * H.\n5. 结合上述数据与实际作战环境J(天气状况等),计算出最终预警时间K = F + I - J.\n6. 若K小于安全阈值L,则考虑部署更多侦察部队M或者增强现有设备N;否则保持现状O.\n7. 最后利用google_search查找相关案例研究P以验证假设Q,并据此制定应对策略R.\n8.定期更新情报S确保决策依据T始终准确有效U.\n" 34 | }, 35 | { 36 | "在遭遇大规模地面进攻时,如何快速调动各兵种进行协同作战?": "\n1.使用military_information_search搜索最近一次类似战斗情景V下的战术运用W及效果X.\n2.根据所得情报Y选择合适的反击方案Z, 包括但不限于动用哪些兵种[如装甲车]及其作用[]比如提供火力支援].\n3.运用address_book联系各个相关部门^, 获取他们的实时状态_ (如人员配备情况`) 和可用资源a .\n4 . 对比所需兵力b与实际可调动力量c , 调整计划d直至两者匹配e .\n5 . 通过QQ_Email向每位负责人发送详细指令f , 包括行动时间g 、目标h 和具体职责i .\n6 . 利用weapon_launch模拟各阶段j 的打击过程k , 验证预案l 是否可行m .\n7 . 在整个过程中n ,持续关注地图o上的动态p , 并准备随时q 调整r 计划s 以应对t 突发u 情况v .\n8 . 定期w 进行x 复盘y 分析z A ,总结经验B 并优化流程C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z 以便下一次能够更加高效地完成此类操作A' .\n9 . 最终形成一套完整的应急预案B', 可供后续参考借鉴C'.\n " 37 | } 38 | ][ 39 | { 40 | "我方需要在敌方指挥中心附近部署一支侦察部队,请确定最佳的部署位置,并计算从我方指挥所到该位置所需的时间。": "\n1. 使用map_search获取敌指挥中心的位置A和我方指挥所的位置B。\n2. 使用distance_calculation计算从我方指挥所到敌指挥中心的距离C。\n3. 根据军事常识,选择距离敌指挥中心一定范围内的隐蔽地点作为最佳部署位置D(例如距离C的80%处)。\n4. 使用knowledge_graph获取侦察部队的速度E。\n5. 计算从我方指挥所到最佳部署位置D所需的时间F(即距离除以速度)。\n6. 通过moving_command工具控制侦察部队移动至目标地点D。\n" 41 | }, 42 | { 43 | "假设我们获得了情报,得知敌人将在明天对我军火箭炮阵地发起攻击,请制定一个防御方案来确保火箭炮阵地的安全,并通知相关人员做好准备。": "\n1. 使用military_information_search搜索有关防御策略的信息,特别是针对火箭炮阵地的防护措施A。\n2. 使用calendar查询明天的具体时间B,以便准确传达信息给相关人员C。\n3. 通过address_book查找负责火箭炮阵地人员的联系方式D(如电话、邮箱等)以及上级指挥部的相关联系人E。\n4. 将获得的情报与防御方案整合成邮件内容F,并使用QQ_Email向相关负责人发送邮件G,提醒他们注意安全并采取相应措施H。 \n5. 如果有必要,在邮件中附上具体的行动计划或指导文件I。 \n6.根据收到回复确认是否所有相关单位都已接收到消息J。 \n7.如果未收到回复,则再次发送或者改用其他通讯方式K。 \n8.持续监控战场态势L,并随时准备调整计划M。 \n9.必要时启动武器发射系统N,准备反击O。 \n10.完成整个行动P后报告上级Q.\n" 44 | }, 45 | { 46 | "为了应对可能发生的化学武器袭击,我们需要快速了解周围环境是否有毒气泄露的风险点,并立即通知附近的友军单位提高警惕性,请提供解决方案及执行步骤说明?": "\n1. 使用google_search搜索关于化学武器泄漏风险评估的方法和技术A, 获取相关信息B.\n2. 结合地图数据利用map_search找到周边可能存在危险物质存储设施或其他潜在威胁区域C.\n3. 对比这些潜在威胁区与友军单位之间的相对位置关系D, 筛选出受影响较大的几个关键点E.\n4 . 通过address_book查找这些关键点所在区域内所有友军单位及其负责人F (包括姓名、职务、联系电话等).\n5 . 制作紧急预警信息G, 包括但不限于:可能发生的情况H、建议采取的安全措施I及联系方式J.\n6 . 利用QQ_Email将预警信息迅速发送给上述筛选出的所有友好单位K, 并要求对方确认接收L.\n7 . 安排专人值守通信频道M, 监听反馈情况N并记录O; 若发现任何异常状况P及时向上级汇报Q .\n8 . 同步更新当前态势图R , 显示各警戒级别S以及相应的应急响应T .\n9 . 持续关注事态发展U , 随时调整防范等级V .\n10 . 在危机解除后W进行总结X并完善应急预案Y .\n " 47 | } 48 | ][ 49 | { 50 | "如果我方指挥所遭遇到敌军反坦克导弹的威胁,是否能够在我方直升机和豹2A7坦克的配合下,在30分钟内解决这个威胁?": "\n1. 使用map_search获取敌军反坦克导弹的位置坐标A。\n2. 使用knowledge_graph查询我方直升机的速度B和续航时间C。\n3. 使用knowledge_graph查询豹2A7坦克的速度D和射程E。\n4. 使用distance_calculation计算我方直升机从当前位置到目标位置A的距离F,以及豹2A7坦克从当前位置到目标位置A的距离G。\n5. 根据速度B计算直升机到达目标位置所需的时间H,并判断其是否在续航时间C之内。\n6. 计算豹2A7坦克以速度D行驶距离G所需的时间I,并判断该时间内能否利用射程E对敌军进行有效打击J。\n7. 综合评估并确定在30分钟内能否完成上述行动K。\n" 51 | }, 52 | { 53 | "假设侦察部队发现了一处未知武器装备,需要通过网络搜索确认其型号及性能,并评估是否有足够的力量进行突击摧毁,请给出解决方案?": "\n1. 侦察部队提供未知武器的照片L给image_gen_prompt工具生成详细描述M。\n2. 将详细描述M作为关键词N输入google_search工具中搜索相关资料O,特别是该武器的具体型号P及其主要属性Q(如重量、携带武器等)。\n3. 利用knowledge_graph根据获得的信息R进一步验证S并补充缺失的重要信息T(例如:适应场景、克制武器等)。\n4. 分析所得数据U与当前可用资源V之间的匹配度W。比如使用distance_calculation工具结合地图上所有单位的位置X来评估最合适的攻击方式Y和参与单位Z(如装甲车、火箭炮等)能否满足需求[条件]a.\n5. 如果符合条件b,则制定具体的行动计划c;否则考虑调整方案d或请求支援e.\n" 54 | }, 55 | { 56 | "为了确保明天上午9点整时能够顺利开始军事演习,请提前一天检查所有单位的状态,并安排一次全体人员会议提醒他们准时参加。如何操作?": "\n1. 使用calendar设置明日9点为target_time并将“今天”设为time_query以获取今天的日期f作为计划起始日g.\n2.h=使用military_information_search将\"今日全体单位状态\"设为search_query检索各单元i现状j.\n3.k=对于状态不佳l或存在问题m的任何单元n,立即采取相应措施o(如维修p,补给q)确保第二天r前恢复s最佳t状态u.\n4.v=编写一封邮件w内容x包括:明日y演习z重要性[,具体集合地点],以及强调按时到场的重要性{]. \n5.|=使用address_book分别查询每个相关人员或部门领导的邮箱地址}. \n6.=通过QQ_Email向所有关键人员发送提醒邮件~.\n7.^最后再次确认通讯录中是否有遗漏_成员`或者备用联系人a以便紧急情况下快速通知b.\n8.c若有必要d,也可电话通知e重要f人物g以增加h效率i且保证j信息k传达l准确m无误n].\n9.o针对无法及时回复p或存在疑问q的人r,s可以通过进一步沟通t解决u他们的v担忧w,x直至所有人y都明确z了解{演习}安排}.\n10.|最终确认一切准备就绪},等待次日演练开始~!\n- " 57 | } 58 | ] -------------------------------------------------------------------------------- /readme_1.md: -------------------------------------------------------------------------------- 1 | # AutoPlan2 2 | ## Download Data 3 | [点击此处下载数据集,密码adan](https://pan.baidu.com/s/1VE98p-QiKqG9VOORUPtEDg) 4 | [English](./README.md) 5 | ## [AutoPlan1](https://github.com/LDLINGLINGLING/AutoPlan) 6 | ### 背景与挑战 7 | - 在AutoPlan1推出之前,市场上的智能代理(Agents)大多功能较为基础,面对复杂的问题处理能力有限。 8 | - 这些早期的Agents缺乏处理复杂逻辑或执行长序列任务的能力,或者即便能够尝试解决,其解决方案的准确性也常常不尽如人意。 9 | 10 | ### 目标与成果 11 | - **核心目的**:AutoPlan1旨在克服上述局限性,通过开发出能够胜任特定领域内更复杂工作的高级Agents。 12 | - **技术进步**: 13 | - 引入了先进的算法和技术框架,显著提升了Agents在处理细分领域复杂任务时的表现。 14 | - 提高了Agent系统的稳定性以及解决问题的准确度。 15 | - 成功地从仅能执行简单任务的初级Agents过渡到了具备强大处理能力的高级Agents。 16 | 17 | ## AutoPlan2 18 | 19 | ### 新挑战与改进方向 20 | - 尽管AutoPlan1成功地提高了Agents应对复杂场景的能力,但这一过程中也暴露出了一些新的问题。 21 | - 构建这类复杂Agent的成本较高,尤其是涉及到大量人工标注的数据准备阶段。 22 | - 对于那些需要快速部署新类型Agent的应用场景来说,高昂的数据成本成为了阻碍因素之一。 23 | 24 | ### 目标与创新 25 | - **核心目标**:AutoPlan2项目致力于降低新Agent的创建门槛,特别是针对那些要求迅速上线且性能稳定的场合。 26 | - **关键技术点**: 27 | - **冷启动优化**:开发了一套机制使得即使是初次接触某一领域的Agent也能基于现有知识库快速形成初步服务能力。 28 | - **成本控制**:通过自动化工具减少对人工干预的需求,在保证至少90%服务准确性的同时,力求将复杂Agent的数据准备成本控制在总成本的10%以内。 29 | - **兼容性增强**:确保即使是为简单任务设计的Agent也能无缝接入更加复杂的系统中使用,无需额外调整。 30 | # 效果展示: 31 | ## [零人工构造长链条数据](./data_demo) 32 | ### 以下数据为500条中随意挑选,未经任何人工修改或者挑选。 33 | ```plaintext 34 | Question1: 35 | 确认我方直升机的最大作战范围内是否包含敌方的指挥中心位置。 36 | 37 | Plan: 38 | 1.使用knowledge_graph获取直升机的续航里程A。 39 | 2.使用map_search获取敌方指挥中心的坐标B。 40 | 3.使用distance_calculation计算我方直升机和敌方指挥中心的距离C。 41 | 4.对比续航里程A和距离C,确认是否在作战范围内。 42 | 43 | React_data: 44 | Thought: 首先,我需要使用knowledge_graph来获取直升机的续航里程。 45 | Action: knowledge_graph 46 | Action Input: {\"weapon_query\": \"直升机\", \"attribute\": \"续航\"}\nObservation: 直升机的续航是:500km 47 | Thought: 现在我知道了直升机的续航里程是500km,接下来我需要使用map_search来获取敌方指挥中心的坐标。 48 | Action: map_search\nAction Input: {\"lauch\": \"敌指挥中心\"} 49 | Observation: {'我方直升机': [100, 80], '敌直升机': [170, 45], '我方指挥所': [0, 2], '敌坦克': [20, 13], '我方火箭炮': [100, 120], '我方发射阵地1': [50, 70], '我方发射阵地2': [150, 170], '敌指挥中心': [70, 35], '敌反坦克导弹': [50, 100], '我方坦克': [32, 21]} 50 | Thought: 我已经获取到了敌方指挥中心的坐标是[70, 35],接下来我需要使用distance_calculation来计算我方直升机和敌方指挥中心的距离。 51 | Action: distance_calculation\nAction Input: {\"weapon_query\": \"{\\\"我方直升机\\\":[100,80]}\", \"map_dict\": \"{\\\"敌指挥中心\\\":[70,35]}\"}\nObservation: 以下是所有单位与{'我方直升机': [100, 80]}的距离:{'敌指挥中心': '54.1km'} 52 | Thought: 我已经得到了我方直升机和敌方指挥中心的距离是54.1km,现在需要对比这个距离与直升机的续航里程。 53 | Action: python_math\nAction Input: {\"math_formulation\": \"500 > 54.1\"} 54 | Observation: 执行结果是True\nThought: 由于500km大于54.1km,所以我方直升机的最大作战范围内包含敌方的指挥中心位置。 55 | Final Answer: 我方直升机的最大作战范围内包含敌方的指挥中心位置。 56 | ``` 57 | ```plaintext 58 | Question2:请选择武器打击敌方坦克,打击后将结果图片给到张三将军. 59 | 60 | Plan: 61 | 1.使用map_search获取敌方坦克的位置坐标A 62 | 2.使用knowledge_graph查询敌方坦克的克制武器B 63 | 3.使用weapon_launch发射克制武器B打击敌方坦克位置坐标A 64 | 4.使用map_search查询克制武器B的位置坐标C 65 | 5.使用knowledge_graph获取克制武器B的速度D 66 | 6.使用distance_calculation计算克制武器B的位置坐标C到敌方坦克的位置坐标A的距离E 67 | 7.根据距离E和速度D计算武器飞行时间F 68 | 8.使用Situation_display显示敌方坦克位置坐标A,获得图片G 69 | 9.使用address_book查询张三将军的QQ_EmailH。 70 | 10.F时间后使用QQ_Email将图片C发送到张三将军的QQ_EmailH 71 | 72 | React_data: 73 | Thought: 首先,我需要使用map_search来获取敌方坦克的位置坐标A。 74 | Action: map_search 75 | Action Input: {\"lauch\": \"敌坦克\"} 76 | Observation: {'我方直升机': [100, 80], '敌直升机': [170, 45], '我方指挥所': [0, 2], '敌坦克': [20, 13], '我方火箭炮': [100, 120], '我方发射阵地1': [50, 70], '我方发射阵地2': [150, 170], '敌指挥中心': [70, 35], '敌反坦克导弹': [50, 100], '我方坦克': [32, 21]} 77 | Thought: 我已经获取到了敌方坦克的位置坐标A,接下来需要使用knowledge_graph查询克制敌方坦克的武器B。 78 | Action: knowledge_graph\nAction Input: {\"weapon_query\": \"敌坦克\", \"attribute\": \"克制武器\"} 79 | Observation: '豹2A7坦克': { '克制武器': '反坦克导弹'} 80 | Thought: 我已经获取到了克制敌方坦克的武器B,接下来需要使用weapon_launch发射克制武器B打击敌方坦克位置坐标A。 81 | Action: weapon_launch 82 | Action Input: {\"weapon_query\": \"反坦克导弹\", \"target_name\": \"敌坦克\", \"target_coordinate\": \"[20, 13]\"} 83 | Observation: 已启动反坦克导弹打击敌坦克打击位置:[20, 13] \nThought: 武器已经发射,接下来需要使用map_search查询克制武器B的位置坐标C。 84 | Action: map_search 85 | Action Input: {\"lauch\": \"反坦克导弹\"} 86 | Observation: { '敌反坦克导弹': [50, 100]} 87 | Thought: 我已经获取到了克制武器B的位置坐标C,接下来需要使用knowledge_graph获取克制武器B的速度D。 88 | Action: knowledge_graph 89 | Action Input: {\"weapon_query\": \"反坦克导弹\", \"attribute\": \"速度\"} 90 | Observation: 反坦克导弹的速度是:200km/h 91 | Thought: 我已经获取到了克制武器B的速度D,接下来需要使用distance_calculation计算克制武器B的位置坐标C到敌方坦克的位置坐标A的距离E。 92 | Action: distance_calculation 93 | Action Input: {\"weapon_query\": \"{'反坦克导弹':[50, 100]}\", \"map_dict\": \"{'敌坦克': [20, 13]}\"} 94 | Observation: 以下是所有单位与{'反坦克导弹': [50, 100]}的距离:{'敌坦克': '92.0km'} 95 | Thought: 我已经获取到了克制武器B的位置坐标C到敌方坦克的位置坐标A的距离E,接下来需要根据距离E和速度D计算武器飞行时间F。 96 | Action: python_math 97 | Action Input: {\"math_formulation\": \"92.0/200\"} 98 | Observation: 执行结果是0.46 99 | Thought: 我已经计算出了武器飞行时间F,接下来需要使用Situation_display显示敌方坦克位置坐标A,获得图片G。 100 | Action: Situation_display 101 | Action Input: {\"coordinate\": \"[20, 13]\", \"radio\": \"300\"}\nObservation: 已经显示以[20, 13]为中心以300为半径的态势地图,图片地址为/ai/ld/picture1.png 102 | Thought: 我已经获取到了图片G,接下来需要使用address_book查询张三将军的QQ_EmailH。 103 | Action: address_book 104 | Action Input: {\"person_name\": \"张三\"} 105 | Observation: {'邮箱': '45123456@qq.com', '电话': '13713156111', '部队': '黑狐坦克', '职务': '副总师'} 106 | Thought: 我已经获取到了张三将军的QQ_EmailH,接下来需要使用QQ_Email将图片C发送到张三将军的QQ_EmailH。 107 | Action: QQ_Email 108 | Action Input: {\"E-mail_address\": \"45123456@qq.com\", \"E-mail_content\": \"打击敌方坦克的结果如图所示:/ai/ld/picture1.png\"} 109 | Observation: 已将打击敌方坦克的结果如图所示:/ai/ld/picture1.png发送到45123456@qq.com \nThought: 我已经完成了所有任务。 110 | Final Answer: 通过以上步骤,我成功使用反坦克导弹打击了敌方坦克 111 | ``` 112 | 113 | # 使用方法 114 | 1. 首先修改config.py配置文件,[config.py](./config.py)文件中已有注释。 115 | 2. 修改tools_caption.py文件,填写Agent需要调用工具的配置(可多个),以下是一个示例。 116 | ```python 117 | tools=[ 118 | { 119 | "name_for_human": "知识图谱", # name_for_human写工具名称,用来给模型提示,需要能够望文生义, 120 | "name_for_model": "knowledge_graph", # name_for_model是函数名称,是真实调用工具的函数名 121 | "excute_function": True, # excute_function表示构造数据时,是否真实的调用工具以获得更加高质量的数据。 122 | "description_for_model": "知识图谱是输入武器种类获取该武器的属性,也可以输入某种属性获得所有武器的该属性",# description_for_model是用于提示模型,本工具的作用。需要描述清晰明了 123 | "example": "帮我查一下敌方直升机的续航里程", # example 表示一个能使用本工具解决的问题。 124 | "parameters": [ 125 | { 126 | "name": "weapon_query",# 这是第一个参数名称 127 | "description": "武器名称", # 这是对本参数的文字描述,用于提示模型,需要能够望文生义 128 | "scope": ["直升机", '豹2A7坦克','黑狐坦克',"雷达",'装甲车','狙击枪', "反坦克导弹", "直升机", "火箭炮", "所有武器",'无人机','步兵'], # 参数的取值范围 129 | "required": True, # 这个参数是否是必须的 130 | "schema": {"type": "string"}, # 本参数的数据结构类型 131 | }, 132 | { 133 | "name": "attribute",# 这是第二个参数名称 134 | "description": "武器的属性",# 这是对本参数的文字描述,用于提示模型,需要能够望文生义 135 | "scope": ['射程','携带武器','重量','速度','适应场景','克制武器','续航','满载人数','飞行高度','承载重量','所有属性','探测范围'],# 参数的取值范围 136 | "required": True,# 这个参数是否是必须的 137 | "schema": {"type": "string"},# 本参数的数据结构类型 138 | }, 139 | ], 140 | } 141 | ] 142 | ``` 143 | 3. 对于第二步中"excute_function": True的工具,需要在tools_call.py的文件中进行实现,以下是一个示例。 144 | ```python 145 | if plugin_name == "knowledge_graph": 146 | weapon_name = args_dict["weapon_query"] # 输入参数的解析,需要和第步中参数的name值相同(weapon_query) 147 | attribute = args_dict["attribute"] # 输入参数的解析,需要和第步中参数的name值相同(attribute) 148 | kg = { 149 | "直升机": { 150 | "飞行高度": "0.3km以内", 151 | "携带武器": "火箭弹", 152 | "克制武器": "对空导弹", 153 | "重量": "3000kg", 154 | "速度": "100km/h", 155 | "射程": "2km", 156 | "适应场景": "空战", 157 | "续航": "500km", 158 | "满载人数": "7人", 159 | "承载重量": "10000kg", 160 | "续航里程": "1000km", 161 | }, 162 | #、、、、、、、、、、此处省略 163 | "狙击枪": {"射程": "1.2km", "重量": "30kg", "适应场景": "暗杀"}, 164 | } 165 | if weapon_name != "所有武器": 166 | try: 167 | return "{}的{}是:{}".format( 168 | weapon_name, attribute, kg[weapon_name][attribute] 169 | ) 170 | except: 171 | return kg 172 | return kg #返回值需要是容易被模型理解的文字 173 | ``` 174 | 4. 根据具体需求,修改main.py文件最下方,执行以下函数的其中一个,执行前请保证第一步根据执行函数进行了配置: 175 | ```python 176 | if __name__ == "__main__": 177 | #get_question()# 获取简单Agent问题数据 178 | #get_complex_question() 179 | #get_react_data # 获取agent执行过程数据 180 | get_complex_react_data() # 获取复杂agent的执行过程数据 181 | ``` 182 | 5. 执行get_react_data()或get_complex_react_data()后保存的训练数据已经保存为llamafactory的qwen训练格式,可以直接进行sft训练。 183 | -------------------------------------------------------------------------------- /tools_call.py: -------------------------------------------------------------------------------- 1 | import json5 2 | import re 3 | import math 4 | def function_call(plugin_name, plugin_args,llm,tokenizer): 5 | args_dict = json5.loads(plugin_args) 6 | if plugin_name == "knowledge_graph": 7 | weapon_name = args_dict["weapon_query"] 8 | attribute = args_dict["attribute"] 9 | kg = { 10 | "直升机": { 11 | "飞行高度": "0.3km以内", 12 | "携带武器": "火箭弹", 13 | "克制武器": "对空导弹", 14 | "重量": "3000kg", 15 | "速度": "100km/h", 16 | "射程": "2km", 17 | "适应场景": "空战", 18 | "续航": "500km", 19 | "满载人数": "7人", 20 | "承载重量": "10000kg", 21 | "续航里程": "1000km", 22 | }, 23 | "反坦克导弹": { 24 | "重量": "100kg", 25 | "射程": "0.5千米", 26 | "克制武器": "拦截导弹", 27 | "适应场景": "打击重装甲武器", 28 | "速度": "200km/h", 29 | }, 30 | "步兵": { 31 | "射程": "0.3km", 32 | "克制武器": "无人机", 33 | "适应场景": "陆地", 34 | "速度": "40km/h", 35 | "重量": "60kg", 36 | "承载重量": "50kg", 37 | }, 38 | "无人机": { 39 | "速度": "100km/h", 40 | "重量": "10kg", 41 | "适应场景": "侦察和暗杀", 42 | "飞行高度": "0.3km以下", 43 | "克制武器": "电磁攻击", 44 | "续航": "50km", 45 | }, 46 | "豹2A7坦克": { 47 | "速度": "50km/h", 48 | "携带武器": "激光炮", 49 | "克制武器": "反坦克导弹", 50 | "射程": "5km", 51 | "重量": "10000kg", 52 | "续航": "1000km", 53 | "承载重量": "200000kg", 54 | "满载人数": "5人", 55 | "适应场景": "野战和掩护步兵", 56 | }, 57 | "黑狐坦克": { 58 | "速度": "70km/h", 59 | "携带武器": "主炮", 60 | "克制武器": "反坦克导弹", 61 | "射程": "15km", 62 | "重量": "10000kg", 63 | "承载重量": "50000kg", 64 | "续航": "1000km", 65 | "满载人数": "5人", 66 | "适应场景": "野战和掩护步兵", 67 | }, 68 | "火箭炮": { 69 | "速度": "4500km/h", 70 | "重量": "500kg", 71 | "射程": "1000km", 72 | "适应场景": "超远程打击", 73 | "飞行高度": "万米高空", 74 | "克制武器": "拦截导弹", 75 | }, 76 | "雷达": {"重量": "5000kg", "探测范围": "2km以上20km以下", "适应场景": "探测敌军"}, 77 | "装甲车": { 78 | "速度": "80km/h", 79 | "携带武器": "副炮", 80 | "克制武器": "穿甲弹", 81 | "射程": "0.5km", 82 | "重量": "10000kg", 83 | "承载重量": "10000kg", 84 | "续航": "600km", 85 | "满载人数": "10人", 86 | }, 87 | "狙击枪": {"射程": "1.2km", "重量": "30kg", "适应场景": "暗杀"}, 88 | } 89 | if weapon_name != "所有武器": 90 | try: 91 | return "{}的{}是:{}".format( 92 | weapon_name, attribute, kg[weapon_name][attribute] 93 | ) 94 | except: 95 | return kg 96 | return kg 97 | elif plugin_name == 'google_search': 98 | # 使用 SerpAPI 需要在这里填入您的 SERPAPI_API_KEY! 99 | search_query=json5.loads(plugin_args)['search_query'] 100 | #model.chat(tokenizer,task_split_prompt,history=[]) 101 | messages = [ 102 | {"role": "system", "content":"You are a helpful assistant."}, 103 | {"role": "user", "content": '现在请你模拟无所不知的百科全书,直接正面回复以下问题。'+search_query} 104 | ] 105 | search_query= tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 106 | outputs = llm.generate( 107 | search_query, 108 | ) 109 | return outputs[0].outputs[0].text 110 | #return query_bing(search_query, max_tries=3,model=model,tokenizer=tokenizer) 111 | elif plugin_name == 'military_information_search': 112 | search_query=json5.loads(plugin_args)['search_query'] 113 | messages = [ 114 | {"role": "system", "content":"You are a helpful assistant."}, 115 | {"role": "user", "content": '现在请你模拟军事专家,直接正面回复以下问题。'+search_query} 116 | ] 117 | search_query= tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 118 | outputs = llm.generate( 119 | search_query, 120 | ) 121 | return outputs[0].outputs[0].text 122 | #return query_bing(search_query, max_tries=3,model=model,tokenizer=tokenizer) 123 | 124 | elif plugin_name == 'image_gen': 125 | import urllib.parse,json 126 | 127 | prompt = json5.loads(plugin_args)["prompt"]#输入的文本 128 | prompt = urllib.parse.quote(prompt) 129 | return json.dumps({'image_url': f'https://image.pollinations.ai/{prompt}'.format(prompt=prompt)}, ensure_ascii=False) 130 | elif plugin_name == 'QQ_Email': 131 | import urllib.parse,json 132 | Email_address = json5.loads(plugin_args)["E-mail_address"] 133 | Email_content = json5.loads(plugin_args)["E-mail_content"] 134 | return "已将{}发送到{}".format(Email_content,Email_address) 135 | elif plugin_name=='calendar': 136 | from datetime import datetime 137 | format_str="%Y年%m月%d日 %H:%M:%S" 138 | # 如果提供了time_str,将字符串解析为datetime对象 139 | time = datetime.now() 140 | # 将时间格式化为字符串 141 | formatted_time = time.strftime(format_str) 142 | return formatted_time 143 | elif plugin_name=='map_search':#这个是地图信息的api 144 | map_dict={'我方直升机':[100,80],'敌直升机':[170,45],'我方指挥所':[0,2],'敌坦克':[20,13],'我方火箭炮':[100,120],'我方发射阵地1':[50,70],'我方发射阵地2':[150,170],"敌指挥中心": [70, 35],"敌反坦克导弹":[50,100],'我方坦克':[32,21]} 145 | import json 146 | args_dict = json.loads(plugin_args) 147 | #if args_dict['lauch']=='yes': 148 | return str(map_dict) 149 | elif plugin_name=='address_book':#这个是地图信息的api 150 | book_dict={'李四':{'邮箱':'403644786@qq.com','电话':'13077329411','部队':'直升机','职务':'算法工程师'}, 151 | '张三':{'邮箱':'45123456@qq.com','电话':'13713156111','部队':'黑狐坦克','职务':'副总师'}, 152 | '王五':{'邮箱':'45343438@qq.com','电话':'13745432','部队':'指挥所','职务':'C++开发'}, 153 | '我方指挥所':{'邮箱':'15sadf63@qq.com','电话':'062221234'}, 154 | '特种部队':{'邮箱':'112322233@qq.com','电话':'156123459','队长':'赵六'}, 155 | '侦察部队':{'邮箱':'1456412333@qq.com','电话':'056486123135','队长':'周八'}, 156 | '指挥官':{'邮箱':'123456789@qq.com','电话':'6220486123135'} 157 | } 158 | import json 159 | args_dict = json.loads(plugin_args) 160 | person_name=args_dict['person_name'] 161 | return str(book_dict[person_name]) 162 | elif plugin_name=='weapon_launch':#这里是发射武器的api 163 | import json 164 | args_dict = json.loads(plugin_args) 165 | weapon=args_dict["weapon_query"] 166 | target_name = args_dict["target_name"] 167 | coordinate=args_dict["target_coordinate"] 168 | return '已启动'+weapon+'打击'+str(target_name)+'打击位置:'+str(coordinate) 169 | elif plugin_name=='Situation_display':#这里是发射武器的api 170 | import json 171 | args_dict = json.loads(plugin_args) 172 | if 'radio' not in args_dict.keys(): 173 | radio=300 174 | else: 175 | radio=args_dict["radio"] 176 | coordinate = args_dict["coordinate"] 177 | return '已经显示以{}为中心以{}为半径的态势地图,图片地址为/ai/ld/picture1'.format(coordinate,radio) 178 | elif plugin_name=='distance_calculation':#这里是计算距离的api 179 | def distance(query,map_dict):#计算距离 180 | distance_dict={} 181 | query_coordinate=list(query.values())[0] 182 | for weapon,item in map_dict.items(): 183 | if weapon==query: 184 | continue 185 | else: 186 | distance_dict[weapon]=str(round(math.sqrt((float(query_coordinate[0])-float(item[0]))**2+(float(query_coordinate[1])-float(item[1]))**2),1))+'km' 187 | return [query,distance_dict] 188 | import json,ast 189 | args_dict = json.loads(plugin_args) 190 | weapon=json.loads(re.sub(r"'",'"',args_dict["weapon_query"]))#传进来的武器参数 191 | coordinate=json.loads(re.sub(r"'",'"',args_dict["map_dict"]))#传进来的整个位置信息 192 | items=list(coordinate.keys()) 193 | distance_list=distance(weapon,coordinate) 194 | min_distance_unit=min(distance_list[1],key=distance_list[1].get) 195 | max_distance_unit=max(distance_list[1],key=distance_list[1].get) 196 | return '以下是所有单位与{}的距离:{}'.format(list(weapon.keys())[0],str(distance_list[1])) 197 | elif plugin_name=='python_math':#这里是计算距离的api 198 | import json 199 | args_dict = json.loads(plugin_args) 200 | math_formulation=args_dict['math_formulation'] 201 | 202 | math_formulation=re.sub('km','',math_formulation) 203 | math_formulation=re.sub('km/h','',math_formulation) 204 | try: 205 | result=eval(math_formulation) 206 | 207 | return "执行结果是{}".format(str(result)) 208 | except: 209 | pattern = re.compile(r"[^0-9/+*-/<>=%()](max|min|abs|pow|sqrt|exp)") 210 | math_formulation=re.sub(pattern,'',math_formulation) 211 | try: 212 | result=eval(math_formulation) 213 | 214 | return "执行结果是{}".format(str(result)) 215 | except: 216 | return '执行失败' 217 | else: 218 | return '没有找到该工具' -------------------------------------------------------------------------------- /tool_call_en.py: -------------------------------------------------------------------------------- 1 | import json5 2 | import re 3 | import math 4 | 5 | def function_call(plugin_name, plugin_args, llm, tokenizer): 6 | args_dict = json5.loads(plugin_args) 7 | 8 | if plugin_name == "knowledge_graph": 9 | weapon_name = args_dict["weapon_query"] 10 | attribute = args_dict["attribute"] 11 | kg = { 12 | "Helicopter": { 13 | "Flight Altitude": "Within 0.3km", 14 | "Carried Weapons": "Rockets", 15 | "Counter Weapons": "Anti-Air Missiles", 16 | "Weight": "3000kg", 17 | "Speed": "100km/h", 18 | "Range": "2km", 19 | "Applicable Scenarios": "Aerial Combat", 20 | "Endurance": "500km", 21 | "Full Capacity": "7 personnel", 22 | "Load Capacity": "10000kg", 23 | "Endurance Mileage": "1000km", 24 | }, 25 | "Anti-Tank Missile": { 26 | "Weight": "100kg", 27 | "Range": "0.5km", 28 | "Counter Weapons": "Intercept Missiles", 29 | "Applicable Scenarios": "Heavy Armor Strikes", 30 | "Speed": "200km/h", 31 | }, 32 | "Infantry": { 33 | "Range": "0.3km", 34 | "Counter Weapons": "Drones", 35 | "Applicable Scenarios": "Ground Combat", 36 | "Speed": "40km/h", 37 | "Weight": "60kg", 38 | "Load Capacity": "50kg", 39 | }, 40 | "Drone": { 41 | "Speed": "100km/h", 42 | "Weight": "10kg", 43 | "Applicable Scenarios": "Reconnaissance and Assassination", 44 | "Flight Altitude": "Below 0.3km", 45 | "Counter Weapons": "Electromagnetic Attacks", 46 | "Endurance": "50km", 47 | }, 48 | "Leopard 2A7 Tank": { 49 | "Speed": "50km/h", 50 | "Carried Weapons": "Laser Cannon", 51 | "Counter Weapons": "Anti-Tank Missiles", 52 | "Range": "5km", 53 | "Weight": "10000kg", 54 | "Endurance": "1000km", 55 | "Load Capacity": "200000kg", 56 | "Full Capacity": "5 personnel", 57 | "Applicable Scenarios": "Field Combat and Infantry Support", 58 | }, 59 | "Black Fox Tank": { 60 | "Speed": "70km/h", 61 | "Carried Weapons": "Main Cannon", 62 | "Counter Weapons": "Anti-Tank Missiles", 63 | "Range": "15km", 64 | "Weight": "10000kg", 65 | "Load Capacity": "50000kg", 66 | "Endurance": "1000km", 67 | "Full Capacity": "5 personnel", 68 | "Applicable Scenarios": "Field Combat and Infantry Support", 69 | }, 70 | "Rocket Launcher": { 71 | "Speed": "4500km/h", 72 | "Weight": "500kg", 73 | "Range": "1000km", 74 | "Applicable Scenarios": "Ultra-Long Range Strikes", 75 | "Flight Altitude": "High Altitude", 76 | "Counter Weapons": "Intercept Missiles", 77 | }, 78 | "Radar": { 79 | "Weight": "5000kg", 80 | "Detection Range": "2km to 20km", 81 | "Applicable Scenarios": "Enemy Detection", 82 | }, 83 | "Armored Vehicle": { 84 | "Speed": "80km/h", 85 | "Carried Weapons": "Secondary Cannon", 86 | "Counter Weapons": "Armor-Piercing Rounds", 87 | "Range": "0.5km", 88 | "Weight": "10000kg", 89 | "Load Capacity": "10000kg", 90 | "Endurance": "600km", 91 | "Full Capacity": "10 personnel", 92 | }, 93 | "Sniper Rifle": { 94 | "Range": "1.2km", 95 | "Weight": "30kg", 96 | "Applicable Scenarios": "Assassination", 97 | }, 98 | } 99 | if weapon_name != "All Weapons": 100 | try: 101 | return "The {} of {} is: {}".format(attribute, weapon_name, kg[weapon_name][attribute]) 102 | except: 103 | return kg 104 | return kg 105 | 106 | elif plugin_name == 'google_search': 107 | search_query = json5.loads(plugin_args)['search_query'] 108 | messages = [ 109 | {"role": "system", "content": "You are a helpful assistant."}, 110 | {"role": "user", "content": 'Simulate an encyclopedia to answer: ' + search_query} 111 | ] 112 | search_query = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 113 | outputs = llm.generate(search_query) 114 | return outputs[0].outputs[0].text 115 | 116 | elif plugin_name == 'military_information_search': 117 | search_query = json5.loads(plugin_args)['search_query'] 118 | messages = [ 119 | {"role": "system", "content": "You are a military expert."}, 120 | {"role": "user", "content": 'Answer military-related: ' + search_query} 121 | ] 122 | search_query = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 123 | outputs = llm.generate(search_query) 124 | return outputs[0].outputs[0].text 125 | 126 | elif plugin_name == 'QQ_Email': 127 | return "The content '{}' has been sent to {}".format( 128 | json5.loads(plugin_args)["E-mail_content"], 129 | json5.loads(plugin_args)["E-mail_address"] 130 | ) 131 | 132 | elif plugin_name == 'calendar': 133 | from datetime import datetime 134 | return datetime.now().strftime("%Y-%m-%d %H:%M:%S") 135 | 136 | elif plugin_name == 'map_search': 137 | map_data = { 138 | 'Our Helicopter': [100,80], 139 | 'Enemy Helicopter': [170,45], 140 | 'Our Command Post': [0,2], 141 | 'Enemy Tank': [20,13], 142 | 'Our Rocket Launcher': [100,120], 143 | 'Our Launch Site 1': [50,70], 144 | 'Our Launch Site 2': [150,170], 145 | "Enemy Command Center": [70,35], 146 | "Enemy Anti-Tank Missile": [50,100], 147 | 'Our Tank': [32,21], 148 | } 149 | return str(map_data) 150 | 151 | elif plugin_name == 'address_book': 152 | contacts = { 153 | 'Li Si': {'Email': '403644786@qq.com', 'Phone': '13077329411', 'Unit': 'Helicopter', 'Position': 'Algorithm Engineer'}, 154 | 'Zhang San': {'Email': '45123456@qq.com', 'Phone': '13713156111', 'Unit': 'Black Fox Tank', 'Position': 'Deputy Chief Engineer'}, 155 | 'Wang Wu': {'Email': '45343438@qq.com', 'Phone': '13745432', 'Unit': 'Command Post', 'Position': 'C++ Developer'}, 156 | 'Our Command Post': {'Email': '15sadf63@qq.com', 'Phone': '062221234'}, 157 | 'Special Forces': {'Email': '112322233@qq.com', 'Phone': '156123459', 'Commander': 'Zhao Liu'}, 158 | 'Reconnaissance Unit': {'Email': '1456412333@qq.com', 'Phone': '056486123135', 'Commander': 'Zhou Ba'}, 159 | 'Commander': {'Email': '123456789@qq.com', 'Phone': '6220486123135'}, 160 | } 161 | return str(contacts[json5.loads(plugin_args)['person_name']]) 162 | 163 | elif plugin_name == 'weapon_launch': 164 | return 'Activated {} to strike {} at {}'.format( 165 | args_dict["weapon_query"], 166 | args_dict["target_name"], 167 | args_dict["target_coordinate"] 168 | ) 169 | 170 | elif plugin_name == 'Situation_display': 171 | return 'Displaying situation map centered at {} with {}km radius. Image URL: /ai/ld/picture1'.format( 172 | args_dict["coordinate"], 173 | args_dict.get("radio", 300) 174 | ) 175 | 176 | elif plugin_name == 'distance_calculation': 177 | def distance(query, map_dict): 178 | distance_dict = {} 179 | query_coordinate = list(query.values())[0] 180 | for weapon, item in map_dict.items(): 181 | if weapon == query: 182 | continue 183 | else: 184 | distance_dict[weapon] = str(round(math.sqrt((float(query_coordinate[0])-float(item[0]))**2 + (float(query_coordinate[1])-float(item[1]))**2),1)) + 'km' 185 | return [query, distance_dict] 186 | 187 | weapon = json5.loads(re.sub(r"'", '"', args_dict["weapon_query"])) 188 | coordinate = json5.loads(re.sub(r"'", '"', args_dict["map_dict"])) 189 | distance_list = distance(weapon, coordinate) 190 | return 'Distances between all units and {}: {}'.format(list(weapon.keys())[0], str(distance_list[1])) 191 | 192 | elif plugin_name == 'python_math': 193 | math_formulation = args_dict['math_formulation'] 194 | math_formulation = re.sub('km', '', math_formulation) 195 | math_formulation = re.sub('km/h', '', math_formulation) 196 | try: 197 | result = eval(math_formulation) 198 | return "The result is {}".format(str(result)) 199 | except: 200 | pattern = re.compile(r"[^0-9/+*-/<>=%()](max|min|abs|pow|sqrt|exp)") 201 | math_formulation = re.sub(pattern, '', math_formulation) 202 | try: 203 | result = eval(math_formulation) 204 | return "The result is {}".format(str(result)) 205 | except: 206 | return 'Execution failed' 207 | 208 | else: 209 | return 'Tool not found' 210 | -------------------------------------------------------------------------------- /tool_caption_en.py: -------------------------------------------------------------------------------- 1 | tools = [ 2 | { 3 | "name_for_human": "Image to Text", 4 | "name_for_model": "image_gen_prompt", 5 | "excute_function": False, 6 | "description_for_model": "Service that generates detailed textual descriptions from images. Input an image URL/path to get the description.", 7 | "example": "Please check the stock price shown in today's image at www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png", 8 | "parameters": [ 9 | { 10 | "name": "image_path", 11 | "description": "Image URL or local path", 12 | "scope": None, 13 | "required": True, 14 | "schema": {"type": "string"}, 15 | } 16 | ], 17 | }, 18 | { 19 | "name_for_human": "Knowledge Graph", 20 | "name_for_model": "knowledge_graph", 21 | "excute_function": True, 22 | "description_for_model": "Query weapon attributes by type or find weapons with specific attributes.", 23 | "example": "Find the endurance mileage of enemy helicopters", 24 | "parameters": [ 25 | { 26 | "name": "weapon_query", 27 | "description": "Weapon name", 28 | "scope": ["Helicopter", "Leopard 2A7 Tank", "Black Fox Tank", "Radar", "Armored Vehicle", "Sniper Rifle", "Anti-Tank Missile", "Rocket Launcher", "All Weapons", "UAV", "Infantry"], 29 | "required": True, 30 | "schema": {"type": "string"}, 31 | }, 32 | { 33 | "name": "attribute", 34 | "description": "Weapon attribute", 35 | "scope": ["Range", "Armament", "Weight", "Speed", "Scenario", "Countermeasure", "Endurance", "Capacity", "Altitude", "Payload", "All Attributes", "Detection Range"], 36 | "required": True, 37 | "schema": {"type": "string"}, 38 | }, 39 | ], 40 | }, 41 | { 42 | 'name_for_human': 'Google Search', 43 | 'name_for_model': 'google_search', 44 | 'excute_function': True, 45 | 'description_for_model': 'General search engine for internet access, encyclopedia queries, and news updates.', 46 | "example": "Check the latest economic situation", 47 | 'parameters': [ 48 | { 49 | 'name': 'search_query', 50 | 'description': 'Search keywords/phrases', 51 | 'scope': False, 52 | 'required': True, 53 | 'schema': {'type': 'string'}, 54 | } 55 | ] 56 | }, 57 | { 58 | 'name_for_human': 'Military Intel Search', 59 | 'name_for_model': 'military_information_search', 60 | 'excute_function': True, 61 | 'description_for_model': 'Specialized search engine for military networks and intelligence.', 62 | "example": "Check enemy troop movements", 63 | 'parameters': [ 64 | { 65 | 'name': 'search_query', 66 | 'description': 'Search keywords/phrases', 67 | 'scope': 'All military-related searches', 68 | 'required': True, 69 | 'schema': {'type': 'string'}, 70 | } 71 | ], 72 | }, 73 | { 74 | 'name_for_human': 'Address Book', 75 | 'name_for_model': 'address_book', 76 | 'excute_function': True, 77 | 'example': "What is Li Si's phone number?", 78 | 'description_for_model': 'Retrieves personal information like contacts and addresses.', 79 | 'parameters': [ 80 | { 81 | 'name': 'person_name', 82 | 'description': 'Name of person to query', 83 | 'scope': ['Zhang San', 'Li Si', 'Wang Wu', 'Our Command Center', 'Recon Unit', 'Commander'], 84 | 'required': True, 85 | 'schema': {'type': 'string'}, 86 | } 87 | ], 88 | }, 89 | { 90 | 'name_for_human': 'Email Client', 91 | 'name_for_model': 'QQ_Email', 92 | 'excute_function': True, 93 | "example": "Send 'Spy detected, abort meeting' to 403644785@163.com", 94 | 'description_for_model': 'Email tool for sending/receiving messages', 95 | 'parameters': [ 96 | { 97 | 'name': 'E-mail_address', 98 | 'description': 'Recipient email address', 99 | 'scope': None, 100 | 'required': True, 101 | 'schema': {'type': 'string'}, 102 | }, 103 | {'name': "E-mail_content", 104 | 'description': 'Email content', 105 | 'scope': None, 106 | 'required': True, 107 | 'schema': {'type':'string'} 108 | } 109 | ], 110 | }, 111 | { 112 | 'name_for_human': 'Situation Display', 113 | 'name_for_model': 'Situation_display', 114 | 'excute_function': True, 115 | 'example':'Show situational map at enemy HQ [400,200]', 116 | 'description_for_model': 'Displays battlefield situation image based on coordinates and radius', 117 | 'parameters': [ 118 | { 119 | 'name': 'coordinate', 120 | 'description': 'Target coordinates (x,y) as list', 121 | 'scope':'x,y values (0-400 integers)', 122 | 'required': True, 123 | 'schema': {'type': 'list'}, 124 | }, 125 | { 126 | 'name': 'radio', 127 | 'description': 'Display radius in km (default 300km)', 128 | 'scope':'0-560 integer', 129 | 'required': False, 130 | 'schema': {'type': 'string'}, 131 | } 132 | ], 133 | }, 134 | { 135 | 'name_for_human': 'Calendar', 136 | 'name_for_model': 'calendar', 137 | 'excute_function': True, 138 | 'example':'What is today\'s date?', 139 | 'description_for_model': 'Tool for getting current date/time', 140 | 'parameters': [ 141 | { 142 | 'name': 'time_query', 143 | 'description':'Target time (e.g. yesterday, today, tomorrow)', 144 | 'required': True, 145 | 'schema': {'type': 'string'}, 146 | } 147 | ], 148 | }, 149 | { 150 | 'name_for_human': 'Map Search', 151 | 'name_for_model': 'map_search', 152 | 'excute_function': True, 153 | 'example':'Where is our helicopter now?', 154 | 'description_for_model': 'Queries position information of all map units', 155 | 'parameters': [ 156 | { 157 | 'name': 'lauch', 158 | 'description': 'Unit name or "yes" to activate', 159 | 'scope':['Our Helicopter', 'Enemy Helicopter', 'Our Command Center', 'Enemy Tank', 'Our Rocket Launcher', 'Launch Site 1', 'Launch Site 2', "Enemy Command Center", "Enemy Anti-Tank Missile", 'Our Tank', 'All Units'], 160 | 'required': True, 161 | 'schema': {'type': 'string'}, 162 | } 163 | ], 164 | }, 165 | { 166 | 'name_for_human': 'Python Calculator', 167 | 'name_for_model': 'python_math', 168 | 'excute_function': True, 169 | 'example':'100//3+20**2', 170 | 'description_for_model': 'Evaluates mathematical expressions using Python', 171 | 'parameters': [ 172 | { 173 | 'name': 'math_formulation', 174 | 'description': 'Mathematical expression to evaluate', 175 | 'scope':'Basic arithmetic operations', 176 | 'required': True, 177 | 'schema': {'type': 'string'}, 178 | } 179 | ], 180 | }, 181 | { 182 | 'name_for_human': 'Weapon Launch', 183 | 'name_for_model': 'weapon_launch', 184 | 'excute_function': True, 185 | 'example':'Launch rocket launcher at enemy position [10,30]', 186 | 'description_for_model': 'Activates weapons to strike targets', 187 | 'parameters': [ 188 | { 189 | 'name': 'weapon_query', 190 | 'description': 'Weapon to launch', 191 | 'scope':"['Our Helicopter','Enemy Helicopter','Our Command Center','Enemy Tank','Our Rocket Launcher','Enemy Anti-Tank Missile','Our Tank'] with 0-400 coordinates", 192 | 'required': True, 193 | 'schema': {'type': 'string'}, 194 | }, 195 | { 196 | 'name': 'target_name', 197 | 'description': "Target unit name", 198 | 'scope': None, 199 | 'required': True, 200 | 'schema': {'type': 'string'}, 201 | }, 202 | { 203 | 'name': 'target_coordinate' , 204 | 'description': 'Target coordinates [x,y]', 205 | 'scope':"0-400 integers", 206 | 'required': True, 207 | 'schema': {'type': 'string'}, 208 | } 209 | ], 210 | }, 211 | { 212 | 'name_for_human': 'Distance Calculator', 213 | 'name_for_model': 'distance_calculation', 214 | 'excute_function': True, 215 | 'example':'Calculate distance between our helicopter[200,300] and command center[100,200]', 216 | 'description_for_model': 'Calculates distances between units on map', 217 | 'parameters': [ 218 | { 219 | 'name': 'weapon_query', 220 | 'description': '{TargetUnit:[x,y]} (single unit)', 221 | 'scope':'Any map unit', 222 | 'required': True, 223 | 'schema': {'type': 'string'}, 224 | }, 225 | { 226 | 'name': 'map_dict', 227 | 'description': '{Unit:[x,y], ...}', 228 | 'scope':'Other units on map', 229 | 'required': True, 230 | 'schema': {'type': 'dict'}, 231 | } 232 | ], 233 | } 234 | ] 235 | -------------------------------------------------------------------------------- /tools_caption.py: -------------------------------------------------------------------------------- 1 | tools = [ 2 | { 3 | "name_for_human": "图生文", 4 | "name_for_model": "image_gen_prompt", 5 | "excute_function": False, # 是否可以使用这个工具进行函数调用以生成数据 6 | "description_for_model": "图生文是一个可以看图生成文字描述的服务,输入一张图片的地址,将返回图片详细逼真的表述", 7 | "example": "帮我看一下www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png这张图片上的今日股价是多少", 8 | "parameters": [ 9 | { 10 | "name": "image_path", 11 | "description": "需要图片描述的URL或者本地地址", 12 | "scope": None, # 这个参数的取值范围,如果不限定为None 13 | "required": True, # 这个是否必须 14 | "schema": {"type": "string"}, 15 | } 16 | ], 17 | }, 18 | { 19 | "name_for_human": "知识图谱", 20 | "name_for_model": "knowledge_graph", 21 | "excute_function": True, 22 | "description_for_model": "知识图谱是输入武器种类获取该武器的属性,也可以输入某种属性获得所有武器的该属性", 23 | "example": "帮我查一下敌方直升机的续航里程", 24 | "parameters": [ 25 | { 26 | "name": "weapon_query", 27 | "description": "武器名称", 28 | "scope": ["直升机", '豹2A7坦克','黑狐坦克',"雷达",'装甲车','狙击枪', "反坦克导弹", "直升机", "火箭炮", "所有武器",'无人机','步兵'], # 参数的取值范围 29 | "required": True, 30 | "schema": {"type": "string"}, 31 | }, 32 | { 33 | "name": "attribute", 34 | "description": "武器的属性", 35 | "scope": ['射程','携带武器','重量','速度','适应场景','克制武器','续航','满载人数','飞行高度','承载重量','所有属性','探测范围'], 36 | "required": True, 37 | "schema": {"type": "string"}, 38 | }, 39 | ], 40 | }, 41 | { 42 | 'name_for_human': '谷歌搜索', 43 | 'name_for_model': 'google_search', 44 | 'excute_function':True, 45 | 'description_for_model': '谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。', 46 | "example": "帮我查一下最新的经济形势", 47 | 'parameters': [ 48 | { 49 | 'name': 'search_query', 50 | 'description': '搜索关键词或短语', 51 | 'scope':False, 52 | 'required': True, 53 | 'schema': {'type': 'string'}, 54 | } 55 | ] 56 | }, 57 | { 58 | 'name_for_human': '军事情报搜索', 59 | 'name_for_model': 'military_information_search', 60 | 'excute_function':True, 61 | 'description_for_model': '军事情报搜索是一个通用搜索引擎,可用于访问军事情报网、查询军网、了解军事新闻等。', 62 | "example": "帮我查一下敌军的走向", 63 | 'parameters': [ 64 | { 65 | 'name': 'search_query', 66 | 'description': '搜索关键词或短语', 67 | 'scope':'所有军事类信息搜索', 68 | 'required': True, 69 | 'schema': {'type': 'string'}, 70 | } 71 | ], 72 | }, 73 | { 74 | 'name_for_human': '通讯录', 75 | 'name_for_model': 'address_book', 76 | 'excute_function':True, 77 | 'example':'李四的电话号号码是多少?', 78 | 'description_for_model': '通讯录是用来获取个人信息如电话、邮箱地址、公司地址的软件。', 79 | 'parameters': [ 80 | { 81 | 'name': 'person_name', 82 | 'description': '被查询者的姓名', 83 | 'scope':['张三','李四','王五','我方指挥所','侦察部队','指挥官'], 84 | 'required': True, 85 | 'schema': {'type': 'string'}, 86 | } 87 | ], 88 | }, 89 | { 90 | 'name_for_human': 'qq邮箱', 91 | 'name_for_model': 'QQ_Email', 92 | 'excute_function':True, 93 | "example": "帮我将‘有间谍,停止接头’发到403644785@163.com", 94 | 'description_for_model': 'qq邮箱是一个可以用来发送合接受邮件的工具', 95 | 'parameters': [ 96 | { 97 | 'name': 'E-mail_address', 98 | 'description': '对方邮箱的地址 发给对方的内容', 99 | 'scope':None, 100 | 'required': True, 101 | 'schema': {'type': 'string'}, 102 | }, 103 | {'name':"E-mail_content", 104 | 'description': '发给对方的内容', 105 | 'scope':None, 106 | 'required': True, 107 | 'schema': {'type':'string'}} 108 | ], 109 | }, 110 | { 111 | 'name_for_human': '态势显示', 112 | 'name_for_model': 'Situation_display', 113 | 'excute_function':True, 114 | 'example':'我需要查看敌军总部[400,200]处的态势图,请显示', 115 | 'description_for_model': ':态势显示是通过输入目标位置坐标和显示范围,从而显示当前敌我双方的战场态势图像,并生成图片', 116 | 'parameters': [ 117 | { 118 | 'name': 'coordinate', 119 | 'description': '目标位置的x和y坐标,输入一个列表,如[300,200]', 120 | 'scope':'coordinate_x,coordinate_y的取值都在0到400之间的整数', 121 | 'required': True, 122 | 'schema': {'type': 'list'}, 123 | } 124 | , 125 | { 126 | 'name': 'radio', 127 | 'description': '态势图像显示的范围半径,单位是km,默认值为300km', 128 | 'scope':'radio取值都在0到560之间的整数', 129 | 'required': False, 130 | 'schema': {'type': 'string'}, 131 | } 132 | ], 133 | }, 134 | { 135 | 'name_for_human': '万年历', 136 | 'name_for_model': 'calendar', 137 | 'excute_function':True, 138 | 'example':'请告诉我今天的日期', 139 | 140 | 'description_for_model': '万年历获取当前时间的工具', 141 | 'parameters': [ 142 | { 143 | 'name': 'time_query', 144 | 'description':'目标的时间,例如昨天、今天、明天', 145 | 'location':'location_query', 146 | 'scope':None, 147 | 'required': True, 148 | 'schema': {'type': 'string'}, 149 | } 150 | ], 151 | }, 152 | { 153 | 'name_for_human': '地图', 154 | 'name_for_model': 'map_search', 155 | 'excute_function':True, 156 | 'example':'我方直升机的现在在哪里', 157 | 'description_for_model': '地图是一个可以查询地图上所有单位位置信息的工具,返回所有敌军的位置信息。', 158 | 'parameters': [ 159 | { 160 | 'name': 'lauch', 161 | 'description': '输入单位名称或者yes,yes代表启用地图搜索', 162 | 'scope':['我方直升机','敌直升机','我方指挥所','敌坦克','我方火箭炮','我方发射阵地1','我方发射阵地2',"敌指挥中心","敌反坦克导弹",'我方坦克','所有单位'], 163 | 'required': True, 164 | 'schema': {'type': 'string'}, 165 | } 166 | ], 167 | }, 168 | { 169 | 'name_for_human': 'python计算器', 170 | 'name_for_model': 'python_math', 171 | 'excute_function':True, 172 | 'example':'100//3+20**2', 173 | 'description_for_model': 'python计算器可以通过python的eval()函数计算出输入的字符串表达式结果并返回,表达式仅包含数字、加减乘除、逻辑运算符、次方运算', 174 | 'parameters': [ 175 | { 176 | 'name': 'math_formulation', 177 | 'description': '根据问题提炼出的python数学表达式,表达式仅包含数字、加减乘除、逻辑运算符', 178 | 'scope':'加、减、乘、除、平方、开平方等基本算数操作', 179 | 'required': True, 180 | 'schema': {'type': 'string'}, 181 | } 182 | ], 183 | }, 184 | { 185 | 'name_for_human': '武器发射按钮', 186 | 'name_for_model': 'weapon_launch', 187 | 'excute_function':True, 188 | 'example':'发射火箭炮打击地方火箭炮[10,30]', 189 | 'description_for_model': '武器发射按钮是可以启动指定武器打击指定目标位置工具。', 190 | 'parameters': [ 191 | { 192 | 'name': 'weapon_query', 193 | 'description': '启动的打击武器名称', 194 | 'scope':"weapon_query的取值为['我方直升机','敌直升机','我方指挥所','敌坦克','我方火箭炮','敌反坦克导弹','我方坦克'],x,y坐标都是0到400之间的整数", 195 | 'required': True, 196 | 'schema': {'type': 'string'}, 197 | }, 198 | { 199 | 'name': 'target_name', 200 | 'description': "被打击的单位名称", 201 | 'scope':None, 202 | 'required': True, 203 | 'schema': {'type': 'string'}, 204 | } 205 | , 206 | { 207 | 'name': 'target_coordinate' , 208 | 'description': '被打击目标的坐标地点比如[x, y]', 209 | 'scope':"x,y坐标都是0到400之间的整数", 210 | 'required': True, 211 | 'schema': {'type': 'string'}, 212 | } 213 | ], 214 | }, 215 | # { 216 | # 'name_for_human': '数学计算', 217 | # 'name_for_model': 'math_model', 218 | # 'excute_function':True, 219 | # 'example':'根据飞机速度和A、B两地的距离,计算来回一次时间', 220 | # 'description_for_model': '使用大语言模型完成一系列的推理问题如基本的加减乘除、最大、最小计算', 221 | # 'parameters': [ 222 | # { 223 | # 'name': 'question', 224 | # 'description': '当前的问题,需要清楚的给足背景知识', 225 | # 'scope':'加、减、乘、除、平方、开平方等基本算数操作', 226 | # 'required': True, 227 | # 'schema': {'type': 'string'}, 228 | # } 229 | # ], 230 | # }, 231 | { 232 | 'name_for_human': '距离计算器', 233 | 'name_for_model': 'distance_calculation', 234 | 'excute_function':True, 235 | 'example':'计算我方直升机[200,300]和我方指挥所[100,200]的距离', 236 | 'description_for_model': '会将map_dict上所有单位都与weapon_query进行距离计算,返回map_dict上每一个单位和weapon_query的距离', 237 | 'parameters': [ 238 | { 239 | 'name': 'weapon_query', 240 | 'description': '{目标单位名称:[目标单位名称的x坐标,目标单位名称的y坐标]},只能是一个单位,比如{我方直升机:[200,300]}', 241 | 'scope':'weapon_query为地图上任意目标,但是只能是一个单位', 242 | 'required': True, 243 | 'schema': {'type': 'string'}, 244 | }, 245 | { 246 | 'name': 'map_dict', 247 | 'description': '{被计算的单位名称:[该单位的x坐标,该单位的y坐标],被计算的第二个单位名称:[该单位的x坐标,该单位的y坐标]},比如{地方坦克:[300,150]}', 248 | 'scope':'map_dict为除目标单位以外的所有地图上单位的名称和位置参数,可以是一个单位也可以是多个单位', 249 | 'required': True, 250 | 'schema': {'type': 'dict'}, 251 | } 252 | ], 253 | } 254 | ] -------------------------------------------------------------------------------- /readme_en.md: -------------------------------------------------------------------------------- 1 | # AutoPlan 2 | 3 | ## [AutoPlan1](https://github.com/LDLINGLINGLING/AutoPlan) 4 | 5 | ### Background and Challenges 6 | - Before the launch of AutoPlan1, most intelligent agents (Agents) on the market had relatively basic functionalities with limited capability to handle complex problems. 7 | - These early Agents lacked the ability to process complex logic or perform long sequences of tasks, or even if they could attempt to solve them, the accuracy of their solutions was often unsatisfactory. 8 | 9 | ### Goals and Achievements 10 | - **Core Purpose**: AutoPlan1 aims to overcome these limitations by developing advanced Agents capable of performing more complex work within specific domains. 11 | - **Technological Advancements**: 12 | - The introduction of advanced algorithms and technical frameworks has significantly improved the performance of Agents in handling complex tasks within specialized areas. 13 | - The stability of Agent systems and the accuracy of problem-solving have been enhanced. 14 | - A successful transition from basic Agents that can only perform simple tasks to advanced Agents with powerful processing capabilities has been achieved. 15 | 16 | ## AutoPlan2 17 | 18 | ### New Challenges and Improvement Directions 19 | - Although AutoPlan1 successfully enhanced the Agents' ability to cope with complex scenarios, this process also exposed some new issues. 20 | - The cost of building such complex Agents is high, especially during the data preparation phase, which involves extensive manual labeling. 21 | - For application scenarios requiring rapid deployment of new types of Agents, the high costs became a hindrance. 22 | 23 | ### Goals and Innovations 24 | - **Core Goal**: The AutoPlan2 project is dedicated to lowering the entry barrier for creating new Agents, particularly for those situations demanding swift deployment with stable performance. 25 | - **Key Technical Points**: 26 | - **Cold Start Optimization**: Developed a mechanism allowing Agents, even when first encountering a particular domain, to quickly establish initial service capabilities based on existing knowledge bases. 27 | - **Cost Control**: By employing automation tools, the need for human intervention is reduced, aiming to maintain at least 90% service accuracy while striving to limit the data preparation costs for complex Agents to no more than 10% of the total cost. 28 | - **Enhanced Compatibility**: Ensures that Agents designed for simple tasks can be seamlessly integrated into more complex systems without additional adjustments. 29 | 30 | # Effect Demonstration: 31 | ## [Zero Manual Construction of Long Chain Data](./data_demo) 32 | ### The following data is randomly selected from 500 entries, without any manual modification or selection. 33 | ```plaintext 34 | Question1: 35 | Confirm whether the maximum operational range of our helicopter includes the location of the enemy's command center. 36 | 37 | Plan: 38 | 1. Use knowledge_graph to obtain the helicopter's endurance A. 39 | 2. Use map_search to get the coordinates B of the enemy's command center. 40 | 3. Use distance_calculation to calculate the distance C between our helicopter and the enemy's command center. 41 | 4. Compare the endurance A with the distance C to confirm if it is within the operational range. 42 | 43 | React_data: 44 | Thought: First, I need to use knowledge_graph to get the helicopter's endurance. 45 | Action: knowledge_graph 46 | Action Input: {\"weapon_query\": \"helicopter\", \"attribute\": \"endurance\"} 47 | Observation: The helicopter's endurance is: 500km 48 | Thought: Now that I know the helicopter's endurance is 500km, next, I will use map_search to get the coordinates of the enemy's command center. 49 | Action: map_search 50 | Action Input: {\"launch\": \"enemy command center\"} 51 | Observation: {'our helicopter': [100, 80], 'enemy helicopter': [170, 45], 'our command post': [0, 2], 'enemy tank': [20, 13], 'our rocket launcher': [100, 120], 'our firing position 1': [50, 70], 'our firing position 2': [150, 170], 'enemy command center': [70, 35], 'enemy anti-tank missile': [50, 100], 'our tank': [32, 21]} 52 | Thought: I've obtained the coordinates of the enemy command center, which are [70, 35]. Next, I need to use distance_calculation to find the distance between our helicopter and the enemy command center. 53 | Action: distance_calculation 54 | Action Input: {\"weapon_query\": \"{\\\"our helicopter\\\":[100,80]}\", \"map_dict\": \"{\\\"enemy command center\\\":[70,35]}\"} 55 | Observation: Here are all the distances from {'our helicopter': [100, 80]}: {'enemy command center': '54.1km'} 56 | Thought: I've got the distance between our helicopter and the enemy command center, which is 54.1km. Now I need to compare this distance with the helicopter's endurance. 57 | Action: python_math 58 | Action Input: {\"math_formulation\": \"500 > 54.1\"} 59 | Observation: The result is True 60 | Thought: Since 500km is greater than 54.1km, our helicopter's maximum operational range does include the location of the enemy's command center. 61 | Final Answer: Our helicopter's maximum operational range includes the location of the enemy's command center. 62 | ``` 63 | ```plaintext 64 | Question2: Select a weapon to strike the enemy tank and send the result image to General Zhang San. 65 | 66 | Plan: 67 | 1. Use map_search to get the location coordinates A of the enemy tank. 68 | 2. Use knowledge_graph to query the counter-weapon B for the enemy tank. 69 | 3. Use weapon_launch to fire the counter-weapon B at the enemy tank's location coordinates A. 70 | 4. Use map_search to query the location coordinates C of the counter-weapon B. 71 | 5. Use knowledge_graph to get the speed D of the counter-weapon B. 72 | 6. Use distance_calculation to calculate the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. 73 | 7. Calculate the weapon flight time F based on the distance E and speed D. 74 | 8. Use Situation_display to show the enemy tank's location coordinates A and obtain the image G. 75 | 9. Use address_book to look up General Zhang San's QQ Email H. 76 | 10. After F time, use QQ_Email to send the image G to General Zhang San's QQ Email H. 77 | 78 | React_data: 79 | Thought: First, I need to use map_search to get the location coordinates A of the enemy tank. 80 | Action: map_search 81 | Action Input: {\"launch\": \"enemy tank\"} 82 | Observation: {'our helicopter': [100, 80], 'enemy helicopter': [170, 45], 'our command post': [0, 2], 'enemy tank': [20, 13], 'our rocket launcher': [100, 120], 'our firing position 1': [50, 70], 'our firing position 2': [150, 170], 'enemy command center': [70, 35], 'enemy anti-tank missile': [50, 100], 'our tank': [32, 21]} 83 | Thought: I've obtained the location coordinates A of the enemy tank. Next, I need to use knowledge_graph to query the counter-weapon B for the enemy tank. 84 | Action: knowledge_graph 85 | Action Input: {\"weapon_query\": \"enemy tank\", \"attribute\": \"counter-weapon\"} 86 | Observation: 'Leopard 2A7 Tank': {'counter-weapon': 'anti-tank missile'} 87 | Thought: I've obtained the counter-weapon B for the enemy tank. Next, I need to use weapon_launch to fire the counter-weapon B at the enemy tank's location coordinates A. 88 | Action: weapon_launch 89 | Action Input: {\"weapon_query\": \"anti-tank missile\", \"target_name\": \"enemy tank\", \"target_coordinate\": \"[20, 13]\"} 90 | Observation: Anti-tank missile launched at enemy tank; target location: [20, 13] 91 | Thought: The weapon has been launched. Next, I need to use map_search to query the location coordinates C of the counter-weapon B. 92 | Action: map_search 93 | Action Input: {\"launch\": \"anti-tank missile\"} 94 | Observation: {'enemy anti-tank missile': [50, 100]} 95 | Thought: I've obtained the location coordinates C of the counter-weapon B. Next, I need to use knowledge_graph to get the speed D of the counter-weapon B. 96 | Action: knowledge_graph 97 | Action Input: {\"weapon_query\": \"anti-tank missile\", \"attribute\": \"speed\"} 98 | Observation: The speed of the anti-tank missile is: 200km/h 99 | Thought: I've obtained the speed D of the counter-weapon B. Next, I need to use distance_calculation to calculate the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. 100 | Action: distance_calculation 101 | Action Input: {\"weapon_query\": \"{'anti-tank missile':[50, 100]}\", \"map_dict\": \"{'enemy tank': [20, 13]}\"} 102 | Observation: Here are all the distances from {'anti-tank missile': [50, 100]}: {'enemy tank': '92.0km'} 103 | Thought: I've obtained the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. Next, I need to calculate the weapon flight time F based on the distance E and speed D. 104 | Action: python_math 105 | Action Input: {\"math_formulation\": \"92.0/200\"} 106 | Observation: The result is 0.46 107 | Thought: I've calculated the weapon flight time F. Next, I need to use Situation_display to show the enemy tank's location coordinates A and obtain the image G. 108 | Action: Situation_display 109 | Action Input: {\"coordinate\": \"[20, 13]\", \"radius\": \"300\"} 110 | Observation: Displayed the situation map centered at [20, 13] with a radius of 300, the image URL is /ai/ld/picture1.png 111 | Thought: I've obtained the image G. Next, I need to use address_book to look up General Zhang San's QQ Email H. 112 | Action: address_book 113 | Action Input: {\"person_name\": \"Zhang San\"} 114 | Observation: {'email': '45123456@qq.com', 'phone': '13713156111', 'unit': 'Black Fox Tank', 'position': 'Deputy Chief Engineer'} 115 | Thought: I've obtained General Zhang San's QQ Email H. Next, I need to use QQ_Email to send the image G to General Zhang San's QQ Email H. 116 | Action: QQ_Email 117 | Action Input: {\"E-mail_address\": \"45123456@qq.com\", \"E-mail_content\": \"The result of striking the enemy tank as shown in the image: /ai/ld/picture1.png\"} 118 | Observation: Sent the image showing the result of striking the enemy tank: /ai/ld/picture1.png to 45123456@qq.com 119 | Thought: I have completed all tasks. 120 | Final Answer: Through the above steps, I successfully used an anti-tank missile to strike the enemy tank. 121 | ``` 122 | 123 | # Usage Instructions 124 | 1. First, modify the config.py configuration file. There are comments already in the [config.py](./config.py) file. 125 | 2. Modify the tools_caption.py file, filling in the configurations for the tools that the Agent needs to call (multiple tools can be configured). Below is an example. 126 | ```python 127 | tools=[ 128 | { 129 | "name_for_human": "Knowledge Graph", # name_for_human writes the tool name, which should be self-explanatory, 130 | "name_for_model": "knowledge_graph", # name_for_model is the function name, which is the actual name called by the tool 131 | "execute_function": True, # execute_function indicates whether the tool should be actually called to obtain higher quality data when constructing the data. 132 | "description_for_model": "The Knowledge Graph inputs a type of weapon to obtain its attributes, or inputs an attribute to get all weapons' corresponding attributes", # description_for_model is a prompt for the model, explaining the purpose of the tool. It needs to be clear and concise. 133 | "example": "Help me check the endurance of the enemy helicopter", # example represents a problem that can be solved using this tool. 134 | "parameters": [ 135 | { 136 | "name": "weapon_query", # This is the first parameter name 137 | "description": "Weapon name", # This is a textual description of the parameter, used to prompt the model. It needs to be self-explanatory. 138 | "scope": ["Helicopter", 'Leopard 2A7 Tank', 'Black Fox Tank', "Radar", 'Armored Vehicle', 'Sniper Rifle', "Anti-Tank Missile", "Helicopter", "Rocket Launcher", "All Weapons", 'Drone', 'Infantry'], # The range of values for the parameter 139 | "required": True, # Whether this parameter is required 140 | "schema": {"type": "string"}, # The data structure type of this parameter 141 | }, 142 | { 143 | "name": "attribute", # This is the second parameter name 144 | "description": "Weapon attribute", # This is a textual description of the parameter, used to prompt the model. It needs to be self-explanatory. 145 | "scope": ['Range', 'Carried Weapon', 'Weight', 'Speed', 'Adaptation Scenario', 'Counter-Weapon', 'Endurance', 'Full Load Personnel', 'Flight Altitude', 'Load Capacity', 'All Attributes', 'Detection Range'], # The range of values for the parameter 146 | "required": True, # Whether this parameter is required 147 | "schema": {"type": "string"}, # The data structure type of this parameter 148 | }, 149 | ], 150 | } 151 | ] 152 | ``` 153 | 3. For the tools where "execute_function": True in step 2, implementation is needed in the tools_call.py file. Below is an example. 154 | ```python 155 | if plugin_name == "knowledge_graph": 156 | weapon_name = args_dict["weapon_query"] # Parsing of input parameters, must match the name value of the parameter (weapon_query) in step 2 157 | attribute = args_dict["attribute"] # Parsing of input parameters, must match the name value of the parameter (attribute) in step 2 158 | kg = { 159 | "Helicopter": { 160 | "Flight Altitude": "within 0.3km", 161 | "Carried Weapon": "Rocket", 162 | "Counter-Weapon": "Anti-Air Missile", 163 | "Weight": "3000kg", 164 | "Speed": "100km/h", 165 | "Range": "2km", 166 | "Adaptation Scenario": "Air Combat", 167 | "Endurance": "500km", 168 | "Full Load Personnel": "7 people", 169 | "Load Capacity": "10000kg", 170 | "Endurance Mileage": "1000km", 171 | }, 172 | # Additional weapons and attributes omitted here... 173 | "Sniper Rifle": {"Range": "1.2km", "Weight": "30kg", "Adaptation Scenario": "Assassination"}, 174 | } 175 | if weapon_name != "All Weapons": 176 | try: 177 | return "{}'s {} is:{}".format( 178 | weapon_name, attribute, kg[weapon_name][attribute] 179 | ) 180 | except: 181 | return kg 182 | return kg # The return value should be text that is easily understood by the model 183 | ``` 184 | 4. Depending on the specific requirements, modify the main.py file at the bottom, and execute one of the following functions. Make sure that the first step has been configured according to the executed function: 185 | ```python 186 | if __name__ == "__main__": 187 | #get_question() # Obtain simple Agent question data 188 | #get_complex_question() 189 | #get_react_data # Obtain Agent execution process data 190 | get_complex_react_data() # Obtain complex Agent execution process data 191 | ``` 192 | 5. After executing `get_react_data()` or `get_complex_react_data()`, the training data saved is in the Qwen training format by LLaMAFactory and can be directly used for SFT (Supervised Fine-Tuning) training. 193 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # AutoPlan2 3 | ## [中文](./readme_1.md) 4 | ## Download Data 5 | [please click here the password is adan](https://pan.baidu.com/s/1SUxJY4zMMTVeGxcoq2UuQQ?pwd=adan) 6 | ## [AutoPlan1](https://github.com/LDLINGLINGLING/AutoPlan) 7 | ### Background and Challenges 8 | - Before the launch of AutoPlan1, most intelligent agents (Agents) on the market had relatively basic functionalities with limited capability to handle complex problems. 9 | - These early Agents lacked the ability to process complex logic or perform long sequences of tasks, or even if they could attempt to solve them, the accuracy of their solutions was often unsatisfactory. 10 | 11 | ### Goals and Achievements 12 | - **Core Purpose**: AutoPlan1 aims to overcome these limitations by developing advanced Agents capable of performing more complex work within specific domains. 13 | - **Technological Advancements**: 14 | - The introduction of advanced algorithms and technical frameworks has significantly improved the performance of Agents in handling complex tasks within specialized areas. 15 | - The stability of Agent systems and the accuracy of problem-solving have been enhanced. 16 | - A successful transition from basic Agents that can only perform simple tasks to advanced Agents with powerful processing capabilities has been achieved. 17 | 18 | ## AutoPlan2 19 | 20 | ### New Challenges and Improvement Directions 21 | - Although AutoPlan1 successfully enhanced the Agents' ability to cope with complex scenarios, this process also exposed some new issues. 22 | - The cost of building such complex Agents is high, especially during the data preparation phase, which involves extensive manual labeling. 23 | - For application scenarios requiring rapid deployment of new types of Agents, the high costs became a hindrance. 24 | 25 | ### Goals and Innovations 26 | - **Core Goal**: The AutoPlan2 project is dedicated to lowering the entry barrier for creating new Agents, particularly for those situations demanding swift deployment with stable performance. 27 | - **Key Technical Points**: 28 | - **Cold Start Optimization**: Developed a mechanism allowing Agents, even when first encountering a particular domain, to quickly establish initial service capabilities based on existing knowledge bases. 29 | - **Cost Control**: By employing automation tools, the need for human intervention is reduced, aiming to maintain at least 90% service accuracy while striving to limit the data preparation costs for complex Agents to no more than 10% of the total cost. 30 | - **Enhanced Compatibility**: Ensures that Agents designed for simple tasks can be seamlessly integrated into more complex systems without additional adjustments. 31 | 32 | # Effect Demonstration: 33 | ## [Zero Manual Construction of Long COT Data](./data_demo) 34 | ### The following data is randomly selected from 500 entries, without any manual modification or selection. 35 | ```plaintext 36 | Question1: 37 | Confirm whether the maximum operational range of our helicopter includes the location of the enemy's command center. 38 | 39 | Plan: 40 | 1. Use knowledge_graph to obtain the helicopter's endurance A. 41 | 2. Use map_search to get the coordinates B of the enemy's command center. 42 | 3. Use distance_calculation to calculate the distance C between our helicopter and the enemy's command center. 43 | 4. Compare the endurance A with the distance C to confirm if it is within the operational range. 44 | 45 | React_data: 46 | Thought: First, I need to use knowledge_graph to get the helicopter's endurance. 47 | Action: knowledge_graph 48 | Action Input: {\"weapon_query\": \"helicopter\", \"attribute\": \"endurance\"} 49 | Observation: The helicopter's endurance is: 500km 50 | Thought: Now that I know the helicopter's endurance is 500km, next, I will use map_search to get the coordinates of the enemy's command center. 51 | Action: map_search 52 | Action Input: {\"launch\": \"enemy command center\"} 53 | Observation: {'our helicopter': [100, 80], 'enemy helicopter': [170, 45], 'our command post': [0, 2], 'enemy tank': [20, 13], 'our rocket launcher': [100, 120], 'our firing position 1': [50, 70], 'our firing position 2': [150, 170], 'enemy command center': [70, 35], 'enemy anti-tank missile': [50, 100], 'our tank': [32, 21]} 54 | Thought: I've obtained the coordinates of the enemy command center, which are [70, 35]. Next, I need to use distance_calculation to find the distance between our helicopter and the enemy command center. 55 | Action: distance_calculation 56 | Action Input: {\"weapon_query\": \"{\\\"our helicopter\\\":[100,80]}\", \"map_dict\": \"{\\\"enemy command center\\\":[70,35]}\"} 57 | Observation: Here are all the distances from {'our helicopter': [100, 80]}: {'enemy command center': '54.1km'} 58 | Thought: I've got the distance between our helicopter and the enemy command center, which is 54.1km. Now I need to compare this distance with the helicopter's endurance. 59 | Action: python_math 60 | Action Input: {\"math_formulation\": \"500 > 54.1\"} 61 | Observation: The result is True 62 | Thought: Since 500km is greater than 54.1km, our helicopter's maximum operational range does include the location of the enemy's command center. 63 | Final Answer: Our helicopter's maximum operational range includes the location of the enemy's command center. 64 | ``` 65 | ```plaintext 66 | Question2: Select a weapon to strike the enemy tank and send the result image to General Zhang San. 67 | 68 | Plan: 69 | 1. Use map_search to get the location coordinates A of the enemy tank. 70 | 2. Use knowledge_graph to query the counter-weapon B for the enemy tank. 71 | 3. Use weapon_launch to fire the counter-weapon B at the enemy tank's location coordinates A. 72 | 4. Use map_search to query the location coordinates C of the counter-weapon B. 73 | 5. Use knowledge_graph to get the speed D of the counter-weapon B. 74 | 6. Use distance_calculation to calculate the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. 75 | 7. Calculate the weapon flight time F based on the distance E and speed D. 76 | 8. Use Situation_display to show the enemy tank's location coordinates A and obtain the image G. 77 | 9. Use address_book to look up General Zhang San's QQ Email H. 78 | 10. After F time, use QQ_Email to send the image G to General Zhang San's QQ Email H. 79 | 80 | React_data: 81 | Thought: First, I need to use map_search to get the location coordinates A of the enemy tank. 82 | Action: map_search 83 | Action Input: {\"launch\": \"enemy tank\"} 84 | Observation: {'our helicopter': [100, 80], 'enemy helicopter': [170, 45], 'our command post': [0, 2], 'enemy tank': [20, 13], 'our rocket launcher': [100, 120], 'our firing position 1': [50, 70], 'our firing position 2': [150, 170], 'enemy command center': [70, 35], 'enemy anti-tank missile': [50, 100], 'our tank': [32, 21]} 85 | Thought: I've obtained the location coordinates A of the enemy tank. Next, I need to use knowledge_graph to query the counter-weapon B for the enemy tank. 86 | Action: knowledge_graph 87 | Action Input: {\"weapon_query\": \"enemy tank\", \"attribute\": \"counter-weapon\"} 88 | Observation: 'Leopard 2A7 Tank': {'counter-weapon': 'anti-tank missile'} 89 | Thought: I've obtained the counter-weapon B for the enemy tank. Next, I need to use weapon_launch to fire the counter-weapon B at the enemy tank's location coordinates A. 90 | Action: weapon_launch 91 | Action Input: {\"weapon_query\": \"anti-tank missile\", \"target_name\": \"enemy tank\", \"target_coordinate\": \"[20, 13]\"} 92 | Observation: Anti-tank missile launched at enemy tank; target location: [20, 13] 93 | Thought: The weapon has been launched. Next, I need to use map_search to query the location coordinates C of the counter-weapon B. 94 | Action: map_search 95 | Action Input: {\"launch\": \"anti-tank missile\"} 96 | Observation: {'enemy anti-tank missile': [50, 100]} 97 | Thought: I've obtained the location coordinates C of the counter-weapon B. Next, I need to use knowledge_graph to get the speed D of the counter-weapon B. 98 | Action: knowledge_graph 99 | Action Input: {\"weapon_query\": \"anti-tank missile\", \"attribute\": \"speed\"} 100 | Observation: The speed of the anti-tank missile is: 200km/h 101 | Thought: I've obtained the speed D of the counter-weapon B. Next, I need to use distance_calculation to calculate the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. 102 | Action: distance_calculation 103 | Action Input: {\"weapon_query\": \"{'anti-tank missile':[50, 100]}\", \"map_dict\": \"{'enemy tank': [20, 13]}\"} 104 | Observation: Here are all the distances from {'anti-tank missile': [50, 100]}: {'enemy tank': '92.0km'} 105 | Thought: I've obtained the distance E from the counter-weapon B's location coordinates C to the enemy tank's location coordinates A. Next, I need to calculate the weapon flight time F based on the distance E and speed D. 106 | Action: python_math 107 | Action Input: {\"math_formulation\": \"92.0/200\"} 108 | Observation: The result is 0.46 109 | Thought: I've calculated the weapon flight time F. Next, I need to use Situation_display to show the enemy tank's location coordinates A and obtain the image G. 110 | Action: Situation_display 111 | Action Input: {\"coordinate\": \"[20, 13]\", \"radius\": \"300\"} 112 | Observation: Displayed the situation map centered at [20, 13] with a radius of 300, the image URL is /ai/ld/picture1.png 113 | Thought: I've obtained the image G. Next, I need to use address_book to look up General Zhang San's QQ Email H. 114 | Action: address_book 115 | Action Input: {\"person_name\": \"Zhang San\"} 116 | Observation: {'email': '45123456@qq.com', 'phone': '13713156111', 'unit': 'Black Fox Tank', 'position': 'Deputy Chief Engineer'} 117 | Thought: I've obtained General Zhang San's QQ Email H. Next, I need to use QQ_Email to send the image G to General Zhang San's QQ Email H. 118 | Action: QQ_Email 119 | Action Input: {\"E-mail_address\": \"45123456@qq.com\", \"E-mail_content\": \"The result of striking the enemy tank as shown in the image: /ai/ld/picture1.png\"} 120 | Observation: Sent the image showing the result of striking the enemy tank: /ai/ld/picture1.png to 45123456@qq.com 121 | Thought: I have completed all tasks. 122 | Final Answer: Through the above steps, I successfully used an anti-tank missile to strike the enemy tank. 123 | ``` 124 | 125 | # Usage Instructions 126 | 1. First, modify the config.py configuration file. There are comments already in the [config.py](./config.py) file. 127 | 2. Modify the tools_caption.py file, filling in the configurations for the tools that the Agent needs to call (multiple tools can be configured). Below is an example. 128 | ```python 129 | tools=[ 130 | { 131 | "name_for_human": "Knowledge Graph", # name_for_human writes the tool name, which should be self-explanatory, 132 | "name_for_model": "knowledge_graph", # name_for_model is the function name, which is the actual name called by the tool 133 | "execute_function": True, # execute_function indicates whether the tool should be actually called to obtain higher quality data when constructing the data. 134 | "description_for_model": "The Knowledge Graph inputs a type of weapon to obtain its attributes, or inputs an attribute to get all weapons' corresponding attributes", # description_for_model is a prompt for the model, explaining the purpose of the tool. It needs to be clear and concise. 135 | "example": "Help me check the endurance of the enemy helicopter", # example represents a problem that can be solved using this tool. 136 | "parameters": [ 137 | { 138 | "name": "weapon_query", # This is the first parameter name 139 | "description": "Weapon name", # This is a textual description of the parameter, used to prompt the model. It needs to be self-explanatory. 140 | "scope": ["Helicopter", 'Leopard 2A7 Tank', 'Black Fox Tank', "Radar", 'Armored Vehicle', 'Sniper Rifle', "Anti-Tank Missile", "Helicopter", "Rocket Launcher", "All Weapons", 'Drone', 'Infantry'], # The range of values for the parameter 141 | "required": True, # Whether this parameter is required 142 | "schema": {"type": "string"}, # The data structure type of this parameter 143 | }, 144 | { 145 | "name": "attribute", # This is the second parameter name 146 | "description": "Weapon attribute", # This is a textual description of the parameter, used to prompt the model. It needs to be self-explanatory. 147 | "scope": ['Range', 'Carried Weapon', 'Weight', 'Speed', 'Adaptation Scenario', 'Counter-Weapon', 'Endurance', 'Full Load Personnel', 'Flight Altitude', 'Load Capacity', 'All Attributes', 'Detection Range'], # The range of values for the parameter 148 | "required": True, # Whether this parameter is required 149 | "schema": {"type": "string"}, # The data structure type of this parameter 150 | }, 151 | ], 152 | } 153 | ] 154 | ``` 155 | 3. For the tools where "execute_function": True in step 2, implementation is needed in the tools_call.py file. Below is an example. 156 | ```python 157 | if plugin_name == "knowledge_graph": 158 | weapon_name = args_dict["weapon_query"] # Parsing of input parameters, must match the name value of the parameter (weapon_query) in step 2 159 | attribute = args_dict["attribute"] # Parsing of input parameters, must match the name value of the parameter (attribute) in step 2 160 | kg = { 161 | "Helicopter": { 162 | "Flight Altitude": "within 0.3km", 163 | "Carried Weapon": "Rocket", 164 | "Counter-Weapon": "Anti-Air Missile", 165 | "Weight": "3000kg", 166 | "Speed": "100km/h", 167 | "Range": "2km", 168 | "Adaptation Scenario": "Air Combat", 169 | "Endurance": "500km", 170 | "Full Load Personnel": "7 people", 171 | "Load Capacity": "10000kg", 172 | "Endurance Mileage": "1000km", 173 | }, 174 | # Additional weapons and attributes omitted here... 175 | "Sniper Rifle": {"Range": "1.2km", "Weight": "30kg", "Adaptation Scenario": "Assassination"}, 176 | } 177 | if weapon_name != "All Weapons": 178 | try: 179 | return "{}'s {} is:{}".format( 180 | weapon_name, attribute, kg[weapon_name][attribute] 181 | ) 182 | except: 183 | return kg 184 | return kg # The return value should be text that is easily understood by the model 185 | ``` 186 | 4. Depending on the specific requirements, modify the main.py file at the bottom, and execute one of the following functions. Make sure that the first step has been configured according to the executed function: 187 | ```python 188 | if __name__ == "__main__": 189 | #get_question() # Obtain simple Agent question data 190 | #get_complex_question() 191 | #get_react_data # Obtain Agent execution process data 192 | get_complex_react_data() # Obtain complex Agent execution process data 193 | ``` 194 | 5. After executing `get_react_data()` or `get_complex_react_data()`, the training data saved is in the Qwen training format by LLaMAFactory and can be directly used for SFT (Supervised Fine-Tuning) training. 195 | -------------------------------------------------------------------------------- /finetune_tool.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | from dataclasses import dataclass, field 4 | from typing import Dict, Optional 5 | 6 | import torch 7 | import transformers 8 | from torch.utils.data import Dataset 9 | from transformers import ( 10 | AutoModelForCausalLM, 11 | AutoTokenizer, 12 | Trainer, 13 | TrainingArguments, 14 | BitsAndBytesConfig, 15 | ) 16 | 17 | tools = [ 18 | { 19 | "name": "knowledge_graph", 20 | "description": "Query military weapon knowledge graph and information, \n\n Returns: \n str: The attribute value or full knowledge graph \n ", 21 | "parameters": { 22 | "type": "object", 23 | "properties": { 24 | "weapon_query": { 25 | "title": "Weapon Query", 26 | "type": "string", 27 | "description":'Name of the weapon to query. candidate value is one of ["Helicopter","Anti-Tank Missile", "Infantry","Drone","Leopard 2A7 Tank","Black Fox Tank","Black Fox Tank","Rocket Launcher","Radar","Armored Vehicle","Armored Vehicle","Sniper Rifle"]' 28 | } 29 | }, 30 | "required": [ 31 | "weapon_query" 32 | ] 33 | } 34 | }, 35 | { 36 | "name": "QQ_Email", 37 | "description": "Send email via QQ email system \n \n Returns: \n str: Confirmation message \n ", 38 | "parameters": { 39 | "type": "object", 40 | "properties": { 41 | "E-mail_content": { 42 | "title": "E-mail_content", 43 | "type": "string", 44 | "description":"Content of the email to send" 45 | }, 46 | "E-mail_address": { 47 | "title": "E-mail_address", 48 | "type": "string", 49 | "description":"Recipient email address" 50 | } 51 | }, 52 | "required": [ 53 | "E-mail_content", 54 | "E-mail_address" 55 | ] 56 | } 57 | }, 58 | { 59 | "name": "calendar", 60 | "description": "Get current date and time \n Returns: \n str: Current timestamp in YYYY-MM-DD HH:MM:SS format \n ", 61 | "parameters": { 62 | "type": "object", 63 | "properties": 64 | { 65 | "time_query": { 66 | "title": "time_query", 67 | "type": "string", 68 | "description" : "only support Get current date and time" 69 | } 70 | }, 71 | "required": ["time_query"] 72 | } 73 | }, 74 | { 75 | "name": "map_search", 76 | "description": "Get current tactical map with unit positions lauch \n \n Returns: \n str: Dictionary of unit positions as coordinates \n ", 77 | "parameters": { 78 | "type": "object", 79 | "properties": { 80 | "lauch": { 81 | "title": "Lauch", 82 | "type": "string", 83 | "description":"unit positions lauch. candidate value is one of ['Our Helicopter', 'Enemy Helicopter', 'Our Command Center', 'Enemy Tank', 'Our Rocket Launcher', 'Launch Site 1', 'Launch Site 2', 'Enemy Command Center', 'Enemy Anti-Tank Missile', 'Our Tank', 'All Units']" 84 | } 85 | }, 86 | "required": [ 87 | "lauch" 88 | ] 89 | } 90 | }, 91 | { 92 | "name": "address_book", 93 | "description": "Look up contact information for address or personnel. \n \n Returns: \n str: Contact information including email, phone, unit, and position \n ", 94 | "parameters": { 95 | "type": "object", 96 | "properties": { 97 | "person_name": { 98 | "title": "person_name", 99 | "type": "string", 100 | "description":"['Li Si','Zhang San','Wang Wu',Our Command Post,'Special Forces','Reconnaissance Unit','Commander']" 101 | } 102 | }, 103 | "required": [ 104 | "person_name" 105 | ] 106 | } 107 | }, 108 | { 109 | "name": "weapon_launch", 110 | "description": "Launch weapon at specified target \n \n Returns: \n str: Launch confirmation message \n ", 111 | "parameters": { 112 | "type": "object", 113 | "properties": { 114 | "weapon_query": { 115 | "title": "weapon query", 116 | "type": "string", 117 | "description":'Type of weapon to launch. candidate value is one of ["Helicopter","Anti-Tank Missile", "Infantry","Drone","Leopard 2A7 Tank","Black Fox Tank","Black Fox Tank","Rocket Launcher","Radar","Armored Vehicle","Armored Vehicle","Sniper Rifle"]' 118 | }, 119 | "target_name": { 120 | "title": "target name", 121 | "type": "string", 122 | "description":"Name of the target. " 123 | }, 124 | "target_coordinate": { 125 | "title": "target coordinate", 126 | "type": "string", 127 | "description":"Coordinates of the target. Format: (x, y)" 128 | } 129 | }, 130 | "required": [ 131 | "weapon_query", 132 | "target_name", 133 | "target_coordinate" 134 | ] 135 | } 136 | }, 137 | { 138 | "name": "situation_display", 139 | "description": "Display tactical situation map \n Returns: \n str: Map display information with image URL \n ", 140 | "parameters": { 141 | "type": "object", 142 | "properties": { 143 | "coordinate": { 144 | "title": "coordinate", 145 | "type": "string", 146 | "description":"Center coordinate for the map. Format: (x, y)" 147 | }, 148 | "radio": { 149 | "default": 300, 150 | "title": "Radio", 151 | "type": "integer", 152 | "description":"Radius in km for the map display. Default is 300km" 153 | } 154 | }, 155 | "required": [ 156 | "coordinate" 157 | ] 158 | } 159 | }, 160 | { 161 | "name": "distance_calculation", 162 | "description": "Calculate distances between units and a specified weapon \n \n Returns: \n str: Distance calculations between all units and the specified weapon \n ", 163 | "parameters": { 164 | "type": "object", 165 | "properties": { 166 | "weapon_query": { 167 | "title": "Weapon Query", 168 | "type": "string", 169 | "description":'JSON string of weapon and its coordinates. Format: {"TargetUnit":[x,y]} (single unit). ' 170 | }, 171 | "map_dict": { 172 | "title": "Map Dict", 173 | "type": "string", 174 | "description":"JSON string of all unit positions. Format: {\"UnitName1\":[x1,y1],\"UnitName2\":[x2,y2],...}" 175 | } 176 | }, 177 | "required": [ 178 | "weapon_query", 179 | "map_dict" 180 | ] 181 | } 182 | } 183 | ] 184 | @dataclass 185 | class ModelArguments: 186 | model_name_or_path: Optional[str] = field(default="openbmb/MiniCPM-2B-sft-bf16") 187 | 188 | 189 | @dataclass 190 | class DataArguments: 191 | train_data_path: str = field( 192 | default="data/AdvertiseGenChatML/train.json", 193 | metadata={"help": "Path to the training data."}, 194 | ) 195 | eval_data_path: str = field( 196 | default="data/AdvertiseGenChatML/dev.json", 197 | metadata={"help": "Path to the test data."}, 198 | ) 199 | 200 | 201 | @dataclass 202 | class TrainingArguments(transformers.TrainingArguments): 203 | cache_dir: Optional[str] = field(default=None) 204 | optim: str = field(default="adamw_torch") 205 | model_max_length: int = field( 206 | default=512, 207 | metadata={ 208 | "help": "Maximum sequence length. Sequences will be right padded (and possibly truncated)." 209 | }, 210 | ) 211 | use_lora: bool = field(default=False) 212 | qlora: bool = field(default=False) 213 | 214 | 215 | class SupervisedDataset(Dataset): 216 | """Dataset for supervised fine-tuning. 217 | Loads the dataset from a json file and preprocesses it.example: 218 | /data/AdvertiseGenChatML/train.json 219 | """ 220 | 221 | def __init__( 222 | self, 223 | data_path, 224 | tokenizer, 225 | model_max_length=4096, 226 | ): 227 | super(SupervisedDataset, self).__init__() 228 | self.data = json.load(open(data_path)) 229 | self.tokenizer = tokenizer 230 | self.model_max_length = model_max_length 231 | self.ignore_index = -100 232 | item = self.preprocessing(self.data[0]) 233 | print("input:", self.tokenizer.decode(item["input_ids"])) 234 | labels = [] 235 | for id_ in item["label_ids"]: 236 | if id_ == -100: 237 | continue 238 | labels.append(id_) 239 | print("label:", self.tokenizer.decode(labels)) 240 | 241 | def __len__(self): 242 | return len(self.data) 243 | 244 | def process_tokens(self,data, tokenizer, tools): 245 | """ 246 | 处理对话数据,生成input_tokens和labels 247 | 248 | Args: 249 | data: 对话数据 250 | tokenizer: 分词器 251 | tools: 工具列表 252 | 253 | Returns: 254 | tuple: (input_tokens, labels) 255 | - input_tokens: 原始tokens列表 256 | - labels: 将指定区间改为-100的tokens列表 257 | """ 258 | toolresponse_token1 = 151665 259 | 260 | toolresponse_token2 = 151666 261 | 262 | # 生成tokens 263 | tokens = tokenizer.apply_chat_template( 264 | data, 265 | tools=tools, 266 | tokenize=True, 267 | add_generation_prompt=True, 268 | enable_thinking=True 269 | ) 270 | 271 | # 一次遍历完成所有查找,降低计算复杂度 272 | indices1 = [] 273 | indices2 = [] 274 | indices3 = None 275 | 276 | for i in range(len(tokens)): 277 | # 查找 toolresponse_token1 和 toolresponse_token2 278 | if tokens[i] == toolresponse_token1: 279 | indices1.append(i) 280 | elif tokens[i] == toolresponse_token2: 281 | indices2.append(i) 282 | 283 | # 查找第一个 [151658,151645,151644] 序列中的 151644 284 | if indices3 is None and i >= 2: 285 | if ( 286 | tokens[i-2] == 151645 and 287 | tokens[i-1] == 198 and 288 | tokens[i] == 151644 and 289 | tokens[i-3] != 151658 ): 290 | indices3 = i 291 | 292 | # # 查找 indices3 后面第一个 [151645,151644] 序列中的 151644 293 | # if indices4 is None and indices3 is not None and i > indices3 and i >= 1: 294 | # if (tokens[i] == 151645 and 295 | # tokens[i+1] == 151644): 296 | # indices4 = i 297 | 298 | # 创建input_tokens和labels 299 | input_tokens = tokens.copy() 300 | labels = tokens.copy() 301 | 302 | # 将indices1和indices2对之间的元素改为-100(不包括indices本身) 303 | assert len(indices1) == len(indices2), "indices1和indices2长度不匹配" 304 | for idx1, idx2 in zip(indices1, indices2): 305 | assert idx1 < idx2, f"Error: indices1={idx1} should be < indices2={idx2}" 306 | # 将idx1+1到idx2-1之间的元素改为-100 307 | for j in range(idx1 + 1, idx2): 308 | labels[j] = -100 309 | 310 | # 将indices3和indices4之间的元素改为-100(不包括indices3和indices4本身) 311 | if indices3 is not None : 312 | 313 | labels[:indices3] = [-100] * indices3 314 | 315 | return input_tokens, labels 316 | def preprocessing(self, example): 317 | 318 | input_ids, label_ids = self.process_tokens(example, self.tokenizer, tools) 319 | # 保持input_ids和label_ids长度一致 320 | input_ids.insert(0, self.tokenizer.eos_token_id) 321 | label_ids.insert(0, self.ignore_index) # bos_token不参与损失计算 322 | 323 | input_ids.append(self.tokenizer.eos_token_id) 324 | label_ids.append(self.tokenizer.eos_token_id) # eos_token参与损失计算 325 | 326 | 327 | 328 | # truncate to max len 329 | input_ids = input_ids[: self.model_max_length] 330 | label_ids = label_ids[: self.model_max_length] 331 | attention_mask = [1] * len(input_ids) 332 | # pad to max len 333 | input_ids += [self.tokenizer.eos_token_id] * ( 334 | self.model_max_length - len(input_ids) 335 | ) 336 | label_ids += [self.ignore_index] * (self.model_max_length - len(label_ids)) 337 | attention_mask += [0] * (self.model_max_length - len(attention_mask)) 338 | # convert to pt tensor 339 | input_ids = torch.LongTensor(input_ids) 340 | label_ids = torch.LongTensor(label_ids) 341 | attention_mask = torch.LongTensor(attention_mask) 342 | return { 343 | "input_ids": input_ids, 344 | "label_ids": label_ids, 345 | "attention_mask": attention_mask, 346 | } 347 | 348 | def __getitem__(self, idx) -> Dict[str, torch.Tensor]: 349 | return self.preprocessing(self.data[idx]) 350 | 351 | 352 | def load_model_and_tokenizer( 353 | model_path: str, 354 | max_length: int = 4096, 355 | use_lora: bool = True, 356 | qlora: bool = False, 357 | bf16: bool = False, 358 | fp16: bool = False, 359 | ): 360 | """load model and tokenizer""" 361 | tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) 362 | tokenizer.pad_token = tokenizer.eos_token 363 | 364 | assert not (bf16 and fp16), "bf16 or fp16, not both" 365 | if bf16: 366 | dtype = torch.bfloat16 367 | elif fp16: 368 | dtype = torch.float16 369 | else: 370 | dtype = torch.float32 371 | if qlora: 372 | assert use_lora, "use_lora must be True when use_qlora is True" 373 | quantization_config = BitsAndBytesConfig( 374 | load_in_4bit=True, # 是否进行4bit量化 375 | load_in_8bit=False, # 是否进行8bit量化 376 | bnb_4bit_compute_dtype=torch.float16, # 计算精度设置 377 | bnb_4bit_quant_storage=torch.uint8, # 量化权重的储存格式 378 | bnb_4bit_quant_type="nf4", # 量化格式,这里用的是正太分布的int4 379 | bnb_4bit_use_double_quant=True, # 是否采用双量化,即对zeropoint和scaling参数进行量化 380 | llm_int8_enable_fp32_cpu_offload=False, # 是否llm使用int8,cpu上保存的参数使用fp32 381 | llm_int8_has_fp16_weight=False, # 是否启用混合精度 382 | # llm_int8_skip_modules=["out_proj", "kv_proj", "lm_head"], # 不进行量化的模块 383 | llm_int8_threshold=6.0, # llm.int8()算法中的离群值,根据这个值区分是否进行量化 384 | ) 385 | model = AutoModelForCausalLM.from_pretrained( 386 | model_path, 387 | torch_dtype=dtype, 388 | trust_remote_code=True, 389 | quantization_config=quantization_config, 390 | ) 391 | else: 392 | model = AutoModelForCausalLM.from_pretrained( 393 | model_path, 394 | torch_dtype=dtype, 395 | trust_remote_code=True, 396 | ) 397 | if use_lora: 398 | from peft import LoraConfig, TaskType, get_peft_model 399 | 400 | lora_config = LoraConfig( 401 | init_lora_weights="gaussian", 402 | task_type=TaskType.CAUSAL_LM, 403 | target_modules=( 404 | ["q_a_proj", "kv_a_proj_with_mqa", "q_b_proj", "kv_b_proj"] 405 | if model.config.architectures == ["MiniCPM3ForCausalLM"] 406 | else ["q_proj", "v_proj"] 407 | ), 408 | r=64, 409 | lora_alpha=32, 410 | lora_dropout=0.1, 411 | inference_mode=False, 412 | ) 413 | model = get_peft_model(model, lora_config) 414 | # trainable params: 2,949,120 || all params: 3,010,652,928 || trainable%: 0.09795616002669305 415 | model.print_trainable_parameters() 416 | # model.enable_input_require_grads() # need when using adapter 417 | 418 | return model, tokenizer 419 | 420 | 421 | if __name__ == "__main__": 422 | model_path = "/mnt/data/user/tc_agi/yh/models/MiniCPM" 423 | parser = transformers.HfArgumentParser( 424 | (ModelArguments, DataArguments, TrainingArguments) 425 | ) 426 | model_args, data_args, training_args = parser.parse_args_into_dataclasses() 427 | model, tokenizer = load_model_and_tokenizer( 428 | model_path=model_args.model_name_or_path, 429 | max_length=training_args.model_max_length, 430 | use_lora=training_args.use_lora, 431 | qlora=training_args.qlora, 432 | bf16=training_args.bf16, 433 | fp16=training_args.fp16, 434 | ) 435 | 436 | train_dataset = SupervisedDataset( 437 | data_path=data_args.train_data_path, 438 | tokenizer=tokenizer, 439 | model_max_length=training_args.model_max_length, 440 | ) 441 | eval_dataset = SupervisedDataset( 442 | data_path=data_args.eval_data_path, 443 | tokenizer=tokenizer, 444 | model_max_length=training_args.model_max_length, 445 | ) 446 | 447 | trainer = Trainer( 448 | model=model, 449 | args=training_args, 450 | train_dataset=train_dataset, 451 | eval_dataset=eval_dataset, 452 | tokenizer=tokenizer, 453 | ) 454 | 455 | trainer.train() 456 | # save the incremental PEFT weights, more details can be found in https://huggingface.co/blog/peft 457 | model.save_pretrained("output_dir") 458 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import re 2 | from vllm import LLM, SamplingParams 3 | from config import * 4 | from build_react_prompt import ( 5 | build_input_text, 6 | TOOL_DESC, 7 | PROMPT_REACT, 8 | parse_latest_plugin_call, 9 | ) 10 | import os 11 | from tools_call import function_call 12 | import json 13 | import json5 14 | from transformers import AutoTokenizer 15 | from tools_caption import tools 16 | from cpm_utils import save_cpm3_data,switch_cpm_tool 17 | # from agent_demo import * 18 | 19 | tokenizer = AutoTokenizer.from_pretrained(model_path,trust_remote_code = True) 20 | 21 | sampling_params = SamplingParams(**params_dict) 22 | 23 | 24 | def split_react_data(react_str): 25 | pattern = re.compile( 26 | r"Thought:\s*(.*?)\nAction:\s*(.*?)\nAction Input:\s*(.*?)\nObservation:\s*(.*?)\nThought:\s*(.*?)\nFinal Answer:\s*(.*)", 27 | re.DOTALL, 28 | ) 29 | 30 | matches = pattern.findall(react_str) 31 | try: 32 | for match in matches: 33 | Thought1 = match[0] 34 | Action = match[1] 35 | Action_Input = match[2] 36 | Observation = match[3] 37 | Thought2 = match[4] 38 | Final_Answer = match[5] 39 | return Thought1, Action, Action_Input, Observation, Thought2, Final_Answer 40 | except: 41 | return None, None, None, None, None, None 42 | 43 | 44 | def get_answer_from_output(output): 45 | pattern = r"「问题开始」(.*?)「问题结束」" 46 | questions = re.findall(pattern, output, re.DOTALL) 47 | questions = [q.strip() for q in questions] 48 | return questions 49 | 50 | def get_complex_question_from_output(output): 51 | pattern = r"--复杂问题_start--(.*?)--复杂问题_end--" 52 | questions = re.findall(pattern, output, re.DOTALL) 53 | pattern2 = r"--任务规划_start--(.*?)--任务规划_end--" 54 | task_plan = re.findall(pattern2, output, re.DOTALL) 55 | if len(task_plan) == len(questions): 56 | questions = [{q.strip():task_plan[i]} for i,q in enumerate(questions)] 57 | else: 58 | questions = [] 59 | return questions 60 | 61 | 62 | def get_tool_description(tool): 63 | tool_descp = "工具名称是{},作用是{},".format( 64 | tool["name_for_model"], tool["description_for_model"] 65 | ) 66 | for t in tool["parameters"]: 67 | if t["required"]: 68 | if t["scope"]: 69 | tool_descp += "参数“{}”是必须输入的,作用是{},该参数的取值范围是{}。".format( 70 | t["name"], t["description"], t["scope"] 71 | ) 72 | else: 73 | tool_descp += "参数“{}”是必须输入的,作用是{}。".format(t["name"], t["description"]) 74 | elif t["scope"]: 75 | tool_descp += "参数“{}”是可选的,作用是{},该参数的取值范围是{}。".format( 76 | t["name"], t["description"], t["scope"] 77 | ) 78 | else: 79 | tool_descp += "参数“{}”是可选的,作用是{}。".format(t["name"], t["description"]) 80 | return tool_descp 81 | 82 | 83 | def get_question(): 84 | if 'llm' not in locals(): 85 | llm = LLM( 86 | model=model_path, 87 | tensor_parallel_size=8, 88 | max_model_len=4096, 89 | dtype="bfloat16", 90 | trust_remote_code=True, 91 | enforce_eager=True, 92 | gpu_memory_utilization=0.8, 93 | ) 94 | 95 | prompt_template = """你是一个智能助手,现在我请你为以下工具生成问题,要求生成的问题能够被这个工具解决。工具的详细介绍如下:\n{}\n我现在给你一个关于此工具问题的示例「问题开始」 96 | {}「问题结束」,接下来请你根据此示例和工具描述再生成{}个能够使用该工具解决的问题,并且用「问题开始」和「问题结束」将其包裹,不要生成其他的无关文字。""" 97 | 98 | all_questions = [] 99 | all_react_prompt = [] 100 | questinos_dict = {} 101 | for tool in tools: 102 | questions = [] 103 | while True: 104 | tool_description = get_tool_description(tool) 105 | input_prompt = prompt_template.format( 106 | tool_description, tool["example"], gen_datas_per_tool 107 | ) 108 | input_prompt = """<|im_start|> system\n you are a helpful assistant<|im_end|>\n<|im_start|> user\n {}<|im_end|>\n<|im_start|> assistant\n""".format( 109 | input_prompt 110 | ) 111 | outputs = llm.generate(input_prompt, sampling_params) 112 | output = outputs[0].outputs[0].text 113 | questions.extend(get_answer_from_output(output)) 114 | 115 | if len(questions) >= gen_datas_per_tool: 116 | all_questions.extend(questions) 117 | print(questions) 118 | questinos_dict[tool["name_for_model"]] = questions 119 | break 120 | 121 | with open(save_question_json, "w", encoding="utf-8") as f: 122 | json.dump(questinos_dict, f, ensure_ascii=False, indent=4) 123 | print("{}条输入指令已经保存到{}".format(len(all_questions), save_question_json)) 124 | 125 | def get_complex_question(): 126 | if 'llm' not in locals(): 127 | llm = LLM( 128 | model=model_path, 129 | tensor_parallel_size=8, 130 | max_model_len=4096, 131 | dtype="bfloat16", 132 | trust_remote_code=True, 133 | enforce_eager=True, 134 | gpu_memory_utilization=0.8, 135 | ) 136 | if complex_example_json.endswith('json'): 137 | with open(complex_example_json,'r',encoding='utf-8') as f: 138 | examples = json.load(f) 139 | else: 140 | examples = [] 141 | all_questions = [] 142 | 143 | for example in examples: 144 | questions = [] 145 | question,plan = list(example.items())[0] 146 | example = '''--复杂问题_start--\n{}\n--复杂问题_end--\n--任务规划_start--\n{}\n--任务规划_end--'''.format(question,plan) 147 | # example += """--复杂问题2_start-- 148 | # 计算一下,如果敌方有意向我方发射阵地1的300人使用化学武器,我方用一架直升机需要多久可以疏散所有人员到我方指挥所完成? 149 | # --复杂问题2_end-- 150 | # --任务规划2_start-- 151 | # 1使用knowledge_graph获取我们直升机的承载人数A. 152 | # 2根据我放发射阵地1的300人和直升机的承载人数B计算需要的疏散次数C. 153 | # 3使用knowledge_graph获取直升机的速度D. 154 | # 4使用map_search获取我方指挥所的坐标F和我方发射阵地1的位置G. 155 | # 5使用distance_calculation计算F到G的距离H. 156 | # 6计算直升机以速度D行驶距离H来回一次需要的时间I. 157 | # 7计算完成C次疏散需要的总时间J,并判断是否在直升机续航E之内. 158 | # --任务规划2_end-- 159 | # """ 160 | prompt_template = """\n所有工具的详细介绍如上所示,你是一个智能助手,现在我请你为以下工具生成复合问题,要求生成的问题是具体的问题,有具体的目标,实体,任务,且能够被这几个工具所解决,并且最少这个复杂问题最少要使用两个以上的工具才能完成。接下来请你根据每个工具的简单问题示例和工具描述再生成{}个能够使用以上最少两个工具解决的复杂问题及其解决方案,接下来我会给你一个示例:/n{},\n.并且严格按照示例的格式,用--复杂问题_start--和--复杂问题_end--以及--任务规划_start--和--任务规划_end--进行包裹,不要生成其他无关的文字.""" 161 | tool_prompt = '' 162 | questinos_dict = {} 163 | for index,tool in enumerate(tools): 164 | questions = [] 165 | 166 | tool_description = get_tool_description(tool) 167 | tool_prompt += '\n第{}个工具:'.format(index+1)+tool_description 168 | input_prompt = tool_prompt + prompt_template.format(3,example) 169 | messages = [ 170 | {"role": "system", "content":"You are a helpful assistant."}, 171 | {"role": "user", "content": input_prompt} 172 | ] 173 | input_prompt= tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 174 | # input_prompt = """<|im_start|> system\n You are a helpful assistant<|im_end|>\n<|im_start|> user\n {}<|im_end|>\n<|im_start|> assistant\n""".format( 175 | # input_prompt 176 | # ) 177 | while True: 178 | outputs = llm.generate(input_prompt, sampling_params) 179 | output = outputs[0].outputs[0].text 180 | print(output) 181 | questions.extend(get_complex_question_from_output(output)) 182 | 183 | if len(questions) >= 2: 184 | 185 | with open(save_complex_question_json, "a+", encoding="utf-8") as f: 186 | json.dump(questions, f, ensure_ascii=False, indent=4) 187 | print("{}条输入指令已经保存到{}".format(len(questions), save_complex_question_json)) 188 | break 189 | 190 | def get_react_data(): 191 | if 'llm' not in locals(): 192 | llm = LLM( 193 | model=model_path, 194 | tensor_parallel_size=8, 195 | max_model_len=4096, 196 | dtype="bfloat16", 197 | trust_remote_code=True, 198 | enforce_eager=True, 199 | gpu_memory_utilization=0.8, 200 | ) 201 | 202 | with open(input_question_json, "r", encoding="utf-8") as file: 203 | # 将json文件内容解析为Python对象 204 | tool_questions = json.load(file) 205 | all_questions = [] 206 | for i in tool_questions: 207 | all_questions.extend(tool_questions[i]) 208 | react_question = [build_input_text([(q, "")], tools) for q in all_questions] 209 | params_dict["top_k"] = 1 210 | params_dict["stop"] = ["Observation:"] 211 | 212 | 213 | sampling_params = SamplingParams(**params_dict) 214 | for index in range(0, len(react_question), inference_batch_size): 215 | react_qa = [] 216 | outputs = llm.generate( 217 | react_question[index : index + inference_batch_size], sampling_params 218 | ) 219 | for i in range(len(outputs)): 220 | output = outputs[i].outputs[0].text 221 | 222 | plugin_name, plugin_args, text = parse_latest_plugin_call(output) 223 | excute_flag = True 224 | for tool in tools: 225 | print(tool) 226 | if ( 227 | tool["name_for_model"] == plugin_name 228 | and tool["excute_function"] == False 229 | ): 230 | excute_flag = False 231 | second_input = ( 232 | react_question[index + i] + output + "Observation: " 233 | ) 234 | output2 = ( 235 | llm.generate(second_input, sampling_params)[0] 236 | .outputs[0] 237 | .text 238 | ) 239 | if excute_flag: 240 | observation = function_call(plugin_name, plugin_args,llm,tokenizer) 241 | second_input = ( 242 | react_question[index + i] 243 | + output 244 | + "Observation: {}".format(observation) 245 | ) 246 | output2 = llm.generate(second_input, sampling_params)[0].outputs[0].text 247 | print(output2) 248 | # react_qa.append({react_question[index+i]: second_input[len(react_question[index+i]):]+output2}) 249 | react_qa.append( 250 | { 251 | "instruction": "You are a helpful assistant.", 252 | "input": react_question[index + i][75:-33], 253 | "output": second_input[len(react_question[index + i]) :] 254 | + output2, 255 | } 256 | ) 257 | with open(save_react_qa_json, "a+", encoding="utf-8") as f: 258 | json.dump(react_qa, f, ensure_ascii=False, indent=4) 259 | print("{}条react qa数据已经保存到{}".format(len(react_qa), save_react_qa_json)) 260 | def get_complex_react_data(): 261 | if 'llm' not in locals(): 262 | llm = LLM( 263 | model=model_path, 264 | tensor_parallel_size=8, 265 | max_model_len=4096, 266 | dtype="bfloat16", 267 | trust_remote_code=True, 268 | enforce_eager=True, 269 | gpu_memory_utilization=0.8, 270 | ) 271 | 272 | with open(input_complex_question_json ,"r", encoding="utf-8") as file: 273 | # 将json文件内容解析为Python对象 274 | tool_questions = json.load(file) 275 | all_questions = [] 276 | for i in tool_questions: 277 | all_questions.append(''.join([f"{key}请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:{value}" for key, value in i.items()])) 278 | react_question = [build_input_text([(q, "")], tools) for q in all_questions] 279 | params_dict["top_k"] = 1 280 | params_dict["stop"] = ["Observation:"] 281 | 282 | 283 | sampling_params = SamplingParams(**params_dict) 284 | for index in range(0, len(react_question), inference_batch_size): 285 | react_qa = [] 286 | outputs = llm.generate( 287 | react_question[index : index + inference_batch_size], sampling_params 288 | ) 289 | for i in range(len(outputs)): 290 | output = outputs[i].outputs[0].text 291 | all_output = react_question[index+i] + output 292 | try: 293 | while 'Final Answer' not in output: 294 | plugin_name, plugin_args, text = parse_latest_plugin_call(output) 295 | excute_flag = True 296 | for tool in tools: 297 | if ( 298 | tool["name_for_model"] == plugin_name 299 | and tool["excute_function"] == False 300 | ): 301 | excute_flag = False 302 | second_input = ( 303 | all_output + "Observation: " 304 | ) 305 | output = ( 306 | llm.generate(second_input, sampling_params)[0] 307 | .outputs[0] 308 | .text 309 | ) 310 | all_output += "Observation: " + output 311 | 312 | if excute_flag: 313 | observation = function_call(plugin_name, plugin_args,llm,tokenizer) 314 | second_input = ( 315 | all_output 316 | + "Observation: {}".format(observation) 317 | ) 318 | output = llm.generate(second_input, sampling_params)[0].outputs[0].text 319 | print(observation) 320 | print(output) 321 | all_output += "Observation: {}".format(observation)+output 322 | # react_qa.append({react_question[index+i]: second_input[len(react_question[index+i]):]+output2}) 323 | react_qa.append( 324 | { 325 | "instruction": "You are a helpful assistant.", 326 | "input": react_question[index + i][75:-33], 327 | "output": all_output[len(react_question[index + i]):] 328 | } 329 | ) 330 | except: 331 | print('#####{}#####'.format(all_questions[index+i])) 332 | continue 333 | 334 | with open(save_complex_react_qa_json, "a+", encoding="utf-8") as f: 335 | json.dump(react_qa, f, ensure_ascii=False, indent=4) 336 | print("{}条react qa数据已经保存到{}".format(len(react_qa), save_react_qa_json)) 337 | 338 | def get_complex_react_data_batch(): 339 | if 'llm' not in locals(): 340 | llm = LLM( 341 | model=model_path, 342 | tensor_parallel_size=8, 343 | max_model_len=4096, 344 | dtype="bfloat16", 345 | trust_remote_code=True, 346 | enforce_eager=True, 347 | gpu_memory_utilization=0.8, 348 | ) 349 | 350 | with open(input_complex_question_json ,"r", encoding="utf-8") as file: 351 | # 将json文件内容解析为Python对象 352 | tool_questions = json.load(file) 353 | all_questions = [] 354 | for i in tool_questions: 355 | all_questions.append(''.join([f"{key}请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:{value}" for key, value in i.items()])) 356 | react_question = [build_input_text([(q, "")], tools) for q in all_questions] 357 | params_dict["top_k"] = 1 358 | params_dict["stop"] = ["Observation:"] 359 | 360 | 361 | sampling_params = SamplingParams(**params_dict) 362 | point = inference_batch_size 363 | batch_inputs = react_question[ : inference_batch_size] 364 | exsit_num = len(react_question) 365 | while exsit_num > 2: 366 | outputs = llm.generate( 367 | batch_inputs, sampling_params 368 | ) 369 | batch_inputs = [batch_inputs[i] + outputs[i].outputs[0].text for i in range(len(batch_inputs))] 370 | for i,line in enumerate(batch_inputs): 371 | if 'Final Answer' in outputs[i].outputs[0].text: 372 | data = { 373 | "instruction": "You are a helpful assistant.", 374 | "input": batch_inputs[i][75:].split('<|im_end|>\n<|im_start|>assistant\n')[0], 375 | "output": batch_inputs[i].split('<|im_end|>\n<|im_start|>assistant\n')[1] 376 | } 377 | with open(save_complex_react_qa_json, "a+", encoding="utf-8") as f: 378 | json.dump(data, f, ensure_ascii=False, indent=4) 379 | print("{}条react qa数据已经保存到{}".format(1, save_complex_react_qa_json)) 380 | point += 1 381 | batch_inputs[i] = react_question[point] 382 | exsit_num -= 1 383 | else: 384 | plugin_name, plugin_args, text = parse_latest_plugin_call(outputs[i].outputs[0].text) 385 | excute_flag = True 386 | for tool in tools: 387 | if ( 388 | tool["name_for_model"] == plugin_name 389 | and tool["excute_function"] == False 390 | ): 391 | excute_flag = False 392 | batch_inputs[i] += "Observation: " 393 | 394 | if excute_flag: 395 | try: 396 | observation = function_call(plugin_name, plugin_args,llm,tokenizer) 397 | batch_inputs[i] += "Observation: {}".format(observation) 398 | except: 399 | data = { 400 | "instruction": "You are a helpful assistant.", 401 | "input": batch_inputs[i][75:].split('<|im_end|>\n<|im_start|>assistant\n')[0], 402 | "output": batch_inputs[i].split('<|im_end|>\n<|im_start|>assistant\n')[1] 403 | } 404 | with open(except_comple_react_json, "a+", encoding="utf-8") as f: 405 | json.dump(data, f, ensure_ascii=False, indent=4) 406 | point += 1 407 | batch_inputs[i] = react_question[point] 408 | exsit_num -= 1 409 | print("{}条react qa数据已经保存到{}".format(1, except_comple_react_json)) 410 | 411 | 412 | if __name__ == "__main__": 413 | #get_question()# 获取简单Agent问题数据 414 | #get_complex_question() 415 | #get_react_data() # 获取agent执行过程数据 416 | get_complex_react_data_batch() # 获取复杂agent的执行过程数据 417 | -------------------------------------------------------------------------------- /config_web.py: -------------------------------------------------------------------------------- 1 | import gradio as gr 2 | import re 3 | from vllm import LLM, SamplingParams 4 | from config import * 5 | from build_react_prompt import ( 6 | build_input_text, 7 | TOOL_DESC, 8 | PROMPT_REACT, 9 | parse_latest_plugin_call, 10 | ) 11 | import os 12 | from tools_call import function_call 13 | import json 14 | import json5 15 | from transformers import AutoTokenizer 16 | from tools_caption import tools 17 | from cpm_utils import save_cpm3_data,switch_cpm_tool 18 | # from agent_demo import * 19 | 20 | tokenizer = AutoTokenizer.from_pretrained(model_path,trust_remote_code = True) 21 | # 定义基础参数 22 | model_path = "/root/ld/ld_model_pretrain/Qwen2.5-72B-Instruct-GPTQ-Int4" 23 | gen_datas_per_tool = 10 24 | params_dict = { 25 | "n": 1, 26 | "best_of": 1, 27 | "presence_penalty": 1, 28 | "frequency_penalty": 1.0, 29 | "temperature": 0.8, 30 | "top_p": 0.8, 31 | "top_k": -1, 32 | "stop": None, 33 | "stop_token_ids": None, 34 | "ignore_eos": False, 35 | "max_tokens": 4096, 36 | "logprobs": None, 37 | "prompt_logprobs": None, 38 | "skip_special_tokens": True, 39 | } 40 | sampling_params = SamplingParams(**params_dict) 41 | def split_react_data(react_str): 42 | pattern = re.compile( 43 | r"Thought:\s*(.*?)\nAction:\s*(.*?)\nAction Input:\s*(.*?)\nObservation:\s*(.*?)\nThought:\s*(.*?)\nFinal Answer:\s*(.*)", 44 | re.DOTALL, 45 | ) 46 | 47 | matches = pattern.findall(react_str) 48 | try: 49 | for match in matches: 50 | Thought1 = match[0] 51 | Action = match[1] 52 | Action_Input = match[2] 53 | Observation = match[3] 54 | Thought2 = match[4] 55 | Final_Answer = match[5] 56 | return Thought1, Action, Action_Input, Observation, Thought2, Final_Answer 57 | except: 58 | return None, None, None, None, None, None 59 | 60 | 61 | def get_answer_from_output(output): 62 | pattern = r"「问题开始」(.*?)「问题结束」" 63 | questions = re.findall(pattern, output, re.DOTALL) 64 | questions = [q.strip() for q in questions] 65 | return questions 66 | 67 | def get_complex_question_from_output(output): 68 | pattern = r"--复杂问题_start--(.*?)--复杂问题_end--" 69 | questions = re.findall(pattern, output, re.DOTALL) 70 | pattern2 = r"--任务规划_start--(.*?)--任务规划_end--" 71 | task_plan = re.findall(pattern2, output, re.DOTALL) 72 | if len(task_plan) == len(questions): 73 | questions = [{q.strip():task_plan[i]} for i,q in enumerate(questions)] 74 | else: 75 | questions = [] 76 | return questions 77 | 78 | 79 | def get_tool_description(tool): 80 | tool_descp = "工具名称是{},作用是{},".format( 81 | tool["name_for_model"], tool["description_for_model"] 82 | ) 83 | for t in tool["parameters"]: 84 | if t["required"]: 85 | if t["scope"]: 86 | tool_descp += "参数“{}”是必须输入的,作用是{},该参数的取值范围是{}。".format( 87 | t["name"], t["description"], t["scope"] 88 | ) 89 | else: 90 | tool_descp += "参数“{}”是必须输入的,作用是{}。".format(t["name"], t["description"]) 91 | elif t["scope"]: 92 | tool_descp += "参数“{}”是可选的,作用是{},该参数的取值范围是{}。".format( 93 | t["name"], t["description"], t["scope"] 94 | ) 95 | else: 96 | tool_descp += "参数“{}”是可选的,作用是{}。".format(t["name"], t["description"]) 97 | return tool_descp 98 | 99 | 100 | def get_question(): 101 | if 'llm' not in locals(): 102 | llm = LLM( 103 | model=model_path, 104 | tensor_parallel_size=8, 105 | max_model_len=4096, 106 | dtype="bfloat16", 107 | trust_remote_code=True, 108 | enforce_eager=True, 109 | gpu_memory_utilization=0.8, 110 | ) 111 | 112 | prompt_template = """你是一个智能助手,现在我请你为以下工具生成问题,要求生成的问题能够被这个工具解决。工具的详细介绍如下:\n{}\n我现在给你一个关于此工具问题的示例「问题开始」 113 | {}「问题结束」,接下来请你根据此示例和工具描述再生成{}个能够使用该工具解决的问题,并且用「问题开始」和「问题结束」将其包裹,不要生成其他的无关文字。""" 114 | 115 | all_questions = [] 116 | all_react_prompt = [] 117 | questinos_dict = {} 118 | for tool in tools: 119 | questions = [] 120 | while True: 121 | tool_description = get_tool_description(tool) 122 | input_prompt = prompt_template.format( 123 | tool_description, tool["example"], gen_datas_per_tool 124 | ) 125 | input_prompt = """<|im_start|> system\n you are a helpful assistant<|im_end|>\n<|im_start|> user\n {}<|im_end|>\n<|im_start|> assistant\n""".format( 126 | input_prompt 127 | ) 128 | outputs = llm.generate(input_prompt, sampling_params) 129 | output = outputs[0].outputs[0].text 130 | questions.extend(get_answer_from_output(output)) 131 | 132 | if len(questions) >= gen_datas_per_tool: 133 | all_questions.extend(questions) 134 | print(questions) 135 | questinos_dict[tool["name_for_model"]] = questions 136 | break 137 | 138 | with open(save_question_json, "w", encoding="utf-8") as f: 139 | json.dump(questinos_dict, f, ensure_ascii=False, indent=4) 140 | print("{}条输入指令已经保存到{}".format(len(all_questions), save_question_json)) 141 | 142 | def get_complex_question(): 143 | if 'llm' not in locals(): 144 | llm = LLM( 145 | model=model_path, 146 | tensor_parallel_size=8, 147 | max_model_len=4096, 148 | dtype="bfloat16", 149 | trust_remote_code=True, 150 | enforce_eager=True, 151 | gpu_memory_utilization=0.8, 152 | ) 153 | if complex_example_json.endswith('json'): 154 | with open(complex_example_json,'r',encoding='utf-8') as f: 155 | examples = json.load(f) 156 | else: 157 | examples = [] 158 | all_questions = [] 159 | questions = [] 160 | for example in examples: 161 | question,plan = list(example.items())[0] 162 | example = '''--复杂问题_start--\n{}\n--复杂问题_end--\n--任务规划_start--\n{}\n--任务规划_end--'''.format(question,plan) 163 | example += """--复杂问题2_start-- 164 | 计算一下,如果敌方有意向我方发射阵地1的300人使用化学武器,我方用一架直升机需要多久可以疏散所有人员到我方指挥所完成? 165 | --复杂问题2_end-- 166 | --任务规划2_start-- 167 | 1使用knowledge_graph获取我们直升机的承载人数A. 168 | 2根据我放发射阵地1的300人和直升机的承载人数B计算需要的疏散次数C. 169 | 3使用knowledge_graph获取直升机的速度D. 170 | 4使用map_search获取我方指挥所的坐标F和我方发射阵地1的位置G. 171 | 5使用distance_calculation计算F到G的距离H. 172 | 6计算直升机以速度D行驶距离H来回一次需要的时间I. 173 | 7计算完成C次疏散需要的总时间J,并判断是否在直升机续航E之内. 174 | --任务规划2_end-- 175 | """ 176 | prompt_template = """\n所有工具的详细介绍如上所示,你是一个智能助手,现在我请你为以下工具生成复合问题,要求生成的问题是具体的问题,有具体的目标,实体,任务,且能够被这几个工具所解决,并且最少这个复杂问题最少要使用两个以上的工具才能完成。接下来请你根据每个工具的简单问题示例和工具描述再生成{}个能够使用以上最少两个工具解决的复杂问题及其解决方案,接下来我会给你一个示例:/n{},\n.并且严格按照示例的格式,用--复杂问题_start--和--复杂问题_end--以及--任务规划_start--和--任务规划_end--进行包裹,请以「任务规划_end」结束,不要生成其他无关的文字.""" 177 | tool_prompt = '' 178 | questinos_dict = {} 179 | for index,tool in enumerate(tools): 180 | questions = [] 181 | 182 | tool_description = get_tool_description(tool) 183 | tool_prompt += '\n第{}个工具:'.format(index+1)+tool_description 184 | input_prompt = tool_prompt + prompt_template.format(gen_datas_per_tool,example) 185 | messages = [ 186 | {"role": "system", "content":"You are a helpful assistant."}, 187 | {"role": "user", "content": input_prompt} 188 | ] 189 | input_prompt= tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) 190 | # input_prompt = """<|im_start|> system\n You are a helpful assistant<|im_end|>\n<|im_start|> user\n {}<|im_end|>\n<|im_start|> assistant\n""".format( 191 | # input_prompt 192 | # ) 193 | while True: 194 | outputs = llm.generate(input_prompt, sampling_params) 195 | output = outputs[0].outputs[0].text 196 | print(output) 197 | questions.extend(get_complex_question_from_output(output)) 198 | 199 | if len(questions) >= gen_datas_per_tool: 200 | break 201 | with open(save_complex_question_json, "w", encoding="utf-8") as f: 202 | json.dump(questinos_dict, f, ensure_ascii=False, indent=4) 203 | print("{}条输入指令已经保存到{}".format(len(all_questions), save_complex_question_json)) 204 | def get_react_data(): 205 | if 'llm' not in locals(): 206 | llm = LLM( 207 | model=model_path, 208 | tensor_parallel_size=8, 209 | max_model_len=4096, 210 | dtype="bfloat16", 211 | trust_remote_code=True, 212 | enforce_eager=True, 213 | gpu_memory_utilization=0.8, 214 | ) 215 | 216 | with open(save_question_json, "r", encoding="utf-8") as file: 217 | # 将json文件内容解析为Python对象 218 | tool_questions = json.load(file) 219 | all_questions = [] 220 | for i in tool_questions: 221 | all_questions.extend(tool_questions[i]) 222 | react_question = [build_input_text([(q, "")], tools) for q in all_questions] 223 | params_dict["top_k"] = 1 224 | params_dict["stop"] = ["Observation:"] 225 | 226 | 227 | sampling_params = SamplingParams(**params_dict) 228 | for index in range(0, len(react_question), inference_batch_size): 229 | react_qa = [] 230 | outputs = llm.generate( 231 | react_question[index : index + inference_batch_size], sampling_params 232 | ) 233 | for i in range(len(outputs)): 234 | output = outputs[i].outputs[0].text 235 | 236 | plugin_name, plugin_args, text = parse_latest_plugin_call(output) 237 | excute_flag = True 238 | for tool in tools: 239 | print(tool) 240 | if ( 241 | tool["name_for_model"] == plugin_name 242 | and tool["excute_function"] == False 243 | ): 244 | excute_flag = False 245 | second_input = ( 246 | react_question[index + i] + output + "Observation: " 247 | ) 248 | output2 = ( 249 | llm.generate(second_input, sampling_params)[0] 250 | .outputs[0] 251 | .text 252 | ) 253 | if excute_flag: 254 | observation = function_call(plugin_name, plugin_args,llm,tokenizer) 255 | second_input = ( 256 | react_question[index + i] 257 | + output 258 | + "Observation: {}".format(observation) 259 | ) 260 | output2 = llm.generate(second_input, sampling_params)[0].outputs[0].text 261 | print(output2) 262 | # react_qa.append({react_question[index+i]: second_input[len(react_question[index+i]):]+output2}) 263 | react_qa.append( 264 | { 265 | "instruction": "You are a helpful assistant.", 266 | "input": react_question[index + i][75:-33], 267 | "output": second_input[len(react_question[index + i]) :] 268 | + output2, 269 | } 270 | ) 271 | with open(save_react_qa_json, "a+", encoding="utf-8") as f: 272 | json.dump(react_qa, f, ensure_ascii=False, indent=4) 273 | print("{}条react qa数据已经保存到{}".format(len(react_qa), save_react_qa_json)) 274 | def get_complex_react_data(): 275 | if 'llm' not in locals(): 276 | llm = LLM( 277 | model=model_path, 278 | tensor_parallel_size=8, 279 | max_model_len=4096, 280 | dtype="bfloat16", 281 | trust_remote_code=True, 282 | enforce_eager=True, 283 | gpu_memory_utilization=0.8, 284 | ) 285 | 286 | with open(save_complex_question_json ,"r", encoding="utf-8") as file: 287 | # 将json文件内容解析为Python对象 288 | tool_questions = json.load(file) 289 | all_questions = [] 290 | for i in tool_questions: 291 | all_questions.append(''.join([f"{key}请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:{value}" for key, value in i.items()])) 292 | react_question = [build_input_text([(q, "")], tools) for q in all_questions] 293 | params_dict["top_k"] = 1 294 | params_dict["stop"] = ["Observation:"] 295 | 296 | 297 | sampling_params = SamplingParams(**params_dict) 298 | for index in range(0, len(react_question), inference_batch_size): 299 | react_qa = [] 300 | outputs = llm.generate( 301 | react_question[index : index + inference_batch_size], sampling_params 302 | ) 303 | for i in range(len(outputs)): 304 | output = outputs[i].outputs[0].text 305 | all_output = react_question[index+i] + output 306 | try: 307 | while 'Final Answer' not in output: 308 | plugin_name, plugin_args, text = parse_latest_plugin_call(output) 309 | excute_flag = True 310 | for tool in tools: 311 | if ( 312 | tool["name_for_model"] == plugin_name 313 | and tool["excute_function"] == False 314 | ): 315 | excute_flag = False 316 | second_input = ( 317 | all_output + "Observation: " 318 | ) 319 | output = ( 320 | llm.generate(second_input, sampling_params)[0] 321 | .outputs[0] 322 | .text 323 | ) 324 | all_output += "Observation: " + output 325 | 326 | if excute_flag: 327 | observation = function_call(plugin_name, plugin_args,llm,tokenizer) 328 | second_input = ( 329 | all_output 330 | + "Observation: {}".format(observation) 331 | ) 332 | output = llm.generate(second_input, sampling_params)[0].outputs[0].text 333 | print(observation) 334 | print(output) 335 | all_output += "Observation: {}".format(observation)+output 336 | # react_qa.append({react_question[index+i]: second_input[len(react_question[index+i]):]+output2}) 337 | react_qa.append( 338 | { 339 | "instruction": "You are a helpful assistant.", 340 | "input": react_question[index + i][75:-33], 341 | "output": all_output[len(react_question[index + i]):] 342 | } 343 | ) 344 | except: 345 | print('#####{}#####'.format(all_questions[index+i])) 346 | continue 347 | 348 | with open(save_complex_react_qa_json, "a+", encoding="utf-8") as f: 349 | json.dump(react_qa, f, ensure_ascii=False, indent=4) 350 | print("{}条react qa数据已经保存到{}".format(len(react_qa), save_react_qa_json)) 351 | 352 | 353 | # Gradio界面定义 354 | def interface(choice, model_path, save_question_json, save_react_qa_json, save_complex_question_json, complex_example_json, inference_batch_size,save_complex_react_qa_json): 355 | if choice == "简单Agent问题构造": 356 | return get_question(save_question_json) 357 | elif choice == "简单Agent训练数据构造": 358 | return get_react_data(save_question_json, save_react_qa_json, inference_batch_size) 359 | elif choice == "复杂Agent 问题构造": 360 | return get_complex_question(save_complex_question_json) 361 | elif choice == "复杂Agent 训练数据构造": 362 | return get_complex_react_data(save_complex_question_json, complex_example_json, save_complex_react_qa_json, inference_batch_size) 363 | 364 | # 创建Gradio界面 365 | with gr.Blocks() as demo: 366 | gr.Markdown("# Agent Data Generation Interface") 367 | 368 | # 基础选项 369 | with gr.Row(): 370 | model_path_input = gr.Textbox(value=model_path, label="Model Path (Required)") 371 | 372 | # 函数选择 373 | with gr.Row(): 374 | function_choice = gr.Dropdown(choices=["简单Agent问题构造", "简单Agent训练数据构造", "复杂Agent 问题构造", "复杂Agent 训练数据构造"], label="Select Function") 375 | 376 | # 根据选择的函数显示相关输入 377 | with gr.Column(visible=False) as question_inputs: 378 | save_question_json_input = gr.Textbox(value="AutoPlan2/data_demo/question_react_11_03.json", label="get_question时作为保存路径,get_react_data时作为react数据的输入") 379 | 380 | with gr.Column(visible=False) as react_data_inputs: 381 | save_react_qa_json_input = gr.Textbox(value="AutoPlan2/datademo/react_qa_react.json", label="get_react_data单链条React训练数据保存地址") 382 | inference_batch_size_input = gr.Number(value=8, label="Inference Batch Size ") 383 | 384 | with gr.Column(visible=False) as complex_question_inputs: 385 | save_complex_question_json_input = gr.Textbox(value="AutoPlan2/datademo/question_complex_react.json", label="get_complex_question时作为保存问题地址,get_complex_react_data时作为query输入") 386 | 387 | with gr.Column(visible=False) as complex_react_data_inputs: 388 | complex_example_json_input = gr.Textbox(value='AutoPlan2/datademo/plan_example.json', label="复杂问题和任务规划的示例json") 389 | save_complex_react_qa_json_input = gr.Textbox(value='AutoPlan2/data_demo/question_react_11_03.json', label="保存复杂react训练数据 ") 390 | 391 | # 输出组件 392 | output = gr.Textbox(label="Output") 393 | 394 | # 创建提交按钮 395 | btn = gr.Button("Generate Data") 396 | 397 | # 设置按钮点击时的行为 398 | btn.click( 399 | fn=interface, 400 | inputs=[ 401 | function_choice, 402 | model_path_input, 403 | save_question_json_input, 404 | save_react_qa_json_input, 405 | save_complex_question_json_input, 406 | complex_example_json_input, 407 | inference_batch_size_input 408 | ], 409 | outputs=output 410 | ) 411 | 412 | # 根据选择的函数切换可见性 413 | def update_visibility(choice): 414 | visibility = { 415 | "question_inputs": True, 416 | "react_data_inputs": False, 417 | "complex_question_inputs": False, 418 | "complex_react_data_inputs": False 419 | } 420 | 421 | if choice == "简单Agent问题构造": 422 | visibility["question_inputs"] = True 423 | elif choice == "简单Agent训练数据构造": 424 | visibility["question_inputs"] = True 425 | visibility["react_data_inputs"] = True 426 | elif choice == "复杂Agent 问题构造": 427 | visibility["complex_question_inputs"] = True 428 | elif choice == "复杂Agent 训练数据构造": 429 | visibility["complex_question_inputs"] = True 430 | visibility["complex_react_data_inputs"] = True 431 | visibility["react_data_inputs"] = True 432 | 433 | return [ 434 | gr.update(visible=visibility["question_inputs"]), 435 | gr.update(visible=visibility["react_data_inputs"]), 436 | gr.update(visible=visibility["complex_question_inputs"]), 437 | gr.update(visible=visibility["complex_react_data_inputs"]) 438 | ] 439 | 440 | function_choice.change( 441 | fn=update_visibility, 442 | inputs=function_choice, 443 | outputs=[ 444 | question_inputs, 445 | react_data_inputs, 446 | complex_question_inputs, 447 | complex_react_data_inputs 448 | ] 449 | ) 450 | 451 | # 启动Gradio应用 452 | demo.launch() -------------------------------------------------------------------------------- /data_demo/complex_react_11_07.json: -------------------------------------------------------------------------------- 1 | "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nAnswer the following questions as best you can. You have access to the following tools:\n\nimage_gen_prompt: Call this tool to interact with the 图生文 API. What is the 图生文 API useful for? 图生文是一个可以看图生成文字描述的服务,输入一张图片的地址,将返回图片详细逼真的表述 Parameters: [{\"name\": \"image_path\", \"description\": \"需要图片描述的URL或者本地地址\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nknowledge_graph: Call this tool to interact with the 知识图谱 API. What is the 知识图谱 API useful for? 知识图谱是输入武器种类获取该武器的属性,也可以输入某种属性获得所有武器的该属性 Parameters: [{\"name\": \"weapon_query\", \"description\": \"武器名称\", \"scope\": [\"直升机\", \"豹2A7坦克\", \"黑狐坦克\", \"雷达\", \"装甲车\", \"狙击枪\", \"反坦克导弹\", \"直升机\", \"火箭炮\", \"所有武器\", \"无人机\", \"步兵\"], \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"attribute\", \"description\": \"武器的属性\", \"scope\": [\"射程\", \"携带武器\", \"重量\", \"速度\", \"适应场景\", \"克制武器\", \"续航\", \"满载人数\", \"飞行高度\", \"承载重量\", \"所有属性\", \"探测范围\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ngoogle_search: Call this tool to interact with the 谷歌搜索 API. What is the 谷歌搜索 API useful for? 谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": false, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmilitary_information_search: Call this tool to interact with the 军事情报搜索 API. What is the 军事情报搜索 API useful for? 军事情报搜索是一个通用搜索引擎,可用于访问军事情报网、查询军网、了解军事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": \"所有军事类信息搜索\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\naddress_book: Call this tool to interact with the 通讯录 API. What is the 通讯录 API useful for? 通讯录是用来获取个人信息如电话、邮箱地址、公司地址的软件。 Parameters: [{\"name\": \"person_name\", \"description\": \"被查询者的姓名\", \"scope\": [\"张三\", \"李四\", \"王五\", \"我方指挥所\", \"侦察部队\", \"指挥官\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nQQ_Email: Call this tool to interact with the qq邮箱 API. What is the qq邮箱 API useful for? qq邮箱是一个可以用来发送合接受邮件的工具 Parameters: [{\"name\": \"E-mail_address\", \"description\": \"对方邮箱的地址 发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"E-mail_content\", \"description\": \"发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nSituation_display: Call this tool to interact with the 态势显示 API. What is the 态势显示 API useful for? :态势显示是通过输入目标位置坐标和显示范围,从而显示当前敌我双方的战场态势图像,并生成图片 Parameters: [{\"name\": \"coordinate\", \"description\": \"目标位置的x和y坐标,输入一个列表,如[300,200]\", \"scope\": \"coordinate_x,coordinate_y的取值都在0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"list\"}}, {\"name\": \"radio\", \"description\": \"态势图像显示的范围半径,单位是km,默认值为300km\", \"scope\": \"radio取值都在0到560之间的整数\", \"required\": false, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ncalendar: Call this tool to interact with the 万年历 API. What is the 万年历 API useful for? 万年历获取当前时间的工具 Parameters: [{\"name\": \"time_query\", \"description\": \"目标的时间,例如昨天、今天、明天\", \"location\": \"location_query\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmap_search: Call this tool to interact with the 地图 API. What is the 地图 API useful for? 地图是一个可以查询地图上所有单位位置信息的工具,返回所有敌军的位置信息。 Parameters: [{\"name\": \"lauch\", \"description\": \"输入单位名称或者yes,yes代表启用地图搜索\", \"scope\": [\"我方直升机\", \"敌直升机\", \"我方指挥所\", \"敌坦克\", \"我方火箭炮\", \"我方发射阵地1\", \"我方发射阵地2\", \"敌指挥中心\", \"敌反坦克导弹\", \"我方坦克\", \"所有单位\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\npython_math: Call this tool to interact with the python计算器 API. What is the python计算器 API useful for? python计算器可以通过python的eval()函数计算出输入的字符串表达式结果并返回,表达式仅包含数字、加减乘除、逻辑运算符、次方运算 Parameters: [{\"name\": \"math_formulation\", \"description\": \"根据问题提炼出的python数学表达式,表达式仅包含数字、加减乘除、逻辑运算符\", \"scope\": \"加、减、乘、除、平方、开平方等基本算数操作\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nweapon_launch: Call this tool to interact with the 武器发射按钮 API. What is the 武器发射按钮 API useful for? 武器发射按钮是可以启动指定武器打击指定目标位置工具。 Parameters: [{\"name\": \"weapon_query\", \"description\": \"启动的打击武器名称\", \"scope\": \"weapon_query的取值为['我方直升机','敌直升机','我方指挥所','敌坦克','我方火箭炮','敌反坦克导弹','我方坦克'],x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_name\", \"description\": \"被打击的单位名称\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_coordinate\", \"description\": \"被打击目标的坐标地点比如[x, y]\", \"scope\": \"x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ndistance_calculation: Call this tool to interact with the 距离计算器 API. What is the 距离计算器 API useful for? 会将map_dict上所有单位都与weapon_query进行距离计算,返回map_dict上每一个单位和weapon_query的距离 Parameters: [{\"name\": \"weapon_query\", \"description\": \"{目标单位名称:[目标单位名称的x坐标,目标单位名称的y坐标]},只能是一个单位,比如{我方直升机:[200,300]}\", \"scope\": \"weapon_query为地图上任意目标,但是只能是一个单位\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"map_dict\", \"description\": \"{被计算的单位名称:[该单位的x坐标,该单位的y坐标],被计算的第二个单位名称:[该单位的x坐标,该单位的y坐标]},比如{地方坦克:[300,150]}\", \"scope\": \"map_dict为除目标单位以外的所有地图上单位的名称和位置参数,可以是一个单位也可以是多个单位\", \"required\": true, \"schema\": {\"type\": \"dict\"}}] Format the arguments as a JSON object.\n\nUse the following format:\n\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [image_gen_prompt, knowledge_graph, google_search, military_information_search, address_book, QQ_Email, Situation_display, calendar, map_search, python_math, weapon_launch, distance_calculation]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Observation can be repeated zero or more times)\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n\nBegin!\n\nQuestion: 我方单位需要在最短时间内到达指定地点[0,0],请给出具体方案。请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:1.使用map_search获取所有我方单位的位置信息A。\n2.使用用distance_calculation计算单位到指定地点[0,0]的距离B。\n3.使用knowledge_graph获取我方所有单位的移动速度C。\n4.计算所有我方单位到达指定地点[0,0]的所需时间D,\n5.找出时间最短的单位E。\n6.通过moving_command工具控制该单位移动到指定地点。<|im_end|>\n<|im_start|>assistant\nThought: 首先,我需要使用map_search工具来获取所有我方单位的位置信息。\nAction: map_search\nAction Input: {\"lauch\": \"所有单位\"}\nObservation: {'我方直升机': [100, 80], '敌直升机': [170, 45], '我方指挥所': [0, 2], '敌坦克': [20, 13], '我方火箭炮': [100, 120], '我方发射阵地1': [50, 70], '我方发射阵地2': [150, 170], '敌指挥中心': [70, 35], '敌反坦克导弹': [50, 100], '我方坦克': [32, 21]} \nThought: 现在我已经得到了所有我方单位的位置信息,接下来需要使用distance_calculation工具来计算这些单位到指定地点[0,0]的距离。\nAction: distance_calculation\nAction Input: {\"weapon_query\": \"{'我方直升机':[100,80]}\", \"map_dict\": {\"'敌直升机'\":[170,45], \"'我方指挥所'\":[0,2], \"'敌坦克':[20,13], \"'我方火箭炮':[100,120], \"'我方发射阵地1':[50,79], \"'我方发射阵地2':[159, 679], '敌指挥中心': [79 ,35 ], '敌反坦克导弹': [59 , 68 ] , ' 我 方 坦 克 ': [32 , 68 ]}\"} \n\n""<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nAnswer the following questions as best you can. You have access to the following tools:\n\nimage_gen_prompt: Call this tool to interact with the 图生文 API. What is the 图生文 API useful for? 图生文是一个可以看图生成文字描述的服务,输入一张图片的地址,将返回图片详细逼真的表述 Parameters: [{\"name\": \"image_path\", \"description\": \"需要图片描述的URL或者本地地址\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nknowledge_graph: Call this tool to interact with the 知识图谱 API. What is the 知识图谱 API useful for? 知识图谱是输入武器种类获取该武器的属性,也可以输入某种属性获得所有武器的该属性 Parameters: [{\"name\": \"weapon_query\", \"description\": \"武器名称\", \"scope\": [\"直升机\", \"豹2A7坦克\", \"黑狐坦克\", \"雷达\", \"装甲车\", \"狙击枪\", \"反坦克导弹\", \"直升机\", \"火箭炮\", \"所有武器\", \"无人机\", \"步兵\"], \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"attribute\", \"description\": \"武器的属性\", \"scope\": [\"射程\", \"携带武器\", \"重量\", \"速度\", \"适应场景\", \"克制武器\", \"续航\", \"满载人数\", \"飞行高度\", \"承载重量\", \"所有属性\", \"探测范围\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ngoogle_search: Call this tool to interact with the 谷歌搜索 API. What is the 谷歌搜索 API useful for? 谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": false, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmilitary_information_search: Call this tool to interact with the 军事情报搜索 API. What is the 军事情报搜索 API useful for? 军事情报搜索是一个通用搜索引擎,可用于访问军事情报网、查询军网、了解军事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": \"所有军事类信息搜索\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\naddress_book: Call this tool to interact with the 通讯录 API. What is the 通讯录 API useful for? 通讯录是用来获取个人信息如电话、邮箱地址、公司地址的软件。 Parameters: [{\"name\": \"person_name\", \"description\": \"被查询者的姓名\", \"scope\": [\"张三\", \"李四\", \"王五\", \"我方指挥所\", \"侦察部队\", \"指挥官\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nQQ_Email: Call this tool to interact with the qq邮箱 API. What is the qq邮箱 API useful for? qq邮箱是一个可以用来发送合接受邮件的工具 Parameters: [{\"name\": \"E-mail_address\", \"description\": \"对方邮箱的地址 发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"E-mail_content\", \"description\": \"发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nSituation_display: Call this tool to interact with the 态势显示 API. What is the 态势显示 API useful for? :态势显示是通过输入目标位置坐标和显示范围,从而显示当前敌我双方的战场态势图像,并生成图片 Parameters: [{\"name\": \"coordinate\", \"description\": \"目标位置的x和y坐标,输入一个列表,如[300,200]\", \"scope\": \"coordinate_x,coordinate_y的取值都在0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"list\"}}, {\"name\": \"radio\", \"description\": \"态势图像显示的范围半径,单位是km,默认值为300km\", \"scope\": \"radio取值都在0到560之间的整数\", \"required\": false, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ncalendar: Call this tool to interact with the 万年历 API. What is the 万年历 API useful for? 万年历获取当前时间的工具 Parameters: [{\"name\": \"time_query\", \"description\": \"目标的时间,例如昨天、今天、明天\", \"location\": \"location_query\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmap_search: Call this tool to interact with the 地图 API. What is the 地图 API useful for? 地图是一个可以查询地图上所有单位位置信息的工具,返回所有敌军的位置信息。 Parameters: [{\"name\": \"lauch\", \"description\": \"输入单位名称或者yes,yes代表启用地图搜索\", \"scope\": [\"我方直升机\", \"敌直升机\", \"我方指挥所\", \"敌坦克\", \"我方火箭炮\", \"我方发射阵地1\", \"我方发射阵地2\", \"敌指挥中心\", \"敌反坦克导弹\", \"我方坦克\", \"所有单位\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\npython_math: Call this tool to interact with the python计算器 API. What is the python计算器 API useful for? python计算器可以通过python的eval()函数计算出输入的字符串表达式结果并返回,表达式仅包含数字、加减乘除、逻辑运算符、次方运算 Parameters: [{\"name\": \"math_formulation\", \"description\": \"根据问题提炼出的python数学表达式,表达式仅包含数字、加减乘除、逻辑运算符\", \"scope\": \"加、减、乘、除、平方、开平方等基本算数操作\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nweapon_launch: Call this tool to interact with the 武器发射按钮 API. What is the 武器发射按钮 API useful for? 武器发射按钮是可以启动指定武器打击指定目标位置工具。 Parameters: [{\"name\": \"weapon_query\", \"description\": \"启动的打击武器名称\", \"scope\": \"weapon_query的取值为['我方直升机','敌直升机','我方指挥所','敌坦克','我方火箭炮','敌反坦克导弹','我方坦克'],x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_name\", \"description\": \"被打击的单位名称\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_coordinate\", \"description\": \"被打击目标的坐标地点比如[x, y]\", \"scope\": \"x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ndistance_calculation: Call this tool to interact with the 距离计算器 API. What is the 距离计算器 API useful for? 会将map_dict上所有单位都与weapon_query进行距离计算,返回map_dict上每一个单位和weapon_query的距离 Parameters: [{\"name\": \"weapon_query\", \"description\": \"{目标单位名称:[目标单位名称的x坐标,目标单位名称的y坐标]},只能是一个单位,比如{我方直升机:[200,300]}\", \"scope\": \"weapon_query为地图上任意目标,但是只能是一个单位\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"map_dict\", \"description\": \"{被计算的单位名称:[该单位的x坐标,该单位的y坐标],被计算的第二个单位名称:[该单位的x坐标,该单位的y坐标]},比如{地方坦克:[300,150]}\", \"scope\": \"map_dict为除目标单位以外的所有地图上单位的名称和位置参数,可以是一个单位也可以是多个单位\", \"required\": true, \"schema\": {\"type\": \"dict\"}}] Format the arguments as a JSON object.\n\nUse the following format:\n\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [image_gen_prompt, knowledge_graph, google_search, military_information_search, address_book, QQ_Email, Situation_display, calendar, map_search, python_math, weapon_launch, distance_calculation]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Observation can be repeated zero or more times)\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n\nBegin!\n\nQuestion: 请确认我方火箭炮是否成功打击敌方坦克。请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:1.使用map_search获取敌方坦克的位置A。\n2.使用weapon_launch工具发射火箭炮打击坐标A。\n3.使用distance_calculation获取我方火箭炮到敌方坦克的距离C\n4.使用knowledge_graph获取火箭炮的速度D。\n5.根据火箭炮的速度D和我方火箭炮到敌方坦克的距离C计算火箭炮飞行时间E。\n6.使用calendar获取当前时间F。\n7.根据当前时间F+飞行时间E后使用态势工具查看敌方坦克位置A。<|im_end|>\n<|im_start|>assistant\nThought: 首先,我需要使用map_search工具来获取敌方坦克的位置A。\nAction: map_search\nAction Input: {\"lauch\": \"敌坦克\"}\nObservation: {'我方直升机': [100, 80], '敌直升机': [170, 45], '我方指挥所': [0, 2], '敌坦克': [20, 13], '我方火箭炮': [100, 120], '我方发射阵地1': [50, 70], '我方发射阵地2': [150, 170], '敌指挥中心': [70, 35], '敌反坦克导弹': [50, 100], '我方坦克': [32, 21]} \nThought: 我已经获取到了敌方坦克的位置A,接下来我需要使用weapon_launch工具发射火箭炮打击坐标A。\nAction: weapon_launch\nAction Input: {\"weapon_query\": \"我方火箭炮\", \"target_name\": \"敌坦克\", \"target_coordinate\": [20, 13]}\nObservation: 已启动我方火箭炮打击敌坦克打击位置:[20, 13]。\nThought: 火箭炮已经发射,现在我需要使用distance_calculation工具来获取我方火箭炮到敌方坦克的距离C。\nAction: distance_calculation\nAction Input: {\"weapon_query\": \"{我方火箭炮:[100,120]}\", \"map_dict\": \"{敌坦克:[20,13]}\"}\n\n""<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nAnswer the following questions as best you can. You have access to the following tools:\n\nimage_gen_prompt: Call this tool to interact with the 图生文 API. What is the 图生文 API useful for? 图生文是一个可以看图生成文字描述的服务,输入一张图片的地址,将返回图片详细逼真的表述 Parameters: [{\"name\": \"image_path\", \"description\": \"需要图片描述的URL或者本地地址\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nknowledge_graph: Call this tool to interact with the 知识图谱 API. What is the 知识图谱 API useful for? 知识图谱是输入武器种类获取该武器的属性,也可以输入某种属性获得所有武器的该属性 Parameters: [{\"name\": \"weapon_query\", \"description\": \"武器名称\", \"scope\": [\"直升机\", \"豹2A7坦克\", \"黑狐坦克\", \"雷达\", \"装甲车\", \"狙击枪\", \"反坦克导弹\", \"直升机\", \"火箭炮\", \"所有武器\", \"无人机\", \"步兵\"], \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"attribute\", \"description\": \"武器的属性\", \"scope\": [\"射程\", \"携带武器\", \"重量\", \"速度\", \"适应场景\", \"克制武器\", \"续航\", \"满载人数\", \"飞行高度\", \"承载重量\", \"所有属性\", \"探测范围\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ngoogle_search: Call this tool to interact with the 谷歌搜索 API. What is the 谷歌搜索 API useful for? 谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": false, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmilitary_information_search: Call this tool to interact with the 军事情报搜索 API. What is the 军事情报搜索 API useful for? 军事情报搜索是一个通用搜索引擎,可用于访问军事情报网、查询军网、了解军事新闻等。 Parameters: [{\"name\": \"search_query\", \"description\": \"搜索关键词或短语\", \"scope\": \"所有军事类信息搜索\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\naddress_book: Call this tool to interact with the 通讯录 API. What is the 通讯录 API useful for? 通讯录是用来获取个人信息如电话、邮箱地址、公司地址的软件。 Parameters: [{\"name\": \"person_name\", \"description\": \"被查询者的姓名\", \"scope\": [\"张三\", \"李四\", \"王五\", \"我方指挥所\", \"侦察部队\", \"指挥官\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nQQ_Email: Call this tool to interact with the qq邮箱 API. What is the qq邮箱 API useful for? qq邮箱是一个可以用来发送合接受邮件的工具 Parameters: [{\"name\": \"E-mail_address\", \"description\": \"对方邮箱的地址 发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"E-mail_content\", \"description\": \"发给对方的内容\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nSituation_display: Call this tool to interact with the 态势显示 API. What is the 态势显示 API useful for? :态势显示是通过输入目标位置坐标和显示范围,从而显示当前敌我双方的战场态势图像,并生成图片 Parameters: [{\"name\": \"coordinate\", \"description\": \"目标位置的x和y坐标,输入一个列表,如[300,200]\", \"scope\": \"coordinate_x,coordinate_y的取值都在0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"list\"}}, {\"name\": \"radio\", \"description\": \"态势图像显示的范围半径,单位是km,默认值为300km\", \"scope\": \"radio取值都在0到560之间的整数\", \"required\": false, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ncalendar: Call this tool to interact with the 万年历 API. What is the 万年历 API useful for? 万年历获取当前时间的工具 Parameters: [{\"name\": \"time_query\", \"description\": \"目标的时间,例如昨天、今天、明天\", \"location\": \"location_query\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nmap_search: Call this tool to interact with the 地图 API. What is the 地图 API useful for? 地图是一个可以查询地图上所有单位位置信息的工具,返回所有敌军的位置信息。 Parameters: [{\"name\": \"lauch\", \"description\": \"输入单位名称或者yes,yes代表启用地图搜索\", \"scope\": [\"我方直升机\", \"敌直升机\", \"我方指挥所\", \"敌坦克\", \"我方火箭炮\", \"我方发射阵地1\", \"我方发射阵地2\", \"敌指挥中心\", \"敌反坦克导弹\", \"我方坦克\", \"所有单位\"], \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\npython_math: Call this tool to interact with the python计算器 API. What is the python计算器 API useful for? python计算器可以通过python的eval()函数计算出输入的字符串表达式结果并返回,表达式仅包含数字、加减乘除、逻辑运算符、次方运算 Parameters: [{\"name\": \"math_formulation\", \"description\": \"根据问题提炼出的python数学表达式,表达式仅包含数字、加减乘除、逻辑运算符\", \"scope\": \"加、减、乘、除、平方、开平方等基本算数操作\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\nweapon_launch: Call this tool to interact with the 武器发射按钮 API. What is the 武器发射按钮 API useful for? 武器发射按钮是可以启动指定武器打击指定目标位置工具。 Parameters: [{\"name\": \"weapon_query\", \"description\": \"启动的打击武器名称\", \"scope\": \"weapon_query的取值为['我方直升机','敌直升机','我方指挥所','敌坦克','我方火箭炮','敌反坦克导弹','我方坦克'],x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_name\", \"description\": \"被打击的单位名称\", \"scope\": null, \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"target_coordinate\", \"description\": \"被打击目标的坐标地点比如[x, y]\", \"scope\": \"x,y坐标都是0到400之间的整数\", \"required\": true, \"schema\": {\"type\": \"string\"}}] Format the arguments as a JSON object.\n\ndistance_calculation: Call this tool to interact with the 距离计算器 API. What is the 距离计算器 API useful for? 会将map_dict上所有单位都与weapon_query进行距离计算,返回map_dict上每一个单位和weapon_query的距离 Parameters: [{\"name\": \"weapon_query\", \"description\": \"{目标单位名称:[目标单位名称的x坐标,目标单位名称的y坐标]},只能是一个单位,比如{我方直升机:[200,300]}\", \"scope\": \"weapon_query为地图上任意目标,但是只能是一个单位\", \"required\": true, \"schema\": {\"type\": \"string\"}}, {\"name\": \"map_dict\", \"description\": \"{被计算的单位名称:[该单位的x坐标,该单位的y坐标],被计算的第二个单位名称:[该单位的x坐标,该单位的y坐标]},比如{地方坦克:[300,150]}\", \"scope\": \"map_dict为除目标单位以外的所有地图上单位的名称和位置参数,可以是一个单位也可以是多个单位\", \"required\": true, \"schema\": {\"type\": \"dict\"}}] Format the arguments as a JSON object.\n\nUse the following format:\n\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [image_gen_prompt, knowledge_graph, google_search, military_information_search, address_book, QQ_Email, Situation_display, calendar, map_search, python_math, weapon_launch, distance_calculation]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Observation can be repeated zero or more times)\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n\nBegin!\n\nQuestion: 请提供在我方反坦克导弹打击范围内的敌方单位信息。请按以下执行顺序完成以上问题,请注意A、B、C等等都是指代某些特殊值。:1.使用knowledge_graph获取反坦克导弹的打击距离。\n2.使用map_search获取所有敌方单位的位置坐标。\n3.使用distance_calculation计算我方反坦克导弹与所有敌方单位之间的距离,找出在打击范围内的敌方单位。<|im_end|>\n<|im_start|>assistant\nThought: 首先,我需要使用knowledge_graph来获取反坦克导弹的打击距离。\nAction: knowledge_graph\nAction Input: {\"weapon_query\": \"反坦克导弹\", \"attribute\": \"射程\"}\nObservation: 反坦克导弹的射程是:0.5千米到5千米\nThought: 现在我知道了反坦克导弹的射程,接下来我需要使用map_search来获取所有敌方单位的位置坐标。\nAction: map_search\nAction Input: {\"lauch\": \"所有单位\"}\nObservation: {'我方直升机': [100, 80], '敌直升机': [170, 45], '我方指挥所': [0, 2], '敌坦克': [20, 13], '我方火箭炮': [100, 120], '我方发射阵地1': [50, 70], '我方发射阵地2': [150, 170], '敌指挥中心': [70, 35], '敌反坦克导弹': [50, 100], '我方坦克': [32, 21]} \nThought: 现在我知道了所有敌方单位的位置坐标,接下来我需要使用distance_calculation来计算我方反坦克导弹与所有敌方单位之间的距离。\nAction: distance_calculation\nAction Input: {\"weapon_query\": \"{'我方反坦克导弹':[100, 100]}\", \"map_dict\": {\"敌直升机\":[170, 45], \"敌坦克\":[20, 13], \"敌指挥中心\":[70, 35], \"敌反坦克导弹\":[50, 100]}}\n\n" --------------------------------------------------------------------------------