Add linux_admin agent, funny~

This commit is contained in:
Liu Zhicong
2023-09-21 23:18:52 -07:00
parent 270debef67
commit ad12e795c5
10 changed files with 208 additions and 18 deletions
+1 -2
View File
@@ -7,12 +7,11 @@ max_token_size = 16000
enable_timestamp = "true"
owner_prompt = "我是你的主人{name}"
contact_prompt = "我是你的朋友{name}"
guest_prompt = "xxx"
owner_env = "calender"
[[prompt]]
role = "system"
content = """
现在是{now}
你叫Jarvis,是我的超级私人助理。
你领导一个团队为我服务,团队的成员有:
Tracy,私人英语老师
+4 -3
View File
@@ -1,12 +1,13 @@
instance_id = "linux_admin"
fullname = "linux_admin"
owner_env = "bash"
[[prompt]]
role = "system"
content = """你的名字是linux_admin,是非常资深的linux系统管理员,我理解一些linux,但对linux的sh命令记得不太清楚了。
我给你的输入有两种
1. 标准的linux bash命令,如果你认为这些命令在当前系统上是正确的,那么直接返回这些命令,我会去执行
2. 如果你为这些命令需要调整后才能执行,先把你修正后的命令告诉我,我确认后再执行
1. 标准的linux bash命令,如果你认为这些命令在当前系统上是正确且可执行的,那么你可以直接执行
2. 如果我的命令不对,或则命令可能对系统有害,你要对这些命令进行调整后,先把你调整后的命令告诉我,我确认后再执行正确的命令
3. 如果我给你的信息不是linux bash操作,而是一些需求。你可以尝试理解后,给出一组实现这些需求的命令,我确认后再执行
4. 其它信息,请站在你专业角度尽力执行。
5. 每次执行命令后,要把结果告诉我。
"""
+1
View File
@@ -19,6 +19,7 @@ from .tg_tunnel import TelegramTunnel
from .email_tunnel import EmailTunnel
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
from .contact_manager import ContactManager,Contact,FamilyMember
from .workspace_env import WorkspaceEnvironment
AIOS_Version = "0.5.1, build 2023-9-17"
+2
View File
@@ -162,6 +162,8 @@ class AIAgent:
if config.get("contact_prompt") is not None:
self.contact_prompt_str = config["contact_prompt"]
if config.get("owner_env") is not None:
self.owner_env = Environment.get_env_by_id(config["owner_env"])
if config.get("powerby") is not None:
self.powerby = config["powerby"]
+1 -5
View File
@@ -4,11 +4,7 @@ import asyncio
import uuid
import time
from typing import Callable
from telegram import ForceReply, Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
from telegram import Update
from telegram import Bot
from telegram.ext import Updater
from telegram.error import Forbidden, NetworkError
-2
View File
@@ -1,2 +0,0 @@
# this env is designed for workflow owner filesystem, support file/directory operations
+173
View File
@@ -0,0 +1,173 @@
# this env is designed for workflow owner filesystem, support file/directory operations
import subprocess
import tempfile
import threading
import traceback
import time
import ast
import sys
import os
import re
from .environment import Environment,EnvironmentEvent
from .ai_function import AIFunction,SimpleAIFunction
class CodeInterpreter:
def __init__(self, language, debug_mode):
self.language = language
self.proc = None
self.active_line = None
self.debug_mode = debug_mode
def start_process(self):
start_cmd = sys.executable + " -i -q -u"
self.proc = subprocess.Popen(start_cmd.split(),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=0)
# Start watching ^ its `stdout` and `stderr` streams
threading.Thread(target=self.save_and_display_stream,
args=(self.proc.stdout, False), # Passes False to is_error_stream
daemon=True).start()
threading.Thread(target=self.save_and_display_stream,
args=(self.proc.stderr, True), # Passes True to is_error_stream
daemon=True).start()
def warp_code(self,pycode:str)->str:
# Add import traceback
code = "import traceback\n" + pycode
# Parse the input code into an AST
parsed_code = ast.parse(code)
# Wrap the entire code's AST in a single try-except block
try_except = ast.Try(
body=parsed_code.body,
handlers=[
ast.ExceptHandler(
type=ast.Name(id="Exception", ctx=ast.Load()),
name=None,
body=[
ast.Expr(
value=ast.Call(
func=ast.Attribute(value=ast.Name(id="traceback", ctx=ast.Load()), attr="print_exc", ctx=ast.Load()),
args=[],
keywords=[]
)
),
]
)
],
orelse=[],
finalbody=[]
)
parsed_code.body = [try_except]
return ast.unparse(parsed_code)
def run(self,py_code:str):
"""
Executes code.
"""
# Get code to execute
self.code = py_code
# Start the subprocess if it hasn't been started
if not self.proc:
try:
self.start_process()
except Exception as e:
# Sometimes start_process will fail!
# Like if they don't have `node` installed or something.
traceback_string = traceback.format_exc()
self.output = traceback_string
# Before you return, wait for the display to catch up?
# (I'm not sure why this works)
time.sleep(0.1)
return self.output
self.output = ""
self.print_cmd = 'print("{}")'
code = self.warp_code(py_code)
if self.debug_mode:
print("Running code:")
print(code)
print("---")
self.done = threading.Event()
self.done.clear()
# Write code to stdin of the process
try:
self.proc.stdin.write(code + "\n")
self.proc.stdin.flush()
except BrokenPipeError:
return
self.done.wait()
time.sleep(0.1)
return self.output
def save_and_display_stream(self, stream, is_error_stream):
for line in iter(stream.readline, ''):
if self.debug_mode:
print("Recieved output line:")
print(line)
print("---")
line = line.strip()
if is_error_stream and "KeyboardInterrupt" in line:
raise KeyboardInterrupt
elif "END_OF_EXECUTION" in line:
self.done.set()
self.active_line = None
else:
self.output += "\n" + line
self.output = self.output.strip()
class WorkspaceEnvironment(Environment):
def __init__(self, env_id: str) -> None:
super().__init__(env_id)
operator_param = {
"command": "command will execute",
}
self.add_ai_function(SimpleAIFunction("shell_exec",
"execute shell command in linux bash",
self.shell_exec,operator_param))
#run_code_param = {
# "pycode": "python code will execute",
#}
#self.add_ai_function(SimpleAIFunction("run_code",
# "execute python code",
# self.run_code,run_code_param))
async def shell_exec(self,command:str) -> str:
import asyncio.subprocess
process = await asyncio.create_subprocess_shell(
command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
returncode = process.returncode
if returncode == 0:
return f"Execute success! stdout is:\n{stdout}\n"
else:
return f"Execute failed! stderr is:\n{stderr}\n"
async def run_code(self,pycode:str) -> str:
interpreter = CodeInterpreter("python",True)
return interpreter.run(pycode)
+3 -1
View File
@@ -64,7 +64,6 @@ class AIOS_Shell:
target_id = msg.target.split(".")[0]
agent : AIAgent = await AgentManager.get_instance().get(target_id)
if agent is not None:
agent.owner_env = Environment.get_env_by_id("calender")
bus.register_message_handler(target_id,agent._process_msg)
return True
@@ -87,6 +86,9 @@ class AIOS_Shell:
await cal_env.start()
Environment.set_env_by_id("calender",cal_env)
workspace_env = WorkspaceEnvironment("bash")
Environment.set_env_by_id("bash",workspace_env)
await AgentManager.get_instance().initial()
await WorkflowManager.get_instance().initial()
+1 -1
View File
@@ -1,6 +1,6 @@
import unittest
import os
import toml
import os
import sys
directory = os.path.dirname(__file__)
+22 -4
View File
@@ -1,9 +1,22 @@
import os
import sys
import asyncio
directory = os.path.dirname(__file__)
sys.path.append(directory + '/../src')
from aios_kernel import WorkspaceEnvironment
def test_workflow():
async def test_workflow():
env = WorkspaceEnvironment("test")
test_code ="""
import toml
print("hello world")
print(100+23)
toml.dump({"abc":"123"},open("test.toml","w"))
"""
await env.run_code(test_code)
pass
async def _test_llm_parser():
@@ -39,4 +52,9 @@ sfsadfasdf
llm_result = Workflow.prase_llm_result(test_llm_result)
assert len(llm_result.calls) == 1
assert len(llm_result.send_msgs) == 1
print(llm_result)
print(llm_result)
if __name__ == "__main__":
asyncio.run(test_workflow())
print("OK!")