Javirs control calender~
This commit is contained in:
@@ -4,6 +4,7 @@ fullname = "Jarvis"
|
|||||||
[[prompt]]
|
[[prompt]]
|
||||||
role = "system"
|
role = "system"
|
||||||
content = """
|
content = """
|
||||||
|
现在是{now}
|
||||||
你叫Jarvis,是我的超级私人助理。
|
你叫Jarvis,是我的超级私人助理。
|
||||||
你领导一个团队为我服务,团队的成员有:
|
你领导一个团队为我服务,团队的成员有:
|
||||||
Tracy,私人英语老师
|
Tracy,私人英语老师
|
||||||
|
|||||||
@@ -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,15 +217,20 @@ 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})
|
||||||
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)
|
||||||
@@ -242,6 +245,9 @@ class AIAgent:
|
|||||||
else:
|
else:
|
||||||
return task_result.result_str
|
return task_result.result_str
|
||||||
|
|
||||||
|
async def _get_agent_prompt(self) -> AgentPrompt:
|
||||||
|
return self.prompt
|
||||||
|
|
||||||
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 +261,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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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,20 +29,187 @@ 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():
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -27,6 +34,9 @@ class AgentManager:
|
|||||||
self.loaded_agent_instance = {}
|
self.loaded_agent_instance = {}
|
||||||
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:
|
||||||
|
|||||||
@@ -19,3 +19,4 @@ base58
|
|||||||
google-cloud-texttospeech
|
google-cloud-texttospeech
|
||||||
openai
|
openai
|
||||||
Pillow
|
Pillow
|
||||||
|
aiosqlite
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user