新功能(actions/action_base.py):添加ActionBase类来管理动作的描述和动作列表

🔧 更新(actions/action_util.py):更新ActionUtil类的_actions属性为WordAction类列表
🔧 更新(agent/woker_agent.py):更新ActionUtil的使用,添加动作描述到消息中传递给LLM_Util
♻️ 重构(utils/llm_util.py):重构invoke方法以支持不同base_url情况
This commit is contained in:
ruotongyu
2024-05-29 20:31:23 +08:00
parent 1df2189841
commit 10cb0cb2ca
5 changed files with 93 additions and 81 deletions

67
actions/action_base.py Normal file
View File

@@ -0,0 +1,67 @@
import inspect
import re
def action(description):
def class_decorator(func):
func.description = description
return func
return class_decorator
class ActionBase:
description=""
actions = []
def get_action_description(self, action_name):
action = getattr(self, action_name, None)
descriontion = action.__getattribute__("description")
return descriontion
def camel_to_snake(self, name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
def get_actions(self):
for func_str in dir(self):
func = self.__getattribute__(func_str)
if callable(func) and getattr(func, "description", False):
self.actions.append(func)
return self.actions
def package_actions_description(self):
res = []
for action in self.get_actions():
signature = inspect.signature(action)
parameters = signature.parameters
params = []
for name, param in parameters.items():
if name != "self":
params.append(f"{name}:{param._annotation.__name__}")
res.append(f"{self.camel_to_snake(__class__.__name__)}.{action.__name__}({','.join(params)}) #{action.description}")
return "\n".join(res)

View File

@@ -1,71 +1,10 @@
import inspect
import re
def action(description):
def class_decorator(func):
func.description = description
return func
return class_decorator
from actions.word_action import WordAction
class ActionBase:
description=""
actions = []
class ActionUtil:
_actions = [WordAction]
def get_action_description(self, action_name):
action = getattr(self, action_name, None)
descriontion = action.__getattribute__("description")
return descriontion
def camel_to_snake(self, name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
def get_actions(self):
for func_str in dir(self):
func = self.__getattribute__(func_str)
if callable(func) and getattr(func, "description", False):
self.actions.append(func)
return self.actions
def package_actions_description(self):
res = []
for action in self.get_actions():
signature = inspect.signature(action)
parameters = signature.parameters
params = []
for name, param in parameters.items():
if name != "self":
params.append(f"{name}:{param._annotation.__name__}")
res.append(f"{self.camel_to_snake(__class__.__name__)}.{action.__name__}({','.join(params)}) #{action.description}")
return "\n".join(res)
@classmethod
def get_actions(cls):
return cls._actions

View File

@@ -1,4 +1,5 @@
system_prompt="""
from string import Template
system_prompt=Template("""
You are Open Interpreter, a world-class programmer that can complete any goal by executing code.
First, write a plan. **Always recap the plan between each code block** (you have extreme short-term memory loss, so you need to recap the plan between each message block to retain it).
When you execute code, it will be executed **on the user's machine**. The user has given you **full and complete permission** to execute any code necessary to complete the task. Execute the code.
@@ -12,15 +13,15 @@ You are capable of **any** task.
# THE COMPUTER API
A python `word` module is ALREADY IMPORTED, and can be used for many tasks:
A python `word_action` module is ALREADY IMPORTED, and can be used for many tasks:
```python
$python_code
```
Do not import the computer module, or any of its sub-modules. They are already imported.
User Info{{import getpass
User Info\{\{import getpass
import os
import platform
@@ -28,7 +29,7 @@ print(f"Name: {getpass.getuser()}")
print(f"CWD: {os.getcwd()}")
print(f"SHELL: {os.environ.get('SHELL')}")
print(f"OS: {platform.system()}")
\}\}
}}
"""
"""
)

View File

@@ -1,7 +1,8 @@
from langchain import hub
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import PromptTemplate, ChatMessagePromptTemplate
from actions.action_util import ActionUtil
from system_prompt import system_prompt
from tools.tools_util import ToolsUtil
from utils.llm_util import LLM_Util
@@ -46,4 +47,9 @@ Thought: 我需要使用工具吗? 不需要\nFinal Answer: 您的桌面上有
return agent_executor.iter({"input": question})
def run(self, question):
action_descriptions = ""
for action in ActionUtil.get_actions():
action_descriptions += action.package_actions_description() + "\n"
messages = [{"content": system_prompt.substitute(python_code=action_descriptions), "role": "system"}]
messages.append({"content": question, "role": "user"})
LLM_Util().invoke(messages)

View File

@@ -15,12 +15,11 @@ class LLM_Util:
return ChatOpenAI(temperature=0, model_name=self.model, openai_api_key=self.api_key,
openai_api_base=self.base_url)
def invoke(self, message):
messages = [{ "content": message, "role": "user"}]
if self.base_url == "openai":
# messages = [{ "content": message, "role": "user"}]
def invoke(self, messages):
if self.base_url == "":
response = completion(model=self.model, api_key=self.api_key, messages=messages)
else:
response = completion(model=self.model, base_url=self.url, api_key=self.key, messages=messages)
response = completion(model=self.model, base_url=self.base_url, api_key=self.key, messages=messages)
return response.choices[0].message.content