Merge branch 'fiatrete:MVP' into MVP

This commit is contained in:
Song
2023-09-20 22:32:40 +08:00
committed by GitHub
10 changed files with 234 additions and 14 deletions
+2
View File
@@ -1,9 +1,11 @@
instance_id = "Jarvis" instance_id = "Jarvis"
fullname = "Jarvis" fullname = "Jarvis"
llm_model_name = "gpt-3.5-turbo-16k-0613"
[[prompt]] [[prompt]]
role = "system" role = "system"
content = """ content = """
现在是{now}
你叫Jarvis,是我的超级私人助理。 你叫Jarvis,是我的超级私人助理。
你领导一个团队为我服务,团队的成员有: 你领导一个团队为我服务,团队的成员有:
Tracy,私人英语老师 Tracy,私人英语老师
+19 -4
View File
@@ -198,8 +198,6 @@ class AIAgent:
if self.owner_env is None: if self.owner_env is None:
return None return None
return None
all_inner_function = self.owner_env.get_all_ai_functions() all_inner_function = self.owner_env.get_all_ai_functions()
if all_inner_function is None: if all_inner_function is None:
return None return None
@@ -219,14 +217,19 @@ class AIAgent:
func_name = inenr_func_call_node.get("name") func_name = inenr_func_call_node.get("name")
arguments = json.loads(inenr_func_call_node.get("arguments")) arguments = json.loads(inenr_func_call_node.get("arguments"))
logger.info(f"llm execute inner func:{func_name} ({json.dumps(arguments)})")
func_node : AIFunction = self.owner_env.get_ai_function(func_name) func_node : AIFunction = self.owner_env.get_ai_function(func_name)
if func_node is None: if func_node is None:
return "execute failed,function not found" return "execute failed,function not found"
ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target) ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target)
try:
result_str:str = await func_node.execute(**arguments)
except Exception as e:
result_str = "call error:" + str(e)
logger.error(f"llm execute inner func:{func_name} error:{e}")
result_str:str = await func_node.execute(**arguments)
inner_functions = self._get_inner_functions() inner_functions = self._get_inner_functions()
prompt.messages.append({"role":"function","content":result_str,"name":func_name}) prompt.messages.append({"role":"function","content":result_str,"name":func_name})
@@ -242,6 +245,17 @@ class AIAgent:
else: else:
return task_result.result_str return task_result.result_str
async def _get_agent_prompt(self) -> AgentPrompt:
return self.prompt
def _format_msg_by_env_value(self,prompt:AgentPrompt):
if self.owner_env is None:
return
for msg in prompt.messages:
old_content = msg.get("content")
msg["content"] = old_content.format_map(self.owner_env)
async def _process_msg(self,msg:AgentMsg) -> AgentMsg: async def _process_msg(self,msg:AgentMsg) -> AgentMsg:
from .compute_kernel import ComputeKernel from .compute_kernel import ComputeKernel
from .bus import AIBus from .bus import AIBus
@@ -255,7 +269,7 @@ class AIAgent:
return None return None
prompt = AgentPrompt() prompt = AgentPrompt()
prompt.append(self.prompt) prompt.append(await self._get_agent_prompt())
# prompt.append(self._get_knowlege_prompt(the_role.get_name())) # prompt.append(self._get_knowlege_prompt(the_role.get_name()))
prompt.append(await self._get_prompt_from_session(chatsession)) # chat context prompt.append(await self._get_prompt_from_session(chatsession)) # chat context
@@ -263,6 +277,7 @@ class AIAgent:
msg_prompt.messages = [{"role":"user","content":msg.body}] msg_prompt.messages = [{"role":"user","content":msg.body}]
prompt.append(msg_prompt) prompt.append(msg_prompt)
self._format_msg_by_env_value(prompt)
inner_functions = self._get_inner_functions() inner_functions = self._get_inner_functions()
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions) task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
+1 -3
View File
@@ -35,7 +35,7 @@ class AgentMsgStatus(Enum):
class AgentMsg: class AgentMsg:
def __init__(self,msg_type=AgentMsgType.TYPE_MSG) -> None: def __init__(self,msg_type=AgentMsgType.TYPE_MSG) -> None:
self.msg_id = "" self.msg_id = "msg#" + uuid.uuid4().hex
self.msg_type:AgentMsgType = msg_type self.msg_type:AgentMsgType = msg_type
self.prev_msg_id:str = None self.prev_msg_id:str = None
@@ -89,7 +89,6 @@ class AgentMsg:
def create_resp_msg(self,resp_body): def create_resp_msg(self,resp_body):
resp_msg = AgentMsg() resp_msg = AgentMsg()
resp_msg.msg_id = "msg#" + uuid.uuid4().hex
resp_msg.create_time = time.time() resp_msg.create_time = time.time()
resp_msg.rely_msg_id = self.msg_id resp_msg.rely_msg_id = self.msg_id
@@ -101,7 +100,6 @@ class AgentMsg:
return resp_msg return resp_msg
def set(self,sender:str,target:str,body:str,topic:str=None) -> None: def set(self,sender:str,target:str,body:str,topic:str=None) -> None:
self.msg_id = "msg#" + uuid.uuid4().hex
self.sender = sender self.sender = sender
self.target = target self.target = target
self.body = body self.body = body
+18 -1
View File
@@ -1,6 +1,13 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Dict,Coroutine,Callable from typing import Dict,Coroutine,Callable
class ParameterDefine:
def __init__(self) -> None:
self.name = None
self.type = None
self.description = None
class AIFunction: class AIFunction:
def __init__(self) -> None: def __init__(self) -> None:
self.description : str = None self.description : str = None
@@ -107,9 +114,19 @@ class SimpleAIFunction(AIFunction):
def get_parameters(self) -> Dict: def get_parameters(self) -> Dict:
if self.parameters is not None: if self.parameters is not None:
return self.parameters result = {}
result["type"] = "object"
parm_defines = {}
for parm,desc in self.parameters.items():
parm_item = {}
parm_item["type"] = "string"
parm_item["description"] = desc
parm_defines[parm] = parm_item
result["properties"] = parm_defines
return result
return {"type": "object", "properties": {}} return {"type": "object", "properties": {}}
async def execute(self,**kwargs) -> str: async def execute(self,**kwargs) -> str:
if self.func_handler is None: if self.func_handler is None:
return "error: function not implemented" return "error: function not implemented"
+5 -1
View File
@@ -167,8 +167,12 @@ class OpenAI_ComputeNode(ComputeNode):
def is_support(self, task: ComputeTask) -> bool: def is_support(self, task: ComputeTask) -> bool:
if task.task_type == ComputeTaskType.LLM_COMPLETION: if task.task_type == ComputeTaskType.LLM_COMPLETION:
if not task.params["model_name"] or task.params["model_name"] == "gpt-4-0613": if not task.params["model_name"]:
return True return True
model_name : str = task.params["model_name"]
if model_name.startswith("gpt-"):
return True
if task.task_type == ComputeTaskType.TEXT_EMBEDDING: if task.task_type == ComputeTaskType.TEXT_EMBEDDING:
if task.params["model_name"] == "text-embedding-ada-002": if task.params["model_name"] == "text-embedding-ada-002":
return True return True
+172 -1
View File
@@ -1,6 +1,7 @@
from datetime import datetime from datetime import datetime
import asyncio import asyncio
import json
import sqlite3 # Because sqlite3 IO operation is small, so we can use sqlite3 directly.(so we don't need to use async sqlite3 now) import sqlite3 # Because sqlite3 IO operation is small, so we can use sqlite3 directly.(so we don't need to use async sqlite3 now)
from sqlite3 import Error from sqlite3 import Error
import threading import threading
@@ -8,6 +9,9 @@ import logging
from typing import Optional from typing import Optional
from .environment import Environment,EnvironmentEvent from .environment import Environment,EnvironmentEvent
from .ai_function import SimpleAIFunction from .ai_function import SimpleAIFunction
from .storage import AIStorage
import aiosqlite
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -25,19 +29,186 @@ class CalenderEvent(EnvironmentEvent):
class CalenderEnvironment(Environment): class CalenderEnvironment(Environment):
def __init__(self, env_id: str) -> None: def __init__(self, env_id: str) -> None:
super().__init__(env_id) super().__init__(env_id)
self.db_file = AIStorage.get_instance().get_myai_dir() / "calender.db"
self.is_run = False self.is_run = False
self.add_ai_function(SimpleAIFunction("get_time", self.add_ai_function(SimpleAIFunction("get_time",
"get current time", "get current time",
self._get_now)) self._get_now))
#self.add_ai_function(SimpleAIFunction("serach_events",
# "search events in calender",
# self._search_events))
get_param = {
"start_time": "start time (UTC) of event",
"end_time": "end time (UTC) of event"
}
self.add_ai_function(SimpleAIFunction("get_events",
"get events in calender by time range",
self._get_events_by_time_range,get_param))
add_param = {
"title": "title of event",
"start_time": "start time (UTC) of event",
"end_time": "end time (UTC) of event",
"participants": "participants of event",
"location": "location of event",
"details": "details of event"
}
self.add_ai_function(SimpleAIFunction("add_event",
"add event to calender",
self._add_event,add_param))
delete_param = {
"event_id": "id of event"
}
self.add_ai_function(SimpleAIFunction("delete_event",
"delete event from calender",
self._delete_event,delete_param))
update_param = {
"event_id": "id of event",
"new_title": "new title of event",
"new_participants": "new participants of event",
"new_location": "new location of event",
"new_details": "new details of event",
"start_time": "new start time (UTC) of event",
"end_time": "new end time (UTC) of event"
}
self.add_ai_function(SimpleAIFunction("update_event",
"update event in calender",
self._update_event,update_param))
#self.add_ai_function(SimpleAIFunction("user_confirm",
# "user confirm",
# self._user_confirm))
async def init_db(self):
async with aiosqlite.connect(self.db_file) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
start_time DATETIME,
end_time DATETIME,
participants TEXT,
location TEXT,
details TEXT
);
""")
await db.commit()
async def _add_event(self,title, start_time, end_time, participants=None, location=None, details=None):
async with aiosqlite.connect(self.db_file) as db:
await db.execute("""
INSERT INTO events (title, start_time, end_time, participants, location, details)
VALUES (?, ?, ?, ?, ?, ?);
""", (title, start_time, end_time, participants, location, details))
await db.commit()
return "Add event ok"
async def _search_events(self,query):
async with aiosqlite.connect(self.db_file) as db:
cursor = await db.execute("""
SELECT id,title, start_time, end_time, participants, location, details FROM events
WHERE title LIKE ? OR participants LIKE ? OR location LIKE ? OR details LIKE ?;
""", (f"%{query}%", f"%{query}%", f"%{query}%", f"%{query}%"))
rows = await cursor.fetchall()
result = {}
for row in rows:
_event = {}
_event["title"] = row[1]
_event["start_time"] = row[2]
_event["end_time"] = row[3]
_event["participants"] = row[4]
_event["location"] = row[5]
_event["details"] = row[6]
result[row[0]] = _event
return json.dumps(result, indent=4, sort_keys=True)
async def _get_events_by_time_range(self,start_time, end_time):
async with aiosqlite.connect(self.db_file) as db:
cursor = await db.execute("""
SELECT id,title, start_time, end_time, participants, location, details FROM events
WHERE start_time >= ? AND end_time <= ?;
""", (start_time, end_time))
rows = await cursor.fetchall()
result = {}
for row in rows:
_event = {}
_event["title"] = row[1]
_event["start_time"] = row[2]
_event["end_time"] = row[3]
_event["participants"] = row[4]
_event["location"] = row[5]
_event["details"] = row[6]
result[row[0]] = _event
return json.dumps(result, indent=4, sort_keys=True)
async def _update_event(self,event_id, new_title=None, new_participants=None, new_location=None, new_details=None ,start_time=None, end_time=None):
fields_to_update = []
values = []
if new_title is not None:
fields_to_update.append("title = ?")
values.append(new_title)
if new_participants is not None:
fields_to_update.append("participants = ?")
values.append(new_participants)
if new_location is not None:
fields_to_update.append("location = ?")
values.append(new_location)
if new_details is not None:
fields_to_update.append("details = ?")
values.append(new_details)
if start_time is not None:
fields_to_update.append("start_time = ?")
values.append(start_time)
if end_time is not None:
fields_to_update.append("end_time = ?")
values.append(end_time)
if not fields_to_update:
return "No fields to update."
sql_update_query = f"""
UPDATE events
SET {', '.join(fields_to_update)}
WHERE id = ?;
"""
values.append(event_id)
async with aiosqlite.connect(self.db_file) as db:
await db.execute(sql_update_query, values)
await db.commit()
return "update ok"
async def _delete_event(self,event_id):
async with aiosqlite.connect(self.db_file) as db:
await db.execute("""
DELETE FROM events
WHERE id = ?;
""", (event_id,))
await db.commit()
return "Delete event ok"
def _do_get_value(self,key:str) -> Optional[str]: def _do_get_value(self,key:str) -> Optional[str]:
return None return None
def start(self) -> None: async def start(self) -> None:
if self.is_run: if self.is_run:
return return
self.is_run = True self.is_run = True
await self.init_db()
self.register_get_handler("now",self.get_now) self.register_get_handler("now",self.get_now)
async def timer_loop(): async def timer_loop():
+2
View File
@@ -0,0 +1,2 @@
# this env is designed for workflow owner filesystem, support file/directory operations
@@ -1,6 +1,7 @@
import logging import logging
import toml import toml
from typing import Any, Callable, Dict, List, Optional, Union
from aios_kernel import AIAgent,AIAgentTemplete,AIStorage from aios_kernel import AIAgent,AIAgentTemplete,AIStorage
from package_manager import PackageEnv,PackageEnvManager,PackageMediaInfo,PackageInstallTask from package_manager import PackageEnv,PackageEnvManager,PackageMediaInfo,PackageInstallTask
@@ -17,6 +18,12 @@ class AgentManager:
cls._instance = AgentManager() cls._instance = AgentManager()
return cls._instance return cls._instance
def __init__(self) -> None:
self.agent_templete_env : PackageEnv = None
self.agent_env : PackageEnv = None
self.db_path : str = None
self.loaded_agent_instance : Dict[str,AIAgent] = None
def initial(self) -> None: def initial(self) -> None:
system_app_dir = AIStorage.get_instance().get_system_app_dir() system_app_dir = AIStorage.get_instance().get_system_app_dir()
user_data_dir = AIStorage.get_instance().get_myai_dir() user_data_dir = AIStorage.get_instance().get_myai_dir()
@@ -28,6 +35,9 @@ class AgentManager:
if self.agent_templete_env is None: if self.agent_templete_env is None:
raise Exception("agent_manager initial failed") raise Exception("agent_manager initial failed")
async def scan_all_agent(self)->None:
pass
async def get(self,agent_id:str) -> AIAgent: async def get(self,agent_id:str) -> AIAgent:
the_agent = self.loaded_agent_instance.get(agent_id) the_agent = self.loaded_agent_instance.get(agent_id)
+1
View File
@@ -19,3 +19,4 @@ base58
google-cloud-texttospeech google-cloud-texttospeech
openai openai
Pillow Pillow
aiosqlite
+2 -2
View File
@@ -81,7 +81,7 @@ class AIOS_Shell:
async def initial(self) -> bool: async def initial(self) -> bool:
cal_env = CalenderEnvironment("calender") cal_env = CalenderEnvironment("calender")
cal_env.start() await cal_env.start()
Environment.set_env_by_id("calender",cal_env) Environment.set_env_by_id("calender",cal_env)
AgentManager.get_instance().initial() AgentManager.get_instance().initial()
@@ -409,7 +409,7 @@ async def main():
await asyncio.sleep(0.2) await asyncio.sleep(0.2)
while True: while True:
user_input = await session.prompt_async(f"{shell.username}<->{shell.current_topic}@{shell.current_target}$",completer=completer,style=shell_style) user_input = await session.prompt_async(f"{shell.username}<->{shell.current_topic}@{shell.current_target}$ ",completer=completer,style=shell_style)
if len(user_input) <= 1: if len(user_input) <= 1:
continue continue