diff --git a/apps/agentfabric/app.py b/apps/agentfabric/app.py index 7c0d558b0..c85df8175 100644 --- a/apps/agentfabric/app.py +++ b/apps/agentfabric/app.py @@ -1,4 +1,3 @@ -import importlib import os import random import shutil @@ -11,7 +10,7 @@ from builder_core import (beauty_output, gen_response_and_process, init_builder_chatbot_agent) from config_utils import (DEFAULT_AGENT_DIR, Config, get_avatar_image, - get_ci_dir, get_user_cfg_file, get_user_dir, + get_ci_dir, get_user_dir, is_valid_plugin_configuration, parse_configuration, save_avatar_image, save_builder_configuration, save_plugin_configuration) @@ -34,10 +33,10 @@ def init_user(uuid_str, state): state['user_agent'] = user_agent state['user_memory'] = user_memory except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), - content={'error_traceback': traceback.format_exc()}) + details={'error_traceback': traceback.format_exc()}) return state @@ -47,10 +46,10 @@ def init_builder(uuid_str, state): state['builder_agent'] = builder_agent state['builder_memory'] = builder_memory except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), - content={'error_traceback': traceback.format_exc()}) + details={'error_traceback': traceback.format_exc()}) return state @@ -60,10 +59,10 @@ def update_builder(uuid_str, state): builder_agent = init_builder_chatbot_agent(uuid_str) state['builder_agent'] = builder_agent except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), - content={'error_traceback': traceback.format_exc()}) + details={'error_traceback': traceback.format_exc()}) return state @@ -292,10 +291,10 @@ def check_uuid(uuid_str): # 初始化表单 def init_ui_config(uuid_str, _state, builder_cfg, model_cfg, tool_cfg): - logger.info( + logger.query_info( uuid=uuid_str, message='builder_cfg', - content={'builder_cfg': str(builder_cfg)}) + details={'builder_cfg': str(builder_cfg)}) # available models models = list(model_cfg.keys()) capabilities = [(tool_cfg[tool_key]['name'], tool_key) @@ -408,8 +407,8 @@ def create_send_message(chatbot, input, _state, uuid_str): llm_result = frame.get('llm_text', '') exec_result = frame.get('exec_result', '') step_result = frame.get('step', '') - logger.info( - uuid=uuid_str, message='frame', content={'frame': str(frame)}) + logger.query_info( + uuid=uuid_str, message='frame', details={'frame': str(frame)}) if len(exec_result) != 0: if isinstance(exec_result, dict): exec_result = exec_result['result'] @@ -506,10 +505,10 @@ def process_configuration(uuid_str, bot_avatar, name, description, if is_valid_plugin_configuration(openapi_plugin_cfg): save_plugin_configuration(openapi_plugin_cfg, uuid_str) except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), - content={'error_traceback': traceback.format_exc()}) + details={'error_traceback': traceback.format_exc()}) save_builder_configuration(builder_cfg, uuid_str) update_builder(uuid_str, state) @@ -585,7 +584,8 @@ def preview_send_message(chatbot, input, _state, uuid_str): input.text, history=history, ref_doc=ref_doc, - append_files=append_files): + append_files=append_files, + uuid_str=uuid_str): # append_files=new_file_paths): # important! do not change this response += frame diff --git a/apps/agentfabric/appBot.py b/apps/agentfabric/appBot.py index b6eeb74c7..505f43e19 100644 --- a/apps/agentfabric/appBot.py +++ b/apps/agentfabric/appBot.py @@ -42,10 +42,10 @@ def init_user(state): state['user_agent'] = user_agent state['user_memory'] = user_memory except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), - content={'error_traceback': traceback.format_exc()}) + details={'error_traceback': traceback.format_exc()}) raise Exception(e) return state diff --git a/apps/agentfabric/builder_core.py b/apps/agentfabric/builder_core.py index 5abbd0e72..28ff90796 100644 --- a/apps/agentfabric/builder_core.py +++ b/apps/agentfabric/builder_core.py @@ -1,6 +1,7 @@ # flake8: noqa E501 import os import re +from http import HTTPStatus import json from config_utils import DEFAULT_UUID_HISTORY, parse_configuration @@ -24,12 +25,12 @@ def init_builder_chatbot_agent(uuid_str: str, session='default'): builder_cfg, model_cfg, _, _, _, _ = parse_configuration(uuid_str) # init agent - logger.info( + logger.query_info( uuid=uuid_str, message=f'using builder model {builder_cfg.model}') llm_config = {'model': builder_cfg.model, 'model_server': 'dashscope'} # function_list = ['image_gen'] # use image_gen to draw logo? - agent = AgentBuilder(llm=llm_config) + agent = AgentBuilder(llm=llm_config, uuid_str=uuid_str) current_history_path = os.path.join(DEFAULT_UUID_HISTORY, uuid_str, session + '_builder.json') @@ -51,7 +52,7 @@ def gen_response_and_process(agent, llm_result = '' llm_result_prefix = '' try: - response = agent.run(query, history=history) + response = agent.run(query, history=history, uuid_str=uuid_str) for s in response: llm_result += s answer, finish, llm_result_prefix = agent.parse_answer( @@ -74,10 +75,10 @@ def gen_response_and_process(agent, Message(role='assistant', content=llm_result), ]) if print_info: - logger.info( + logger.query_info( uuid=uuid_str, message=f'LLM output in round 0', - content={'llm_result': llm_result}) + details={'llm_result': llm_result}) except Exception as e: yield {'error': 'llm result is not valid'} @@ -95,14 +96,14 @@ def gen_response_and_process(agent, try: answer = json.loads(rich_config) except Exception: - logger.error(uuid=uuid_str, error='parse RichConfig error') + logger.query_error(uuid=uuid_str, error='parse RichConfig error') return agent.last_assistant_structured_response['rich_config_dict'] = answer builder_cfg = config_conversion(answer, uuid_str=uuid_str) yield {'exec_result': {'result': builder_cfg}} yield {'step': CONFIG_UPDATED_STEP} except ValueError as e: - logger.error(uuid=uuid_str, error=str(e)) + logger.query_error(uuid=uuid_str, error=str(e)) yield {'error content=[{}]'.format(llm_result)} return diff --git a/apps/agentfabric/config_utils.py b/apps/agentfabric/config_utils.py index 0450b1a17..8b2c89193 100644 --- a/apps/agentfabric/config_utils.py +++ b/apps/agentfabric/config_utils.py @@ -162,7 +162,7 @@ def parse_configuration(uuid_str=''): for name, config in config_dict.items(): available_plugin_list.append(name) except Exception as e: - logger.error( + logger.query_error( uuid=uuid_str, error=str(e), content={ diff --git a/apps/agentfabric/help_tools.py b/apps/agentfabric/help_tools.py index f81423d9b..9eb2507d5 100644 --- a/apps/agentfabric/help_tools.py +++ b/apps/agentfabric/help_tools.py @@ -68,7 +68,7 @@ def call_wanx(prompt, save_path, uuid_str): with open(save_path, 'wb+') as f: f.write(requests.get(result.url).content) else: - logger.error( + logger.query_error( uuid=uuid_str, error='wanx error', content={ diff --git a/apps/agentfabric/user_core.py b/apps/agentfabric/user_core.py index 9b14f5233..64c86ebb9 100644 --- a/apps/agentfabric/user_core.py +++ b/apps/agentfabric/user_core.py @@ -22,10 +22,10 @@ def init_user_chatbot_agent(uuid_str='', session='default'): model_cfg[builder_cfg.model]['generate_cfg']['stop'] = 'Observation' # build model - logger.info( + logger.query_info( uuid=uuid_str, message=f'using model {builder_cfg.model}', - content={'model_config': model_cfg[builder_cfg.model]}) + details={'model_config': model_cfg[builder_cfg.model]}) # update function_list function_list = parse_tool_cfg(tool_cfg) @@ -39,7 +39,10 @@ def init_user_chatbot_agent(uuid_str='', session='default'): 'instruction': builder_cfg.description } agent = RolePlay( - function_list=function_list, llm=llm_config, instruction=instruction) + function_list=function_list, + llm=llm_config, + instruction=instruction, + uuid_str=uuid_str) # build memory storage_path = get_user_dir(uuid_str) diff --git a/modelscope_agent/agent.py b/modelscope_agent/agent.py index 5adb198c7..3627225ba 100644 --- a/modelscope_agent/agent.py +++ b/modelscope_agent/agent.py @@ -50,6 +50,7 @@ def __init__(self, self.name = name self.description = description self.instruction = instruction + self.uuid_str = kwargs.get('uuid_str', None) def run(self, *args, **kwargs) -> Union[str, Iterator[str]]: if 'lang' not in kwargs: @@ -57,6 +58,8 @@ def run(self, *args, **kwargs) -> Union[str, Iterator[str]]: kwargs['lang'] = 'zh' else: kwargs['lang'] = 'en' + if 'uuid_str' not in kwargs and self.uuid_str is not None: + kwargs['uuid_str'] = self.uuid_str return self._run(*args, **kwargs) @abstractmethod diff --git a/modelscope_agent/agents/agent_builder.py b/modelscope_agent/agents/agent_builder.py index 51a641a02..7cb69f2e1 100644 --- a/modelscope_agent/agents/agent_builder.py +++ b/modelscope_agent/agents/agent_builder.py @@ -115,7 +115,7 @@ def _run(self, # concat the new messages messages.append({'role': 'user', 'content': user_request}) - return self._call_llm(messages=messages) + return self._call_llm(messages=messages, **kwargs) def parse_answer(self, llm_result_prefix: str, llm_result: str): """ diff --git a/modelscope_agent/agents/function_calling.py b/modelscope_agent/agents/function_calling.py index d01bdfdfa..39aa3f889 100644 --- a/modelscope_agent/agents/function_calling.py +++ b/modelscope_agent/agents/function_calling.py @@ -3,7 +3,7 @@ from modelscope_agent import Agent from modelscope_agent.agents.react import ReAct from modelscope_agent.agents.react_chat import ReActChat -from modelscope_agent.log import logger +from modelscope_agent.utils.logger import agent_logger as logger class FunctionCalling(Agent): diff --git a/modelscope_agent/agents/role_play.py b/modelscope_agent/agents/role_play.py index f9aa63aa5..2949a903b 100644 --- a/modelscope_agent/agents/role_play.py +++ b/modelscope_agent/agents/role_play.py @@ -212,7 +212,7 @@ def _run(self, prompt=planning_prompt, stream=True, stop=['Observation:', 'Observation:\n'], - ) + **kwargs) llm_result = '' for s in output: diff --git a/modelscope_agent/llm/dashscope.py b/modelscope_agent/llm/dashscope.py index 54034268b..ddf06a411 100644 --- a/modelscope_agent/llm/dashscope.py +++ b/modelscope_agent/llm/dashscope.py @@ -3,17 +3,25 @@ from typing import Dict, Iterator, List, Optional import dashscope +from modelscope_agent.utils.logger import agent_logger as logger from .base import BaseChatModel, register_llm -def stream_output(response): +def stream_output(response, **kwargs): last_len = 0 delay_len = 5 in_delay = False text = '' for trunk in response: if trunk.status_code == HTTPStatus.OK: + logger.query_info( + uuid=kwargs.get('uuid_str', ''), + details={ + 'dashscope.request_id': trunk.request_id, + 'dashscope.output': trunk.output + }, + message='call dashscope generation api success') text = trunk.output.choices[0].message.content if (len(text) - last_len) <= delay_len: in_delay = True @@ -25,6 +33,15 @@ def stream_output(response): yield now_rsp last_len = len(real_text) else: + logger.query_error( + uuid=kwargs.get('uuid_str', ''), + details={ + 'dashscope.request_id': trunk.request_id, + 'dashscope.status_code': trunk.status_code, + 'dashscope.code': trunk.code, + 'dashscope.message': trunk.message + }, + message='call dashscope generation api error') err = '\nError code: %s. Error message: %s' % (trunk.code, trunk.message) if trunk.code == 'DataInspectionFailed': @@ -55,20 +72,24 @@ def _chat_stream(self, stop: Optional[List[str]] = None, **kwargs) -> Iterator[str]: stop = stop or [] - top_p = kwargs.get('top_p', 0.8) - - response = dashscope.Generation.call( - self.model, - messages=messages, # noqa - stop_words=[{ + generation_input = { + 'model': self.model, + 'messages': messages, # noqa + 'stop_words': [{ 'stop_str': word, 'mode': 'exclude' } for word in stop], - top_p=top_p, - result_format='message', - stream=True, - ) - return stream_output(response) + 'top_p': kwargs.get('top_p', 0.8), + 'result_format': 'message', + 'stream': True, + } + + logger.query_info( + uuid=kwargs.get('uuid_str', ''), + details=generation_input, + message='call dashscope generation api') + response = dashscope.Generation.call(**generation_input) + return stream_output(response, **kwargs) def _chat_no_stream(self, messages: List[Dict], diff --git a/modelscope_agent/log.py b/modelscope_agent/log.py deleted file mode 100644 index bca90357c..000000000 --- a/modelscope_agent/log.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging - - -def setup_logger(level=logging.INFO): - logger = logging.getLogger('modelscope_agent_logger') - logger.setLevel(level) - handler = logging.StreamHandler() - handler.setLevel(level) - formatter = logging.Formatter( - '%(asctime)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s' - ) - handler.setFormatter(formatter) - logger.addHandler(handler) - return logger - - -logger = setup_logger() diff --git a/modelscope_agent/storage/file_storage.py b/modelscope_agent/storage/file_storage.py index 0e93eca51..c4f50211a 100644 --- a/modelscope_agent/storage/file_storage.py +++ b/modelscope_agent/storage/file_storage.py @@ -1,7 +1,7 @@ import hashlib import os -from modelscope_agent.log import logger +from modelscope_agent.utils.logger import agent_logger as logger from modelscope_agent.utils.utils import (print_traceback, read_text_from_file, save_text_to_file) diff --git a/modelscope_agent/tools/doc_parser.py b/modelscope_agent/tools/doc_parser.py index bc09d2c3e..2cb196735 100644 --- a/modelscope_agent/tools/doc_parser.py +++ b/modelscope_agent/tools/doc_parser.py @@ -7,12 +7,12 @@ import json import json5 -from modelscope_agent.log import logger from modelscope_agent.schemas import Document from modelscope_agent.storage import BaseStorage, DocumentStorage from modelscope_agent.tools.base import BaseTool, register_tool from modelscope_agent.tools.similarity_search import (RefMaterialInput, RefMaterialInputItem) +from modelscope_agent.utils.logger import agent_logger as logger from modelscope_agent.utils.parse_doc import (count_tokens, parse_doc, parse_html_bs) from modelscope_agent.utils.utils import print_traceback, save_text_to_file diff --git a/modelscope_agent/utils/logger.py b/modelscope_agent/utils/logger.py index e8d826c44..084dd6f45 100644 --- a/modelscope_agent/utils/logger.py +++ b/modelscope_agent/utils/logger.py @@ -41,8 +41,8 @@ def format(self, record): 'message': record.getMessage(), # Extract additional fields if they are in the 'extra' dict 'uuid': getattr(record, 'uuid', None), - 'request_id': getattr(record, 'request_id', None), - 'content': getattr(record, 'content', None), + # 'request_id': getattr(record, 'request_id', None), + 'details': getattr(record, 'details', None), 'error': getattr(record, 'error', None), 'step': getattr(record, 'step', None) } @@ -65,8 +65,8 @@ def format(self, record): # Collect additional fields if they are in the 'extra' dict uuid = getattr(record, 'uuid', '-') - request_id = getattr(record, 'request_id', '-') - content = getattr(record, 'content', '-') + # request_id = getattr(record, 'request_id', '-') + details = getattr(record, 'details', '-') step = getattr(record, 'step', '-') error = getattr(record, 'error', '-') @@ -75,10 +75,10 @@ def format(self, record): log_message = log_message + f' | message: {message}' if uuid != '-': log_message += f' | uuid: {uuid}' - if request_id != '-': - log_message += f' | request_id: {request_id}' - if content != '-': - log_message += f' | content: {content}' + # if request_id != '-': + # log_message += f' | request_id: {request_id}' + if details != '-': + log_message += f' | details: {details}' if step != '-': log_message += f' | step: {step}' if error != '-': @@ -91,6 +91,24 @@ def format(self, record): class AgentLogger: + r""" + The AgentLogger class has two modes of operation: one is for global logging, + which allows the use of functions such as info; the other is for query-level + logging, which requires the use of a UUID in conjunction with functions like + query_info. + + Examples: + ```python + >>> agent_logger = AgentLogger() + >>> agent_logger.info('simple log') + + >>> agent_logger.query_info( + >>> uuid=uuid_str, + >>> details={ + >>> 'info': 'complex log' + >>> } + >>> ) + """ def __init__(self): self.logger = logging.getLogger(LOG_NAME) @@ -150,64 +168,74 @@ def set_file_handle(self, self.logger.addHandler(info_file_handler) self.logger.addHandler(error_file_handler) - def info(self, - uuid: str = 'default_user', - request_id: str = 'default_request_id', - content: Dict = None, - step: str = '', - message: str = '', - error: str = ''): - if content is None: - content = {} + def info(self, message: str, *args): + self.logger.info(message, *args) + + def query_info( + self, + uuid: str = 'default_user', + # request_id: str = 'default_request_id', + details: Dict = None, + step: str = '', + message: str = ''): + if details is None: + details = {} self.logger.info( message, extra={ 'uuid': uuid, - 'request_id': request_id, - 'content': content, + # 'request_id': request_id, + 'details': details, 'step': step, - 'error': error + 'error': '' }) - def error(self, - uuid: str = 'default_user', - request_id: str = 'default_request_id', - content: Dict = None, - step: str = '', - message: str = '', - error: str = ''): - if content is None: - content = {} + def error(self, message: str = '', *args): + self.logger.error(message, *args) + + def query_error( + self, + uuid: str = 'default_user', + # request_id: str = 'default_request_id', + details: Dict = None, + step: str = '', + message: str = '', + error: str = ''): + if details is None: + details = {} self.logger.error( message, extra={ 'uuid': uuid, - 'request_id': request_id, - 'content': content, + # 'request_id': request_id, + 'details': details, 'step': step, 'error': error }) - def warning(self, - uuid: str = 'default_user', - request_id: str = 'default_request_id', - content: Dict = None, - step: str = '', - message: str = '', - error: str = ''): - if content is None: - content = {} + def warning(self, message: str = '', *args): + self.logger.warning(message, *args) + + def query_warning( + self, + uuid: str = 'default_user', + # request_id: str = 'default_request_id', + details: Dict = None, + step: str = '', + message: str = ''): + if details is None: + details = {} self.logger.warning( message, extra={ 'uuid': uuid, - 'request_id': request_id, - 'content': content, + # 'request_id': request_id, + 'details': details, 'step': step, - 'error': error + 'error': '' }) diff --git a/modelscope_agent/utils/utils.py b/modelscope_agent/utils/utils.py index 3d55089d1..5d2e126a5 100644 --- a/modelscope_agent/utils/utils.py +++ b/modelscope_agent/utils/utils.py @@ -12,7 +12,7 @@ from dashscope.common.error import InvalidInput, UploadFileException from dashscope.utils.oss_utils import OssUtils from jieba import analyse -from modelscope_agent.log import logger +from modelscope_agent.utils.logger import agent_logger as logger def get_local_ip(): diff --git a/tests/tools/test_modelscope_tool.py b/tests/tools/test_modelscope_tool.py index 7af1aedeb..d01a7071e 100644 --- a/tests/tools/test_modelscope_tool.py +++ b/tests/tools/test_modelscope_tool.py @@ -51,22 +51,6 @@ def test_modelscope_text_ie(): assert isinstance(res, str) -def test_modelscope_en2zh(): - from modelscope_agent.tools.modelscope_tools import TranslationEn2ZhTool - kwargs = """{'input': 'Autonomous agents have long been a prominent research focus in both academic and industry communities.'}""" # noqa E501 - zh_txt = TranslationEn2ZhTool() - res = zh_txt.call(kwargs) - assert isinstance(res, str) - - -def test_modelscope_zh2en(): - from modelscope_agent.tools.modelscope_tools import TranslationZh2EnTool - kwargs = """{'input': '北京今天天气怎样?'}""" - en_txt = TranslationZh2EnTool() - res = en_txt.call(kwargs) - assert isinstance(res, str) - - def test_modelscope_image_chat(): from modelscope_agent.tools.modelscope_tools import ImageChatTool kwargs = """{'image': 'http://mm-chatgpt.oss-cn-zhangjiakou.aliyuncs.com/mplug_owl_demo/released_checkpoint/portrait_input.png', 'text': 'Describe the facial expression of the man.'}""" # noqa E501