0) Complete Docker build scriptes. 1) Refactor storage dir struct for release. 2) Add a common 'user_config' model. 3)More friendly CLI experience
This commit is contained in:
@@ -14,3 +14,6 @@ from .google_text_to_speech_node import GoogleTextToSpeechNode
|
||||
from .tunnel import AgentTunnel
|
||||
from .tg_tunnel import TelegramTunnel
|
||||
from .email_tunnel import EmailTunnel
|
||||
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
|
||||
|
||||
AIOS_Version = "0.5.1, build 2023-9-17"
|
||||
|
||||
@@ -7,6 +7,7 @@ import logging
|
||||
|
||||
from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType
|
||||
from .compute_node import ComputeNode
|
||||
from .storage import AIStorage,UserConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -19,23 +20,35 @@ class OpenAI_ComputeNode(ComputeNode):
|
||||
cls._instance = OpenAI_ComputeNode()
|
||||
return cls._instance
|
||||
|
||||
@classmethod
|
||||
def declare_user_config(cls):
|
||||
if os.getenv("OPENAI_API_KEY_") is None:
|
||||
user_config = AIStorage.get_instance().get_user_config()
|
||||
user_config.add_user_config("openai_api_key","openai api key",False,None)
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.is_start = False
|
||||
# openai.organization = "org-AoKrOtF2myemvfiFfnsSU8rF" #buckycloud
|
||||
self.openai_api_key = ""
|
||||
self.openai_api_key = None
|
||||
self.node_id = "openai_node"
|
||||
|
||||
self.task_queue = Queue()
|
||||
|
||||
if os.getenv("OPENAI_API_KEY") is not None:
|
||||
openai.api_key = os.getenv("OPENAI_API_KEY")
|
||||
else:
|
||||
openai.api_key = self.openai_api_key
|
||||
|
||||
async def initial(self):
|
||||
if os.getenv("OPENAI_API_KEY") is not None:
|
||||
self.openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
else:
|
||||
self.openai_api_key = AIStorage.get_instance().get_user_config().get_user_config("openai_api_key")
|
||||
|
||||
if self.openai_api_key is None:
|
||||
logger.error("openai_api_key is None!")
|
||||
return False
|
||||
|
||||
openai.api_key = self.openai_api_key
|
||||
self.start()
|
||||
return True
|
||||
|
||||
async def push_task(self, task: ComputeTask, proiority: int = 0):
|
||||
logger.info(f"openai_node push task: {task.display()}")
|
||||
|
||||
@@ -10,6 +10,7 @@ import stability_sdk.interfaces.gooseai.generation.generation_pb2 as generation
|
||||
|
||||
from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType
|
||||
from .compute_node import ComputeNode
|
||||
from .storage import AIStorage,UserConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -21,7 +22,11 @@ class Stability_ComputeNode(ComputeNode):
|
||||
if cls._instance is None:
|
||||
cls._instance = Stability_ComputeNode()
|
||||
return cls._instance
|
||||
|
||||
|
||||
@classmethod
|
||||
def declare_user_config(cls):
|
||||
user_config = AIStorage.get_instance().get_user_config()
|
||||
user_config.add_user_config("stability_api_key",False,None,"STABILITY_API_KEY")
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
from typing import Any
|
||||
from pathlib import Path
|
||||
import os
|
||||
import logging
|
||||
import toml
|
||||
import aiofiles
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_file_dir = os.path.dirname(__file__)
|
||||
|
||||
class ResourceLocation:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
class UserConfigItem:
|
||||
def __init__(self) -> None:
|
||||
self.default_value = None
|
||||
self.is_optional = False
|
||||
self.item_type = "str"
|
||||
self.desc = None
|
||||
self.value = None
|
||||
self.user_set = False
|
||||
|
||||
|
||||
class UserConfig:
|
||||
def __init__(self) -> None:
|
||||
self.config_table = {}
|
||||
self.user_config_path:str = None
|
||||
|
||||
|
||||
def add_user_config(self,key:str,desc:str,is_optional:bool,default_value:Any=None,item_type="str") -> None:
|
||||
if self.config_table.get(key) is not None:
|
||||
logger.warning("user config key %s already exist, will be overrided",key)
|
||||
|
||||
new_config_item = UserConfigItem()
|
||||
new_config_item.default_value = default_value
|
||||
new_config_item.is_optional = is_optional
|
||||
new_config_item.desc = desc
|
||||
new_config_item.item_type = item_type
|
||||
self.config_table[key] = new_config_item
|
||||
|
||||
async def load_value_from_file(self,file_path:str,is_user_config = False) -> None:
|
||||
try:
|
||||
all_config = toml.load(file_path)
|
||||
if all_config is not None:
|
||||
for key,value in all_config.items():
|
||||
config_item = self.config_table.get(key)
|
||||
if config_item is None:
|
||||
logger.warning("user config key %s not exist",key)
|
||||
continue
|
||||
config_item.value = value
|
||||
config_item.user_set = is_user_config
|
||||
|
||||
except Exception as e:
|
||||
logger.warn(f"load user config from {file_path} failed!")
|
||||
|
||||
async def save_value_to_user_config(self) -> None:
|
||||
will_save_config = {}
|
||||
for key,value in self.config_table.items():
|
||||
if value.user_set:
|
||||
will_save_config[key] = value.value
|
||||
|
||||
if len(will_save_config) > 0:
|
||||
try:
|
||||
directory = os.path.dirname(self.user_config_path)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
async with aiofiles.open(self.user_config_path,"w") as f:
|
||||
toml_str = toml.dumps(will_save_config)
|
||||
await f.write(toml_str)
|
||||
except Exception as e:
|
||||
logger.error(f"save user config to {self.user_config_path} failed!")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_user_config(self,key:str) -> Any:
|
||||
config_item = self.config_table.get(key)
|
||||
if config_item is None:
|
||||
raise Exception("user config key %s not exist",key)
|
||||
|
||||
if config_item.value is None:
|
||||
return config_item.default_value
|
||||
|
||||
return config_item.value
|
||||
|
||||
def set_user_config(self,key:str,value:Any) -> None:
|
||||
config_item = self.config_table.get(key)
|
||||
if config_item is None:
|
||||
logger.warning("user config key %s not exist",key)
|
||||
return
|
||||
|
||||
config_item.value = value
|
||||
config_item.user_set = True
|
||||
#TODO: save to file?
|
||||
|
||||
|
||||
def check_user_config(self) -> None:
|
||||
check_result = {}
|
||||
for key,config_item in self.config_table.items():
|
||||
if config_item.value is None and not config_item.is_optional:
|
||||
check_result[key] = config_item
|
||||
|
||||
if len(check_result) > 0:
|
||||
return check_result
|
||||
else:
|
||||
return None
|
||||
|
||||
# storage sytem for current user
|
||||
class AIStorage:
|
||||
_instance = None
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = AIStorage()
|
||||
return cls._instance
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.is_dev_mode = False
|
||||
self.user_config = UserConfig()
|
||||
|
||||
async def initial(self)->bool:
|
||||
self.user_config.user_config_path = str(self.get_myai_dir() / "etc/system.cfg.toml")
|
||||
await self.user_config.load_value_from_file(self.get_system_dir() + "/system.cfg.toml")
|
||||
await self.user_config.load_value_from_file(self.user_config.user_config_path,True)
|
||||
|
||||
def get_user_config(self) -> UserConfig:
|
||||
return self.user_config
|
||||
|
||||
def get_system_dir(self) -> str:
|
||||
"""
|
||||
system dir is dir for aios system
|
||||
/opt/aios
|
||||
"""
|
||||
if self.is_dev_mode:
|
||||
return os.path.abspath(_file_dir + "/../")
|
||||
else:
|
||||
return "/opt/aios/"
|
||||
|
||||
|
||||
def get_system_app_dir(self)->str:
|
||||
"""
|
||||
system app dir is the dir for aios build-in app
|
||||
/opt/aios/app
|
||||
"""
|
||||
if self.is_dev_mode:
|
||||
return os.path.abspath(_file_dir + "/../../rootfs/")
|
||||
else:
|
||||
return "/opt/aios/app/"
|
||||
|
||||
def get_myai_dir(self) -> str:
|
||||
"""
|
||||
my ai dir is the dir for user to store their ai app and data
|
||||
~/myai/
|
||||
"""
|
||||
return Path.home() / "myai"
|
||||
|
||||
def get_db(self,app_name:str)->ResourceLocation:
|
||||
pass
|
||||
|
||||
def open_file(self,file_path:str,options:dict):
|
||||
pass
|
||||
|
||||
def get_named_object(self,name:str) -> Any:
|
||||
pass
|
||||
|
||||
def put_named_object(self,name:str,obj:Any) -> None:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user