From 32397b0b4dd21eab9199b04bae2a39855add0797 Mon Sep 17 00:00:00 2001 From: xukunliu2000 <57486241+liuxukun2000@users.noreply.github.com> Date: Thu, 15 Jun 2023 21:15:57 +0800 Subject: [PATCH] Add config and react agent (#6) * Added configuration, refactored Agent and Tools * Added configuration, refactored Agent and Tools * Clear code * Add agent config * Fix bugs and add react agent * Clear code * Remove redundant --------- Co-authored-by: Satan --- config.yaml | 103 +++++++++++++++----- gentopia/agent/__init__.py | 3 - gentopia/agent/base_agent.py | 8 +- gentopia/agent/plugin_manager.py | 27 ++++++ gentopia/agent/react/__init__.py | 1 + gentopia/agent/react/agent.py | 129 +++++++++++++++++++++++++- gentopia/agent/rewoo/__init__.py | 1 + gentopia/agent/rewoo/agent.py | 5 +- gentopia/agent/rewoo/nodes/Planner.py | 4 +- gentopia/agent/rewoo/nodes/Solver.py | 4 +- gentopia/agent/tools_manager.py | 36 ------- gentopia/agent/vanilla/__init__.py | 1 + gentopia/config/agent_config.py | 95 +++++++++++++++---- gentopia/config/task.py | 11 +++ gentopia/llm/client/openai.py | 13 ++- gentopia/model/agent_model.py | 20 ++++ gentopia/prompt/react.py | 22 +++++ gentopia/util/convert_to_openai.py | 55 +++++++++++ test.ipynb | 0 test.py | 26 +++--- 20 files changed, 456 insertions(+), 108 deletions(-) create mode 100755 gentopia/agent/plugin_manager.py delete mode 100755 gentopia/agent/tools_manager.py create mode 100755 gentopia/config/task.py create mode 100755 gentopia/prompt/react.py create mode 100755 gentopia/util/convert_to_openai.py mode change 100644 => 100755 test.ipynb diff --git a/config.yaml b/config.yaml index 0d28c8a..cf73764 100755 --- a/config.yaml +++ b/config.yaml @@ -1,25 +1,86 @@ -name: example +name: main version: 0.0.1 description: example +type: rewoo +prompt_template: + - Planner: + input_variables: + - foo + template: "Say {foo}" + - Solver: + input_variables: + - foo + template: "Say {foo}" +llm: + - Planner: + name: llm + description: 111 + model_param: + model_name: 123 + model_name: 111123 + - Solver: + name: llm + description: 122223 + model_param: + model_name: 123 + model_name: 123 +target_tasks: + - print + - find + +plugins: + - name: main + version: 0.0.1 + description: example + type: rewoo + prompt_template: + - Planner: + input_variables: + - foo + template: "Say {foo}" + - Solver: + input_variables: + - foo + template: "Say {foo}" + llm: + - Planner: + name: llm + description: 111 + model_param: + model_name: 123 + model_name: 111123 + - Solver: + name: llm + description: 122223 + model_param: + model_name: 123 + model_name: 123 + +## - !include: ./plugins/React/React-Router.js +## - !include: ./plugins/React/React-Redux.js +# - name: React-Router +# type: rewoo +# version: 0.0.1 +# description: example +# prompt_template: +# input_variables: +# - foo +# template: "Say {foo}" +# llm: +## - Planner: +# name: llm +# description: 111 +# model_param: +# model_name: 123 +# model_name: 111123 +## - Solver: +## name: llm +## description: 122223 +## model_param: +## model_name: 123 +## model_name: 123 +## plugins: +## - !include: ./plugins/React/React-Router.js + -agents: - - solver: !include solver.yaml - - planner: - name: GPT4 - version: 0.0.1 - description: example - config: - temperature: 0.1 - api_key: example - token_limit: 1000 - prompt: example - - worker: - - name: Google - description: Worker that searches results from Google. - config: - max_length: 10 - - name: WolfAlpha - description: Worker that searches results from WolfAlpha. - config: - api_key: example diff --git a/gentopia/agent/__init__.py b/gentopia/agent/__init__.py index 03a4a37..8b13789 100644 --- a/gentopia/agent/__init__.py +++ b/gentopia/agent/__init__.py @@ -1,4 +1 @@ -from gentopia.agent.tools.google_search import GoogleSearch -from gentopia.agent.tools.wikipedia import Wikipedia -WORKER_REGISTRY = {"Google": GoogleSearch, "Wikipedia": Wikipedia} diff --git a/gentopia/agent/base_agent.py b/gentopia/agent/base_agent.py index 389a76c..f49713c 100644 --- a/gentopia/agent/base_agent.py +++ b/gentopia/agent/base_agent.py @@ -1,8 +1,8 @@ from abc import ABC, abstractmethod -from typing import List, Dict, Union, Any +from typing import List, Dict, Union, Any, Optional, Type from langchain import PromptTemplate -from pydantic import BaseModel +from pydantic import BaseModel, create_model from gentopia.llm.base_llm import BaseLLM from gentopia.model.agent_model import AgentType, AgentOutput @@ -17,8 +17,8 @@ class BaseAgent(ABC, BaseModel): llm: Union[BaseLLM, Dict[str, BaseLLM]] prompt_template: Union[PromptTemplate, Dict[str, PromptTemplate]] plugins: List[Any] - + args_schema: Optional[Type[BaseModel]] = create_model("ArgsSchema", input=(str, ...)) @abstractmethod - def run(self, input) -> AgentOutput: + def run(self, *args, **kwargs) -> AgentOutput: pass diff --git a/gentopia/agent/plugin_manager.py b/gentopia/agent/plugin_manager.py new file mode 100755 index 0000000..8fcd65a --- /dev/null +++ b/gentopia/agent/plugin_manager.py @@ -0,0 +1,27 @@ +from pathlib import Path + +from gentopia.config.agent_config import AgentConfig + + +class PluginManager: + def __init__(self, config): + if isinstance(config, str) or isinstance(config, Path): + config = AgentConfig(file=config) + elif isinstance(config, list): + config = AgentConfig(config=config) + config.get_agent() + self.config = config + self.plugins = self.config.plugins + + def run(self, name, *args, **kwargs): + if name not in self.plugins: + return "No evidence found" + plugin = self.plugins[name] + return plugin.run(*args, **kwargs) + + def __call__(self, plugin, *args, **kwargs): + self.run(plugin, *args, **kwargs) + + # @property + # def cost(self): + # return {name: self.plugins[name].cost for name in self.tools} diff --git a/gentopia/agent/react/__init__.py b/gentopia/agent/react/__init__.py index e69de29..db04d4a 100644 --- a/gentopia/agent/react/__init__.py +++ b/gentopia/agent/react/__init__.py @@ -0,0 +1 @@ +from .agent import ReactAgent diff --git a/gentopia/agent/react/agent.py b/gentopia/agent/react/agent.py index f962643..0e64dcd 100644 --- a/gentopia/agent/react/agent.py +++ b/gentopia/agent/react/agent.py @@ -1,7 +1,132 @@ +import logging +import re +from typing import List, Union, Optional, Type, Tuple + +from langchain import PromptTemplate +from langchain.schema import AgentFinish +from langchain.tools import BaseTool +from pydantic import create_model, BaseModel + from gentopia.agent.base_agent import BaseAgent +from gentopia.config.task import AgentAction +from gentopia.llm.client.openai import OpenAIGPTClient +from gentopia.model.agent_model import AgentType, AgentOutput +from gentopia.util.cost_helpers import calculate_cost + +FINAL_ANSWER_ACTION = "Final Answer:" -# TODO: Implement this class class ReactAgent(BaseAgent): + name: str = "ReactAgent" + type: AgentType = AgentType.REACT + version: str + description: str + target_tasks: list[str] + llm: OpenAIGPTClient + prompt_template: PromptTemplate + plugins: List[Union[BaseTool, BaseAgent]] + examples: Union[str, List[str]] = None + args_schema: Optional[Type[BaseModel]] = create_model("ReactArgsSchema", instruction=(str, ...)) + + intermediate_steps: List[Tuple[AgentAction, str]] = [] + + def _compose_plugin_description(self) -> str: + """ + Compose the worker prompt from the workers. + + Example: + toolname1[input]: tool1 description + toolname2[input]: tool2 description + """ + prompt = "" + try: + for plugin in self.plugins: + prompt += f"{plugin.name}[input]: {plugin.description}\n" + except Exception: + raise ValueError("Worker must have a name and description.") + return prompt + + def _construct_scratchpad( + self, intermediate_steps: List[Tuple[AgentAction, str]] + ) -> str: + """Construct the scratchpad that lets the agent continue its thought process.""" + thoughts = "" + for action, observation in intermediate_steps: + thoughts += action.log + thoughts += f"\nObservation: {observation}\nThought:" + return thoughts + + def _parse_output(self, text: str) -> Union[AgentAction, AgentFinish]: + includes_answer = FINAL_ANSWER_ACTION in text + regex = ( + r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)" + ) + action_match = re.search(regex, text, re.DOTALL) + if action_match: + if includes_answer: + raise Exception( + "Parsing LLM output produced both a final answer " + f"and a parse-able action: {text}" + ) + action = action_match.group(1).strip() + action_input = action_match.group(2) + tool_input = action_input.strip(" ") + # ensure if its a well formed SQL query we don't remove any trailing " chars + if tool_input.startswith("SELECT ") is False: + tool_input = tool_input.strip('"') + + return AgentAction(action, tool_input, text) + + elif includes_answer: + return AgentFinish( + {"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text + ) + + if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL): + raise Exception( + f"Could not parse LLM output: `{text}`", + ) + elif not re.search( + r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)", text, re.DOTALL + ): + raise Exception( + f"Could not parse LLM output: `{text}`" + ) + else: + raise Exception(f"Could not parse LLM output: `{text}`") + + def _compose_prompt(self, instruction) -> str: + """ + Compose the prompt from template, worker description, examples and instruction. + """ + agent_scratchpad = self._construct_scratchpad(self.intermediate_steps) + tool_description = self._compose_plugin_description() + tool_names = ", ".join([plugin.name for plugin in self.plugins]) + if self.prompt_template is None: + from gentopia.prompt.react import ZeroShotReactPrompt + self.prompt_template = ZeroShotReactPrompt + return self.prompt_template.format( + instruction=instruction, + agent_scratchpad=agent_scratchpad, + tool_description=tool_description, + tool_names=tool_names + ) + def run(self, instruction): - pass + logging.info(f"Running {self.name + ':' + self.version} with instruction: {instruction}") + total_cost = 0.0 + total_token = 0 + + prompt = self._compose_prompt(instruction) + logging.info(f"Prompt: {prompt}") + response = self.llm.completion(prompt) + if response.state == "error": + logging.error("Planner failed to retrieve response from LLM") + raise ValueError("Planner failed to retrieve response from LLM") + + logging.info(f"Planner run successful.") + total_cost += calculate_cost(self.llm.model_name, response.prompt_token, + response.completion_token) + total_token += response.prompt_token + response.completion_token + self.intermediate_steps.append(self._parse_output(response.content)) + return AgentOutput(output=response.content, cost=total_cost, token_usage=total_token) diff --git a/gentopia/agent/rewoo/__init__.py b/gentopia/agent/rewoo/__init__.py index e69de29..4182b07 100644 --- a/gentopia/agent/rewoo/__init__.py +++ b/gentopia/agent/rewoo/__init__.py @@ -0,0 +1 @@ +from .agent import RewooAgent diff --git a/gentopia/agent/rewoo/agent.py b/gentopia/agent/rewoo/agent.py index e4c640d..97d240a 100644 --- a/gentopia/agent/rewoo/agent.py +++ b/gentopia/agent/rewoo/agent.py @@ -24,7 +24,7 @@ class RewooAgent(BaseAgent): prompt_template: Dict[str, PromptTemplate] # {"Planner": xxx, "Solver": xxx} plugins: List[Union[BaseTool, BaseAgent]] examples: Dict[str, Union[str, List[str]]] = None - logger = logging.getLogger('application') + # logger = logging.getLogger('application') def _get_llms(self): if isinstance(self.llm, BaseLLM): @@ -72,9 +72,8 @@ def _parse_planner_evidences(self, planner_response: str) -> (dict[str, str], Li Example: {"*E1": "Tool1", "*E2": "Tool2", "*E3": "Tool3", "*E4": "Tool4"}, [[*E1, *E2], [*E3, *E4]] """ - evidences = dict() + evidences, dependence = dict(), dict() num = 0 - dependence = dict() for line in planner_response.splitlines(): if line.startswith("*E") and line[2].isdigit(): e, tool_call = line.split(":", 1) diff --git a/gentopia/agent/rewoo/nodes/Planner.py b/gentopia/agent/rewoo/nodes/Planner.py index 00d49b9..8e455f3 100644 --- a/gentopia/agent/rewoo/nodes/Planner.py +++ b/gentopia/agent/rewoo/nodes/Planner.py @@ -1,4 +1,3 @@ -import logging from typing import List, Union from langchain.tools import BaseTool @@ -6,7 +5,6 @@ from gentopia.agent.base_agent import BaseAgent from gentopia.llm.base_llm import BaseLLM -from gentopia.llm.llm_info import * from gentopia.model.completion_model import BaseCompletion from gentopia.prompt.rewoo import * @@ -16,7 +14,7 @@ class Planner(BaseModel): prompt_template: PromptTemplate = None examples: Union[str, List[str]] = None workers: List[Union[BaseTool, BaseAgent]] - logger = logging.getLogger('application') + # logger = logging.getLogger('application') def _compose_worker_description(self) -> str: """ diff --git a/gentopia/agent/rewoo/nodes/Solver.py b/gentopia/agent/rewoo/nodes/Solver.py index 32b2fe7..95f6032 100644 --- a/gentopia/agent/rewoo/nodes/Solver.py +++ b/gentopia/agent/rewoo/nodes/Solver.py @@ -1,10 +1,8 @@ -import logging from typing import List, Union from pydantic import BaseModel from gentopia.llm.base_llm import BaseLLM -from gentopia.llm.llm_info import * from gentopia.model.completion_model import BaseCompletion from gentopia.prompt.rewoo import * @@ -13,7 +11,7 @@ class Solver(BaseModel): model: BaseLLM prompt_template: PromptTemplate = None examples: Union[str, List[str]] = None - logger = logging.getLogger('application') + # logger = logging.getLogger('application') def _compose_fewshot_prompt(self) -> str: if self.examples is None: diff --git a/gentopia/agent/tools_manager.py b/gentopia/agent/tools_manager.py deleted file mode 100755 index b2f9cb6..0000000 --- a/gentopia/agent/tools_manager.py +++ /dev/null @@ -1,36 +0,0 @@ -from pathlib import Path - -from gentopia.config.tools_config import ToolsConfig - - -class ToolsManager: - def __init__(self, config): - if isinstance(config, str) or isinstance(config, Path): - config = ToolsConfig(file=config) - elif isinstance(config, list): - config = ToolsConfig(config=config) - self.config = config - self.tools = {} - self._load_tools() - - def _load_tools(self): - if self.config is None or self.config.config is None: - return - self.tools = self.config.get_tools() - - def generate_worker_prompt(self): - prompt = "Tools can be one of the following:\n" - for name in self.tools: - worker = self.tools[name] - prompt += f"{worker.name}[input]: {worker.description}\n" - return prompt + "\n" - - def run(self, name, args): - if name not in self.tools: - return "No evidence found" - tool = self.tools[name] - return tool.run(args) - - @property - def cost(self): - return {name: self.tools[name].cost for name in self.tools} diff --git a/gentopia/agent/vanilla/__init__.py b/gentopia/agent/vanilla/__init__.py index e69de29..1b5e114 100644 --- a/gentopia/agent/vanilla/__init__.py +++ b/gentopia/agent/vanilla/__init__.py @@ -0,0 +1 @@ +from .agent import VanillaAgent diff --git a/gentopia/config/agent_config.py b/gentopia/config/agent_config.py index 8801416..68656c9 100755 --- a/gentopia/config/agent_config.py +++ b/gentopia/config/agent_config.py @@ -1,8 +1,12 @@ -from gentopia.agent.agent import Agent -from gentopia.agent.nodes.Planner import Planner -from gentopia.agent.nodes.Solver import Solver -from gentopia.agent.tools_manager import ToolsManager +from typing import List, Union, Dict + +from langchain import PromptTemplate + +from gentopia.agent.base_agent import BaseAgent from gentopia.config.config import Config +from gentopia.llm.base_llm import BaseLLM +from gentopia.llm.tmp_llm import TmpLLM +from gentopia.model.agent_model import AgentType class AgentConfig: @@ -12,16 +16,73 @@ def __init__(self, file=None, config=None): elif config is not None: self.config = Config.from_dict(config) - def get_agent(self): - assert self.config is not None - name = self.config['name'] - tools = ToolsManager(self.config['tools']) - planner_config = self.config['planner'] - solver_config = self.config['solver'] - planner = Planner(tools, planner_config['prefix'], planner_config['suffix'], self.config['fewshot'], - planner_config['model_name'], planner_config['stop'] - ) - solver = Solver(solver_config['prefix'], solver_config['suffix'], - solver_config['model_name'], solver_config['stop'] - ) - return Agent(name, tools, planner, solver) + self.plugins: Dict[Union[BaseAgent, List]] = [] + + def get_agent(self, config=None): + if config is None: + config = self.config + assert config is not None + name = config['name'] + _type = AgentType(config['type']) + version = config['version'] + description = config['description'] + AgentClass = AgentType.get_agent_class(_type) + prompt_template = self.get_prompt_template(config['prompt_template']) + agent = AgentClass( + name=name, + type=_type, + version=version, + description=description, + target_tasks=config.get('target_tasks', []), + llm=self.get_llm(config['llm']), + prompt_template=prompt_template, + plugins=self.parse_plugins(config.get('plugins', [])) + ) + return agent + + def get_llm(self, obj) -> Union[BaseLLM, Dict[str, BaseLLM]]: + assert isinstance(obj, dict) or isinstance(obj, list) + if isinstance(obj, list): + return { + list(item.keys())[0]: self.parse_llm(list(item.values())[0]) for item in obj + } + else: + return self.parse_llm(obj) + + def parse_llm(self, obj) -> BaseLLM: + name = obj['name'] + description = obj['description'] + model_param = obj['model_param'] + return TmpLLM(model_name=name, model_description=description, model_param=model_param) + + def get_prompt_template(self, obj): + assert isinstance(obj, dict) or isinstance(obj, list) + if isinstance(obj, list): + return { + list(item.keys())[0]: self.parse_prompt_template(list(item.values())[0]) for item in obj + } + else: + ans = self.parse_prompt_template(obj) + return ans + + def parse_prompt_template(self, obj): + assert isinstance(obj, dict) + input_variables = obj['input_variables'] + template = obj['template'] + template_format = obj.get('template_format', 'f-string') + validate_template = bool(obj.get('validate_template', True)) + return PromptTemplate(input_variables=input_variables, template=template, template_format=template_format, + validate_template=validate_template) + + def parse_plugins(self, obj): + assert isinstance(obj, list) + result = [] + for i in obj: + if i['type'] != 'tool': + agent = self.get_agent(i) + result.append(agent) + self.plugins[i['name']] = agent + else: + pass + # TODO: load tools + return result diff --git a/gentopia/config/task.py b/gentopia/config/task.py new file mode 100755 index 0000000..3ad4d10 --- /dev/null +++ b/gentopia/config/task.py @@ -0,0 +1,11 @@ +from dataclasses import dataclass +from typing import Union + + +@dataclass +class AgentAction: + """Agent's action to take.""" + + tool: str + tool_input: Union[str, dict] + log: str diff --git a/gentopia/llm/client/openai.py b/gentopia/llm/client/openai.py index 3176936..f353dbb 100644 --- a/gentopia/llm/client/openai.py +++ b/gentopia/llm/client/openai.py @@ -1,10 +1,12 @@ +import os +from typing import List + +import openai + from gentopia.llm.base_llm import BaseLLM +from gentopia.llm.llm_info import * from gentopia.model.completion_model import * from gentopia.model.param_model import * -from gentopia.llm.llm_info import * -from typing import List -import openai -import os class OpenAIGPTClient(BaseLLM): @@ -22,7 +24,7 @@ def get_model_name(self): def get_model_param(self): return self.params - def completion(self, prompt: str): + def completion(self, prompt: str, **kwargs): try: response = openai.ChatCompletion.create( n=self.params.n, @@ -33,6 +35,7 @@ def completion(self, prompt: str): top_p=self.params.top_p, frequency_penalty=self.params.frequency_penalty, presence_penalty=self.params.presence_penalty, + **kwargs ) return BaseCompletion(state="success", content=response.choices[0].message["content"], diff --git a/gentopia/model/agent_model.py b/gentopia/model/agent_model.py index 64b3d23..28cc98f 100644 --- a/gentopia/model/agent_model.py +++ b/gentopia/model/agent_model.py @@ -1,4 +1,5 @@ from enum import Enum + from pydantic import BaseModel @@ -10,6 +11,25 @@ class AgentType(Enum): REWOO = "rewoo" DIRECT = "direct" + @staticmethod + def get_agent_class(_type: 'AgentType'): + """ + Get agent class from agent type. + :param _type: agent type + :return: agent class + """ + if _type == AgentType.REACT: + from gentopia.agent.react import ReactAgent + return ReactAgent + elif _type == AgentType.REWOO: + from gentopia.agent.rewoo import RewooAgent + return RewooAgent + elif _type == AgentType.DIRECT: + from gentopia.agent.vanilla import VanillaAgent + return VanillaAgent + else: + raise ValueError(f"Unknown agent type: {_type}") + class AgentOutput(BaseModel): """ diff --git a/gentopia/prompt/react.py b/gentopia/prompt/react.py new file mode 100755 index 0000000..a6ce7d3 --- /dev/null +++ b/gentopia/prompt/react.py @@ -0,0 +1,22 @@ +from langchain import PromptTemplate + +ZeroShotReactPrompt = PromptTemplate( + input_variables=["instruction", "agent_scratchpad", "tool_names", "tool_description"], + template="""Answer the following questions as best you can. You have access to the following tools: +{tool_description}. +Use the following format: + +Question: the input question you must answer +Thought: you should always think about what to do +Action: the action to take, should be one of [{tool_names}] +Action Input: the input to the action +Observation: the result of the action +... (this Thought/Action/Action Input/Observation can repeat N times) +Thought: I now know the final answer +Final Answer: the final answer to the original input question +Begin! + +Question: {input} +Thought:{agent_scratchpad} + """ +) diff --git a/gentopia/util/convert_to_openai.py b/gentopia/util/convert_to_openai.py new file mode 100755 index 0000000..5483426 --- /dev/null +++ b/gentopia/util/convert_to_openai.py @@ -0,0 +1,55 @@ +from typing import TypedDict, Union + +from langchain.tools import BaseTool, StructuredTool + +from gentopia.agent.base_agent import BaseAgent + + +class FunctionDescription(TypedDict): + """Representation of a callable function to the OpenAI API.""" + + name: str + """The name of the function.""" + description: str + """A description of the function.""" + parameters: dict + """The parameters of the function.""" + + +def format_tool_to_openai_function(tool: Union[BaseTool, BaseAgent]) -> FunctionDescription: + """Format tool into the open AI function API.""" + if isinstance(tool, StructuredTool): + schema_ = tool.args_schema.schema() + # Bug with required missing for structured tools. + required = sorted(schema_["properties"]) # BUG WORKAROUND + return { + "name": tool.name, + "description": tool.description, + "parameters": { + "type": "object", + "properties": schema_["properties"], + "required": required, + }, + } + else: + if tool.args_schema: + parameters = tool.args_schema.schema() + else: + parameters = { + # This is a hack to get around the fact that some tools + # do not expose an args_schema, and expect an argument + # which is a string. + # And Open AI does not support an array type for the + # parameters. + "properties": { + "__arg1": {"title": "__arg1", "type": "string"}, + }, + "required": ["__arg1"], + "type": "object", + } + + return { + "name": tool.name, + "description": tool.description, + "parameters": parameters, + } diff --git a/test.ipynb b/test.ipynb old mode 100644 new mode 100755 diff --git a/test.py b/test.py index b700be5..7774517 100755 --- a/test.py +++ b/test.py @@ -1,13 +1,17 @@ -from gentopia.config.config import Config +import logging -x = Config.load("gentopia/agent/agent.yaml") -print(x) +# +# x = Config.load("gentopia/agent/agent.yaml") +# print(x) +# +# from gentopia.config.agent_config import AgentConfig +# +# x = AgentConfig("gentopia/agent/agent.yaml") +# a = x.get_agent() +# print(a) +# print(a.tools.tools['Wikipedia'].description) +# print(a.tools.generate_worker_prompt()) +# print(x) -from gentopia.config.agent_config import AgentConfig - -x = AgentConfig("gentopia/agent/agent.yaml") -a = x.get_agent() -print(a) -print(a.tools.tools['Wikipedia'].description) -print(a.tools.generate_worker_prompt()) -print(x) +if __name__ == '__main__': + logging.warning("123")