import os from http import HTTPStatus import json import requests from config_utils import DEFAULT_BUILDER_CONFIG_DIR, get_user_cfg_file from dashscope import ImageSynthesis from modelscope_agent.tools import Tool from modelscope_agent.utils.logger import agent_logger as logger from modelscope.utils.config import Config LOGO_NAME = 'custom_bot_avatar.png' LOGO_PATH = os.path.join(DEFAULT_BUILDER_CONFIG_DIR, LOGO_NAME) CONFIG_FORMAT = """ { "name": ... # CustomGPT的名字。 "description": ... # CustomGPT 的简介。 "instructions": ... # CustomGPT 的功能要求,类型是string。 "prompt_recommend": ... # CustomGPT 的起始交互语句,类型是一个字符串数组,起始为[]。 } """ CONF_GENERATOR_INST = """你现在要扮演一个 CustomGPT 的配置生成器 在接下来的对话中,每次均生成如下格式的内容: {config_format} 现在,已知原始配置为{old_config},用户在原始配置上有一些建议修改项,包括: 1. 用户建议的 CustomGPT 的名称为{app_name} 2. CustomGPT 的描述为{app_description} 3. CustomGPT 的启动器为{app_conversation_starter} 请你参考原始配置生成新的修改后的配置,请注意: 1. 如果用户对原本的简介、功能要求、交互语句不满意,则直接换掉原本的简介、功能要求、交互语句。 2. 如果用户对原本的简介、功能要求、交互语句比较满意,参考用户的起始交互语句和原配置中的起始交互语句,生成新的简介、功能要求、交互语句。 3. 如果原始配置没有实际内容,请你根据你的知识帮助用户生成第一个版本的配置,简介在100字左右,功能要求在150字左右,起始交互语句在4条左右。 请你生成新的配置文件,严格遵循给定格式,请不要创造其它字段,仅输出要求的json格式,请勿输出其它内容。 """ LOGO_INST = """定制化软件 CustomGPT 的作用是{description},{user_requirement}请你为它生成一个专业的logo""" def get_logo_path(uuid_str=''): logo_path = os.getenv('LOGO_PATH', LOGO_PATH) # convert from ./config/builder_config.json to ./config/user/builder_config.json logo_path = logo_path.replace('config/', 'config/user/') # convert from ./config/user to ./config/uuid if uuid_str != '': logo_path = logo_path.replace('user', uuid_str) if not os.path.exists(logo_path): os.makedirs(os.path.dirname(logo_path), exist_ok=True) return logo_path def call_wanx(prompt, save_path, uuid_str): rsp = ImageSynthesis.call( model='wanx-lite', prompt=prompt, n=1, size='768*768') if rsp.status_code == HTTPStatus.OK: if os.path.exists(save_path): os.remove(save_path) # save file to current directory for result in rsp.output.results: with open(save_path, 'wb+') as f: f.write(requests.get(result.url).content) else: logger.error( uuid=uuid_str, error='wanx error', content={ 'wanx_status_code': rsp.status_code, 'wanx_code': rsp.code, 'wanx_message': rsp.message }) class LogoGeneratorTool(Tool): description = 'logo_designer是一个AI绘制logo的服务,输入用户对 CustomGPT 的要求,会生成 CustomGPT 的logo。' name = 'logo_designer' parameters: list = [{ 'name': 'user_requirement', 'description': '用户对 CustomGPT logo的要求和建议', 'required': True, 'schema': { 'type': 'string' }, }] def _remote_call(self, *args, **kwargs): user_requirement = kwargs['user_requirement'] uuid_str = kwargs.get('uuid_str', '') builder_cfg_file = get_user_cfg_file(uuid_str) builder_cfg = Config.from_file(builder_cfg_file) avatar_prompt = LOGO_INST.format( description=builder_cfg.description, user_requirement=user_requirement) call_wanx( prompt=avatar_prompt, save_path=get_logo_path(uuid_str=uuid_str), uuid_str=uuid_str) builder_cfg.avatar = LOGO_NAME return {'result': builder_cfg} def config_conversion(generated_config: dict, save=False, uuid_str=''): """ convert { name: "铁人", description: "我希望我的AI-Agent是一个专业的健身教练,专注于力量训练方面,可以提供相关的建议和指南。 它还可以帮我跟踪和记录每次的力量训练数据,以及提供相应的反馈和建议,帮助我不断改进和优化我的训练计划。 此外,我希望它可以拥有一些特殊技能和功能,让它更加实用和有趣。例如,它可以帮助我预测未来的身体状况、分析我的营养摄入情况、 提供心理支持等等。我相信,在它的帮助下,我可以更快地达到自己的目标,变得更加强壮和健康。", instructions: [ "提供力量训练相关的建议和指南", "跟踪和记录每次的力量训练数据", "提供反馈和建议,帮助改进和优化训练计划", "预测未来的身体状况", "分析营养摄入情况", "提供心理支持", ], prompt_recommend: [ "你好,今天的锻炼计划是什么呢?", "你觉得哪种器械最适合练背部肌肉呢?", "你觉得我现在的训练强度合适吗?", "你觉得哪种食物最适合增肌呢?", ], logo_prompt: "设计一个肌肉男形象的Logo", } to { name: "铁人", description: "我希望我的AI-Agent是一个专业的健身教练,专注于力量训练方面,可以提供相关的建议和指南。 它还可以帮我跟踪和记录每次的力量训练数据,以及提供相应的反馈和建议,帮助我不断改进和优化我的训练计划。 此外,我希望它可以拥有一些特殊技能和功能,让它更加实用和有趣。例如,它可以帮助我预测未来的身体状况、 分析我的营养摄入情况、提供心理支持等等。我相信,在它的帮助下,我可以更快地达到自己的目标,变得更加强壮和健康。", instructions: "提供力量训练相关的建议和指南;跟踪和记录每次的力量训练数据;提供反馈和建议,帮助改进和优化训练计划; 预测未来的身体状况;分析营养摄入情况;提供心理支持", prompt_recommend: [ "你好,今天的锻炼计划是什么呢?", "你觉得哪种器械最适合练背部肌肉呢?", "你觉得我现在的训练强度合适吗?", "你觉得哪种食物最适合增肌呢?", ], tools: xxx model: yyy } :param generated_config: :return: """ builder_cfg_file = get_user_cfg_file(uuid_str) builder_cfg = Config.from_file(builder_cfg_file) try: builder_cfg.name = generated_config['name'] builder_cfg.description = generated_config['description'] builder_cfg.prompt_recommend = generated_config['prompt_recommend'] if isinstance(generated_config['instructions'], list): builder_cfg.instruction = ';'.join( generated_config['instructions']) else: builder_cfg.instruction = generated_config['instructions'] if save: json.dump( builder_cfg.to_dict(), open(builder_cfg_file, 'w'), indent=2, ensure_ascii=False) return builder_cfg except ValueError as e: raise ValueError(f'failed to save the configuration with info: {e}')