2023-11-30 14:00:06 +08:00
from copy import deepcopy
2023-09-22 15:28:22 +08:00
from typing import List , Tuple
from mmengine . registry import Registry
REGISTRY = Registry ( ' helper ' )
class LagentAgent :
""" Agent wrapper for Lagent.
https : / / github . com / InternLM / lagent .
"""
2023-11-30 14:00:06 +08:00
is_api = True
2023-09-22 15:28:22 +08:00
2023-11-30 14:00:06 +08:00
def __init__ ( self , agent_type , llm , actions = None , protocol = None , * * kwargs ) :
2023-09-22 15:28:22 +08:00
llm = REGISTRY . build ( llm )
agent_cfg = { ' type ' : agent_type , ' llm ' : llm , * * kwargs }
if actions is not None :
from lagent . actions import ActionExecutor
2023-11-30 14:00:06 +08:00
executor = ActionExecutor ( [ ] )
for action in actions :
action = REGISTRY . build ( action )
if ' agentlego ' in type ( action ) . __module__ :
action = action . to_lagent ( )
executor . add_action ( action )
2023-09-22 15:28:22 +08:00
agent_cfg [ ' action_executor ' ] = executor
if protocol is not None :
protocol = REGISTRY . build ( protocol )
agent_cfg [ ' protocol ' ] = protocol
2023-11-30 14:00:06 +08:00
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 )
@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 ,
2023-12-11 17:42:53 +08:00
history : List [ dict ] = None ) - > Tuple [ str , List [ dict ] , List [ dict ] ] :
2023-11-30 14:00:06 +08:00
""" Chat with agent. """
if history :
self . agent . _session_history = history
2023-11-07 19:11:44 +08:00
2023-11-30 14:00:06 +08:00
from lagent . schema import ActionReturn , AgentReturn
2023-09-22 15:28:22 +08:00
generation : AgentReturn = self . agent . chat ( user_input )
2023-11-30 14:00:06 +08:00
2023-12-11 17:42:53 +08:00
inner_steps = generation . inner_steps
2023-09-22 15:28:22 +08:00
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 ) ,
) )
2023-10-25 23:05:15 +08:00
2023-12-11 17:42:53 +08:00
return answer , steps , inner_steps
2023-11-07 19:11:44 +08:00
FORCE_STOP_PROMPT_EN = (
""" You should directly give results based on history information. """ # noqa
)
2023-10-25 23:05:15 +08:00
FEWSHOT_INSTRUCTION = """ \
2023-11-30 14:00:06 +08:00
You are a assistant who can utilize external tools .
{ tool_description }
To use a tool , please response with the following format :
2023-10-25 23:05:15 +08:00
` ` `
2023-11-30 14:00:06 +08:00
{ 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 .
2023-10-25 23:05:15 +08:00
` ` `
2023-11-30 14:00:06 +08:00
The tool will give you response after your response using the following format :
2023-10-25 23:05:15 +08:00
` ` `
2023-11-30 14:00:06 +08:00
{ response } the results after call the tool .
2023-10-25 23:05:15 +08:00
` ` `
2023-11-30 14:00:06 +08:00
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 .
2023-10-25 23:05:15 +08:00
Begin !
2023-11-07 19:11:44 +08:00
""" # noqa
2023-10-25 23:05:15 +08:00
2023-11-07 19:11:44 +08:00
PYTHON_INTERPRETER_DESCRIPTION = """ \
2023-10-25 23:05:15 +08:00
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
2023-11-07 19:11:44 +08:00
final_answer = func ( mid_variable )
2023-10-25 23:05:15 +08:00
return final_answer
2023-11-07 19:11:44 +08:00
` ` ` """ # noqa
2023-10-25 23:05:15 +08:00
2023-11-30 14:00:06 +08:00
class CodeAgent ( LagentAgent ) :
2023-11-07 19:11:44 +08:00
""" Code Agent wrapper for Lagent. """
2023-10-25 23:05:15 +08:00
2023-11-30 14:00:06 +08:00
def __init__ ( self , llm , * * kwargs ) :
from lagent import PythonInterpreter , ReAct
2023-10-25 23:05:15 +08:00
from lagent . agents . react import ReActProtocol
2023-11-07 19:11:44 +08:00
2023-10-25 23:05:15 +08:00
agent_type = kwargs . pop ( ' agent_type ' , ReAct )
max_turn = kwargs . pop ( ' max_turn ' , 3 )
2023-11-07 19:11:44 +08:00
actions = kwargs . pop (
' actions ' ,
[
dict ( type = PythonInterpreter ,
description = PYTHON_INTERPRETER_DESCRIPTION ) ,
] ,
)
2023-10-25 23:05:15 +08:00
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 ' ) ,
2023-11-07 19:11:44 +08:00
) ,
)
2023-11-30 14:00:06 +08:00
super ( ) . __init__ ( agent_type = agent_type ,
llm = llm ,
actions = actions ,
protocol = protocol ,
max_turn = max_turn ,
* * kwargs )