from copy import deepcopy from typing import List, Tuple from mmengine.registry import Registry REGISTRY = Registry('helper') class LagentAgent: """Agent wrapper for Lagent. https://github.com/InternLM/lagent. """ is_api = True def __init__(self, agent_type, llm, actions=None, protocol=None, **kwargs): llm = REGISTRY.build(llm) agent_cfg = {'type': agent_type, 'llm': llm, **kwargs} if actions is not None: from lagent.actions import ActionExecutor executor = ActionExecutor([]) for action in actions: action = REGISTRY.build(action) if 'agentlego' in type(action).__module__: action = action.to_lagent() executor.add_action(action) agent_cfg['action_executor'] = executor if protocol is not None: protocol = REGISTRY.build(protocol) agent_cfg['protocol'] = protocol from lagent import BaseAgent self.agent: BaseAgent = REGISTRY.build(agent_cfg) def reset(self): self.agent._session_history = [] for action in self.agent._action_executor.actions: if hasattr(action, 'reset'): action.reset() def set_history(self, history): self.agent._session_history = deepcopy(history) def gt_response(self, prompt): if 'CIReAct' in str(self.agent.__class__): gold = prompt prompt = f"""{self.agent._protocol.action['begin']} IPythonInterpreter {self.agent._protocol.action_input['begin']} ```python\n{gold}\n```\n""" # noqa action_input = dict( command=f"""```python\n{gold}\n```\n""", timeout=120, ) response = self.agent._action_executor('IPythonInterpreter', action_input) gt_response = dict(role='assistant', content=prompt) system_response = dict( role='system', content=self.agent._protocol.format_response(response)) return [gt_response, system_response] else: gt_response = dict(role='assistant', content=prompt) return [gt_response] @property def template_parser(self): return self.agent._llm.template_parser @template_parser.setter def template_parser(self, value): self.agent._llm.template_parser = value def chat(self, user_input: str, history: List[dict] = None) -> Tuple[str, List[dict], List[dict]]: """Chat with agent.""" if history: self.agent._session_history = history from lagent.schema import ActionReturn, AgentReturn generation: AgentReturn = self.agent.chat(user_input) inner_steps = generation.inner_steps answer = generation.response steps = [] for step in generation.actions: step: ActionReturn steps.append( dict( type=step.type, args=step.args, result=step.result, thought=step.thought, state=int(step.state), errmsg=step.errmsg, valid=int(step.valid), )) return answer, steps, inner_steps FORCE_STOP_PROMPT_EN = ( """You should directly give results based on history information.""" # noqa ) FEWSHOT_INSTRUCTION = """\ You are a assistant who can utilize external tools. {tool_description} To use a tool, please response with the following format: ``` {thought} Think what you need to solve, do you need to use tools? {action} The tool name, should be one of [{action_names}]. {action_input} The input to the tool that you want to use. ``` The tool will give you response after your response using the following format: ``` {response} the results after call the tool. ``` Therefore DO NOT generate tool response by yourself. Also please follow the guidelines: 1. Always use code interpreter to solve the problem. 2. The generated codes should always in a markdown code block format. 3. The generated codes will be executed in an ipython manner and the results will be cached. 4. Your responded code should always be simple and only solves the problem in current step. Begin! """ # noqa PYTHON_INTERPRETER_DESCRIPTION = """\ It can run a Python code. The code must be a valid code that contains only python method, and the method' name must be 'solution' and returns a dict, which key is variable name. The libraries I recommend are sympy and scipy. the format is: ```python # import packages import xxx def solution(): # initialize some variables variable_names_with_real_meaning = xxx # middle steps mid_variable = func(mid_variable) # final answer final_answer = func(mid_variable) return final_answer ```""" # noqa class CodeAgent(LagentAgent): """Code Agent wrapper for Lagent.""" def __init__(self, llm, **kwargs): from lagent import PythonInterpreter, ReAct from lagent.agents.react import ReActProtocol agent_type = kwargs.pop('agent_type', ReAct) max_turn = kwargs.pop('max_turn', 3) actions = kwargs.pop( 'actions', [ dict(type=PythonInterpreter, description=PYTHON_INTERPRETER_DESCRIPTION), ], ) protocol = kwargs.pop( 'protocol', dict( type=ReActProtocol, call_protocol=FEWSHOT_INSTRUCTION, force_stop=FORCE_STOP_PROMPT_EN, finish=dict(role='FINISH', begin='Final Answer:', end='\n'), ), ) super().__init__(agent_type=agent_type, llm=llm, actions=actions, protocol=protocol, max_turn=max_turn, **kwargs)