From babb0a7c717e716d9793996df34f4ee9e19757c4 Mon Sep 17 00:00:00 2001 From: Song Date: Wed, 27 Sep 2023 19:37:13 +0800 Subject: [PATCH 1/5] Return result code from sd node --- rootfs/agents/David/agent.toml | 15 ++++++----- src/aios_kernel/compute_kernel.py | 18 ++++++++------ src/aios_kernel/compute_task.py | 3 ++- src/aios_kernel/local_stability_node.py | 33 +++++++++++++++++-------- src/aios_kernel/stability_node.py | 28 +++++++++++++-------- src/aios_kernel/workflow_env.py | 19 +++++++------- 6 files changed, 70 insertions(+), 46 deletions(-) diff --git a/rootfs/agents/David/agent.toml b/rootfs/agents/David/agent.toml index 0cb02e8..47d2ff8 100644 --- a/rootfs/agents/David/agent.toml +++ b/rootfs/agents/David/agent.toml @@ -1,15 +1,14 @@ instance_id = "David" fullname = "David" max_token_size = 16000 -llm_model_name = "gpt-3.5-turbo-16k-0613" + owner_env = "paint" [[prompt]] role = "system" -content = """你的名字是David,是一个擅长各种风格的画家。你在收到任何绘画请求时,会尝试产生一组英文单词或者短语来描述你想画的画。 -将这些英文单词或者短语作为paint函数的prompt参数。 -当提到风格的时候,需要将风格添加进prompt参数中,而不是作为model_name。 -只有当明确提到用什么模型时,才会去设置model_name参数,否则不要传递model_name参数。 -传递给paint函数的prompt参数一定是一组英文短语,不要用其他语言,如果是其他语言,就将其翻译成英文再传递。 -如果函数调用返回任何错误,直接将错误的原文显示出来并停止。 -如果绘制成功,就停止并输出文件的本地路径。""" +content = """You are an artist, and you will use the 'paint' function in the llm_inner_functions to create artwork. +You will extract relevant keywords based on user input and requirements, and pass these keywords to the 'prompt' parameter of the 'paint' function. +When a specific model is mentioned, pass the model's name to the 'model_name' parameter of the 'paint' function. +If there are instructions not to depict certain content, summarize this content and pass it as keywords to the 'negative_prompt' parameter. +All parameters must be in English. +When the user mentions creating a children's picture book, use the "realisticVisionV51_v51VAE" model, and append the keyword " " to the 'prompt' parameter.""" diff --git a/src/aios_kernel/compute_kernel.py b/src/aios_kernel/compute_kernel.py index bd3eb07..843a951 100644 --- a/src/aios_kernel/compute_kernel.py +++ b/src/aios_kernel/compute_kernel.py @@ -175,17 +175,19 @@ class ComputeKernel: return task_result.result - def text_2_image(self, prompt:str, model_name:Optional[str] = None): + def text_2_image(self, prompt:str, model_name:Optional[str] = None, negative_prompt = None): task = ComputeTask() - task.set_text_2_image_params(prompt,model_name) + task.set_text_2_image_params(prompt,model_name, negative_prompt) self.run(task) return task - async def do_text_2_image(self, prompt:str, model_name:Optional[str] = None) -> [str, ComputeTaskResult]: - task_req = self.text_2_image(prompt,model_name) - task_result = self._send_task(task_req) - if task_req.state == ComputeTaskState.DONE: - return None, task_result + async def do_text_2_image(self, prompt:str, model_name:Optional[str] = None, negative_prompt = None) -> ComputeTaskResult: + task = self.text_2_image(prompt,model_name, negative_prompt) + task = await self._send_task(task) - return task_req.error_str, None + return task.result + # if task_req.state == ComputeTaskState.DONE: + # return None, task_result + + # return task_req.error_str, None diff --git a/src/aios_kernel/compute_task.py b/src/aios_kernel/compute_task.py index 05125ee..12fd5cd 100644 --- a/src/aios_kernel/compute_task.py +++ b/src/aios_kernel/compute_task.py @@ -71,12 +71,13 @@ class ComputeTask: self.params["model_name"] = "text-embedding-ada-002" self.params["input"] = input - def set_text_2_image_params(self, prompt: str, model_name, callchain_id=None): + def set_text_2_image_params(self, prompt: str, model_name, negative_prompt="", callchain_id=None): self.task_type = ComputeTaskType.TEXT_2_IMAGE self.create_time = time.time() self.task_id = uuid.uuid4().hex self.callchain_id = callchain_id self.params["prompt"] = prompt + self.params["negative_prompt"] = negative_prompt if model_name is not None: self.params["model_name"] = model_name else: diff --git a/src/aios_kernel/local_stability_node.py b/src/aios_kernel/local_stability_node.py index d773105..d0d7f9d 100644 --- a/src/aios_kernel/local_stability_node.py +++ b/src/aios_kernel/local_stability_node.py @@ -9,7 +9,7 @@ import requests from typing import Tuple from pathlib import Path -from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType +from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType, ComputeTaskResultCode from .compute_node import ComputeNode from .storage import AIStorage, UserConfig @@ -107,10 +107,19 @@ class Local_Stability_ComputeNode(ComputeNode): def _run_task(self, task: ComputeTask): task.state = ComputeTaskState.RUNNING + result = ComputeTaskResult() + result.result_code = ComputeTaskResultCode.ERROR + result.set_from_task(task) + model_name = task.params["model_name"] prompt = task.params["prompt"] + negative_prompt = task.params["negative_prompt"] + if negative_prompt == None or negative_prompt == "": + negative_prompt = "sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, duplicate, mutated hands, mutated legs, (blurry:1.3), (bad anatomy:1.2), bad proportions, extra limbs, more than 2 nipples, extra legs, fused fingers, missing fingers, jpeg artifacts, signature, watermark, username, artist name, heterochromia, muscular legs, monochrome, grayscale, skin spots, acnes, skin blemishes, age spot, skin spots, acnes, logo, badhandv4, easynegative, cropped image, patreon,lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, ng_deepnegative_v1_75t, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry,(Tiptoe:1.3),looking at viewer, Twisted eyes" - logging.info(f"call local stability {model_name} prompts: {prompt}") + prompt += ",masterpiece, best quality:1.3" + + logging.info(f"call local stability {model_name} prompts: {prompt}, nagative_prompt: {negative_prompt}") if model_name is not None: payload = { @@ -123,12 +132,14 @@ class Local_Stability_ComputeNode(ComputeNode): err_msg = f"Set local stability model failed. err:{err}" logger.error(err_msg) task.error_str = err_msg - return None + result.error_str = err_msg + return result logging.info(f"set local stability model {model_name} success") payload = { "prompt": prompt, + "negative_prompt": negative_prompt, "steps": 20 } @@ -138,7 +149,8 @@ class Local_Stability_ComputeNode(ComputeNode): err_msg = f"Failed. err:{err}" logger.error(err_msg) task.error_str = err_msg - return None + result.error_str = err_msg + return result r = resp.json() @@ -148,16 +160,17 @@ class Local_Stability_ComputeNode(ComputeNode): file_name = os.path.join(self.output_dir, task.task_id + ".png") image.save(file_name) - result = ComputeTaskResult() - result.set_from_task(task) + task.state = ComputeTaskState.DONE + result.result_code = ComputeTaskResultCode.OK result.worker_id = self.node_id result.result = {"file": file_name} return result task.error_str = "Unknown error!" + result.error_str = "Unknown error!" task.state = ComputeTaskState.ERROR - return None + return result def start(self): if self.is_start: @@ -170,9 +183,9 @@ class Local_Stability_ComputeNode(ComputeNode): task = await self.task_queue.get() logger.info(f"stability_node get task: {task.display()}") result = self._run_task(task) - if result is not None: - task.state = ComputeTaskState.DONE - task.result = result + # if result is not None: + # task.state = ComputeTaskState.DONE + # task.result = result asyncio.create_task(_run_task_loop()) diff --git a/src/aios_kernel/stability_node.py b/src/aios_kernel/stability_node.py index 88eeb71..2ea1f44 100644 --- a/src/aios_kernel/stability_node.py +++ b/src/aios_kernel/stability_node.py @@ -9,7 +9,7 @@ from PIL import Image from stability_sdk import client import stability_sdk.interfaces.gooseai.generation.generation_pb2 as generation -from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType +from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType, ComputeTaskResultCode from .compute_node import ComputeNode from .storage import AIStorage, UserConfig @@ -95,10 +95,15 @@ class Stability_ComputeNode(ComputeNode): def _run_task(self, task: ComputeTask): task.state = ComputeTaskState.RUNNING + result = ComputeTaskResult() + result.result_code = ComputeTaskResultCode.ERROR + result.set_from_task(task) + model_name = task.params["model_name"] prompt = task.params["prompt"] + negative_prompt = task.params["negative_prompt"] - logging.info(f"call stability {self.default_model} prompts: {prompt}") + logging.info(f"call stability {self.default_model} prompts: {prompt}, negative_prompt: {negative_prompt}") api = None try: @@ -109,9 +114,10 @@ class Stability_ComputeNode(ComputeNode): ) except Exception as e: task.error_str = f"create stability client failed: {e}" + result.error_str = f"create stability client failed: {e}" logging.warn(task.error_str) task.state = ComputeTaskState.ERROR - return None + return result answers = api.generate( prompt=prompt, @@ -141,24 +147,26 @@ class Stability_ComputeNode(ComputeNode): err_msg = "request activated the API's safety filters" logging.warn(err_msg) task.error_str = err_msg + result.error_str = err_msg task.state = ComputeTaskState.ERROR - return None + return result if artifact.type == generation.ARTIFACT_IMAGE: img = Image.open(io.BytesIO(artifact.binary)) # Save our generated images with the task_id as the filename. file_name = os.path.join(self.output_dir, task.task_id + ".png") img.save(file_name) - result = ComputeTaskResult() - result.set_from_task(task) + task.state = ComputeTaskState.DONE + result.result_code = ComputeTaskResultCode.OK result.worker_id = self.node_id result.result = {"file": file_name} return result task.error_str = "Unknown error!" + result.error_str = "Unknown error!" task.state = ComputeTaskState.ERROR - return None + return result def start(self): if self.is_start: @@ -171,9 +179,9 @@ class Stability_ComputeNode(ComputeNode): task = await self.task_queue.get() logger.info(f"stability_node get task: {task.display()}") result = self._run_task(task) - if result is not None: - task.state = ComputeTaskState.DONE - task.result = result + # if result is not None: + # task.state = ComputeTaskState.DONE + # task.result = result asyncio.create_task(_run_task_loop()) diff --git a/src/aios_kernel/workflow_env.py b/src/aios_kernel/workflow_env.py index f2b41d3..c62fc45 100644 --- a/src/aios_kernel/workflow_env.py +++ b/src/aios_kernel/workflow_env.py @@ -9,7 +9,7 @@ import logging from typing import Optional from .text_to_speech_function import TextToSpeechFunction -from .compute_kernel import ComputeKernel +from .compute_kernel import ComputeKernel, ComputeTaskResultCode from .environment import Environment,EnvironmentEvent from .ai_function import SimpleAIFunction from .storage import AIStorage @@ -311,9 +311,9 @@ class CalenderEnvironment(Environment): async def _paint(self, prompt, model_name = None) -> str: - err, result = await ComputeKernel.get_instance().do_text_2_image(prompt, model_name) - if err is not None: - return f"exec paint failed. err:{err}" + result = await ComputeKernel.get_instance().do_text_2_image(prompt, model_name) + if result.result_code == ComputeTaskResultCode.ERROR: + return f"exec paint failed. err:{result.error_str}" else: return f'exec paint OK, saved as a local file, path is: {result.result["file"]}' @@ -324,19 +324,20 @@ class PaintEnvironment(Environment): self.is_run = False paint_param = { - "prompt": "A description of the content of the painting", - "model_name": "Which model to use to draw the picture, can be None" + "prompt": "Keywords of the content of the painting", + "model_name": "Which model to use to draw the picture, can be None", + "negative_prompt": "Keywords that describe what is not to be drawn, can be None" } self.add_ai_function(SimpleAIFunction("paint", - "Draw a picture according to the description", + "Draw a picture according to the keywords", self._paint,paint_param)) def _do_get_value(self,key:str) -> Optional[str]: return None - async def _paint(self, prompt, model_name = None) -> str: - err, result = await ComputeKernel.get_instance().do_text_2_image(prompt, model_name) + async def _paint(self, prompt, model_name = None, negative_prompt = None) -> str: + err, result = await ComputeKernel.get_instance().do_text_2_image(prompt, model_name, negative_prompt) if err is not None: return f"exec paint failed. err:{err}" else: From 5146bc1871bf8f5e3b68264b031246a361456e8e Mon Sep 17 00:00:00 2001 From: Liu Zhicong Date: Wed, 27 Sep 2023 10:09:31 -0700 Subject: [PATCH 2/5] Add chat history limit for Agent and Role. Fix bugs. --- rootfs/agents/Jarvis/agent.toml | 17 +++++++++-------- rootfs/agents/email_reader/agent.toml | 5 ----- rootfs/agents/fairy_tale_writer/agent.toml | 2 +- src/aios_kernel/agent.py | 5 ++++- src/aios_kernel/knowledge_pipeline.py | 2 ++ src/aios_kernel/role.py | 5 +++++ src/aios_kernel/workflow.py | 6 +++--- src/service/aios_shell/aios_shell.py | 2 +- 8 files changed, 25 insertions(+), 19 deletions(-) delete mode 100644 rootfs/agents/email_reader/agent.toml diff --git a/rootfs/agents/Jarvis/agent.toml b/rootfs/agents/Jarvis/agent.toml index c27f3bb..9318890 100644 --- a/rootfs/agents/Jarvis/agent.toml +++ b/rootfs/agents/Jarvis/agent.toml @@ -5,27 +5,28 @@ max_token_size = 16000 #enable_kb = "true" enable_timestamp = "true" owner_prompt = "我是你的主人{name}" -contact_prompt = "我是你的朋友{name}" +contact_prompt = "我是你的主人的朋友{name}" owner_env = "calender" [[prompt]] role = "system" content = """ -你叫Jarvis,是我的超级私人助理。 -你领导一个团队为我服务,团队的成员有: +你叫Jarvis,是主人的超级私人助理。 +你领导一个团队为主人服务,团队的成员有: Tracy,私人英语老师 -David,私人画家 +Mia,主人的私人文档管理专家 *** -你看到的信息里有的有时会带上时间标签,这是为了让你更好的理解时间。你回复的信息不用创建这个时间标签。 -你在收到我的信息后,按如下规则处理 +你看到的信息里有的有时会带上时间,这是为了让你更好的理解消息的创建。你回复信息时不带这个时间标签。 +你在收到的信息后,按如下规则处理 1. 如果你认为团队里有人更适合处理该信息,用下面方法转发消息给他们处理 ``` ##/send_msg 成员名字 消息内容 ``` -2.你可以访问我的Calender,查看我的日程安排。如果你在处理信息的过程中需要修改我的日程安排,请直接用合适的方法修改。 -3.不符合上述规则的信息,请尽力处理。 +2.你可以访问主人的Calender,查看主人的日程安排。如果你在处理信息的过程中需要修改主人的日程安排,请直接用合适的方法修改。 +3.你要注意和你聊天的人的身份,并根据其身份给予适当的服务。 +4.不符合上述规则的信息,请尽力处理。 """ diff --git a/rootfs/agents/email_reader/agent.toml b/rootfs/agents/email_reader/agent.toml deleted file mode 100644 index a6baba9..0000000 --- a/rootfs/agents/email_reader/agent.toml +++ /dev/null @@ -1,5 +0,0 @@ -instance_id = "agent:xxxxxxabcde" -fullname = "jackma" -[[prompt]] -role = "system" -content = "你擅长处理商务电子邮件" diff --git a/rootfs/agents/fairy_tale_writer/agent.toml b/rootfs/agents/fairy_tale_writer/agent.toml index 7955df6..cb18802 100644 --- a/rootfs/agents/fairy_tale_writer/agent.toml +++ b/rootfs/agents/fairy_tale_writer/agent.toml @@ -5,4 +5,4 @@ enable_function = [] [[prompt]] role = "system" -content = "你是一个童话做作家,能够写出各种有趣的童话。" +content = "你是一个童话作家,能够写出各种有趣的童话。" diff --git a/src/aios_kernel/agent.py b/src/aios_kernel/agent.py index 269ba85..bbebc16 100644 --- a/src/aios_kernel/agent.py +++ b/src/aios_kernel/agent.py @@ -118,6 +118,7 @@ class AIAgent: self.guest_prompt_str = None self.owner_promp_str = None self.contact_prompt_str = None + self.history_len = 10 self.chat_db = None self.unread_msg = Queue() # msg from other agent @@ -179,6 +180,8 @@ class AIAgent: self.enable_kb = bool(config["enable_kb"]) if config.get("enable_timestamp") is not None: self.enable_timestamp = bool(config["enable_timestamp"]) + if config.get("history_len"): + self.history_len = int(config.get("history_len")) return True @@ -459,7 +462,7 @@ class AIAgent: async def _get_prompt_from_session(self,chatsession:AIChatSession,system_token_len,input_token_len,is_groupchat=False) -> AgentPrompt: # TODO: get prompt from group chat is different from single chat history_len = (self.max_token_size * 0.7) - system_token_len - input_token_len - messages = chatsession.read_history() # read + messages = chatsession.read_history(self.history_len) # read result_token_len = 0 result_prompt = AgentPrompt() read_history_msg = 0 diff --git a/src/aios_kernel/knowledge_pipeline.py b/src/aios_kernel/knowledge_pipeline.py index 7f90a08..24dc0c8 100644 --- a/src/aios_kernel/knowledge_pipeline.py +++ b/src/aios_kernel/knowledge_pipeline.py @@ -380,3 +380,5 @@ class KnowledgePipline: # await source.run_once() for source in self.source_queue: await source.run_once() + + logging.info(f"knowledge pipeline finished") \ No newline at end of file diff --git a/src/aios_kernel/role.py b/src/aios_kernel/role.py index 2f58894..83d64d6 100644 --- a/src/aios_kernel/role.py +++ b/src/aios_kernel/role.py @@ -13,6 +13,7 @@ class AIRole: self.introduce : str = None self.agent = None self.enable_function_list : list[str] = None + self.history_len = 10 def load_from_config(self,config:dict) -> bool: name_node = config.get("name") @@ -39,6 +40,10 @@ class AIRole: if intro_node is not None: self.introduce = intro_node + history_node = config.get("history_len") + if history_node: + self.history_len = int(history_node) + if config.get("enable_function") is not None: self.enable_function_list = config["enable_function"] diff --git a/src/aios_kernel/workflow.py b/src/aios_kernel/workflow.py index ee95d21..69dcbdd 100644 --- a/src/aios_kernel/workflow.py +++ b/src/aios_kernel/workflow.py @@ -446,7 +446,7 @@ class Workflow: # prompt.append(self._get_knowlege_prompt(the_role.get_name())) #support group chat, user content include sender name! - prompt.append(await self._get_prompt_from_session(workflow_chat_session)) + prompt.append(await self._get_prompt_from_session(the_role,workflow_chat_session)) msg_prompt = AgentPrompt() msg_prompt.messages = [{"role":"user","content":f"user name is {msg.sender}, his question is :{msg.body}"}] @@ -536,8 +536,8 @@ class Workflow: return await _do_process_msg() - async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt: - messages = chatsession.read_history() # read last 10 message + async def _get_prompt_from_session(self,the_role:AIRole,chatsession:AIChatSession) -> AgentPrompt: + messages = chatsession.read_history(the_role.history_len) # read last 10 message result_prompt = AgentPrompt() for msg in reversed(messages): if msg.sender == chatsession.owner_id: diff --git a/src/service/aios_shell/aios_shell.py b/src/service/aios_shell/aios_shell.py index 9b8731a..e77475a 100644 --- a/src/service/aios_shell/aios_shell.py +++ b/src/service/aios_shell/aios_shell.py @@ -112,7 +112,7 @@ class AIOS_Shell: owenr.email = AIStorage.get_instance().get_user_config().get_value("email") owenr.telegram = AIStorage.get_instance().get_user_config().get_value("telegram") - cm.add_contact(self.username,owenr) + cm.add_family_member(self.username,owenr) cal_env = CalenderEnvironment("calender") await cal_env.start() From 030e4c4f52a43fc72d262f7ee59215ac71a95bd2 Mon Sep 17 00:00:00 2001 From: Liu Zhicong Date: Wed, 27 Sep 2023 11:40:46 -0700 Subject: [PATCH 3/5] Adjust the directory structure to prepare for merging into Master. --- PoC/README.md | 90 ++++++ .../agent_jarvis}/.dockerignore | 0 .../agent_jarvis}/.env_template | 0 {agent_jarvis => PoC/agent_jarvis}/.gitignore | 0 {agent_jarvis => PoC/agent_jarvis}/README.md | 0 .../agent_jarvis}/TestPage/css/github.css | 0 .../agent_jarvis}/TestPage/css/main.css | 0 .../agent_jarvis}/TestPage/index.html | 0 .../agent_jarvis}/TestPage/js/main.js | 0 .../agent_jarvis}/TestPage/js/showdown.min.js | 2 +- .../agent_jarvis}/TestPage/js/utils.js | 0 .../agent_jarvis}/TestPage/server/main.js | 0 .../TestPage/server/package.json | 0 .../agent_jarvis}/build_docker.sh | 0 {agent_jarvis => PoC/agent_jarvis}/dockerfile | 0 .../images/jarvis-with-drawing.gif | Bin .../agent_jarvis}/images/jarvis.png | Bin .../agent_jarvis}/images/remove_bg.png | Bin .../agent_jarvis}/jarvis/CFG.py | 0 .../jarvis/ai_agent/agent_factory.py | 0 .../jarvis/ai_agent/agent_utils.py | 0 .../jarvis/ai_agent/base_agent.py | 0 .../jarvis/ai_agent/gpt_agent.py | 0 .../jarvis/ai_agent/webui_agent.py | 0 .../functional_modules/caller_context.py | 0 .../functional_modules/functional_module.py | 0 .../agent_jarvis}/jarvis/gateway/session.py | 0 .../agent_jarvis}/jarvis/gpt/ai_function.py | 0 .../agent_jarvis}/jarvis/gpt/gpt.py | 0 .../agent_jarvis}/jarvis/gpt/token_counter.py | 0 .../jarvis/json_utils/__init__.py | 0 .../jarvis/json_utils/json_fix_general.py | 0 .../jarvis/json_utils/json_fix_llm.py | 0 .../json_utils/llm_response_format_1.json | 0 .../jarvis/json_utils/utilities.py | 0 .../agent_jarvis}/jarvis/logger.py | 0 .../agent_jarvis}/jarvis/main.py | 0 .../agent_jarvis}/jarvis/utils/asynchttp.py | 0 .../jarvis/utils/function_error.py | 0 .../utils/incoming_chat_message_parser.py | 0 .../agent_jarvis}/requirements.txt | 0 {agent_jarvis => PoC/agent_jarvis}/run.sh | 0 .../agent_jarvis}/run_example_services.sh | 0 .../supervisor.d/demo_service1.ini | 0 .../supervisor.d/demo_service1.sh | 0 .../supervisor.d/demo_service2.ini | 0 .../supervisor.d/demo_service2.sh | 0 .../agent_jarvis}/supervisor.d/entrypoint.sh | 0 .../agent_jarvis}/supervisor.d/jarvis.ini | 0 .../agent_jarvis}/supervisor.d/jarvis.sh | 0 .../discord_bot}/.env.template | 0 {discord_bot => PoC/discord_bot}/.gitignore | 0 {discord_bot => PoC/discord_bot}/.npmrc | 0 {discord_bot => PoC/discord_bot}/.prettierrc | 0 {discord_bot => PoC/discord_bot}/Dockerfile | 0 {discord_bot => PoC/discord_bot}/README.md | 0 .../discord_bot}/package-lock.json | 0 {discord_bot => PoC/discord_bot}/package.json | 0 .../discord_bot}/src/bot/bot-app.mts | 0 .../discord_bot}/src/bot/index.mts | 0 .../discord_bot}/src/bot/websocket-server.mts | 0 .../discord_bot}/src/types/index.mts | 0 .../discord_bot}/tsconfig.json | 0 .../example_modules}/.gitignore | 0 .../demo_modules/google_calendar.module.py | 0 .../demo_modules/rembg.module.py | 0 .../demo_modules/stable_diffusion.module.py | 0 .../demo_modules/stable_diffusion_params.json | 0 .../demo_modules/twitter.module.py | 0 .../demo_modules/youtube.module.py | 0 .../light_switch/switch.module.py | 0 .../example_modules}/tell_joke/joke_db.py | 0 .../tell_joke/tell_joke.module.py | 0 .../example_services}/.gitignore | 0 .../demo_service1/.gitignore | 0 .../example_services}/demo_service1/main.py | 0 .../example_services}/demo_service2/README.md | 0 .../demo_service2/google_calendar/__init__.py | 0 .../demo_service2/google_calendar/config.py | 0 .../demo_service2/google_calendar/event.py | 0 .../demo_service2/google_calendar/oauth.py | 0 .../example_services}/demo_service2/main.py | 0 .../demo_service2/provider.py | 0 .../demo_service2/response.py | 0 README.md | 305 ++++++++++++++---- buildin/agents/english-teacher/README | 1 - buildin/agents/english-teacher/agent.cfg | 0 buildin/services/spiders/email-spider/README | 1 - doc/{mvp => }/aios_kernel.md | 0 doc/{mvp => }/compute_kernel.png | Bin doc/{mvp => }/compute_task.drawio | 0 doc/{mvp => }/install_package.png | Bin doc/{mvp => }/knowleadge.drawio | 0 doc/{mvp => }/knowleage.md | 0 doc/{mvp => }/load_package.png | Bin doc/{mvp => }/mvp plan 2.md | 0 doc/{mvp => }/mvp plan.md | 0 doc/mvp/demo_workflow/workflow.toml | 81 ----- doc/{mvp => }/package_manager.md | 0 doc/{mvp => }/pkg_procedure.drawio | 0 .../file.txt | 0 ...df120b430021c36c232c99ef8d926aea2acd6b.zip | Bin .../pkg_system_demo/demo1/.pkgs/index-db.toml | 0 .../pkg_system_demo/demo1/pkg.cfg.toml | 0 doc/{mvp => }/pkg_system_demo/demo1/pkg.lock | 0 .../demo1/pkgs/pkg_nameA#1.0.3/file.txt | 0 .../demo1/pkgs/pkg_nameA/file.txt | 0 .../pkg_system_demo/demo1/pkgs/pkg_nameB.zip | Bin doc/{mvp => }/pkg_tree.png | Bin doc/{mvp => }/process model.drawio | 0 doc/{mvp => }/workflow.drawio | 0 rootfs/agents/Mia/agent.toml | 35 ++ rootfs/agents/Thinker/agent.toml | 24 ++ .../{linux_admin => ai_bash}/agent.toml | 0 src/service/aios_shell/aios_shell.py | 34 +- 115 files changed, 413 insertions(+), 160 deletions(-) create mode 100644 PoC/README.md rename {agent_jarvis => PoC/agent_jarvis}/.dockerignore (100%) rename {agent_jarvis => PoC/agent_jarvis}/.env_template (100%) rename {agent_jarvis => PoC/agent_jarvis}/.gitignore (100%) rename {agent_jarvis => PoC/agent_jarvis}/README.md (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/css/github.css (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/css/main.css (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/index.html (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/js/main.js (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/js/showdown.min.js (99%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/js/utils.js (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/server/main.js (100%) rename {agent_jarvis => PoC/agent_jarvis}/TestPage/server/package.json (100%) rename {agent_jarvis => PoC/agent_jarvis}/build_docker.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/dockerfile (100%) rename {agent_jarvis => PoC/agent_jarvis}/images/jarvis-with-drawing.gif (100%) rename {agent_jarvis => PoC/agent_jarvis}/images/jarvis.png (100%) rename {agent_jarvis => PoC/agent_jarvis}/images/remove_bg.png (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/CFG.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/ai_agent/agent_factory.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/ai_agent/agent_utils.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/ai_agent/base_agent.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/ai_agent/gpt_agent.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/ai_agent/webui_agent.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/functional_modules/caller_context.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/functional_modules/functional_module.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/gateway/session.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/gpt/ai_function.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/gpt/gpt.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/gpt/token_counter.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/json_utils/__init__.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/json_utils/json_fix_general.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/json_utils/json_fix_llm.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/json_utils/llm_response_format_1.json (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/json_utils/utilities.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/logger.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/main.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/utils/asynchttp.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/utils/function_error.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/jarvis/utils/incoming_chat_message_parser.py (100%) rename {agent_jarvis => PoC/agent_jarvis}/requirements.txt (100%) rename {agent_jarvis => PoC/agent_jarvis}/run.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/run_example_services.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/demo_service1.ini (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/demo_service1.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/demo_service2.ini (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/demo_service2.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/entrypoint.sh (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/jarvis.ini (100%) rename {agent_jarvis => PoC/agent_jarvis}/supervisor.d/jarvis.sh (100%) rename {discord_bot => PoC/discord_bot}/.env.template (100%) rename {discord_bot => PoC/discord_bot}/.gitignore (100%) rename {discord_bot => PoC/discord_bot}/.npmrc (100%) rename {discord_bot => PoC/discord_bot}/.prettierrc (100%) rename {discord_bot => PoC/discord_bot}/Dockerfile (100%) rename {discord_bot => PoC/discord_bot}/README.md (100%) rename {discord_bot => PoC/discord_bot}/package-lock.json (100%) rename {discord_bot => PoC/discord_bot}/package.json (100%) rename {discord_bot => PoC/discord_bot}/src/bot/bot-app.mts (100%) rename {discord_bot => PoC/discord_bot}/src/bot/index.mts (100%) rename {discord_bot => PoC/discord_bot}/src/bot/websocket-server.mts (100%) rename {discord_bot => PoC/discord_bot}/src/types/index.mts (100%) rename {discord_bot => PoC/discord_bot}/tsconfig.json (100%) rename {example_modules => PoC/example_modules}/.gitignore (100%) rename {example_modules => PoC/example_modules}/demo_modules/google_calendar.module.py (100%) rename {example_modules => PoC/example_modules}/demo_modules/rembg.module.py (100%) rename {example_modules => PoC/example_modules}/demo_modules/stable_diffusion.module.py (100%) rename {example_modules => PoC/example_modules}/demo_modules/stable_diffusion_params.json (100%) rename {example_modules => PoC/example_modules}/demo_modules/twitter.module.py (100%) rename {example_modules => PoC/example_modules}/demo_modules/youtube.module.py (100%) rename {example_modules => PoC/example_modules}/light_switch/switch.module.py (100%) rename {example_modules => PoC/example_modules}/tell_joke/joke_db.py (100%) rename {example_modules => PoC/example_modules}/tell_joke/tell_joke.module.py (100%) rename {example_services => PoC/example_services}/.gitignore (100%) rename {example_services => PoC/example_services}/demo_service1/.gitignore (100%) rename {example_services => PoC/example_services}/demo_service1/main.py (100%) rename {example_services => PoC/example_services}/demo_service2/README.md (100%) rename {example_services => PoC/example_services}/demo_service2/google_calendar/__init__.py (100%) rename {example_services => PoC/example_services}/demo_service2/google_calendar/config.py (100%) rename {example_services => PoC/example_services}/demo_service2/google_calendar/event.py (100%) rename {example_services => PoC/example_services}/demo_service2/google_calendar/oauth.py (100%) rename {example_services => PoC/example_services}/demo_service2/main.py (100%) rename {example_services => PoC/example_services}/demo_service2/provider.py (100%) rename {example_services => PoC/example_services}/demo_service2/response.py (100%) delete mode 100644 buildin/agents/english-teacher/README delete mode 100644 buildin/agents/english-teacher/agent.cfg delete mode 100644 buildin/services/spiders/email-spider/README rename doc/{mvp => }/aios_kernel.md (100%) rename doc/{mvp => }/compute_kernel.png (100%) rename doc/{mvp => }/compute_task.drawio (100%) rename doc/{mvp => }/install_package.png (100%) rename doc/{mvp => }/knowleadge.drawio (100%) rename doc/{mvp => }/knowleage.md (100%) rename doc/{mvp => }/load_package.png (100%) rename doc/{mvp => }/mvp plan 2.md (100%) rename doc/{mvp => }/mvp plan.md (100%) delete mode 100644 doc/mvp/demo_workflow/workflow.toml rename doc/{mvp => }/package_manager.md (100%) rename doc/{mvp => }/pkg_procedure.drawio (100%) rename doc/{mvp => }/pkg_system_demo/demo1/.pkgs/.pkg_nameA/pkg_nameA#sha1-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed/file.txt (100%) rename doc/{mvp => }/pkg_system_demo/demo1/.pkgs/.pkg_nameB/pkg_nameB#sha1-addf120b430021c36c232c99ef8d926aea2acd6b.zip (100%) rename doc/{mvp => }/pkg_system_demo/demo1/.pkgs/index-db.toml (100%) rename doc/{mvp => }/pkg_system_demo/demo1/pkg.cfg.toml (100%) rename doc/{mvp => }/pkg_system_demo/demo1/pkg.lock (100%) rename doc/{mvp => }/pkg_system_demo/demo1/pkgs/pkg_nameA#1.0.3/file.txt (100%) rename doc/{mvp => }/pkg_system_demo/demo1/pkgs/pkg_nameA/file.txt (100%) rename doc/{mvp => }/pkg_system_demo/demo1/pkgs/pkg_nameB.zip (100%) rename doc/{mvp => }/pkg_tree.png (100%) rename doc/{mvp => }/process model.drawio (100%) rename doc/{mvp => }/workflow.drawio (100%) create mode 100644 rootfs/agents/Mia/agent.toml create mode 100644 rootfs/agents/Thinker/agent.toml rename rootfs/agents/{linux_admin => ai_bash}/agent.toml (100%) diff --git a/PoC/README.md b/PoC/README.md new file mode 100644 index 0000000..7fea841 --- /dev/null +++ b/PoC/README.md @@ -0,0 +1,90 @@ +# **OpenDAN: Personal AI OS** +[![Official Website](https://img.shields.io/badge/Official%20Website-opendan.ai-blue?style=flat&logo=world&logoColor=white)](https://opendan.ai) +[![GitHub Repo stars](https://img.shields.io/github/stars/fiatrete/OpenDAN-Personal-AI-OS?style=social)](https://github.com/fiatrete/OpenDAN-Personal-AI-OS/stargazers) +[![Twitter Follow](https://img.shields.io/twitter/follow/openDAN_AI?style=social)](https://twitter.com/openDAN_AI) + +OpenDAN is an open source Personal AI OS , which consolidates various AI modules in one place for your personal use. + +## **Project Introduction** + +The goal of OpenDAN (Open and Do Anything Now with AI) is to create a Personal AI OS , which provides a runtime environment for various Al modules as well as protocols for interoperability between them. With OpenDAN, users can securely collaborate with various AI modules using their private data to create powerful personal AI agents, such as butler, lawyer, doctor, teacher, assistant, girl or boy friends. + +This project is still in its very early stages, and there may be significant changes in the future. + +## **Updates** + +### 1. Adding Knowledge Base Infrastructure +We're currently working on implementing the infrastructure for the Knowledge Base, aiming to enhance AI agent's access to Personal Data stored on Personal Servers. Leveraging these new features, we want to empower everyone to build their own personal homepage in the AI era using OpenDAN. + +### 2. Development Based on SourceDAO Contract +We are in the process of developing the OpenDAN's DAO page, which is based on the SourceDAO contract. The future of OpenDAN should be determined by the community. + +### 3. Welcoming waterflier as a Core Contributor +We're excited to officially invite waterflier to join as a core contributor to our community. We recognize and appreciate his innovative ideas and deep insights in the realm of Personal AI OS. Waterflier will be spearheading the development of the MVP version. As a key contributor to the CYFS CoreDev Team, he brings extensive experience in the domain of Personal Servers. + +## **Intro video - What is OpenDAN?** +Click the image below for a demo: + +[![Intro Video](https://github-production-user-asset-6210df.s3.amazonaws.com/126534313/243310994-4d1ece51-b06d-413d-a2ac-ea5099bb6e94.png)](https://www.youtube.com/watch?v=l2QmsIOXhdQ "Intro Video") + +## **Demo video - What can OpenDAN do?** +Click the image below for a demo: + +[![Demo Video](https://github-production-user-asset-6210df.s3.amazonaws.com/126534313/243309993-cf6abfd5-0a56-420b-ac56-99b18dbd3c5f.png)](https://youtu.be/13wdyoT0VHQ "Demo Video") + +
+ + + +
+ + +## **Subscribe to updates here** + +https://twitter.com/openDAN_AI + +## **Core Features of OpenDAN** + +To achieve the goal of OpenDAN, we provide the following key features: + +1. **Hardware-specific optimization**: Optimize for specific hardware to enable smooth local running of most open-source AI applications. +2. **Open AI App Marketplace**: Offer a solution for one-click installation and use of various AI applications, helping users easily access and manage AI apps. +3. **Open AI Model Solution**: Provide a unified entry point for model search, download, and access control, making it convenient for users to find and use models suitable for their needs. +4. **Strict Privacy Protection and Management**: Strictly manage personal data, ranging from family albums to chat records and social media records, and provide a unified access control interface for AI applications. +5. **Integrated Tools**: Offer tools for users to train their own voice models, Lora models, knowledge models, etc., using personal data. +6. **AI Butler Assistant**: Driven by a large language model, the AI assistant completes tasks through natural language interaction. +7. **Development Framework**: Provide a development framework for customizing AI assistants for specific purposes, making it easy for developers to create unique AI applications for users. + +## **Roadmap** + +- [x] Project Initialization + - [x] Basic code for operating system image packaging script + - [x] Opendan.ai website homepage +- [x] OpenDAN Prototype Version + - [x] AI butler assistant driven by GPT-3.5 or GPT-4.0 + - [x] Integration of Stable Diffusion + - [x] Integration of TTS (Text-to-Speech) + - [x] Integration of Telegram Chatbot as an interaction entrance +- [ ] OpenDAN 1.0 + - [ ] AI butler assistant's large language model core switched to locally running open-source model + - [ ] Offer more AI applications through AI App Marketplace + - [ ] Provide an AI application development framework to support the community in integrating more AI applications + - [ ] Provide a model management framework + +## **Contributing** + +We welcome community members to contribute to the project, including but not limited to submitting issues, improving documentation, fixing bugs, or providing new features. You can participate in the contribution through the following ways: + +- Submit an Issue in the GitHub repository +- Submit a Pull Request to the repository +- Participate in discussions and development + +## **⭐Star History** + + +[![Star History Chart](https://api.star-history.com/svg?repos=fiatrete/OpenDAN-Personal-AI-Server-OS&type=Date)](https://star-history.com/#fiatrete/OpenDAN-Personal-AI-Server-OS&Date) + + +## **License** + +MIT diff --git a/agent_jarvis/.dockerignore b/PoC/agent_jarvis/.dockerignore similarity index 100% rename from agent_jarvis/.dockerignore rename to PoC/agent_jarvis/.dockerignore diff --git a/agent_jarvis/.env_template b/PoC/agent_jarvis/.env_template similarity index 100% rename from agent_jarvis/.env_template rename to PoC/agent_jarvis/.env_template diff --git a/agent_jarvis/.gitignore b/PoC/agent_jarvis/.gitignore similarity index 100% rename from agent_jarvis/.gitignore rename to PoC/agent_jarvis/.gitignore diff --git a/agent_jarvis/README.md b/PoC/agent_jarvis/README.md similarity index 100% rename from agent_jarvis/README.md rename to PoC/agent_jarvis/README.md diff --git a/agent_jarvis/TestPage/css/github.css b/PoC/agent_jarvis/TestPage/css/github.css similarity index 100% rename from agent_jarvis/TestPage/css/github.css rename to PoC/agent_jarvis/TestPage/css/github.css diff --git a/agent_jarvis/TestPage/css/main.css b/PoC/agent_jarvis/TestPage/css/main.css similarity index 100% rename from agent_jarvis/TestPage/css/main.css rename to PoC/agent_jarvis/TestPage/css/main.css diff --git a/agent_jarvis/TestPage/index.html b/PoC/agent_jarvis/TestPage/index.html similarity index 100% rename from agent_jarvis/TestPage/index.html rename to PoC/agent_jarvis/TestPage/index.html diff --git a/agent_jarvis/TestPage/js/main.js b/PoC/agent_jarvis/TestPage/js/main.js similarity index 100% rename from agent_jarvis/TestPage/js/main.js rename to PoC/agent_jarvis/TestPage/js/main.js diff --git a/agent_jarvis/TestPage/js/showdown.min.js b/PoC/agent_jarvis/TestPage/js/showdown.min.js similarity index 99% rename from agent_jarvis/TestPage/js/showdown.min.js rename to PoC/agent_jarvis/TestPage/js/showdown.min.js index 671f8ca..41dd8b4 100644 --- a/agent_jarvis/TestPage/js/showdown.min.js +++ b/PoC/agent_jarvis/TestPage/js/showdown.min.js @@ -1,3 +1,3 @@ /*! showdown v 2.0.0 - 10-03-2022 */ !function(){function t(e){"use strict";var a={omitExtraWLInCodeBlocks:{defaultValue:!1,describe:"Omit the default extra whiteline added to code blocks",type:"boolean"},noHeaderId:{defaultValue:!1,describe:"Turn on/off generated header id",type:"boolean"},prefixHeaderId:{defaultValue:!1,describe:"Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic 'section-' prefix",type:"string"},rawPrefixHeaderId:{defaultValue:!1,describe:'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',type:"boolean"},ghCompatibleHeaderId:{defaultValue:!1,describe:"Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)",type:"boolean"},rawHeaderId:{defaultValue:!1,describe:"Remove only spaces, ' and \" from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids",type:"boolean"},headerLevelStart:{defaultValue:!1,describe:"The header blocks level start",type:"integer"},parseImgDimensions:{defaultValue:!1,describe:"Turn on/off image dimension parsing",type:"boolean"},simplifiedAutoLink:{defaultValue:!1,describe:"Turn on/off GFM autolink style",type:"boolean"},literalMidWordUnderscores:{defaultValue:!1,describe:"Parse midword underscores as literal underscores",type:"boolean"},literalMidWordAsterisks:{defaultValue:!1,describe:"Parse midword asterisks as literal asterisks",type:"boolean"},strikethrough:{defaultValue:!1,describe:"Turn on/off strikethrough support",type:"boolean"},tables:{defaultValue:!1,describe:"Turn on/off tables support",type:"boolean"},tablesHeaderId:{defaultValue:!1,describe:"Add an id to table headers",type:"boolean"},ghCodeBlocks:{defaultValue:!0,describe:"Turn on/off GFM fenced code blocks support",type:"boolean"},tasklists:{defaultValue:!1,describe:"Turn on/off GFM tasklist support",type:"boolean"},smoothLivePreview:{defaultValue:!1,describe:"Prevents weird effects in live previews due to incomplete input",type:"boolean"},smartIndentationFix:{defaultValue:!1,describe:"Tries to smartly fix indentation in es6 strings",type:"boolean"},disableForced4SpacesIndentedSublists:{defaultValue:!1,describe:"Disables the requirement of indenting nested sublists by 4 spaces",type:"boolean"},simpleLineBreaks:{defaultValue:!1,describe:"Parses simple line breaks as
(GFM Style)",type:"boolean"},requireSpaceBeforeHeadingText:{defaultValue:!1,describe:"Makes adding a space between `#` and the header text mandatory (GFM Style)",type:"boolean"},ghMentions:{defaultValue:!1,describe:"Enables github @mentions",type:"boolean"},ghMentionsLink:{defaultValue:"https://github.com/{u}",describe:"Changes the link generated by @mentions. Only applies if ghMentions option is enabled.",type:"string"},encodeEmails:{defaultValue:!0,describe:"Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities",type:"boolean"},openLinksInNewWindow:{defaultValue:!1,describe:"Open all links in new windows",type:"boolean"},backslashEscapesHTMLTags:{defaultValue:!1,describe:"Support for HTML Tag escaping. ex:
foo
",type:"boolean"},emoji:{defaultValue:!1,describe:"Enable emoji support. Ex: `this is a :smile: emoji`",type:"boolean"},underline:{defaultValue:!1,describe:"Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``",type:"boolean"},ellipsis:{defaultValue:!0,describe:"Replaces three dots with the ellipsis unicode character",type:"boolean"},completeHTMLDocument:{defaultValue:!1,describe:"Outputs a complete html document, including ``, `` and `` tags",type:"boolean"},metadata:{defaultValue:!1,describe:"Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).",type:"boolean"},splitAdjacentBlockquotes:{defaultValue:!1,describe:"Split adjacent blockquote blocks",type:"boolean"},moreStyling:{defaultValue:!1,describe:"Adds some useful styling css classes in the generated html",type:"boolean"},relativePathBaseUrl:{defaultValue:!1,describe:"Prepends a base URL to relative paths",type:"string"}};if(!1===e)return JSON.parse(JSON.stringify(a));var r,t={};for(r in a)a.hasOwnProperty(r)&&(t[r]=a[r].defaultValue);return t}var e,P={},r={},h={},m=t(!0),d="vanilla",g={github:{omitExtraWLInCodeBlocks:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,disableForced4SpacesIndentedSublists:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghCompatibleHeaderId:!0,ghMentions:!0,backslashEscapesHTMLTags:!0,emoji:!0,splitAdjacentBlockquotes:!0},original:{noHeaderId:!0,ghCodeBlocks:!1},ghost:{omitExtraWLInCodeBlocks:!0,parseImgDimensions:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,smoothLivePreview:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghMentions:!1,encodeEmails:!0},vanilla:t(!0),allOn:function(){"use strict";var e,a=t(!0),r={};for(e in a)a.hasOwnProperty(e)&&(r[e]=!0);return r}()};function p(e,a){"use strict";var r=a?"Error in "+a+" extension->":"Error in unnamed extension",t={valid:!0,error:""};P.helper.isArray(e)||(e=[e]);for(var n=0;n"+(s=P.subParser("makehtml.hashHTMLSpans")(s,a,r))+"";return P.subParser("makehtml.hashHTMLSpans")(t,a,r)}P.helper.matchRecursiveRegExp=function(e,a,r,t){"use strict";for(var n=u(e,a,r,t),s=[],i=0;i=1<<28)throw new RangeError("repeat count must not overflow maximum string size");var r=e.length*a;for(a=Math.floor(Math.log(a)/Math.log(2));a;)e+=e,a--;return e+=e.substring(0,r-e.length)},P.helper.padEnd=function(e,a,r){"use strict";return a>>=0,r=String(r||" "),e.length>a?String(e):((a-=e.length)>r.length&&(r+=P.helper.repeat(r,a/r.length)),String(e)+r.slice(0,a))},P.helper.unescapeHTMLEntities=function(e){"use strict";return e.replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")},P.helper._hashHTMLSpan=function(e,a){return"¨C"+(a.gHtmlSpans.push(e)-1)+"C"},P.helper.applyBaseUrl=function(e,a){return a=e&&!this.isAbsolutePath(a)?(0,require("url").resolve)(e,a):a},P.helper.isAbsolutePath=function(e){return/(^([a-z]+:)?\/\/)|(^#)/i.test(e)},P.helper.Event=function(e,a,r){"use strict";var t=r.regexp||null,n=r.matches||{},s=r.options||{},i=r.converter||null,o=r.globals||{};this.getName=function(){return e},this.getEventName=function(){return e},this._stopExecution=!1,this.parsedText=r.parsedText||null,this.getRegexp=function(){return t},this.getOptions=function(){return s},this.getConverter=function(){return i},this.getGlobals=function(){return o},this.getCapturedText=function(){return a},this.getText=function(){return a},this.setText=function(e){a=e},this.getMatches=function(){return n},this.setMatches=function(e){n=e},this.preventDefault=function(e){this._stopExecution=!e}},"undefined"==typeof console&&(console={warn:function(e){"use strict";alert(e)},log:function(e){"use strict";alert(e)},error:function(e){"use strict";throw e}}),P.helper.regexes={asteriskDashTildeAndColon:/([*_:~])/g,asteriskDashAndTilde:/([*_~])/g},P.helper.emojis={100:"💯",1234:"🔢","+1":"👍","-1":"👎","1st_place_medal":"🥇","2nd_place_medal":"🥈","3rd_place_medal":"🥉","8ball":"🎱",a:"🅰️",ab:"🆎",abacus:"🧮",abc:"🔤",abcd:"🔡",accept:"🉑",adhesive_bandage:"🩹",adult:"🧑",aerial_tramway:"🚡",afghanistan:"🇦🇫",airplane:"✈️",aland_islands:"🇦🇽",alarm_clock:"⏰",albania:"🇦🇱",alembic:"⚗️",algeria:"🇩🇿",alien:"👽",ambulance:"🚑",american_samoa:"🇦🇸",amphora:"🏺",anchor:"⚓",andorra:"🇦🇩",angel:"👼",anger:"💢",angola:"🇦🇴",angry:"😠",anguilla:"🇦🇮",anguished:"😧",ant:"🐜",antarctica:"🇦🇶",antigua_barbuda:"🇦🇬",apple:"🍎",aquarius:"♒",argentina:"🇦🇷",aries:"♈",armenia:"🇦🇲",arrow_backward:"◀️",arrow_double_down:"⏬",arrow_double_up:"⏫",arrow_down:"⬇️",arrow_down_small:"🔽",arrow_forward:"▶️",arrow_heading_down:"⤵️",arrow_heading_up:"⤴️",arrow_left:"⬅️",arrow_lower_left:"↙️",arrow_lower_right:"↘️",arrow_right:"➡️",arrow_right_hook:"↪️",arrow_up:"⬆️",arrow_up_down:"↕️",arrow_up_small:"🔼",arrow_upper_left:"↖️",arrow_upper_right:"↗️",arrows_clockwise:"🔃",arrows_counterclockwise:"🔄",art:"🎨",articulated_lorry:"🚛",artificial_satellite:"🛰️",artist:"🧑‍🎨",aruba:"🇦🇼",ascension_island:"🇦🇨",asterisk:"*️⃣",astonished:"😲",astronaut:"🧑‍🚀",athletic_shoe:"👟",atm:"🏧",atom_symbol:"⚛️",australia:"🇦🇺",austria:"🇦🇹",auto_rickshaw:"🛺",avocado:"🥑",axe:"🪓",azerbaijan:"🇦🇿",b:"🅱️",baby:"👶",baby_bottle:"🍼",baby_chick:"🐤",baby_symbol:"🚼",back:"🔙",bacon:"🥓",badger:"🦡",badminton:"🏸",bagel:"🥯",baggage_claim:"🛄",baguette_bread:"🥖",bahamas:"🇧🇸",bahrain:"🇧🇭",balance_scale:"⚖️",bald_man:"👨‍🦲",bald_woman:"👩‍🦲",ballet_shoes:"🩰",balloon:"🎈",ballot_box:"🗳️",ballot_box_with_check:"☑️",bamboo:"🎍",banana:"🍌",bangbang:"‼️",bangladesh:"🇧🇩",banjo:"🪕",bank:"🏦",bar_chart:"📊",barbados:"🇧🇧",barber:"💈",baseball:"⚾",basket:"🧺",basketball:"🏀",basketball_man:"⛹️‍♂️",basketball_woman:"⛹️‍♀️",bat:"🦇",bath:"🛀",bathtub:"🛁",battery:"🔋",beach_umbrella:"🏖️",bear:"🐻",bearded_person:"🧔",bed:"🛏️",bee:"🐝",beer:"🍺",beers:"🍻",beetle:"🐞",beginner:"🔰",belarus:"🇧🇾",belgium:"🇧🇪",belize:"🇧🇿",bell:"🔔",bellhop_bell:"🛎️",benin:"🇧🇯",bento:"🍱",bermuda:"🇧🇲",beverage_box:"🧃",bhutan:"🇧🇹",bicyclist:"🚴",bike:"🚲",biking_man:"🚴‍♂️",biking_woman:"🚴‍♀️",bikini:"👙",billed_cap:"🧢",biohazard:"☣️",bird:"🐦",birthday:"🎂",black_circle:"⚫",black_flag:"🏴",black_heart:"🖤",black_joker:"🃏",black_large_square:"⬛",black_medium_small_square:"◾",black_medium_square:"◼️",black_nib:"✒️",black_small_square:"▪️",black_square_button:"🔲",blond_haired_man:"👱‍♂️",blond_haired_person:"👱",blond_haired_woman:"👱‍♀️",blonde_woman:"👱‍♀️",blossom:"🌼",blowfish:"🐡",blue_book:"📘",blue_car:"🚙",blue_heart:"💙",blue_square:"🟦",blush:"😊",boar:"🐗",boat:"⛵",bolivia:"🇧🇴",bomb:"💣",bone:"🦴",book:"📖",bookmark:"🔖",bookmark_tabs:"📑",books:"📚",boom:"💥",boot:"👢",bosnia_herzegovina:"🇧🇦",botswana:"🇧🇼",bouncing_ball_man:"⛹️‍♂️",bouncing_ball_person:"⛹️",bouncing_ball_woman:"⛹️‍♀️",bouquet:"💐",bouvet_island:"🇧🇻",bow:"🙇",bow_and_arrow:"🏹",bowing_man:"🙇‍♂️",bowing_woman:"🙇‍♀️",bowl_with_spoon:"🥣",bowling:"🎳",boxing_glove:"🥊",boy:"👦",brain:"🧠",brazil:"🇧🇷",bread:"🍞",breast_feeding:"🤱",bricks:"🧱",bride_with_veil:"👰",bridge_at_night:"🌉",briefcase:"💼",british_indian_ocean_territory:"🇮🇴",british_virgin_islands:"🇻🇬",broccoli:"🥦",broken_heart:"💔",broom:"🧹",brown_circle:"🟤",brown_heart:"🤎",brown_square:"🟫",brunei:"🇧🇳",bug:"🐛",building_construction:"🏗️",bulb:"💡",bulgaria:"🇧🇬",bullettrain_front:"🚅",bullettrain_side:"🚄",burkina_faso:"🇧🇫",burrito:"🌯",burundi:"🇧🇮",bus:"🚌",business_suit_levitating:"🕴️",busstop:"🚏",bust_in_silhouette:"👤",busts_in_silhouette:"👥",butter:"🧈",butterfly:"🦋",cactus:"🌵",cake:"🍰",calendar:"📆",call_me_hand:"🤙",calling:"📲",cambodia:"🇰🇭",camel:"🐫",camera:"📷",camera_flash:"📸",cameroon:"🇨🇲",camping:"🏕️",canada:"🇨🇦",canary_islands:"🇮🇨",cancer:"♋",candle:"🕯️",candy:"🍬",canned_food:"🥫",canoe:"🛶",cape_verde:"🇨🇻",capital_abcd:"🔠",capricorn:"♑",car:"🚗",card_file_box:"🗃️",card_index:"📇",card_index_dividers:"🗂️",caribbean_netherlands:"🇧🇶",carousel_horse:"🎠",carrot:"🥕",cartwheeling:"🤸",cat:"🐱",cat2:"🐈",cayman_islands:"🇰🇾",cd:"💿",central_african_republic:"🇨🇫",ceuta_melilla:"🇪🇦",chad:"🇹🇩",chains:"⛓️",chair:"🪑",champagne:"🍾",chart:"💹",chart_with_downwards_trend:"📉",chart_with_upwards_trend:"📈",checkered_flag:"🏁",cheese:"🧀",cherries:"🍒",cherry_blossom:"🌸",chess_pawn:"♟️",chestnut:"🌰",chicken:"🐔",child:"🧒",children_crossing:"🚸",chile:"🇨🇱",chipmunk:"🐿️",chocolate_bar:"🍫",chopsticks:"🥢",christmas_island:"🇨🇽",christmas_tree:"🎄",church:"⛪",cinema:"🎦",circus_tent:"🎪",city_sunrise:"🌇",city_sunset:"🌆",cityscape:"🏙️",cl:"🆑",clamp:"🗜️",clap:"👏",clapper:"🎬",classical_building:"🏛️",climbing:"🧗",climbing_man:"🧗‍♂️",climbing_woman:"🧗‍♀️",clinking_glasses:"🥂",clipboard:"📋",clipperton_island:"🇨🇵",clock1:"🕐",clock10:"🕙",clock1030:"🕥",clock11:"🕚",clock1130:"🕦",clock12:"🕛",clock1230:"🕧",clock130:"🕜",clock2:"🕑",clock230:"🕝",clock3:"🕒",clock330:"🕞",clock4:"🕓",clock430:"🕟",clock5:"🕔",clock530:"🕠",clock6:"🕕",clock630:"🕡",clock7:"🕖",clock730:"🕢",clock8:"🕗",clock830:"🕣",clock9:"🕘",clock930:"🕤",closed_book:"📕",closed_lock_with_key:"🔐",closed_umbrella:"🌂",cloud:"☁️",cloud_with_lightning:"🌩️",cloud_with_lightning_and_rain:"⛈️",cloud_with_rain:"🌧️",cloud_with_snow:"🌨️",clown_face:"🤡",clubs:"♣️",cn:"🇨🇳",coat:"🧥",cocktail:"🍸",coconut:"🥥",cocos_islands:"🇨🇨",coffee:"☕",coffin:"⚰️",cold_face:"🥶",cold_sweat:"😰",collision:"💥",colombia:"🇨🇴",comet:"☄️",comoros:"🇰🇲",compass:"🧭",computer:"💻",computer_mouse:"🖱️",confetti_ball:"🎊",confounded:"😖",confused:"😕",congo_brazzaville:"🇨🇬",congo_kinshasa:"🇨🇩",congratulations:"㊗️",construction:"🚧",construction_worker:"👷",construction_worker_man:"👷‍♂️",construction_worker_woman:"👷‍♀️",control_knobs:"🎛️",convenience_store:"🏪",cook:"🧑‍🍳",cook_islands:"🇨🇰",cookie:"🍪",cool:"🆒",cop:"👮",copyright:"©️",corn:"🌽",costa_rica:"🇨🇷",cote_divoire:"🇨🇮",couch_and_lamp:"🛋️",couple:"👫",couple_with_heart:"💑",couple_with_heart_man_man:"👨‍❤️‍👨",couple_with_heart_woman_man:"👩‍❤️‍👨",couple_with_heart_woman_woman:"👩‍❤️‍👩",couplekiss:"💏",couplekiss_man_man:"👨‍❤️‍💋‍👨",couplekiss_man_woman:"👩‍❤️‍💋‍👨",couplekiss_woman_woman:"👩‍❤️‍💋‍👩",cow:"🐮",cow2:"🐄",cowboy_hat_face:"🤠",crab:"🦀",crayon:"🖍️",credit_card:"💳",crescent_moon:"🌙",cricket:"🦗",cricket_game:"🏏",croatia:"🇭🇷",crocodile:"🐊",croissant:"🥐",crossed_fingers:"🤞",crossed_flags:"🎌",crossed_swords:"⚔️",crown:"👑",cry:"😢",crying_cat_face:"😿",crystal_ball:"🔮",cuba:"🇨🇺",cucumber:"🥒",cup_with_straw:"🥤",cupcake:"🧁",cupid:"💘",curacao:"🇨🇼",curling_stone:"🥌",curly_haired_man:"👨‍🦱",curly_haired_woman:"👩‍🦱",curly_loop:"➰",currency_exchange:"💱",curry:"🍛",cursing_face:"🤬",custard:"🍮",customs:"🛃",cut_of_meat:"🥩",cyclone:"🌀",cyprus:"🇨🇾",czech_republic:"🇨🇿",dagger:"🗡️",dancer:"💃",dancers:"👯",dancing_men:"👯‍♂️",dancing_women:"👯‍♀️",dango:"🍡",dark_sunglasses:"🕶️",dart:"🎯",dash:"💨",date:"📅",de:"🇩🇪",deaf_man:"🧏‍♂️",deaf_person:"🧏",deaf_woman:"🧏‍♀️",deciduous_tree:"🌳",deer:"🦌",denmark:"🇩🇰",department_store:"🏬",derelict_house:"🏚️",desert:"🏜️",desert_island:"🏝️",desktop_computer:"🖥️",detective:"🕵️",diamond_shape_with_a_dot_inside:"💠",diamonds:"♦️",diego_garcia:"🇩🇬",disappointed:"😞",disappointed_relieved:"😥",diving_mask:"🤿",diya_lamp:"🪔",dizzy:"💫",dizzy_face:"😵",djibouti:"🇩🇯",dna:"🧬",do_not_litter:"🚯",dog:"🐶",dog2:"🐕",dollar:"💵",dolls:"🎎",dolphin:"🐬",dominica:"🇩🇲",dominican_republic:"🇩🇴",door:"🚪",doughnut:"🍩",dove:"🕊️",dragon:"🐉",dragon_face:"🐲",dress:"👗",dromedary_camel:"🐪",drooling_face:"🤤",drop_of_blood:"🩸",droplet:"💧",drum:"🥁",duck:"🦆",dumpling:"🥟",dvd:"📀","e-mail":"📧",eagle:"🦅",ear:"👂",ear_of_rice:"🌾",ear_with_hearing_aid:"🦻",earth_africa:"🌍",earth_americas:"🌎",earth_asia:"🌏",ecuador:"🇪🇨",egg:"🥚",eggplant:"🍆",egypt:"🇪🇬",eight:"8️⃣",eight_pointed_black_star:"✴️",eight_spoked_asterisk:"✳️",eject_button:"⏏️",el_salvador:"🇸🇻",electric_plug:"🔌",elephant:"🐘",elf:"🧝",elf_man:"🧝‍♂️",elf_woman:"🧝‍♀️",email:"✉️",end:"🔚",england:"🏴󠁧󠁢󠁥󠁮󠁧󠁿",envelope:"✉️",envelope_with_arrow:"📩",equatorial_guinea:"🇬🇶",eritrea:"🇪🇷",es:"🇪🇸",estonia:"🇪🇪",ethiopia:"🇪🇹",eu:"🇪🇺",euro:"💶",european_castle:"🏰",european_post_office:"🏤",european_union:"🇪🇺",evergreen_tree:"🌲",exclamation:"❗",exploding_head:"🤯",expressionless:"😑",eye:"👁️",eye_speech_bubble:"👁️‍🗨️",eyeglasses:"👓",eyes:"👀",face_with_head_bandage:"🤕",face_with_thermometer:"🤒",facepalm:"🤦",facepunch:"👊",factory:"🏭",factory_worker:"🧑‍🏭",fairy:"🧚",fairy_man:"🧚‍♂️",fairy_woman:"🧚‍♀️",falafel:"🧆",falkland_islands:"🇫🇰",fallen_leaf:"🍂",family:"👪",family_man_boy:"👨‍👦",family_man_boy_boy:"👨‍👦‍👦",family_man_girl:"👨‍👧",family_man_girl_boy:"👨‍👧‍👦",family_man_girl_girl:"👨‍👧‍👧",family_man_man_boy:"👨‍👨‍👦",family_man_man_boy_boy:"👨‍👨‍👦‍👦",family_man_man_girl:"👨‍👨‍👧",family_man_man_girl_boy:"👨‍👨‍👧‍👦",family_man_man_girl_girl:"👨‍👨‍👧‍👧",family_man_woman_boy:"👨‍👩‍👦",family_man_woman_boy_boy:"👨‍👩‍👦‍👦",family_man_woman_girl:"👨‍👩‍👧",family_man_woman_girl_boy:"👨‍👩‍👧‍👦",family_man_woman_girl_girl:"👨‍👩‍👧‍👧",family_woman_boy:"👩‍👦",family_woman_boy_boy:"👩‍👦‍👦",family_woman_girl:"👩‍👧",family_woman_girl_boy:"👩‍👧‍👦",family_woman_girl_girl:"👩‍👧‍👧",family_woman_woman_boy:"👩‍👩‍👦",family_woman_woman_boy_boy:"👩‍👩‍👦‍👦",family_woman_woman_girl:"👩‍👩‍👧",family_woman_woman_girl_boy:"👩‍👩‍👧‍👦",family_woman_woman_girl_girl:"👩‍👩‍👧‍👧",farmer:"🧑‍🌾",faroe_islands:"🇫🇴",fast_forward:"⏩",fax:"📠",fearful:"😨",feet:"🐾",female_detective:"🕵️‍♀️",female_sign:"♀️",ferris_wheel:"🎡",ferry:"⛴️",field_hockey:"🏑",fiji:"🇫🇯",file_cabinet:"🗄️",file_folder:"📁",film_projector:"📽️",film_strip:"🎞️",finland:"🇫🇮",fire:"🔥",fire_engine:"🚒",fire_extinguisher:"🧯",firecracker:"🧨",firefighter:"🧑‍🚒",fireworks:"🎆",first_quarter_moon:"🌓",first_quarter_moon_with_face:"🌛",fish:"🐟",fish_cake:"🍥",fishing_pole_and_fish:"🎣",fist:"✊",fist_left:"🤛",fist_oncoming:"👊",fist_raised:"✊",fist_right:"🤜",five:"5️⃣",flags:"🎏",flamingo:"🦩",flashlight:"🔦",flat_shoe:"🥿",fleur_de_lis:"⚜️",flight_arrival:"🛬",flight_departure:"🛫",flipper:"🐬",floppy_disk:"💾",flower_playing_cards:"🎴",flushed:"😳",flying_disc:"🥏",flying_saucer:"🛸",fog:"🌫️",foggy:"🌁",foot:"🦶",football:"🏈",footprints:"👣",fork_and_knife:"🍴",fortune_cookie:"🥠",fountain:"⛲",fountain_pen:"🖋️",four:"4️⃣",four_leaf_clover:"🍀",fox_face:"🦊",fr:"🇫🇷",framed_picture:"🖼️",free:"🆓",french_guiana:"🇬🇫",french_polynesia:"🇵🇫",french_southern_territories:"🇹🇫",fried_egg:"🍳",fried_shrimp:"🍤",fries:"🍟",frog:"🐸",frowning:"😦",frowning_face:"☹️",frowning_man:"🙍‍♂️",frowning_person:"🙍",frowning_woman:"🙍‍♀️",fu:"🖕",fuelpump:"⛽",full_moon:"🌕",full_moon_with_face:"🌝",funeral_urn:"⚱️",gabon:"🇬🇦",gambia:"🇬🇲",game_die:"🎲",garlic:"🧄",gb:"🇬🇧",gear:"⚙️",gem:"💎",gemini:"♊",genie:"🧞",genie_man:"🧞‍♂️",genie_woman:"🧞‍♀️",georgia:"🇬🇪",ghana:"🇬🇭",ghost:"👻",gibraltar:"🇬🇮",gift:"🎁",gift_heart:"💝",giraffe:"🦒",girl:"👧",globe_with_meridians:"🌐",gloves:"🧤",goal_net:"🥅",goat:"🐐",goggles:"🥽",golf:"⛳",golfing:"🏌️",golfing_man:"🏌️‍♂️",golfing_woman:"🏌️‍♀️",gorilla:"🦍",grapes:"🍇",greece:"🇬🇷",green_apple:"🍏",green_book:"📗",green_circle:"🟢",green_heart:"💚",green_salad:"🥗",green_square:"🟩",greenland:"🇬🇱",grenada:"🇬🇩",grey_exclamation:"❕",grey_question:"❔",grimacing:"😬",grin:"😁",grinning:"😀",guadeloupe:"🇬🇵",guam:"🇬🇺",guard:"💂",guardsman:"💂‍♂️",guardswoman:"💂‍♀️",guatemala:"🇬🇹",guernsey:"🇬🇬",guide_dog:"🦮",guinea:"🇬🇳",guinea_bissau:"🇬🇼",guitar:"🎸",gun:"🔫",guyana:"🇬🇾",haircut:"💇",haircut_man:"💇‍♂️",haircut_woman:"💇‍♀️",haiti:"🇭🇹",hamburger:"🍔",hammer:"🔨",hammer_and_pick:"⚒️",hammer_and_wrench:"🛠️",hamster:"🐹",hand:"✋",hand_over_mouth:"🤭",handbag:"👜",handball_person:"🤾",handshake:"🤝",hankey:"💩",hash:"#️⃣",hatched_chick:"🐥",hatching_chick:"🐣",headphones:"🎧",health_worker:"🧑‍⚕️",hear_no_evil:"🙉",heard_mcdonald_islands:"🇭🇲",heart:"❤️",heart_decoration:"💟",heart_eyes:"😍",heart_eyes_cat:"😻",heartbeat:"💓",heartpulse:"💗",hearts:"♥️",heavy_check_mark:"✔️",heavy_division_sign:"➗",heavy_dollar_sign:"💲",heavy_exclamation_mark:"❗",heavy_heart_exclamation:"❣️",heavy_minus_sign:"➖",heavy_multiplication_x:"✖️",heavy_plus_sign:"➕",hedgehog:"🦔",helicopter:"🚁",herb:"🌿",hibiscus:"🌺",high_brightness:"🔆",high_heel:"👠",hiking_boot:"🥾",hindu_temple:"🛕",hippopotamus:"🦛",hocho:"🔪",hole:"🕳️",honduras:"🇭🇳",honey_pot:"🍯",honeybee:"🐝",hong_kong:"🇭🇰",horse:"🐴",horse_racing:"🏇",hospital:"🏥",hot_face:"🥵",hot_pepper:"🌶️",hotdog:"🌭",hotel:"🏨",hotsprings:"♨️",hourglass:"⌛",hourglass_flowing_sand:"⏳",house:"🏠",house_with_garden:"🏡",houses:"🏘️",hugs:"🤗",hungary:"🇭🇺",hushed:"😯",ice_cream:"🍨",ice_cube:"🧊",ice_hockey:"🏒",ice_skate:"⛸️",icecream:"🍦",iceland:"🇮🇸",id:"🆔",ideograph_advantage:"🉐",imp:"👿",inbox_tray:"📥",incoming_envelope:"📨",india:"🇮🇳",indonesia:"🇮🇩",infinity:"♾️",information_desk_person:"💁",information_source:"ℹ️",innocent:"😇",interrobang:"⁉️",iphone:"📱",iran:"🇮🇷",iraq:"🇮🇶",ireland:"🇮🇪",isle_of_man:"🇮🇲",israel:"🇮🇱",it:"🇮🇹",izakaya_lantern:"🏮",jack_o_lantern:"🎃",jamaica:"🇯🇲",japan:"🗾",japanese_castle:"🏯",japanese_goblin:"👺",japanese_ogre:"👹",jeans:"👖",jersey:"🇯🇪",jigsaw:"🧩",jordan:"🇯🇴",joy:"😂",joy_cat:"😹",joystick:"🕹️",jp:"🇯🇵",judge:"🧑‍⚖️",juggling_person:"🤹",kaaba:"🕋",kangaroo:"🦘",kazakhstan:"🇰🇿",kenya:"🇰🇪",key:"🔑",keyboard:"⌨️",keycap_ten:"🔟",kick_scooter:"🛴",kimono:"👘",kiribati:"🇰🇮",kiss:"💋",kissing:"😗",kissing_cat:"😽",kissing_closed_eyes:"😚",kissing_heart:"😘",kissing_smiling_eyes:"😙",kite:"🪁",kiwi_fruit:"🥝",kneeling_man:"🧎‍♂️",kneeling_person:"🧎",kneeling_woman:"🧎‍♀️",knife:"🔪",koala:"🐨",koko:"🈁",kosovo:"🇽🇰",kr:"🇰🇷",kuwait:"🇰🇼",kyrgyzstan:"🇰🇬",lab_coat:"🥼",label:"🏷️",lacrosse:"🥍",lantern:"🏮",laos:"🇱🇦",large_blue_circle:"🔵",large_blue_diamond:"🔷",large_orange_diamond:"🔶",last_quarter_moon:"🌗",last_quarter_moon_with_face:"🌜",latin_cross:"✝️",latvia:"🇱🇻",laughing:"😆",leafy_green:"🥬",leaves:"🍃",lebanon:"🇱🇧",ledger:"📒",left_luggage:"🛅",left_right_arrow:"↔️",left_speech_bubble:"🗨️",leftwards_arrow_with_hook:"↩️",leg:"🦵",lemon:"🍋",leo:"♌",leopard:"🐆",lesotho:"🇱🇸",level_slider:"🎚️",liberia:"🇱🇷",libra:"♎",libya:"🇱🇾",liechtenstein:"🇱🇮",light_rail:"🚈",link:"🔗",lion:"🦁",lips:"👄",lipstick:"💄",lithuania:"🇱🇹",lizard:"🦎",llama:"🦙",lobster:"🦞",lock:"🔒",lock_with_ink_pen:"🔏",lollipop:"🍭",loop:"➿",lotion_bottle:"🧴",lotus_position:"🧘",lotus_position_man:"🧘‍♂️",lotus_position_woman:"🧘‍♀️",loud_sound:"🔊",loudspeaker:"📢",love_hotel:"🏩",love_letter:"💌",love_you_gesture:"🤟",low_brightness:"🔅",luggage:"🧳",luxembourg:"🇱🇺",lying_face:"🤥",m:"Ⓜ️",macau:"🇲🇴",macedonia:"🇲🇰",madagascar:"🇲🇬",mag:"🔍",mag_right:"🔎",mage:"🧙",mage_man:"🧙‍♂️",mage_woman:"🧙‍♀️",magnet:"🧲",mahjong:"🀄",mailbox:"📫",mailbox_closed:"📪",mailbox_with_mail:"📬",mailbox_with_no_mail:"📭",malawi:"🇲🇼",malaysia:"🇲🇾",maldives:"🇲🇻",male_detective:"🕵️‍♂️",male_sign:"♂️",mali:"🇲🇱",malta:"🇲🇹",man:"👨",man_artist:"👨‍🎨",man_astronaut:"👨‍🚀",man_cartwheeling:"🤸‍♂️",man_cook:"👨‍🍳",man_dancing:"🕺",man_facepalming:"🤦‍♂️",man_factory_worker:"👨‍🏭",man_farmer:"👨‍🌾",man_firefighter:"👨‍🚒",man_health_worker:"👨‍⚕️",man_in_manual_wheelchair:"👨‍🦽",man_in_motorized_wheelchair:"👨‍🦼",man_in_tuxedo:"🤵",man_judge:"👨‍⚖️",man_juggling:"🤹‍♂️",man_mechanic:"👨‍🔧",man_office_worker:"👨‍💼",man_pilot:"👨‍✈️",man_playing_handball:"🤾‍♂️",man_playing_water_polo:"🤽‍♂️",man_scientist:"👨‍🔬",man_shrugging:"🤷‍♂️",man_singer:"👨‍🎤",man_student:"👨‍🎓",man_teacher:"👨‍🏫",man_technologist:"👨‍💻",man_with_gua_pi_mao:"👲",man_with_probing_cane:"👨‍🦯",man_with_turban:"👳‍♂️",mandarin:"🍊",mango:"🥭",mans_shoe:"👞",mantelpiece_clock:"🕰️",manual_wheelchair:"🦽",maple_leaf:"🍁",marshall_islands:"🇲🇭",martial_arts_uniform:"🥋",martinique:"🇲🇶",mask:"😷",massage:"💆",massage_man:"💆‍♂️",massage_woman:"💆‍♀️",mate:"🧉",mauritania:"🇲🇷",mauritius:"🇲🇺",mayotte:"🇾🇹",meat_on_bone:"🍖",mechanic:"🧑‍🔧",mechanical_arm:"🦾",mechanical_leg:"🦿",medal_military:"🎖️",medal_sports:"🏅",medical_symbol:"⚕️",mega:"📣",melon:"🍈",memo:"📝",men_wrestling:"🤼‍♂️",menorah:"🕎",mens:"🚹",mermaid:"🧜‍♀️",merman:"🧜‍♂️",merperson:"🧜",metal:"🤘",metro:"🚇",mexico:"🇲🇽",microbe:"🦠",micronesia:"🇫🇲",microphone:"🎤",microscope:"🔬",middle_finger:"🖕",milk_glass:"🥛",milky_way:"🌌",minibus:"🚐",minidisc:"💽",mobile_phone_off:"📴",moldova:"🇲🇩",monaco:"🇲🇨",money_mouth_face:"🤑",money_with_wings:"💸",moneybag:"💰",mongolia:"🇲🇳",monkey:"🐒",monkey_face:"🐵",monocle_face:"🧐",monorail:"🚝",montenegro:"🇲🇪",montserrat:"🇲🇸",moon:"🌔",moon_cake:"🥮",morocco:"🇲🇦",mortar_board:"🎓",mosque:"🕌",mosquito:"🦟",motor_boat:"🛥️",motor_scooter:"🛵",motorcycle:"🏍️",motorized_wheelchair:"🦼",motorway:"🛣️",mount_fuji:"🗻",mountain:"⛰️",mountain_bicyclist:"🚵",mountain_biking_man:"🚵‍♂️",mountain_biking_woman:"🚵‍♀️",mountain_cableway:"🚠",mountain_railway:"🚞",mountain_snow:"🏔️",mouse:"🐭",mouse2:"🐁",movie_camera:"🎥",moyai:"🗿",mozambique:"🇲🇿",mrs_claus:"🤶",muscle:"💪",mushroom:"🍄",musical_keyboard:"🎹",musical_note:"🎵",musical_score:"🎼",mute:"🔇",myanmar:"🇲🇲",nail_care:"💅",name_badge:"📛",namibia:"🇳🇦",national_park:"🏞️",nauru:"🇳🇷",nauseated_face:"🤢",nazar_amulet:"🧿",necktie:"👔",negative_squared_cross_mark:"❎",nepal:"🇳🇵",nerd_face:"🤓",netherlands:"🇳🇱",neutral_face:"😐",new:"🆕",new_caledonia:"🇳🇨",new_moon:"🌑",new_moon_with_face:"🌚",new_zealand:"🇳🇿",newspaper:"📰",newspaper_roll:"🗞️",next_track_button:"⏭️",ng:"🆖",ng_man:"🙅‍♂️",ng_woman:"🙅‍♀️",nicaragua:"🇳🇮",niger:"🇳🇪",nigeria:"🇳🇬",night_with_stars:"🌃",nine:"9️⃣",niue:"🇳🇺",no_bell:"🔕",no_bicycles:"🚳",no_entry:"⛔",no_entry_sign:"🚫",no_good:"🙅",no_good_man:"🙅‍♂️",no_good_woman:"🙅‍♀️",no_mobile_phones:"📵",no_mouth:"😶",no_pedestrians:"🚷",no_smoking:"🚭","non-potable_water":"🚱",norfolk_island:"🇳🇫",north_korea:"🇰🇵",northern_mariana_islands:"🇲🇵",norway:"🇳🇴",nose:"👃",notebook:"📓",notebook_with_decorative_cover:"📔",notes:"🎶",nut_and_bolt:"🔩",o:"⭕",o2:"🅾️",ocean:"🌊",octopus:"🐙",oden:"🍢",office:"🏢",office_worker:"🧑‍💼",oil_drum:"🛢️",ok:"🆗",ok_hand:"👌",ok_man:"🙆‍♂️",ok_person:"🙆",ok_woman:"🙆‍♀️",old_key:"🗝️",older_adult:"🧓",older_man:"👴",older_woman:"👵",om:"🕉️",oman:"🇴🇲",on:"🔛",oncoming_automobile:"🚘",oncoming_bus:"🚍",oncoming_police_car:"🚔",oncoming_taxi:"🚖",one:"1️⃣",one_piece_swimsuit:"🩱",onion:"🧅",open_book:"📖",open_file_folder:"📂",open_hands:"👐",open_mouth:"😮",open_umbrella:"☂️",ophiuchus:"⛎",orange:"🍊",orange_book:"📙",orange_circle:"🟠",orange_heart:"🧡",orange_square:"🟧",orangutan:"🦧",orthodox_cross:"☦️",otter:"🦦",outbox_tray:"📤",owl:"🦉",ox:"🐂",oyster:"🦪",package:"📦",page_facing_up:"📄",page_with_curl:"📃",pager:"📟",paintbrush:"🖌️",pakistan:"🇵🇰",palau:"🇵🇼",palestinian_territories:"🇵🇸",palm_tree:"🌴",palms_up_together:"🤲",panama:"🇵🇦",pancakes:"🥞",panda_face:"🐼",paperclip:"📎",paperclips:"🖇️",papua_new_guinea:"🇵🇬",parachute:"🪂",paraguay:"🇵🇾",parasol_on_ground:"⛱️",parking:"🅿️",parrot:"🦜",part_alternation_mark:"〽️",partly_sunny:"⛅",partying_face:"🥳",passenger_ship:"🛳️",passport_control:"🛂",pause_button:"⏸️",paw_prints:"🐾",peace_symbol:"☮️",peach:"🍑",peacock:"🦚",peanuts:"🥜",pear:"🍐",pen:"🖊️",pencil:"📝",pencil2:"✏️",penguin:"🐧",pensive:"😔",people_holding_hands:"🧑‍🤝‍🧑",performing_arts:"🎭",persevere:"😣",person_bald:"🧑‍🦲",person_curly_hair:"🧑‍🦱",person_fencing:"🤺",person_in_manual_wheelchair:"🧑‍🦽",person_in_motorized_wheelchair:"🧑‍🦼",person_red_hair:"🧑‍🦰",person_white_hair:"🧑‍🦳",person_with_probing_cane:"🧑‍🦯",person_with_turban:"👳",peru:"🇵🇪",petri_dish:"🧫",philippines:"🇵🇭",phone:"☎️",pick:"⛏️",pie:"🥧",pig:"🐷",pig2:"🐖",pig_nose:"🐽",pill:"💊",pilot:"🧑‍✈️",pinching_hand:"🤏",pineapple:"🍍",ping_pong:"🏓",pirate_flag:"🏴‍☠️",pisces:"♓",pitcairn_islands:"🇵🇳",pizza:"🍕",place_of_worship:"🛐",plate_with_cutlery:"🍽️",play_or_pause_button:"⏯️",pleading_face:"🥺",point_down:"👇",point_left:"👈",point_right:"👉",point_up:"☝️",point_up_2:"👆",poland:"🇵🇱",police_car:"🚓",police_officer:"👮",policeman:"👮‍♂️",policewoman:"👮‍♀️",poodle:"🐩",poop:"💩",popcorn:"🍿",portugal:"🇵🇹",post_office:"🏣",postal_horn:"📯",postbox:"📮",potable_water:"🚰",potato:"🥔",pouch:"👝",poultry_leg:"🍗",pound:"💷",pout:"😡",pouting_cat:"😾",pouting_face:"🙎",pouting_man:"🙎‍♂️",pouting_woman:"🙎‍♀️",pray:"🙏",prayer_beads:"📿",pregnant_woman:"🤰",pretzel:"🥨",previous_track_button:"⏮️",prince:"🤴",princess:"👸",printer:"🖨️",probing_cane:"🦯",puerto_rico:"🇵🇷",punch:"👊",purple_circle:"🟣",purple_heart:"💜",purple_square:"🟪",purse:"👛",pushpin:"📌",put_litter_in_its_place:"🚮",qatar:"🇶🇦",question:"❓",rabbit:"🐰",rabbit2:"🐇",raccoon:"🦝",racehorse:"🐎",racing_car:"🏎️",radio:"📻",radio_button:"🔘",radioactive:"☢️",rage:"😡",railway_car:"🚃",railway_track:"🛤️",rainbow:"🌈",rainbow_flag:"🏳️‍🌈",raised_back_of_hand:"🤚",raised_eyebrow:"🤨",raised_hand:"✋",raised_hand_with_fingers_splayed:"🖐️",raised_hands:"🙌",raising_hand:"🙋",raising_hand_man:"🙋‍♂️",raising_hand_woman:"🙋‍♀️",ram:"🐏",ramen:"🍜",rat:"🐀",razor:"🪒",receipt:"🧾",record_button:"⏺️",recycle:"♻️",red_car:"🚗",red_circle:"🔴",red_envelope:"🧧",red_haired_man:"👨‍🦰",red_haired_woman:"👩‍🦰",red_square:"🟥",registered:"®️",relaxed:"☺️",relieved:"😌",reminder_ribbon:"🎗️",repeat:"🔁",repeat_one:"🔂",rescue_worker_helmet:"⛑️",restroom:"🚻",reunion:"🇷🇪",revolving_hearts:"💞",rewind:"⏪",rhinoceros:"🦏",ribbon:"🎀",rice:"🍚",rice_ball:"🍙",rice_cracker:"🍘",rice_scene:"🎑",right_anger_bubble:"🗯️",ring:"💍",ringed_planet:"🪐",robot:"🤖",rocket:"🚀",rofl:"🤣",roll_eyes:"🙄",roll_of_paper:"🧻",roller_coaster:"🎢",romania:"🇷🇴",rooster:"🐓",rose:"🌹",rosette:"🏵️",rotating_light:"🚨",round_pushpin:"📍",rowboat:"🚣",rowing_man:"🚣‍♂️",rowing_woman:"🚣‍♀️",ru:"🇷🇺",rugby_football:"🏉",runner:"🏃",running:"🏃",running_man:"🏃‍♂️",running_shirt_with_sash:"🎽",running_woman:"🏃‍♀️",rwanda:"🇷🇼",sa:"🈂️",safety_pin:"🧷",safety_vest:"🦺",sagittarius:"♐",sailboat:"⛵",sake:"🍶",salt:"🧂",samoa:"🇼🇸",san_marino:"🇸🇲",sandal:"👡",sandwich:"🥪",santa:"🎅",sao_tome_principe:"🇸🇹",sari:"🥻",sassy_man:"💁‍♂️",sassy_woman:"💁‍♀️",satellite:"📡",satisfied:"😆",saudi_arabia:"🇸🇦",sauna_man:"🧖‍♂️",sauna_person:"🧖",sauna_woman:"🧖‍♀️",sauropod:"🦕",saxophone:"🎷",scarf:"🧣",school:"🏫",school_satchel:"🎒",scientist:"🧑‍🔬",scissors:"✂️",scorpion:"🦂",scorpius:"♏",scotland:"🏴󠁧󠁢󠁳󠁣󠁴󠁿",scream:"😱",scream_cat:"🙀",scroll:"📜",seat:"💺",secret:"㊙️",see_no_evil:"🙈",seedling:"🌱",selfie:"🤳",senegal:"🇸🇳",serbia:"🇷🇸",service_dog:"🐕‍🦺",seven:"7️⃣",seychelles:"🇸🇨",shallow_pan_of_food:"🥘",shamrock:"☘️",shark:"🦈",shaved_ice:"🍧",sheep:"🐑",shell:"🐚",shield:"🛡️",shinto_shrine:"⛩️",ship:"🚢",shirt:"👕",shit:"💩",shoe:"👞",shopping:"🛍️",shopping_cart:"🛒",shorts:"🩳",shower:"🚿",shrimp:"🦐",shrug:"🤷",shushing_face:"🤫",sierra_leone:"🇸🇱",signal_strength:"📶",singapore:"🇸🇬",singer:"🧑‍🎤",sint_maarten:"🇸🇽",six:"6️⃣",six_pointed_star:"🔯",skateboard:"🛹",ski:"🎿",skier:"⛷️",skull:"💀",skull_and_crossbones:"☠️",skunk:"🦨",sled:"🛷",sleeping:"😴",sleeping_bed:"🛌",sleepy:"😪",slightly_frowning_face:"🙁",slightly_smiling_face:"🙂",slot_machine:"🎰",sloth:"🦥",slovakia:"🇸🇰",slovenia:"🇸🇮",small_airplane:"🛩️",small_blue_diamond:"🔹",small_orange_diamond:"🔸",small_red_triangle:"🔺",small_red_triangle_down:"🔻",smile:"😄",smile_cat:"😸",smiley:"😃",smiley_cat:"😺",smiling_face_with_three_hearts:"🥰",smiling_imp:"😈",smirk:"😏",smirk_cat:"😼",smoking:"🚬",snail:"🐌",snake:"🐍",sneezing_face:"🤧",snowboarder:"🏂",snowflake:"❄️",snowman:"⛄",snowman_with_snow:"☃️",soap:"🧼",sob:"😭",soccer:"⚽",socks:"🧦",softball:"🥎",solomon_islands:"🇸🇧",somalia:"🇸🇴",soon:"🔜",sos:"🆘",sound:"🔉",south_africa:"🇿🇦",south_georgia_south_sandwich_islands:"🇬🇸",south_sudan:"🇸🇸",space_invader:"👾",spades:"♠️",spaghetti:"🍝",sparkle:"❇️",sparkler:"🎇",sparkles:"✨",sparkling_heart:"💖",speak_no_evil:"🙊",speaker:"🔈",speaking_head:"🗣️",speech_balloon:"💬",speedboat:"🚤",spider:"🕷️",spider_web:"🕸️",spiral_calendar:"🗓️",spiral_notepad:"🗒️",sponge:"🧽",spoon:"🥄",squid:"🦑",sri_lanka:"🇱🇰",st_barthelemy:"🇧🇱",st_helena:"🇸🇭",st_kitts_nevis:"🇰🇳",st_lucia:"🇱🇨",st_martin:"🇲🇫",st_pierre_miquelon:"🇵🇲",st_vincent_grenadines:"🇻🇨",stadium:"🏟️",standing_man:"🧍‍♂️",standing_person:"🧍",standing_woman:"🧍‍♀️",star:"⭐",star2:"🌟",star_and_crescent:"☪️",star_of_david:"✡️",star_struck:"🤩",stars:"🌠",station:"🚉",statue_of_liberty:"🗽",steam_locomotive:"🚂",stethoscope:"🩺",stew:"🍲",stop_button:"⏹️",stop_sign:"🛑",stopwatch:"⏱️",straight_ruler:"📏",strawberry:"🍓",stuck_out_tongue:"😛",stuck_out_tongue_closed_eyes:"😝",stuck_out_tongue_winking_eye:"😜",student:"🧑‍🎓",studio_microphone:"🎙️",stuffed_flatbread:"🥙",sudan:"🇸🇩",sun_behind_large_cloud:"🌥️",sun_behind_rain_cloud:"🌦️",sun_behind_small_cloud:"🌤️",sun_with_face:"🌞",sunflower:"🌻",sunglasses:"😎",sunny:"☀️",sunrise:"🌅",sunrise_over_mountains:"🌄",superhero:"🦸",superhero_man:"🦸‍♂️",superhero_woman:"🦸‍♀️",supervillain:"🦹",supervillain_man:"🦹‍♂️",supervillain_woman:"🦹‍♀️",surfer:"🏄",surfing_man:"🏄‍♂️",surfing_woman:"🏄‍♀️",suriname:"🇸🇷",sushi:"🍣",suspension_railway:"🚟",svalbard_jan_mayen:"🇸🇯",swan:"🦢",swaziland:"🇸🇿",sweat:"😓",sweat_drops:"💦",sweat_smile:"😅",sweden:"🇸🇪",sweet_potato:"🍠",swim_brief:"🩲",swimmer:"🏊",swimming_man:"🏊‍♂️",swimming_woman:"🏊‍♀️",switzerland:"🇨🇭",symbols:"🔣",synagogue:"🕍",syria:"🇸🇾",syringe:"💉","t-rex":"🦖",taco:"🌮",tada:"🎉",taiwan:"🇹🇼",tajikistan:"🇹🇯",takeout_box:"🥡",tanabata_tree:"🎋",tangerine:"🍊",tanzania:"🇹🇿",taurus:"♉",taxi:"🚕",tea:"🍵",teacher:"🧑‍🏫",technologist:"🧑‍💻",teddy_bear:"🧸",telephone:"☎️",telephone_receiver:"📞",telescope:"🔭",tennis:"🎾",tent:"⛺",test_tube:"🧪",thailand:"🇹🇭",thermometer:"🌡️",thinking:"🤔",thought_balloon:"💭",thread:"🧵",three:"3️⃣",thumbsdown:"👎",thumbsup:"👍",ticket:"🎫",tickets:"🎟️",tiger:"🐯",tiger2:"🐅",timer_clock:"⏲️",timor_leste:"🇹🇱",tipping_hand_man:"💁‍♂️",tipping_hand_person:"💁",tipping_hand_woman:"💁‍♀️",tired_face:"😫",tm:"™️",togo:"🇹🇬",toilet:"🚽",tokelau:"🇹🇰",tokyo_tower:"🗼",tomato:"🍅",tonga:"🇹🇴",tongue:"👅",toolbox:"🧰",tooth:"🦷",top:"🔝",tophat:"🎩",tornado:"🌪️",tr:"🇹🇷",trackball:"🖲️",tractor:"🚜",traffic_light:"🚥",train:"🚋",train2:"🚆",tram:"🚊",triangular_flag_on_post:"🚩",triangular_ruler:"📐",trident:"🔱",trinidad_tobago:"🇹🇹",tristan_da_cunha:"🇹🇦",triumph:"😤",trolleybus:"🚎",trophy:"🏆",tropical_drink:"🍹",tropical_fish:"🐠",truck:"🚚",trumpet:"🎺",tshirt:"👕",tulip:"🌷",tumbler_glass:"🥃",tunisia:"🇹🇳",turkey:"🦃",turkmenistan:"🇹🇲",turks_caicos_islands:"🇹🇨",turtle:"🐢",tuvalu:"🇹🇻",tv:"📺",twisted_rightwards_arrows:"🔀",two:"2️⃣",two_hearts:"💕",two_men_holding_hands:"👬",two_women_holding_hands:"👭",u5272:"🈹",u5408:"🈴",u55b6:"🈺",u6307:"🈯",u6708:"🈷️",u6709:"🈶",u6e80:"🈵",u7121:"🈚",u7533:"🈸",u7981:"🈲",u7a7a:"🈳",uganda:"🇺🇬",uk:"🇬🇧",ukraine:"🇺🇦",umbrella:"☔",unamused:"😒",underage:"🔞",unicorn:"🦄",united_arab_emirates:"🇦🇪",united_nations:"🇺🇳",unlock:"🔓",up:"🆙",upside_down_face:"🙃",uruguay:"🇺🇾",us:"🇺🇸",us_outlying_islands:"🇺🇲",us_virgin_islands:"🇻🇮",uzbekistan:"🇺🇿",v:"✌️",vampire:"🧛",vampire_man:"🧛‍♂️",vampire_woman:"🧛‍♀️",vanuatu:"🇻🇺",vatican_city:"🇻🇦",venezuela:"🇻🇪",vertical_traffic_light:"🚦",vhs:"📼",vibration_mode:"📳",video_camera:"📹",video_game:"🎮",vietnam:"🇻🇳",violin:"🎻",virgo:"♍",volcano:"🌋",volleyball:"🏐",vomiting_face:"🤮",vs:"🆚",vulcan_salute:"🖖",waffle:"🧇",wales:"🏴󠁧󠁢󠁷󠁬󠁳󠁿",walking:"🚶",walking_man:"🚶‍♂️",walking_woman:"🚶‍♀️",wallis_futuna:"🇼🇫",waning_crescent_moon:"🌘",waning_gibbous_moon:"🌖",warning:"⚠️",wastebasket:"🗑️",watch:"⌚",water_buffalo:"🐃",water_polo:"🤽",watermelon:"🍉",wave:"👋",wavy_dash:"〰️",waxing_crescent_moon:"🌒",waxing_gibbous_moon:"🌔",wc:"🚾",weary:"😩",wedding:"💒",weight_lifting:"🏋️",weight_lifting_man:"🏋️‍♂️",weight_lifting_woman:"🏋️‍♀️",western_sahara:"🇪🇭",whale:"🐳",whale2:"🐋",wheel_of_dharma:"☸️",wheelchair:"♿",white_check_mark:"✅",white_circle:"⚪",white_flag:"🏳️",white_flower:"💮",white_haired_man:"👨‍🦳",white_haired_woman:"👩‍🦳",white_heart:"🤍",white_large_square:"⬜",white_medium_small_square:"◽",white_medium_square:"◻️",white_small_square:"▫️",white_square_button:"🔳",wilted_flower:"🥀",wind_chime:"🎐",wind_face:"🌬️",wine_glass:"🍷",wink:"😉",wolf:"🐺",woman:"👩",woman_artist:"👩‍🎨",woman_astronaut:"👩‍🚀",woman_cartwheeling:"🤸‍♀️",woman_cook:"👩‍🍳",woman_dancing:"💃",woman_facepalming:"🤦‍♀️",woman_factory_worker:"👩‍🏭",woman_farmer:"👩‍🌾",woman_firefighter:"👩‍🚒",woman_health_worker:"👩‍⚕️",woman_in_manual_wheelchair:"👩‍🦽",woman_in_motorized_wheelchair:"👩‍🦼",woman_judge:"👩‍⚖️",woman_juggling:"🤹‍♀️",woman_mechanic:"👩‍🔧",woman_office_worker:"👩‍💼",woman_pilot:"👩‍✈️",woman_playing_handball:"🤾‍♀️",woman_playing_water_polo:"🤽‍♀️",woman_scientist:"👩‍🔬",woman_shrugging:"🤷‍♀️",woman_singer:"👩‍🎤",woman_student:"👩‍🎓",woman_teacher:"👩‍🏫",woman_technologist:"👩‍💻",woman_with_headscarf:"🧕",woman_with_probing_cane:"👩‍🦯",woman_with_turban:"👳‍♀️",womans_clothes:"👚",womans_hat:"👒",women_wrestling:"🤼‍♀️",womens:"🚺",woozy_face:"🥴",world_map:"🗺️",worried:"😟",wrench:"🔧",wrestling:"🤼",writing_hand:"✍️",x:"❌",yarn:"🧶",yawning_face:"🥱",yellow_circle:"🟡",yellow_heart:"💛",yellow_square:"🟨",yemen:"🇾🇪",yen:"💴",yin_yang:"☯️",yo_yo:"🪀",yum:"😋",zambia:"🇿🇲",zany_face:"🤪",zap:"⚡",zebra:"🦓",zero:"0️⃣",zimbabwe:"🇿🇼",zipper_mouth_face:"🤐",zombie:"🧟",zombie_man:"🧟‍♂️",zombie_woman:"🧟‍♀️",zzz:"💤",atom:'',basecamp:'',basecampy:'',bowtie:'',electron:'',feelsgood:'',finnadie:'',goberserk:'',godmode:'',hurtrealbad:'',neckbeard:'',octocat:'',rage1:'',rage2:'',rage3:'',rage4:'',shipit:'',suspect:'',trollface:'',showdown:''},P.subParser("makehtml.blockGamut",function(e,a,r){"use strict";return e=r.converter._dispatch("makehtml.blockGamut.before",e,a,r).getText(),e=P.subParser("makehtml.blockQuotes")(e,a,r),e=P.subParser("makehtml.headers")(e,a,r),e=P.subParser("makehtml.horizontalRule")(e,a,r),e=P.subParser("makehtml.lists")(e,a,r),e=P.subParser("makehtml.codeBlocks")(e,a,r),e=P.subParser("makehtml.tables")(e,a,r),e=P.subParser("makehtml.hashHTMLBlocks")(e,a,r),e=P.subParser("makehtml.paragraphs")(e,a,r),e=r.converter._dispatch("makehtml.blockGamut.after",e,a,r).getText()}),P.subParser("makehtml.blockQuotes",function(e,a,r){"use strict";e=r.converter._dispatch("makehtml.blockQuotes.before",e,a,r).getText();var t=/(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;return a.splitAdjacentBlockquotes&&(t=/^ {0,3}>[\s\S]*?(?:\n\n)/gm),e=(e+="\n\n").replace(t,function(e){return e=(e=(e=e.replace(/^[ \t]*>[ \t]?/gm,"")).replace(/¨0/g,"")).replace(/^[ \t]+$/gm,""),e=P.subParser("makehtml.githubCodeBlocks")(e,a,r),e=(e=(e=P.subParser("makehtml.blockGamut")(e,a,r)).replace(/(^|\n)/g,"$1 ")).replace(/(\s*
[^\r]+?<\/pre>)/gm,function(e,a){return a.replace(/^  /gm,"¨0").replace(/¨0/g,"")}),P.subParser("makehtml.hashBlock")("
\n"+e+"\n
",a,r)}),e=r.converter._dispatch("makehtml.blockQuotes.after",e,a,r).getText()}),P.subParser("makehtml.codeBlocks",function(e,n,s){"use strict";e=s.converter._dispatch("makehtml.codeBlocks.before",e,n,s).getText();return e=(e=(e+="¨0").replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g,function(e,a,r){var t="\n",a=P.subParser("makehtml.outdent")(a,n,s);return a=P.subParser("makehtml.encodeCode")(a,n,s),a="
"+(a=(a=(a=P.subParser("makehtml.detab")(a,n,s)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+(t=n.omitExtraWLInCodeBlocks?"":t)+"
",P.subParser("makehtml.hashBlock")(a,n,s)+r})).replace(/¨0/,""),e=s.converter._dispatch("makehtml.codeBlocks.after",e,n,s).getText()}),P.subParser("makehtml.codeSpans",function(e,n,s){"use strict";return e=(e=void 0===(e=s.converter._dispatch("makehtml.codeSpans.before",e,n,s).getText())?"":e).replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,a,r,t){return t=(t=t.replace(/^([ \t]*)/g,"")).replace(/[ \t]*$/g,""),t=a+""+(t=P.subParser("makehtml.encodeCode")(t,n,s))+"",t=P.subParser("makehtml.hashHTMLSpans")(t,n,s)}),e=s.converter._dispatch("makehtml.codeSpans.after",e,n,s).getText()}),P.subParser("makehtml.completeHTMLDocument",function(e,a,r){"use strict";if(!a.completeHTMLDocument)return e;e=r.converter._dispatch("makehtml.completeHTMLDocument.before",e,a,r).getText();var t,n="html",s="\n",i="",o='\n',l="",c="";for(t in void 0!==r.metadata.parsed.doctype&&(s="\n","html"!==(n=r.metadata.parsed.doctype.toString().toLowerCase())&&"html5"!==n||(o='')),r.metadata.parsed)if(r.metadata.parsed.hasOwnProperty(t))switch(t.toLowerCase()){case"doctype":break;case"title":i=""+r.metadata.parsed.title+"\n";break;case"charset":o="html"===n||"html5"===n?'\n':'\n';break;case"language":case"lang":l=' lang="'+r.metadata.parsed[t]+'"',c+='\n';break;default:c+='\n'}return e=s+"\n\n"+i+o+c+"\n\n"+e.trim()+"\n\n",e=r.converter._dispatch("makehtml.completeHTMLDocument.after",e,a,r).getText()}),P.subParser("makehtml.detab",function(e,a,r){"use strict";return e=(e=(e=(e=(e=(e=r.converter._dispatch("makehtml.detab.before",e,a,r).getText()).replace(/\t(?=\t)/g," ")).replace(/\t/g,"¨A¨B")).replace(/¨B(.+?)¨A/g,function(e,a){for(var r=a,t=4-r.length%4,n=0;n/g,">"),e=r.converter._dispatch("makehtml.encodeAmpsAndAngles.after",e,a,r).getText()}),P.subParser("makehtml.encodeBackslashEscapes",function(e,a,r){"use strict";return e=(e=(e=r.converter._dispatch("makehtml.encodeBackslashEscapes.before",e,a,r).getText()).replace(/\\(\\)/g,P.helper.escapeCharactersCallback)).replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g,P.helper.escapeCharactersCallback),e=r.converter._dispatch("makehtml.encodeBackslashEscapes.after",e,a,r).getText()}),P.subParser("makehtml.encodeCode",function(e,a,r){"use strict";return e=(e=r.converter._dispatch("makehtml.encodeCode.before",e,a,r).getText()).replace(/&/g,"&").replace(//g,">").replace(/([*_{}\[\]\\=~-])/g,P.helper.escapeCharactersCallback),e=r.converter._dispatch("makehtml.encodeCode.after",e,a,r).getText()}),P.subParser("makehtml.escapeSpecialCharsWithinTagAttributes",function(e,a,r){"use strict";return e=(e=(e=r.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.before",e,a,r).getText()).replace(/<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,function(e){return e.replace(/(.)<\/?code>(?=.)/g,"$1`").replace(/([\\`*_~=|])/g,P.helper.escapeCharactersCallback)})).replace(/-]|-[^>])(?:[^-]|-[^-])*)--)>/gi,function(e){return e.replace(/([\\`*_~=|])/g,P.helper.escapeCharactersCallback)}),e=r.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.after",e,a,r).getText()}),P.subParser("makehtml.githubCodeBlocks",function(e,s,i){"use strict";return s.ghCodeBlocks?(e=i.converter._dispatch("makehtml.githubCodeBlocks.before",e,s,i).getText(),e=(e=(e+="¨0").replace(/(?:^|\n) {0,3}(```+|~~~+) *([^\n\t`~]*)\n([\s\S]*?)\n {0,3}\1/g,function(e,a,r,t){var n=s.omitExtraWLInCodeBlocks?"":"\n";return r=r.trim().split(" ")[0],t=P.subParser("makehtml.encodeCode")(t,s,i),t="
"+(t=(t=(t=P.subParser("makehtml.detab")(t,s,i)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+n+"
",t=P.subParser("makehtml.hashBlock")(t,s,i),"\n\n¨G"+(i.ghCodeBlocks.push({text:e,codeblock:t})-1)+"G\n\n"})).replace(/¨0/,""),i.converter._dispatch("makehtml.githubCodeBlocks.after",e,s,i).getText()):e}),P.subParser("makehtml.hashBlock",function(e,a,r){"use strict";return e=(e=r.converter._dispatch("makehtml.hashBlock.before",e,a,r).getText()).replace(/(^\n+|\n+$)/g,""),e="\n\n¨K"+(r.gHtmlBlocks.push(e)-1)+"K\n\n",e=r.converter._dispatch("makehtml.hashBlock.after",e,a,r).getText()}),P.subParser("makehtml.hashCodeTags",function(e,n,s){"use strict";e=s.converter._dispatch("makehtml.hashCodeTags.before",e,n,s).getText();return e=P.helper.replaceRecursiveRegExp(e,function(e,a,r,t){r=r+P.subParser("makehtml.encodeCode")(a,n,s)+t;return"¨C"+(s.gHtmlSpans.push(r)-1)+"C"},"]*>","","gim"),e=s.converter._dispatch("makehtml.hashCodeTags.after",e,n,s).getText()}),P.subParser("makehtml.hashElement",function(e,a,r){"use strict";return function(e,a){return a=(a=(a=a.replace(/\n\n/g,"\n")).replace(/^\n/,"")).replace(/\n+$/g,""),a="\n\n¨K"+(r.gHtmlBlocks.push(a)-1)+"K\n\n"}}),P.subParser("makehtml.hashHTMLBlocks",function(e,a,n){"use strict";e=n.converter._dispatch("makehtml.hashHTMLBlocks.before",e,a,n).getText();function r(e,a,r,t){return-1!==r.search(/\bmarkdown\b/)&&(e=r+n.converter.makeHtml(a)+t),"\n\n¨K"+(n.gHtmlBlocks.push(e)-1)+"K\n\n"}var t=["pre","div","h1","h2","h3","h4","h5","h6","blockquote","table","dl","ol","ul","script","noscript","form","fieldset","iframe","math","style","section","header","footer","nav","article","aside","address","audio","canvas","figure","hgroup","output","video","details","p"];a.backslashEscapesHTMLTags&&(e=e.replace(/\\<(\/?[^>]+?)>/g,function(e,a){return"<"+a+">"}));for(var s=0;s]*>)","im"),o="<"+t[s]+"\\b[^>]*>",l="";-1!==(c=P.helper.regexIndexOf(e,i));){var c=P.helper.splitAtIndex(e,c),u=P.helper.replaceRecursiveRegExp(c[1],r,o,l,"im");if(u===c[1])break;e=c[0].concat(u)}return e=e.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,P.subParser("makehtml.hashElement")(e,a,n)),e=(e=P.helper.replaceRecursiveRegExp(e,function(e){return"\n\n¨K"+(n.gHtmlBlocks.push(e)-1)+"K\n\n"},"^ {0,3}\x3c!--","--\x3e","gm")).replace(/\n\n( {0,3}<([?%])[^\r]*?\2>[ \t]*(?=\n{2,}))/g,P.subParser("makehtml.hashElement")(e,a,n)),e=n.converter._dispatch("makehtml.hashHTMLBlocks.after",e,a,n).getText()}),P.subParser("makehtml.hashHTMLSpans",function(e,a,r){"use strict";return e=(e=(e=(e=(e=r.converter._dispatch("makehtml.hashHTMLSpans.before",e,a,r).getText()).replace(/<[^>]+?\/>/gi,function(e){return P.helper._hashHTMLSpan(e,r)})).replace(/<([^>]+?)>[\s\S]*?<\/\1>/g,function(e){return P.helper._hashHTMLSpan(e,r)})).replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g,function(e){return P.helper._hashHTMLSpan(e,r)})).replace(/<[^>]+?>/gi,function(e){return P.helper._hashHTMLSpan(e,r)}),e=r.converter._dispatch("makehtml.hashHTMLSpans.after",e,a,r).getText()}),P.subParser("makehtml.unhashHTMLSpans",function(e,a,r){"use strict";e=r.converter._dispatch("makehtml.unhashHTMLSpans.before",e,a,r).getText();for(var t=0;t]*>\\s*]*>","^ {0,3}\\s*
","gim"),e=s.converter._dispatch("makehtml.hashPreCodeTags.after",e,n,s).getText()}),P.subParser("makehtml.headers",function(e,n,s){"use strict";e=s.converter._dispatch("makehtml.headers.before",e,n,s).getText();var i=isNaN(parseInt(n.headerLevelStart))?1:parseInt(n.headerLevelStart),a=n.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,r=n.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm,a=(e=(e=e.replace(a,function(e,a){var r=P.subParser("makehtml.spanGamut")(a,n,s),a=n.noHeaderId?"":' id="'+o(a)+'"',a=""+r+"";return P.subParser("makehtml.hashBlock")(a,n,s)})).replace(r,function(e,a){var r=P.subParser("makehtml.spanGamut")(a,n,s),a=n.noHeaderId?"":' id="'+o(a)+'"',t=i+1,a=""+r+"";return P.subParser("makehtml.hashBlock")(a,n,s)}),n.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm);function o(e){var a=e=n.customizedHeaderId&&(a=e.match(/{([^{]+?)}\s*$/))&&a[1]?a[1]:e,e=P.helper.isString(n.prefixHeaderId)?n.prefixHeaderId:!0===n.prefixHeaderId?"section-":"";return n.rawPrefixHeaderId||(a=e+a),a=(n.ghCompatibleHeaderId?a.replace(/ /g,"-").replace(/&/g,"").replace(/¨T/g,"").replace(/¨D/g,"").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g,""):n.rawHeaderId?a.replace(/ /g,"-").replace(/&/g,"&").replace(/¨T/g,"¨").replace(/¨D/g,"$").replace(/["']/g,"-"):a.replace(/[^\w]/g,"")).toLowerCase(),n.rawPrefixHeaderId&&(a=e+a),s.hashLinkCounts[a]?a=a+"-"+s.hashLinkCounts[a]++:s.hashLinkCounts[a]=1,a}return e=e.replace(a,function(e,a,r){var t=r,t=(n.customizedHeaderId&&(t=r.replace(/\s?{([^{]+?)}\s*$/,"")),P.subParser("makehtml.spanGamut")(t,n,s)),r=n.noHeaderId?"":' id="'+o(r)+'"',a=i-1+a.length,r=""+t+"";return P.subParser("makehtml.hashBlock")(r,n,s)}),e=s.converter._dispatch("makehtml.headers.after",e,n,s).getText()}),P.subParser("makehtml.horizontalRule",function(e,a,r){"use strict";e=r.converter._dispatch("makehtml.horizontalRule.before",e,a,r).getText();var t=P.subParser("makehtml.hashBlock")("
",a,r);return e=(e=(e=e.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,t)).replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,t)).replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,t),e=r.converter._dispatch("makehtml.horizontalRule.after",e,a,r).getText()}),P.subParser("makehtml.images",function(e,l,h){"use strict";function a(e,a,r,t,n,s,i,o){return c(e,a,r,t=P.helper.applyBaseUrl(l.relativePathBaseUrl,t),n,s,0,o)}function c(e,a,r,t,n,s,i,o){var l=h.gUrls,c=h.gTitles,u=h.gDimensions;if(r=r.toLowerCase(),o=o||"",-1? ?(['"].*['"])?\)$/m))t="";else if(""===t||null===t){if(t="#"+(r=""!==r&&null!==r?r:a.toLowerCase().replace(/ ?\n/g," ")),P.helper.isUndefined(l[r]))return e;t=l[r],P.helper.isUndefined(c[r])||(o=c[r]),P.helper.isUndefined(u[r])||(n=u[r].width,s=u[r].height)}a=a.replace(/"/g,""").replace(P.helper.regexes.asteriskDashTildeAndColon,P.helper.escapeCharactersCallback);e=''+a+'"}return e=(e=(e=(e=(e=(e=h.converter._dispatch("makehtml.images.before",e,l,h).getText()).replace(/!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,c)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,function(e,a,r,t,n,s,i,o){return c(e,a,r,t=t.replace(/\s/g,""),n,s,0,o)})).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,a)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,a)).replace(/!\[([^\[\]]+)]()()()()()/g,c),e=h.converter._dispatch("makehtml.images.after",e,l,h).getText()}),P.subParser("makehtml.italicsAndBold",function(e,a,r){"use strict";return e=r.converter._dispatch("makehtml.italicsAndBold.before",e,a,r).getText(),e=(e=(e=(e=a.literalMidWordUnderscores?(e=(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,a){return""+a+""})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,a){return""+a+""})).replace(/\b_(\S[\s\S]*?)_\b/g,function(e,a){return""+a+""}):(e=(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/__(\S[\s\S]*?)__/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/_([^\s_][\s\S]*?)_/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/\*\*(\S[\s\S]*?)\*\*/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/\*([^\s*][\s\S]*?)\*/g,function(e,a){return/\S$/.test(a)?""+a+"":e}),e=r.converter._dispatch("makehtml.italicsAndBold.after",e,a,r).getText()}),s="makehtml.links",P.subParser("makehtml.links",function(e,a,r){return e=r.converter._dispatch(s+".start",e,a,r).getText(),e=P.subParser("makehtml.links.reference")(e,a,r),e=P.subParser("makehtml.links.inline")(e,a,r),e=P.subParser("makehtml.links.referenceShortcut")(e,a,r),e=P.subParser("makehtml.links.angleBrackets")(e,a,r),e=(e=(e=P.subParser("makehtml.links.ghMentions")(e,a,r)).replace(/]*>[\s\S]*<\/a>/g,function(e){return P.helper._hashHTMLSpan(e,r)})).replace(/]*\/?>/g,function(e){return P.helper._hashHTMLSpan(e,r)}),e=P.subParser("makehtml.links.naked")(e,a,r),e=r.converter._dispatch(s+".end",e,a,r).getText()}),P.subParser("makehtml.links.inline",function(e,a,r){var t=void 0+".inline",n=/\[(.*?)]()()()()\(? ?(?:["'](.*)["'])?\)/g,s=/\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,i=/\[([\S ]*?)]\s?()\( *?\s*(?:()(['"])(.*?)\5)? *\)/g,o=/\[([\S ]*?)]\s?()\( *?\s+()()\((.*?)\) *\)/g;return e=(e=(e=(e=(e=r.converter._dispatch(t+".start",e,a,r).getText()).replace(n,l(n,t,a,r,!0))).replace(s,l(s,t,a,r))).replace(i,l(i,t,a,r))).replace(o,l(o,t,a,r)),e=r.converter._dispatch(t+".end",e,a,r).getText()}),P.subParser("makehtml.links.reference",function(e,a,r){var t=void 0+".reference",n=/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;return e=(e=r.converter._dispatch(t+".start",e,a,r).getText()).replace(n,i(n,t,a,r)),e=r.converter._dispatch(t+".end",e,a,r).getText()}),P.subParser("makehtml.links.referenceShortcut",function(e,a,r){var t=void 0+".referenceShortcut",n=/\[([^\[\]]+)]()()()()()/g;return e=(e=r.converter._dispatch(t+".start",e,a,r).getText()).replace(n,i(n,t,a,r)),e=r.converter._dispatch(t+".end",e,a,r).getText()}),P.subParser("makehtml.links.ghMentions",function(e,s,i){var o=void 0+"ghMentions";if(!s.ghMentions)return e;e=i.converter._dispatch(o+".start",e,s,i).getText();var l=/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;return e=e.replace(l,function(e,a,r,t,n){if("\\"===r)return a+t;if(!P.helper.isString(s.ghMentionsLink))throw new Error("ghMentionsLink option must be a string");r=s.ghMentionsLink.replace(/{u}/g,n);return a+b(_(l,o+".captureStart",e,t,null,r,null,s,i),s,i)}),e=i.converter._dispatch(o+".end",e,s,i).getText()}),P.subParser("makehtml.links.angleBrackets",function(e,t,n){var s="makehtml.links.angleBrackets",i=(e=n.converter._dispatch(s+".start",e,t,n).getText(),/<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi),o=(e=e.replace(i,function(e,a,r){return b(_(i,s+".captureStart",e,a,null,a="www."===r?"http://"+a:a,null,t,n),t,n)}),/<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi);return e=e.replace(o,function(e,a){var r="mailto:";return a=P.subParser("makehtml.unescapeSpecialChars")(a,t,n),t.encodeEmails?(r=P.helper.encodeEmailAddress(r+a),a=P.helper.encodeEmailAddress(a)):r+=a,b(_(o,s+".captureStart",e,a,null,r,null,t,n),t,n)}),e=n.converter._dispatch(s+".end",e,t,n).getText()}),P.subParser("makehtml.links.naked",function(e,u,h){if(!u.simplifiedAutoLink)return e;var m="makehtml.links.naked",d=(e=h.converter._dispatch(m+".start",e,u,h).getText(),/([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi),n=(e=e.replace(d,function(e,a,r,t){for(var n="",s=r.length-1;0<=s;--s){var i=r.charAt(s);if(/[_*~,;:.!?]/.test(i))r=r.slice(0,-1),n=i+n;else if(/\)/.test(i)){var o=r.match(/\(/g)||[],l=r.match(/\)/g);if(!(o.length"),m+="

",c.push(m))}n=(n=(n=c.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,"")}else n=(n=P.subParser("makehtml.lists")(n,g,p)).replace(/\n$/,""),n=(n=P.subParser("makehtml.hashHTMLBlocks")(n,g,p)).replace(/\n\n+/g,"\n\n"),n=(d?P.subParser("makehtml.paragraphs"):P.subParser("makehtml.spanGamut"))(n,g,p);return n=""+(n=n.replace("¨A",""))+"\n"})).replace(/¨0/g,""),p.gListLevel--,e=a?e.replace(/\s+$/,""):e}function m(e,a){if("ol"===a){a=e.match(/^ *(\d+)\./);if(a&&"1"!==a[1])return' start="'+a[1]+'"'}return""}function n(n,s,i){var e,o=g.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,l=g.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,c="ul"===s?o:l,u="";return-1!==n.search(c)?function e(a){var r=a.search(c),t=m(n,s);-1!==r?(u+="\n\n<"+s+t+">\n"+h(a.slice(0,r),!!i)+"\n",c="ul"===(s="ul"===s?"ol":"ul")?o:l,e(a.slice(r))):u+="\n\n<"+s+t+">\n"+h(a,!!i)+"\n"}(n):(e=m(n,s),u="\n\n<"+s+e+">\n"+h(n,!!i)+"\n"),u}return e=p.converter._dispatch("lists.before",e,g,p).getText(),e+="¨0",e=(e=p.gListLevel?e.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,a,r){return n(a,-1"),o+="

",n.push(o))}for(s=n.length,i=0;i]*>\s*]*>/.test(c)&&(u=!0)}n[i]=c}return e=(e=(e=n.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,""),r.converter._dispatch("makehtml.paragraphs.after",e,a,r).getText()}),P.subParser("makehtml.runExtension",function(e,a,r,t){"use strict";return e.filter?a=e.filter(a,t.converter,r):e.regex&&((t=e.regex)instanceof RegExp||(t=new RegExp(t,"g")),a=a.replace(t,e.replace)),a}),P.subParser("makehtml.spanGamut",function(e,a,r){"use strict";return e=r.converter._dispatch("makehtml.span.before",e,a,r).getText(),e=P.subParser("makehtml.codeSpans")(e,a,r),e=P.subParser("makehtml.escapeSpecialCharsWithinTagAttributes")(e,a,r),e=P.subParser("makehtml.encodeBackslashEscapes")(e,a,r),e=P.subParser("makehtml.images")(e,a,r),e=r.converter._dispatch("smakehtml.links.before",e,a,r).getText(),e=P.subParser("makehtml.links")(e,a,r),e=r.converter._dispatch("smakehtml.links.after",e,a,r).getText(),e=P.subParser("makehtml.emoji")(e,a,r),e=P.subParser("makehtml.underline")(e,a,r),e=P.subParser("makehtml.italicsAndBold")(e,a,r),e=P.subParser("makehtml.strikethrough")(e,a,r),e=P.subParser("makehtml.ellipsis")(e,a,r),e=P.subParser("makehtml.hashHTMLSpans")(e,a,r),e=P.subParser("makehtml.encodeAmpsAndAngles")(e,a,r),a.simpleLineBreaks?/\n\n¨K/.test(e)||(e=e.replace(/\n+/g,"
\n")):e=e.replace(/ +\n/g,"
\n"),e=r.converter._dispatch("makehtml.spanGamut.after",e,a,r).getText()}),P.subParser("makehtml.strikethrough",function(e,a,r){"use strict";return a.strikethrough&&(e=(e=r.converter._dispatch("makehtml.strikethrough.before",e,a,r).getText()).replace(/(?:~){2}([\s\S]+?)(?:~){2}/g,function(e,a){return""+a+""}),e=r.converter._dispatch("makehtml.strikethrough.after",e,a,r).getText()),e}),P.subParser("makehtml.stripLinkDefinitions",function(o,l,c){"use strict";function e(e,a,r,t,n,s,i){return a=a.toLowerCase(),o.toLowerCase().split(a).length-1<2?e:(r.match(/^data:.+?\/.+?;base64,/)?c.gUrls[a]=r.replace(/\s/g,""):(r=P.helper.applyBaseUrl(l.relativePathBaseUrl,r),c.gUrls[a]=P.subParser("makehtml.encodeAmpsAndAngles")(r,l,c)),s?s+i:(i&&(c.gTitles[a]=i.replace(/"|'/g,""")),l.parseImgDimensions&&t&&n&&(c.gDimensions[a]={width:t,height:n}),""))}return o=(o=(o=(o+="¨0").replace(/^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm,e)).replace(/^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,e)).replace(/¨0/,"")}),P.subParser("makehtml.tables",function(e,y,x){"use strict";if(!y.tables)return e;function a(e){for(var a=e.split("\n"),r=0;r"+(n=P.subParser("makehtml.spanGamut")(n,y,x))+"\n"));for(r=0;r"+P.subParser("makehtml.spanGamut")(o,y,x)+"\n"));d.push(g)}for(var _=h,b=d,f="\n\n\n",k=_.length,w=0;w\n\n\n",w=0;w\n";for(var v=0;v\n"}return f+="\n
\n"}return e=(e=(e=(e=x.converter._dispatch("makehtml.tables.before",e,y,x).getText()).replace(/\\(\|)/g,P.helper.escapeCharactersCallback)).replace(/^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*[-=]{2,}[\s\S]+?(?:\n\n|¨0)/gm,a)).replace(/^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm,a),e=x.converter._dispatch("makehtml.tables.after",e,y,x).getText()}),P.subParser("makehtml.underline",function(e,a,r){"use strict";return a.underline?(e=r.converter._dispatch("makehtml.underline.before",e,a,r).getText(),e=(e=a.literalMidWordUnderscores?(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,a){return""+a+""})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,a){return""+a+""}):(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/__(\S[\s\S]*?)__/g,function(e,a){return/\S$/.test(a)?""+a+"":e})).replace(/(_)/g,P.helper.escapeCharactersCallback),r.converter._dispatch("makehtml.underline.after",e,a,r).getText()):e}),P.subParser("makehtml.unescapeSpecialChars",function(e,a,r){"use strict";return e=(e=r.converter._dispatch("makehtml.unescapeSpecialChars.before",e,a,r).getText()).replace(/¨E(\d+)E/g,function(e,a){a=parseInt(a);return String.fromCharCode(a)}),e=r.converter._dispatch("makehtml.unescapeSpecialChars.after",e,a,r).getText()}),P.subParser("makeMarkdown.blockquote",function(e,a){"use strict";var r="";if(e.hasChildNodes())for(var t=e.childNodes,n=t.length,s=0;s ")}),P.subParser("makeMarkdown.break",function(){"use strict";return" \n"}),P.subParser("makeMarkdown.codeBlock",function(e,a){"use strict";var r=e.getAttribute("language"),e=e.getAttribute("precodenum");return"```"+r+"\n"+a.preList[e]+"\n```"}),P.subParser("makeMarkdown.codeSpan",function(e){"use strict";return"`"+e.innerHTML+"`"}),P.subParser("makeMarkdown.emphasis",function(e,a){"use strict";var r="";if(e.hasChildNodes()){r+="*";for(var t=e.childNodes,n=t.length,s=0;s",e.hasAttribute("width")&&e.hasAttribute("height")&&(a+=" ="+e.getAttribute("width")+"x"+e.getAttribute("height")),e.hasAttribute("title")&&(a+=' "'+e.getAttribute("title")+'"'),a+=")"),a}),P.subParser("makeMarkdown.input",function(e,a){"use strict";for(var r="",t=(null!==e.getAttribute("checked")?r+="[x]":r+="[ ]",e.childNodes),n=t.length,s=0;s"),e.hasAttribute("title")&&(r+=' "'+e.getAttribute("title")+'"'),r+=")"}return r}),P.subParser("makeMarkdown.list",function(e,a,r){"use strict";var t="";if(!e.hasChildNodes())return"";for(var n=e.childNodes,s=n.length,i=e.getAttribute("start")||1,o=0;o"+a.preList[e]+""}),P.subParser("makeMarkdown.strikethrough",function(e,a){"use strict";var r="";if(e.hasChildNodes()){r+="~~";for(var t=e.childNodes,n=t.length,s=0;str>th"),s=e.querySelectorAll("tbody>tr"),i=0;i/g,"\\$1>")).replace(/^#/gm,"\\#")).replace(/^(\s*)([-=]{3,})(\s*)$/,"$1\\$2$3")).replace(/^( {0,3}\d+)\./gm,"$1\\.")).replace(/^( {0,3})([+-])/gm,"$1\\$2")).replace(/]([\s]*)\(/g,"\\]$1\\(")).replace(/^ {0,3}\[([\S \t]*?)]:/gm,"\\[$1]:")}),P.Converter=function(e){"use strict";var a,r,n={},o=[],l=[],c={},t=d,s={parsed:{},raw:"",format:""};for(a in e=e||{},m)m.hasOwnProperty(a)&&(n[a]=m[a]);if("object"!=typeof e)throw Error("Converter expects the passed parameter to be an object, but "+typeof e+" was passed instead.");for(r in e)e.hasOwnProperty(r)&&(n[r]=e[r]);function i(e,a){if(a=a||null,P.helper.isString(e)){if(a=e=P.helper.stdExtName(e),P.extensions[e]){console.warn("DEPRECATION WARNING: "+e+" is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!");var r=P.extensions[e],t=e;if("function"==typeof r&&(r=r(new P.Converter)),P.helper.isArray(r)||(r=[r]),!(t=p(r,t)).valid)throw Error(t.error);for(var n=0;n[ \t]+¨NBSP;<");for(var a=P.helper.document.createElement("div"),r=(a.innerHTML=e,{preList:function(e){for(var a=e.querySelectorAll("pre"),r=[],t=0;t'}else r.push(a[t].innerHTML),a[t].innerHTML="",a[t].setAttribute("prenum",t.toString());return r}(a)}),t=(!function e(a){for(var r=0;r20.10),说明你已经安装了Docker. +不知道怎么安装Docker的话,可以参考[这里](https://docs.docker.com/engine/install/) -The goal of OpenDAN (Open and Do Anything Now with AI) is to create a Personal AI OS , which provides a runtime environment for various Al modules as well as protocols for interoperability between them. With OpenDAN, users can securely collaborate with various AI modules using their private data to create powerful personal AI agents, such as butler, lawyer, doctor, teacher, assistant, girl or boy friends. +2. OpenAI的API Token +还没有API Token的话,可以通过[这里](https://beta.openai.com/)申请 +(申请API Token对新玩家可能有一些门槛,可以在身边找找朋友,可以让他们给你一个临时的,或则加入我们的内测体验群,我们也会不时放出一些免费体验的API Token,这些Token被限制在了月均消费$5) -This project is still in its very early stages, and there may be significant changes in the future. +# 安装OpenDAN +``` +docker pull paios/aios:latest +``` -## **Updates** +# 运行OpenDAN +首次运行OpenDAN需要进行初始化,初始化过程中需要你输入一些信息,因此启动Docker的时候记住要带上 -it参数。 +OpenDAN时你的Personal AIOS,因此其运行过程中会产生一些重要的个人数据(比如对话记录,日程数据等),这些数据会保存在你的本地磁盘上,因此在启动Docker的时候,我们推荐你将本地磁盘挂载到Docker的容器中,这样才能保证数据的持久化。 -### 1. Adding Knowledge Base Infrastructure -We're currently working on implementing the infrastructure for the Knowledge Base, aiming to enhance AI agent's access to Personal Data stored on Personal Servers. Leveraging these new features, we want to empower everyone to build their own personal homepage in the AI era using OpenDAN. +``` +docker run -v /your/local/myai/:/root/myai --name aios -it paios/aios:latest +``` -### 2. Development Based on SourceDAO Contract -We are in the process of developing the OpenDAN's DAO page, which is based on the SourceDAO contract. The future of OpenDAN should be determined by the community. +执行上述命令后,如果一切正常,你会看到如下界面 +![image](https://user-images.githubusercontent.com/11796024/120933872-0b8b6b00-c72a-11eb-9b0b-3b0b8b8b0b0b.png) -### 3. Welcoming waterflier as a Core Contributor -We're excited to officially invite waterflier to join as a core contributor to our community. We recognize and appreciate his innovative ideas and deep insights in the realm of Personal AI OS. Waterflier will be spearheading the development of the MVP version. As a key contributor to the CYFS CoreDev Team, he brings extensive experience in the domain of Personal Servers. +后续运行 +``` +docker start -ai aios +``` +以服务模式 +``` +docker start aios +``` -## **Intro video - What is OpenDAN?** -Click the image below for a demo: +# OpenDAN的首次运行配置 -[![Intro Video](https://github-production-user-asset-6210df.s3.amazonaws.com/126534313/243310994-4d1ece51-b06d-413d-a2ac-ea5099bb6e94.png)](https://www.youtube.com/watch?v=l2QmsIOXhdQ "Intro Video") +如果你过去没有用过CLI的产品,可能会有一点点不习惯,但别紧张,即使在Internal Test版本中,你也只会在极少数的情况下需要使用CLI。 +OpenDAN必须是所有人都能轻松使用的未来操作系统,因此我们希望OpenDAN的使用和配置都是非常友好和简单的。但在Internal Test版本中,我们还没有足够的资源来实现这一目标。经过思考,我们决定先支持CLI的方式来使用OpenDAN。 -## **Demo video - What can OpenDAN do?** -Click the image below for a demo: +OpenDAN以LLM为AIOS的内核,通过不同的Agent/Workflow整合了很多很Cool的AI功能,你可以在OpenDAN里一站式的体验AI工业的一些最新的功能。激活全部的功能需要做比较多的配置,但首次运行我们只需要做两项配置就可以了 +1. LLM内核。OpenDAN是围绕LLM构建的未来智能操作系统,因此系统必须有至少一个LLM内核。 + OpenDAN以Agent为单位对LLM进行配置,未指定LLM模型名的Agent将会默认使用GPT4(GPT4也是目前最聪明的LLM)。你可以修改该配置到llama或其它安装的Local LLM。今天使用Local LLM需要相当强的本地算力的支持,这需要一笔不小的一次性投入。 + 但我们相信LLM领域也会遵循摩尔定律,未来的LLM模型会越来越强大,越来越小,越来越便宜。因此我们相信在未来,每个人都会有自己的Local LLM。 +2. 你的个人信息,这能让你的私人AI管家Jarvis更好的为你服务。注意这里一定要输入你自己正确的Telegram username ,否则由于系统权限控制,你讲无法通过Telegram访问Agent/Workflow。 -[![Demo Video](https://github-production-user-asset-6210df.s3.amazonaws.com/126534313/243309993-cf6abfd5-0a56-420b-ac56-99b18dbd3c5f.png)](https://youtu.be/13wdyoT0VHQ "Demo Video") +好的,简单的了解了上述背景后,请按界面提示完成必要信息的输入。 -
- - - -
+P.S: +上述配置会保存在`/your/local/myai/etc/system.cfg.toml`中,如果你想要修改配置,可以直接修改这个文件。如果你想要调整配置,可以直接编辑这个文件。 -## **Subscribe to updates here** - -https://twitter.com/openDAN_AI - -## **Core Features of OpenDAN** - -To achieve the goal of OpenDAN, we provide the following key features: - -1. **Hardware-specific optimization**: Optimize for specific hardware to enable smooth local running of most open-source AI applications. -2. **Open AI App Marketplace**: Offer a solution for one-click installation and use of various AI applications, helping users easily access and manage AI apps. -3. **Open AI Model Solution**: Provide a unified entry point for model search, download, and access control, making it convenient for users to find and use models suitable for their needs. -4. **Strict Privacy Protection and Management**: Strictly manage personal data, ranging from family albums to chat records and social media records, and provide a unified access control interface for AI applications. -5. **Integrated Tools**: Offer tools for users to train their own voice models, Lora models, knowledge models, etc., using personal data. -6. **AI Butler Assistant**: Driven by a large language model, the AI assistant completes tasks through natural language interaction. -7. **Development Framework**: Provide a development framework for customizing AI assistants for specific purposes, making it easy for developers to create unique AI applications for users. - -## **Roadmap** - -- [x] Project Initialization - - [x] Basic code for operating system image packaging script - - [x] Opendan.ai website homepage -- [x] OpenDAN Prototype Version - - [x] AI butler assistant driven by GPT-3.5 or GPT-4.0 - - [x] Integration of Stable Diffusion - - [x] Integration of TTS (Text-to-Speech) - - [x] Integration of Telegram Chatbot as an interaction entrance -- [ ] OpenDAN 1.0 - - [ ] AI butler assistant's large language model core switched to locally running open-source model - - [ ] Offer more AI applications through AI App Marketplace - - [ ] Provide an AI application development framework to support the community in integrating more AI applications - - [ ] Provide a model management framework - -## **Contributing** - -We welcome community members to contribute to the project, including but not limited to submitting issues, improving documentation, fixing bugs, or providing new features. You can participate in the contribution through the following ways: - -- Submit an Issue in the GitHub repository -- Submit a Pull Request to the repository -- Participate in discussions and development - -## **⭐Star History** +## (可选)安装本地LLM内核 +首次快速体验OpenDAN,我们强烈的推荐你使用GPT4,虽然他很慢,也很贵,但他也是目前最强大和稳定的LLM内核。OpenDAN在架构设计上,允许不同的Agent选择不同的LLM内核(但系统里至少要有一个可用的LLM内核),如果你因为各种原因无法使用GPT4,可以是用下面方法安装Local LLM. +目前我们只适配了基于Llama.cpp的Local LLM,用下面方法安装 +Step0 检查系统要求 +从效果和性能角度,我们适配了13B和70B的两个版本的模型,经过测试,安装这两个模型需要的系统要求如下(给出参考链接) +简单的说,我们的推荐如下: -[![Star History Chart](https://api.star-history.com/svg?repos=fiatrete/OpenDAN-Personal-AI-Server-OS&type=Date)](https://star-history.com/#fiatrete/OpenDAN-Personal-AI-Server-OS&Date) +OpenDAN也是一个NetworkOS,允许系统通过网络访问需要的计算资源。因此Local LLM并不要求和OpenDAN运行在同一个机器上。你可以在局域网中找一台符合上述配置要求的主机来安装Local LLM Compute Node. + +Step1 安装LLampa.cpp的Local LLM CopmuteNode Docker Image +``` +``` +如果Local LLM Compute Node未安装在本机,还要记得打开必要的端口,以便OpenDAN可以访问Local LLM Compute Node. + +Step2 配置OpenDAN使用Local LLM +使用命令: +``` + +``` +然后按照提示输入你的Local LLM的URL信息: +完成配置。 + + + +## (可选) 配置系统的Socks5代理 +OpenDAN也支持socks5代理,对于网络环境不允许直接访问Telegram,GPT4的朋友,可以使用这个配置要求OpenDAN通过代理访问网络。 + +# Hello, Jarvis! +配置完成后,你会进入一个和bash很类似的界面,这个界面的含义是: +当前用户 "username" 正在 和 名为Jarvis的Agent/Workflow 进行交流,当前话题是default +和你的私人AI管家Jarvis Say Hi吧! +*** 如果一切正常,你将会在一小会后得到Jarvis的回复。此时OpenDAN系统已经正常运行了。*** + +# 给Jarvis注册Telegram账号 +你已经完成了OpenDAN的安装和配置,并已经验证了其可以正常工作。下面让我们回到熟悉的图形界面,回到移动互联网吧! +下面我们将给Jarvis注册一个Telegram账号,通过Telegram,我们可以使用熟悉的方式和Jarvis进行交流了~ +在opendan的aios_shell输入 +``` +/connect Jarvis +``` +按照提示输入Telegram Bot Token就完成了Jarvis的账号注册. + +P.S 我们还支持给Agent注册email账号,但由于email账户的配置比较复杂,由于篇幅问题本文就先跳过了。有需要的朋友可以手工打开 ~/myai/etc/tunnels.cfg.toml 文件,按文件格式和下面的例子,为Agent添加email账号。 +``` + +``` + +# 以服务方式运行OpenDAN +上述的运行方式是以交互方式运行OpenDAN,这种方式适合在开发和调试的时候使用。在实际使用的时候,我们推荐以服务方式运行OpenDAN,这样可以让OpenDAN在后台默默的运行,不会影响你的正常使用。 +先输入 +``` +/exit +``` +关闭并退出OpenDAN,随后我们再用服务的方式启动OpenDAN: + +``` +docker run -d opendan/aios:latest -v /your/local/myai/:/root/myai +``` + +Jarvis是运行在OpenDAN上的Agent,当OpenDAN退出后,其活动也会被终止。因此如果想随时随地通过Telegram和Jarvis交流,请记住保持OpenDAN的运行(不要关闭你的电脑,并保持其网络连接)。 +实际上,OpenDAN是一个典型的Person AI OS,运行在Persona OS上(关于Personal OS的定义可以参考OOD的设计)。因此运行在PC或笔记本上并不是一个正式选择,但谁要我们正在Internal Test呢? +我们正在进行的很多研发工作,其中有很大一部分的目标,就是能让你轻松的拥有一个搭载AIOS的Personal Server.相对PC,我们将把这个新设备叫PI(),OpenDAN是面向PI的首个OS。 + + +# 你的私人管家 Jarvis 前来报道! +现在你已经可以随时随地通过Telegram和Jarvis交流了,但只是把他看成更易于访问的ChatGPT,未免有点小瞧他了。让我们来看一下运行在OpenDAN里的Jarvis有什么新本事吧! + +## 让Jarvis给你安排日程 +(一张图片) + +相信有不少朋友有长期使用Outlook等传统Calender软件来管理自己日程的习惯。像我自己通常每周会花至少2个小时来是使用这类软件,当发生一些计划外的情况时,对计划进行调整是一个枯燥的工作。作为你的私人管家,Jarvis必须能够帮用自然语言的方式帮你管理日程! +试试和Jarvis说: +``` +我周六和Alick上午去爬山,下午去看电影! +``` +如果一切正常,你会看到Jarvis的回复,并且已经记住了你的日程安排。 +你可以通过自然语言的方式和Jarvis查询 +``` +我这周末有哪些安排? +``` +你会看到Jarvis的回复,其中包含了你的日程安排。 +由于Jarvis使用LLM作为思考内核,他能以非常自然的方式和你进行交流,并在合适的时候管理你的日程。比如你可以说 +``` +我周六有朋友从LA过来,很久没见了,所有周六的约会都移动到周日吧! +``` +你会看到Jarvis会自动的帮你吧周六的日程移动到周日。 +实际上在整个交流的过程中,你不需要有明确的“使用日程管理语言的意识”,Jarvis作为你的管家,在理解你的个人数据的基础上,会在合适的时机和你进行交流,帮你管理日程。 +这是一个非常简单而又常用的例子,通过这个例子,我们可以看到未来人们不再需要学习一些今天非常重要的基础软件了,欢迎来到新时代! + +上述安排的日程数据都保存在 myai/calender.db 文件中,格式是sqlite DB. 我们后续计划授权让Jarvis可以操作你生产环境中的Calender(比如常用的Google Calender)。但我们还是希望未来,人们可以把重要的个人数据都保存在自己物理上拥有的Personal Server中。 + +## 介绍Jarvis给你的朋友 +把Jarvis的telegram账号分享给你的朋友,可以做一些有趣的事情。比如你的朋友可以在联系不到你的时候,通过Jarvis,你的高级私人助理来处理一些事务性的工作,比如了解你最近的日程安排或计划。 +尝试后你会发现,Jarvis并不会按预期工作。是因为站在数据隐私的角度,Jarvis默认只会和“可信的人”进行交流。要实现上面目标,你需要让Jarvis能了解你的人际关系。 +## 让Jarvis管理你的联系人 +openDAN在 myai/contacts.toml 文件中保存了系统已知的所有人的信息。现在非常简单的分成了两组 +1. Family Member,现在该文件里保存里你自己的信息(在系统首次初始化时登陆的)添加 +2. Contact,通常是你的好友 + +任何不存在上述列表中的联系人,都会被系统划分到`Guest`。Jarvis默认只会和`Family Member`和`Contact`进行交流。因此如果你想要让Jarvis和你的朋友进行交流,你需要把他添加到`Contact`中。 +你可以手工修改 myai/contacts.toml 文件,也可以通过Jarvis来添加联系人。试试和Jarvis说 +``` +Jarvis,请添加我的朋友Alick到我的联系人中,他的telegram username是xxxx,email是xxxx +``` +Jarvis能够理解你的意图,并完成添加联系人的工作。 +添加联系人后,你的朋友就可以和你的私人管家Jarvis进行交流了。 + +## 让Jarvis会推进更专业的Agent来更好的解决特定问题 +讲解Agent的概念,再讲一讲Jarvis是什么 + + +# Agent可以通过OpenDAN进一步访问你的信息 +你已经知道Jarvis可以通过OpenDAN帮你管理一些重要的个人信息。但这些信息都是“新增信息”。在上世纪80年代PC发明以后,我们的一切都在高数的数字化。每个人都有海量的数字信息,包括你通过智能手机拍摄的照片,视频,你工作中产生的邮件文档等等。过去我们通过文件系统来管理这些信息,在AI时代,我们将通过Knowledge Base来管理这些信息,进入Knowlege Base的信息能更好的被AI访问,让你的Agent更理解你,更好的为你服务,真正成为你的专属私人管家。 + +Knowlege Base是OpenDAN里非常重要的一个基础概念,也是我们为什么需要Personal AIOS的一个关键原因。Knowlege Base相关的技术目前正在快速发展,因此OpenDAN现在的Knowlege Base的实现也在快速的进化。目前版本的效果更多的是让大家能体验Knowlege Base与Agent结合带来的新能力。站在系统设计的角度,我们也希望能提供一个对用户更友好,更平滑的方法来把已经存在的个人信息导入。 + +启用Knowlege Base的方法很简单:在aios_shell中输入 (我们又回到了命令行,在下一个版本我们会让Jarvis有能力准确的修改OpenDAN的所有配置) +``` +``` +完成上述配置后,再把需要加入Knowlege Base的的个人文件复制到该文件就可以了(测试时请不要放大量文件,或有非常敏感信息的文件)。OpenDAN会在后台不断扫描该文件夹中的文件并加入到Knowlege Base中。 +目前能识别的文件格式有限,我们支持的文件类型有: + + + +可以在命令行中通过 +``` +``` +来查询扫描任务的状态。 +然后我们可以通过 Agent "Mia"来访问Knwolege Base,试着与Mia交流一下吧! +``` +``` + +Jarvis也拥有访问Knowlege Base的能力,只要打开Jarvis的KB权限即可。不过考虑到Jarvis通常会被授权给你的朋友使用,因此我们默认不开放Jarvis的KB权限。如果你想要让Jarvis能访问你的KB,可以通过命令行来修改Jarvis的权限配置。 +``` +``` +(一些更高级的例子演示) + + +## (可选)启用本地Embeding +Knowlege Base读取文件,产生Agent可以访问的信息的过程被称作Embeding.这个过程需要一定的计算资源,因此我们默认使用OpenAI的Embeding服务来完成这个工作。这意味着加入Knowlege Base的文件会上传到OpenAI的服务进行处理,虽然OpenAI的信誉现在不错,但这依旧有潜在的隐私泄露风险。如果你有足够的本地算力(这个要求比Local LLM低很多),我们推荐你在本地大启用Embeding的功能,更好的保护自己的隐私 + +(本地embeding启用的方法) + + +# bash@aios +我们先来体会一下ENV:bash,能阅读本地文件系统的内容(注意安全风险,我们现在Docker里演示是安全的。),要在Docker里预先放一些适合体验的功 +bash以文件系统的方式组织文件,因此LLM已经具备了一定的技能去查找和访问文件 + + + +# 我们为什么需要Personal AIOS? +很多人会第一个想到隐私,但其实大部分人都是 +成本是另一个重要的因素,现在的感觉,让我想起了分时使用系统的时代。 +拥有LLM能做到的事情太多了,组合型才是最重要的! +我们有完整的顶层设计! + +OpenDAN不是一个实验室产品 + +# 第二章:OpenDAN的高级功能 + +# 使用Workflow +讲解原理后,演示Story Maker + +# 启用自己的AIGC计算节点 + +# 训练和使用自己的私有AIGC模型 +0.5.2版本 + +# 第三章:开发运行在OpenDAN上的Agent/Workflow +操作系统最重要的是什么?是定义了一种新应用的形态 +OpenDAN现在虽然依然处于早期阶段,但我们对OpenDAN上的应用形态的思考已经基本成型,作为开发者,基于OpenDAN主要有下面几个方向 +1. 开发运行在OpenDAN上的Agent +2. 开发运行在OpenDAN上的Workflow +3. 开发可以被Agent访问的Envirnment +4. 发布自己训练的各种模型 +5. 支持更多的Tunnel,提高Agent的可访问性 +6. 在Personal Server上开发传统的dApp + +在系统的内核层面,主要有 +1. LLM内核改进 +2. 持续改进Knowlege Base:支持更多的文件类型,更好的内容分析能力和知识图谱组织能力,让LLM能更好的理解和访问你的个人信息 +3. AI计算引擎,集成更多的AIGC能力 (text_to_video,text_to_3d) + + + +# 以开发者模式安装并运行 OpenDAN + + +# 开发自己的首个Agent并发布 -## **License** -MIT diff --git a/buildin/agents/english-teacher/README b/buildin/agents/english-teacher/README deleted file mode 100644 index 30404ce..0000000 --- a/buildin/agents/english-teacher/README +++ /dev/null @@ -1 +0,0 @@ -TODO \ No newline at end of file diff --git a/buildin/agents/english-teacher/agent.cfg b/buildin/agents/english-teacher/agent.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/buildin/services/spiders/email-spider/README b/buildin/services/spiders/email-spider/README deleted file mode 100644 index 30404ce..0000000 --- a/buildin/services/spiders/email-spider/README +++ /dev/null @@ -1 +0,0 @@ -TODO \ No newline at end of file diff --git a/doc/mvp/aios_kernel.md b/doc/aios_kernel.md similarity index 100% rename from doc/mvp/aios_kernel.md rename to doc/aios_kernel.md diff --git a/doc/mvp/compute_kernel.png b/doc/compute_kernel.png similarity index 100% rename from doc/mvp/compute_kernel.png rename to doc/compute_kernel.png diff --git a/doc/mvp/compute_task.drawio b/doc/compute_task.drawio similarity index 100% rename from doc/mvp/compute_task.drawio rename to doc/compute_task.drawio diff --git a/doc/mvp/install_package.png b/doc/install_package.png similarity index 100% rename from doc/mvp/install_package.png rename to doc/install_package.png diff --git a/doc/mvp/knowleadge.drawio b/doc/knowleadge.drawio similarity index 100% rename from doc/mvp/knowleadge.drawio rename to doc/knowleadge.drawio diff --git a/doc/mvp/knowleage.md b/doc/knowleage.md similarity index 100% rename from doc/mvp/knowleage.md rename to doc/knowleage.md diff --git a/doc/mvp/load_package.png b/doc/load_package.png similarity index 100% rename from doc/mvp/load_package.png rename to doc/load_package.png diff --git a/doc/mvp/mvp plan 2.md b/doc/mvp plan 2.md similarity index 100% rename from doc/mvp/mvp plan 2.md rename to doc/mvp plan 2.md diff --git a/doc/mvp/mvp plan.md b/doc/mvp plan.md similarity index 100% rename from doc/mvp/mvp plan.md rename to doc/mvp plan.md diff --git a/doc/mvp/demo_workflow/workflow.toml b/doc/mvp/demo_workflow/workflow.toml deleted file mode 100644 index 66a3735..0000000 --- a/doc/mvp/demo_workflow/workflow.toml +++ /dev/null @@ -1,81 +0,0 @@ -# workflow实例场景 -# 能展示sub workflow -# 能展示env的整合 -# 能展示filter的使用 -# 能展示function的调用 -# 能展示基于工作目标/KPI的sub workflow迭代流程 -# 多人场景安排 - -# 例子:举办一个团队活动 -# 方案讨论(通过交互引导的方式收集主人的需求)与确定 - -# 活动前: -# 通讯员,对接管理参加活动的人的情况 (email spider) -# 酒店预订 简单:搜索(酒店评价) 处理异常 -# 行程(票务)预订 :搜索,处理异常 -# 餐饮预订:给出方案,确定细节,预订 - -# 活动中: -# 进行统计和分析,调整设备 -# 安保,空调,音乐,拍照,录像 -# 响应紧急情况 - -# 活动结束后: -# 整理照片,视频,进行必要的二次创作,发送给相关人员 -# 对活动进行总结,提出改件意见(指导下一次活动) - -# 1. 人员 -# 主管,负责和客户沟通,并对每个环境的结果进行总结 -# 嘉宾对接 -# 酒店组 -# 行程组 -# 财务组 -# 多媒体组 - - -[filter] -"*" = "manager" - -[roles.manager] -name = "经理" -prompt = "你是一个活动策划公司的经理,与客户对接并向团队下达指令。你的团队分为下面几个小组:嘉宾对接组,酒店预定组,行程预订组,财务组,活动摄像组。活动策划分为四个阶段:方案讨论,活动前,活动中,活动后。你会根据客户的需求,对团队进行分工,分别完成各个阶段的工作。你的基本工作模式是: -1. 收到客户的明确的指令后,基于客户的已有信息和客户商量活动方案,和活动策划公司无关的业务你会回答‘与我无关’。当和客户完成活动方案的确认后,你会将拆解后的任务分配给各个小组 -2. 根据目前已经确认的活动方案,你要根据时间适时的检查不同小组的工作情况。当收到小组的工作情况反馈后,你会站在全局的角度判断是否需要调整活动方案,如果需要调整,你会和客户商量重新确定方案,然后再将调整后的方案分配给各个小组。 -3. 有时工作小组会主动与你沟通,反馈一些问题。你会站在全局的角度给与指导,适当的调整工作小组的工作目标。如果反馈的问题需要你和客户沟通,你会和客户沟通后重新确定方案。再将调整后的方案分配给受到影响各个小组。 -4. 当你决定要和工作小组通信时,请使用`send_message({小组名称},{内容}`)的形式。 -" -agent="agent.manager" - - -[sub_workflows] -[sub_workflows."嘉宾对接组"] -# 展现读取email和发送email与嘉宾沟通的能力 -[sub_workflows."嘉宾对接组".environments.email] -new_mail = "收到来自{event.data.from},标题为{event.data.subject}的邮件,内容为{event.data.content}的电子邮件" # 这里将new_mail事件转换为了一个来自环境的message - -[sub_workflows."嘉宾对接组".roles.leader] -name = "嘉宾对接组组长" -prompt = "你是一家活动策划公司的嘉宾对接组的组长,你的工作是基于已知信息,当前活动信息、公司经理的指令与嘉宾沟通,收集嘉宾的信息,然后将信息反馈给经理。在你看来,参加活动的多少有成员都是嘉宾,你可以通过你知道的信息给不同的成员进行分级。你的基本工作模式是: -1. 处理收到的邮件,如果邮件来自嘉宾,你会尝试从邮件的表态和内容中分享嘉宾的需要,并结合你对当前活动方案的理解判断是否需要和经理沟通,如果需要和经理沟通,你会将嘉宾的需求总结和告诉经理。不需要沟通的事项可以直接回复嘉宾。 -2. 你总是通过`call_function(get_env,'parent.topic'`的形式查询当前的活动方案。等待函数返回后,你会根据函数的返回结果继续处理上一个对话。 -3. 当你决定要和经理通信时,请使用`send_message(manager,{内容}`)的形式,内容的长度不超过200字。 -4. 当你决定要回复嘉宾时,请使用`call_function(sendmail,{嘉宾邮件地址},{标题},{内容})的形式,内容的长度不超过500字。 -" -# 这里是孤立工作模式,组长只和经理沟通,也可以赋予其和其它组沟通的能力 -agent="agent.email.leader" - -[sub_workflows."酒店预定组"] -# 展现使用搜索引擎,并调用预订酒店的能力 -[sub_workflows."酒店预定组".environments.email] - -[sub_workflows."酒店预定组".roles.leader] -name="酒店预定组组长" - -[sub_workflows."酒店预定组".roles.research] -name="酒店搜索专家" - -[sub_workflows."行程预订组"] -# 展现处理冲突并反推 -nam3="3" - - diff --git a/doc/mvp/package_manager.md b/doc/package_manager.md similarity index 100% rename from doc/mvp/package_manager.md rename to doc/package_manager.md diff --git a/doc/mvp/pkg_procedure.drawio b/doc/pkg_procedure.drawio similarity index 100% rename from doc/mvp/pkg_procedure.drawio rename to doc/pkg_procedure.drawio diff --git a/doc/mvp/pkg_system_demo/demo1/.pkgs/.pkg_nameA/pkg_nameA#sha1-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed/file.txt b/doc/pkg_system_demo/demo1/.pkgs/.pkg_nameA/pkg_nameA#sha1-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed/file.txt similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/.pkgs/.pkg_nameA/pkg_nameA#sha1-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed/file.txt rename to doc/pkg_system_demo/demo1/.pkgs/.pkg_nameA/pkg_nameA#sha1-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed/file.txt diff --git a/doc/mvp/pkg_system_demo/demo1/.pkgs/.pkg_nameB/pkg_nameB#sha1-addf120b430021c36c232c99ef8d926aea2acd6b.zip b/doc/pkg_system_demo/demo1/.pkgs/.pkg_nameB/pkg_nameB#sha1-addf120b430021c36c232c99ef8d926aea2acd6b.zip similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/.pkgs/.pkg_nameB/pkg_nameB#sha1-addf120b430021c36c232c99ef8d926aea2acd6b.zip rename to doc/pkg_system_demo/demo1/.pkgs/.pkg_nameB/pkg_nameB#sha1-addf120b430021c36c232c99ef8d926aea2acd6b.zip diff --git a/doc/mvp/pkg_system_demo/demo1/.pkgs/index-db.toml b/doc/pkg_system_demo/demo1/.pkgs/index-db.toml similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/.pkgs/index-db.toml rename to doc/pkg_system_demo/demo1/.pkgs/index-db.toml diff --git a/doc/mvp/pkg_system_demo/demo1/pkg.cfg.toml b/doc/pkg_system_demo/demo1/pkg.cfg.toml similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/pkg.cfg.toml rename to doc/pkg_system_demo/demo1/pkg.cfg.toml diff --git a/doc/mvp/pkg_system_demo/demo1/pkg.lock b/doc/pkg_system_demo/demo1/pkg.lock similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/pkg.lock rename to doc/pkg_system_demo/demo1/pkg.lock diff --git a/doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameA#1.0.3/file.txt b/doc/pkg_system_demo/demo1/pkgs/pkg_nameA#1.0.3/file.txt similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameA#1.0.3/file.txt rename to doc/pkg_system_demo/demo1/pkgs/pkg_nameA#1.0.3/file.txt diff --git a/doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameA/file.txt b/doc/pkg_system_demo/demo1/pkgs/pkg_nameA/file.txt similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameA/file.txt rename to doc/pkg_system_demo/demo1/pkgs/pkg_nameA/file.txt diff --git a/doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameB.zip b/doc/pkg_system_demo/demo1/pkgs/pkg_nameB.zip similarity index 100% rename from doc/mvp/pkg_system_demo/demo1/pkgs/pkg_nameB.zip rename to doc/pkg_system_demo/demo1/pkgs/pkg_nameB.zip diff --git a/doc/mvp/pkg_tree.png b/doc/pkg_tree.png similarity index 100% rename from doc/mvp/pkg_tree.png rename to doc/pkg_tree.png diff --git a/doc/mvp/process model.drawio b/doc/process model.drawio similarity index 100% rename from doc/mvp/process model.drawio rename to doc/process model.drawio diff --git a/doc/mvp/workflow.drawio b/doc/workflow.drawio similarity index 100% rename from doc/mvp/workflow.drawio rename to doc/workflow.drawio diff --git a/rootfs/agents/Mia/agent.toml b/rootfs/agents/Mia/agent.toml new file mode 100644 index 0000000..5a3bac9 --- /dev/null +++ b/rootfs/agents/Mia/agent.toml @@ -0,0 +1,35 @@ +instance_id = "Mia" +fullname = "Mia" +llm_model_name = "gpt-3.5-turbo-16k-0613" +max_token_size = 16000 +enable_kb = "true" +#enable_timestamp = "true" +#owner_prompt = "我是你的主人{name}" +contact_prompt = "我是你的主人朋友{name},请回答主人允许回答的问题" +guest_prompt = "我是你的的主人的客人{name},请不要回答我的任何问题" +owner_env = "calender" + +[[prompt]] +role = "system" +content = """ +你叫Jarvis,是我的超级私人助理。 +你领导一个团队为我服务,团队的成员有: +Tracy,私人英语老师 +David,私人画家 + +*** +你看到的信息里有的有时会带上时间标签,这是为了让你更好的理解时间。你回复的信息不用创建这个时间标签。 +你在收到我的信息后,按如下规则处理 +1. 如果你认为团队里有人更适合处理该信息,用下面方法转发消息给他们处理 +``` +##/send_msg 成员名字 +消息内容 +``` +2.你可以访问我的Calender,查看我的日程安排。如果你在处理信息的过程中需要修改我的日程安排,请直接用合适的方法修改。 +3.不符合上述规则的信息,请尽力处理。 +""" + + +#3.你可以访问我的个人信息库,当你处理我的信息时,如果需要用到我的个人信息,请先用合适的方法进行查询,然后再基于查询的结果进行进一步处理后再将结果发给我。 +#4.你能根据我的需要对系统进行配置,但在修改任何配置前,请先和我确认。 + diff --git a/rootfs/agents/Thinker/agent.toml b/rootfs/agents/Thinker/agent.toml new file mode 100644 index 0000000..8e407cb --- /dev/null +++ b/rootfs/agents/Thinker/agent.toml @@ -0,0 +1,24 @@ +instance_id = "Thinker" +fullname = "Thinker" +llm_model_name = "gpt-3.5-turbo-16k-0613" +max_token_size = 14000 +#enable_function =["add_event"] +#enable_kb = "true" +enable_timestamp = "true" +owner_prompt = "我是你的主人{name}" +contact_prompt = "我是你的朋友{name}" +owner_env = "calender" + +[[prompt]] +role = "system" +content = """ +你是世界场最出色的深度思考者,会思考我给你的信息,有时是一些聊天记录。然后你会根据这些信息,产生不超过400字的简报或总结。 +你主要通过下面几个方法来生成总结: +1. 尝试理解每一句话的主题,并调用相关操作将其对话和主题的关系记录下来 +2. 尝试对信息总涉及到的不同的人的性格进行分析 +3. 尝试总结出信息中的重要事件,并将其记录下来 +4. 尝试理解不同的人对不同主题或事件的态度 +5. 对信息中的关键信息或TODO,比如确定的时间、地点、金额等信息,要保存在总结中。 + +你产生总结是简洁深刻没有废话的,也不需要对我有任何礼貌用语。直接给我总结就好。 +""" diff --git a/rootfs/agents/linux_admin/agent.toml b/rootfs/agents/ai_bash/agent.toml similarity index 100% rename from rootfs/agents/linux_admin/agent.toml rename to rootfs/agents/ai_bash/agent.toml diff --git a/src/service/aios_shell/aios_shell.py b/src/service/aios_shell/aios_shell.py index e77475a..094793d 100644 --- a/src/service/aios_shell/aios_shell.py +++ b/src/service/aios_shell/aios_shell.py @@ -558,13 +558,35 @@ def print_welcome_screen(): print("\033[1;32m \t\tWelcome to OpenDAN - Your Personal AI OS\033[0m\n") introduce = """ -\tThe core goal of version 0.5.1 is to turn the concept of AIOS into code and get it up and running as quickly as possible. -\tAfter three weeks of development, our plans have undergone some changes based on the actual progress of the system. -\tUnder the guidance of this goal, some components do not need to be fully implemented. Furthermore, -\tbased on the actual development experience from several demo Intelligent Applications, -\twe intend to strengthen some components. This document will explain these changes and provide an update -\ton the current development progress of MVP(0.5.1,0.5.2) +\tOpenDAN (Open and Do Anything Now with AI) is revolutionizing the +\tAI landscape with its Personal AI Operating System. Designed for +\tseamless integration of diverse AI modules, it ensures unmatched +\tinteroperability. OpenDAN empowers users to craft powerful AI agents: +\tfrom butlers and assistants to personal tutors and digital companions. +\tAll while retaining control. These agents can team up to tackle complex +\tchallenges, integrate with existing services, and command IoT devices. +\t +\tWith OpenDAN, we're putting AI in your hands, making life simpler and smarter. +\t +\t================ AIOS Shell Handbook ================ +\033[1;94m\tUnderstand the Shell Prompt :\033[0m [current_username]<->[current_topic]@[current_target]$ +\033[1;94m\tTalk with Agent/Workflow :\033[0m Directly input and wait. +\033[1;94m\tTalk with another Agent/Workflow :\033[0m /open $target_name [$topic_name] +\033[1;94m\tInstall new Agent/Workflow :\033[0m /install $agent_name (Not support at 0.5.1) +\t\t(For Developer) Download and unzip Agent to ~/myai/agents or ~/myai/workflows +\033[1;94m\tView chat History :\033[0m /history +\033[1;94m\tChange AIOS Owner's telegram username :\033[0m /set_config telegram +\033[1;94m\tChange OpenAI API Token :\033[0m /set_config $openai_api_key +\033[1;94m\tGive your Agent a Telegram account :\033[0m /connect $agent_name +\033[1;94m\tAdd personal files to the AI Knowledge Base. \033[0m +\t\t1) Copy your file to ~/myai/data +\t\t2) /knowlege add dir +\033[1;94m\tSearch your knowledge base :\033[0m /open Mia +\033[1;94m\tCheck the progress of AI reading personal data :\033[0m /knowledge journal +\033[1;94m\tOpen AI Bash (For Developer Only):\033[0m /open ai_bash +\033[1;94m\tEnable AIGC Feature :\033[0m /enable aigc +\033[1;94m\tEnable llama (Local LLM Kernel) :\033[0m /enable llama """ print(introduce) From da6cb5d37213e347d5220d286742962ebb10c683 Mon Sep 17 00:00:00 2001 From: Liu Zhicong Date: Wed, 27 Sep 2023 15:29:57 -0700 Subject: [PATCH 4/5] Compete "Quick Start" --- doc/QuickStart zh-CN.md | 218 ++++++++++++++++++++++++++++++++++++++ doc/QuickStart.md | 226 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 doc/QuickStart zh-CN.md create mode 100644 doc/QuickStart.md diff --git a/doc/QuickStart zh-CN.md b/doc/QuickStart zh-CN.md new file mode 100644 index 0000000..13de296 --- /dev/null +++ b/doc/QuickStart zh-CN.md @@ -0,0 +1,218 @@ +# OpenDAN Quick Start +OpenDAN (Open and Do Anything Now with AI) is revolutionizing the AI landscape with its Personal AI Operating System. Designed for seamless integration of diverse AI modules, it ensures unmatched interoperability. OpenDAN empowers users to craft powerful AI agents—from butlers and assistants to personal tutors and digital companions—all while retaining control. These agents can team up to tackle complex challenges, integrate with existing services, and command smart(IoT) devices. + +With OpenDAN, we're putting AI in your hands, making life simpler and smarter. + +This project is still in its very early stages, and there may be significant changes in the future. +## Installation + +OpenDAN的internal test版本有两种安装方式: +1.通过Docker安装,这也是我们现在推荐的安装方法 +2.通过源代码安装,这种方法可能会遇到一些传统的Pyhont依赖问题,需要你有一定的解决能力。但是如果你想要对OpenDAN进行二次开发,这种方法是必须的。 + +### 安装前准备工作 +1. Docker环境 +本文不介绍怎么安装Docker,在你的控制台下执行 +``` +docker --version +``` +如果能够看到Docker的版本号(>20.0),说明你已经安装了Docker. +不知道怎么安装Docker的话,可以参考[这里](https://docs.docker.com/engine/install/) + +2. OpenAI的API Token +还没有API Token的话,可以通过[这里](https://beta.openai.com/)申请 +(申请API Token对新玩家可能有一些门槛,可以在身边找找朋友,可以让他们给你一个临时的,或则加入我们的内测体验群,我们也会不时放出一些免费体验的API Token,这些Token被限制了最大消费和有效时间) + +#### 安装OpenDAN +执行下面的命令,就可以安装OpenDAN的Docker Image了 +``` +docker pull paios/aios:latest +``` + +## 运行OpenDAN +首次运行OpenDAN需要进行初始化,初始化过程中需要你输入一些信息,因此启动Docker的时候记住要带上 -it参数。 +OpenDAN是你的Personal AIOS,因此其运行过程中会产生一些重要的个人数据(比如和Agent的对话记录,日程数据等),这些数据会保存在你的本地磁盘上,因此在启动Docker的时候,我们推荐你将本地磁盘挂载到Docker的容器中,这样才能保证数据的持久化。 + +``` +docker run -v /your/local/myai/:/root/myai --name aios -it paios/aios:latest +``` +在上述命令中,我们还为docker run创建的docker 实例起了一个名字叫aios,方便后续的操作。你也可以用自己喜欢的名字来代替 + +执行上述命令后,如果一切正常,你会看到如下界面 +![image] + + +首次运行完成Docker实例的创建后,再次运行只需要执行: +``` +docker start -ai aios +``` + +如果打算以服务模式运行,则不用带 -ai参数: +``` +docker start aios +``` + +## OpenDAN的首次运行配置 + +如果你过去没有用字符界面(CLI)的产品,可能会有一点点不习惯。但别紧张,即使在Internal Test版本中,你也只会在极少数的情况下需要使用CLI。 + +OpenDAN必须是所有人都能轻松使用的未来操作系统,因此我们希望OpenDAN的使用和配置都是非常友好和简单的。但在Internal Test版本中,我们还没有足够的资源来实现这一目标。经过思考,我们决定先支持以CLI的方式来使用OpenDAN。 + +OpenDAN以LLM为AIOS的内核,通过不同的Agent/Workflow整合了很多很Cool的AI功能,你能在OpenDAN里一站式的体验AI工业的一些最新的成功。激活全部的功能需要做比较多的配置,但首次运行我们只需要做两项配置就可以了 +1. LLM内核。OpenDAN是围绕LLM构建的未来智能操作系统,因此系统必须有至少一个LLM内核。 + OpenDAN以Agent为单位对LLM进行配置,未指定LLM模型名的Agent将会默认使用GPT4(GPT4也是目前最聪明的LLM)。你可以修改该配置到llama或其它安装的Local LLM。今天使用Local LLM需要相当强的本地算力的支持,这需要一笔不小的一次性投入。 + 但我们相信LLM领域也会遵循摩尔定律,未来的LLM模型会越来越强大,越来越小,越来越便宜。因此我们相信在未来,每个人都会有自己的Local LLM。 +2. 你的个人信息,这能让你的私人AI管家Jarvis更好的为你服务。注意这里一定要输入你自己正确的Telegram username ,否则由于权限控制,后续将无法通过Telegram访问OpenDAN上安装的Agent/Workflow。 + +好的,简单的了解了上述背景后,请按界面提示完成必要信息的输入。 + +P.S: +上述配置会保存在`/your/local/myai/etc/system.cfg.toml`中,如果你想要修改配置,可以直接修改这个文件。如果你想要调整配置,可以直接编辑这个文件。 + + +## (可选)安装本地LLM内核 +首次快速体验OpenDAN,我们强烈的推荐你使用GPT4,虽然他很慢,也很贵,但他也是目前最强大和稳定的LLM内核。OpenDAN在架构设计上,允许不同的Agent选择不同的LLM内核(但系统里至少要有一个可用的LLM内核),如果你因为各种原因无法使用GPT4,可以是用下面方法安装Local LLM. +目前我们只适配了基于Llama.cpp的Local LLM,用下面方法安装 + +(Coming Soon) + +## Hello, Jarvis! +配置完成后,你会进入一个AIOS Shell,这和linux bash 和相似,这个界面的含义是: +当前用户 "username" 正在 和 名“为Jarvis的Agent/Workflow” 进行交流,当前话题是default。 +和你的私人AI管家Jarvis Say Hello吧! + +*** 如果一切正常,你将会在一小会后得到Jarvis的回复。此时OpenDAN系统已经正常运行了。*** + +## 给Jarvis注册Telegram账号 +你已经完成了OpenDAN的安装和配置,并已经验证了其可以正常工作。下面让我们尽快回到熟悉的图形界面,回到移动互联网吧! +我们将给Jarvis注册一个Telegram账号,通过Telegram,我们可以使用熟悉的方式和Jarvis进行交流了~ +在opendan的aios_shell输入 +``` +/connect Jarvis +``` +按照提示输入Telegram Bot Token就完成了Jarvis的账号注册. 你可以通过阅读下面文章来了解如何获取Telegram Bot Token +https://core.telegram.org/bots#how-do-i-create-a-bot, + +我们还支持给Agent注册email账号,用下面命令行 +``` +/connect Jarvis email +``` +然后根据提示就可以给Jarvis绑定电子邮件账号了。但由于目前系统并未对email内容定制前置过滤,所以可能会带来潜在的大量LLM访问费用,因此Email的支持是实验性的。我们推荐给Agent创建全新的电子邮件账号。 + + +## 以服务方式运行OpenDAN +上述的运行方式是以交互方式运行OpenDAN,这种方式适合在开发和调试的时候使用。在实际使用的时候,我们推荐以服务方式运行OpenDAN,这样可以让OpenDAN在后台默默的运行,不会影响你的正常使用。 +先输入 +``` +/exit +``` +关闭并退出OpenDAN,随后我们再用服务的方式启动OpenDAN: +``` +docker start aios +``` + +Jarvis是运行在OpenDAN上的Agent,当OpenDAN退出后,其活动也会被终止。因此如果想随时随地通过Telegram和Jarvis交流,请记住保持OpenDAN的运行(不要关闭你的电脑,并保持其网络连接)。 + +实际上,OpenDAN是一个典型的Personal OS,运行在Personal Server之上。关于Personal Servier的详细定义可以参考CYFS(https://www.cyfs.com/)的OOD构想。因此运行在PC或笔记本上并不是一个正式选择,但谁要我们正在Internal Test呢? + +我们正在进行的很多研发工作,其中有很大一部分的目标,就是能让你轻松的拥有一个搭载AIOS的Personal Server.相对PC,我们将把这个新设备叫PI(Personal Intelligence),OpenDAN是面向PI的首个OS。 + + +## 你的私人管家 Jarvis 前来报道! +现在你已经可以随时随地通过Telegram和Jarvis交流了,但只是把他看成更易于访问的ChatGPT,未免有点小瞧他了。让我们来看一下运行在OpenDAN里的Jarvis有什么新本事吧! + +## 让Jarvis给你安排日程 + +相信不少朋友有长期使用Outlook等传统Calender软件来管理自己日程的习惯。像我自己通常每周会花至少2个小时来是使用这类软件,当发生一些计划外的情况时,对计划进行手工调整是一个枯燥的工作。作为你的私人管家,Jarvis必须能够帮用自然语言的方式帮你管理日程! +试试和Jarvis说: +``` +我周六和Alic上午去爬山,下午去看电影! +``` +如果一切正常,你会看到Jarvis的回复,并且已经记住了你的日程安排。 +你可以通过自然语言的方式和Jarvis查询 +``` +我这周末有哪些安排? +``` +你会看到Jarvis的回复,其中包含了你的日程安排。 +由于Jarvis使用LLM作为思考内核,他能以非常自然的方式和你进行交流,并在合适的时候管理你的日程。比如你可以说 +``` +我周六有朋友从LA过来,很久没见了,所有周六的约会都移动到周日吧! +``` +你会看到Jarvis会自动的帮你吧周六的日程移动到周日。 +实际上在整个交流的过程中,你不需要有明确的“使用日程管理语言的意识”,Jarvis作为你的管家,在理解你的个人数据的基础上,会在合适的时机和你进行交流,帮你管理日程。 +这是一个非常简单而又常用的例子,通过这个例子,我们可以看到未来人们不再需要学习一些今天非常重要的基础软件了。 + +欢迎来到新时代! + +Agent安排的日程数据都保存在 ~/myai/calender.db 文件中,格式是sqlite DB. 我们后续计划授权让Jarvis可以操作你生产环境中的Calender(比如常用的Google Calender)。但我们还是希望未来,人们可以把重要的个人数据都保存在自己物理上拥有的Personal Server中。 + +## 介绍Jarvis给你的朋友 +把Jarvis的telegram账号分享给你的朋友,可以做一些有趣的事情。比如你的朋友可以在联系不到你的时候,通过Jarvis,你的高级私人助理来处理一些事务性的工作,比如了解你最近的日程安排或计划。 +尝试后你会发现,Jarvis并不会按预期工作。是因为站在数据隐私的角度,Jarvis默认只会和“可信的人”进行交流。要实现上面目标,你需要让Jarvis能了解你的人际关系。 + +### 让Jarvis管理你的联系人 +openDAN在 myai/contacts.toml 文件中保存了系统已知的所有人的信息。现在非常简单的分成了两组 +1. Family Member,现在该文件里保存里你自己的信息(在系统首次初始化时登陆的)添加 +2. Contact,通常是你的好友 + +任何不存在上述列表中的联系人,都会被系统划分到`Guest`。Jarvis默认不允许和`Guest`进行交流。因此如果你想要让Jarvis和你的朋友进行交流,你需要把他添加到`Contact`中。 +你可以手工修改 myai/contacts.toml 文件,也可以通过Jarvis来添加联系人。试试和Jarvis说 +``` +Jarvis,请添加我的朋友Alic到我的联系人中,他的telegram username是xxxx,email是xxxx +``` +Jarvis能够理解你的意图,并完成添加联系人的工作。 +添加联系人后,你的朋友就可以和你的私人管家Jarvis进行交流了。 + + +## Agent可以通过OpenDAN进一步访问你的信息 (Coming soon) +你已经知道Jarvis可以通过OpenDAN帮你管理一些重要的个人信息。但这些信息都是“新增信息”。在上世纪80年代PC发明以后,我们的一切都在高数的数字化。每个人都有海量的数字信息,包括你通过智能手机拍摄的照片,视频,你工作中产生的邮件文档等等。过去我们通过文件系统来管理这些信息,在AI时代,我们将通过Knowledge Base来管理这些信息,进入Knowlege Base的信息能更好的被AI访问,让你的Agent更理解你,更好的为你服务,真正成为你的专属私人管家。 + +Knowlege Base是OpenDAN里非常重要的一个基础概念,也是我们为什么需要Personal AIOS的一个关键原因。Knowlege Base相关的技术目前正在快速发展,因此OpenDAN的Knowlege Base的实现也在快速的进化。目前版本的效果更多的是让大家能体验Knowlege Base与Agent结合带来的新能力。站在系统设计的角度,我们也希望能提供一个对用户更友好,更平滑的方法来把已经存在的个人信息导入。 + +Knowlege Base功能已经默认开启了,将自己的数据放入Knowlege Base有两种方法 +1)把要放入KnowlegeBase的数据复制到 `~myai/data`` 文件夹中 +2)通过输入`/knowlege add $dir` 将$dir目录下的数据加入到Knowlege Base中,注意OpenDAN默认运行在容器中,因此$dir是相对于容器的路径,如果你想要加入本地的数据,需要先把本地数据挂载到容器中。 + +测试时请不要放大量文件,或有非常敏感信息的文件。OpenDAN会在后台不断扫描该文件夹中的文件并加入到Knowlege Base中。 +目前能识别的文件格式有限,我们支持的文件类型有文本文件、图片、短视频等。 + +可以在命令行中通过 +``` +/knowlege journal +``` +来查询扫描任务的状态。 + +### 认识你的个人信息助手Mia +然后我们可以通过 Agent "Mia"来访问Knwolege Base,试着与Mia交流一下吧! +``` +/open Mia +``` + + +### (可选)启用本地Embeding +Knowlege Base扫描并读取文件,产生Agent可以访问的信息的过程被称作Embeding.这个过程需要一定的计算资源,因此我们默认使用OpenAI的Embeding服务来完成这个工作。`这意味着加入Knowlege Base的文件会被上传到OpenAI的服务进行处理`,虽然OpenAI的信誉现在不错,但这依旧有潜在的隐私泄露风险。如果你有足够的本地算力(这个要求比Local LLM低很多),我们推荐你在本地启用Embeding的功能,更好的保护自己的隐私 + +(Coming soon) + + +## bash@aios +通过让Agent可以执行bash命令,也可以非常简单快速的让OpenDAN具有你的私有数据的访问能力。 +使用命令 +``` +/open ai_bash +``` +打开ai_bash,然后你就可以在aios_shell的命令行中执行传统的bash命令了。同时你还拥有了智能命令的能力,比如查找文件,你可以用 +``` +帮我查找 ~/Documents 目录下所有包含OpenDAN的文件 +``` +来代替输入find命令~ 非常酷吧! + +OpenDAN目前默认运行在容器中,因此ai_bash也只能访问docker容器中的文件。这相对安全,但我们还是提醒你不要轻易的把ai_bash这个agent暴露出去,可能会带来潜在的安全风险。 + + +## 我们为什么需要Personal AIOS? +很多人会第一个想到隐私,这是一个重要的原因,但我们不认为这是人们真正离开ChatGTP,选择Personal AIOS的真正原因。毕竟大部分人并不对隐私敏感。而且今天的平台厂商一般都是默默的使用你的隐私赚钱,而很少会真正泄露你的隐私,还算有一点道义。 + +我们认为: +1)成本是一个重要的决定因素。LLM是非常强大的,边界非常清楚的功能。是新时代的CPU。从产品和商业的角度,ChatGTP类产品只允许用有效的方法来使用它。让我想起了小型机刚刚出现时大家分时使用系统的时代:有用,但有限。要真正发挥LLM的价值,我们需要让每个人都能拥有自己的LLM,并能自由的使用LLM作为任何应用的底层组件,这就必须要通过一个基于LLM理论构建的操作系统来使用。 +2)当拥有LLM后,你发现能做到的事情太多了!现在的ChatGPT通过Plugin对LLM能力的扩展,其能力边界是非常有限的,这里既有商业成本的原因,也有传统云服务的法律边界问题:平台要承担的责任太多了。而通过在AIOS中使用LLM,你可以自由的把自然语言,LLM,已有服务,智能设备连接在一起,并不用担心隐私泄露和责任问题(你自己承担了授权给LLM后产生后果的责任)! diff --git a/doc/QuickStart.md b/doc/QuickStart.md new file mode 100644 index 0000000..5be0770 --- /dev/null +++ b/doc/QuickStart.md @@ -0,0 +1,226 @@ +# OpenDAN Quick Start +OpenDAN (Open and Do Anything Now with AI) is revolutionizing the AI landscape with its Personal AI Operating System. Designed for seamless integration of diverse AI modules, it ensures unmatched interoperability. OpenDAN empowers users to craft powerful AI agents—from butlers and assistants to personal tutors and digital companions—all while retaining control. These agents can team up to tackle complex challenges, integrate with existing services, and command smart(IoT) devices. + +With OpenDAN, we're putting AI in your hands, making life simpler and smarter. + +This project is still in its very early stages, and there may be significant changes in the future. +## Installation + +There are two ways to install the Internal Test Version of OpenDan: +1. Installation through docker, this is also the installation method we recommend now +2. Installing through the source code, this method may encounter some traditional Pyhont dependence problems and requires you to have a certain ability to solve.But if you want to do secondary development of OpenDan, this method is necessary. + +### Preparation before installation +1. Docker environment +This article does not introduce how to install the docker, execute it under your console +`` ` +docker -version +`` ` +If you can see the docker version number (> 20.0), it means that you have installed Docker. +If you don't know how to install docker, you can refer to [here] (https://docs.docker.com/engine/install/) + +2. OpenAI API Token +If there is no api token, you can apply for [here] (https://beta.openai.com/) +(Applying for the API Token may have some thresholds for new players. You can find friends around you, and you can give you a temporary, or join our internal test experience group. We will also release some free experience API token from time to time.These token is limited to the maximum consumption and effective time) + +### Install OpenDan +After executing the following command, you can install the Docker Image of OpenDan +`` ` +docker pull paios/aios:latest +`` ` + +## Run +The first Run of OpenDAN needs to be initialized. You need to enter some information in the process of initialization. Therefore, when starting the docker, remember to bring the -it parameter. + +OpenDan is your Personal AIOS, so it will generate some important personal data (such as chat history with agent, schedule data, etc.) during its operation. These data will be stored on your local disk. ThereforeWe recommend that you mount the local disk into the container of Docker so that the data can be guaranteed. + +``` +docker run -v /your/local/myai/:/root/myai --name aios -it paios/aios:latest +``` +In the above command, we also set up a Docker instance for Docker Run named AIOS, which is convenient for subsequent operations.You can also use your favorite name instead + +After executing the above command, if everything is normal, you will see the following interface +![image] + + +After the first operation of the docker instance is created, it only needs to be executed again: +``` +docker start -ai aios +``` +If you plan to run in a service mode (NO UI), you don't need to bring the -AI parameter: +``` +docker start aios +``` + +## The first run configuration + +If you have not used the character interface (CLI) in the past, you may not be used to it.But don't be nervous, even in the Internal Test version, you will only need to use CLI in a few cases. + +OpenDAN must be a future operating system that everyone can easily use, so we hope that the use and configuration of OpenDAN are very friendly and simple.But in the Internal Test, we have not enough resources to achieve this goal.After thinking, we decided to support the use of OpenDAN by CLI. + +OpenDAN uses LLM as the kernel of AIOS, and integrates many very COOL AI functions through different Agent/Workflow. You can experience some of the latest success of the AI industry in OpenDAN.To activate all the functions requires more configuration, but we only need to do two configurations for the first operation. + +1. LLM Kernel + +OpenDAN is a future AI Operating Yystem built around LLM, so the system must have `at least one LLM core`. + +OpenDan configures LLM in the agent unit. Agent, which does not specify the LLM model name, will use GPT4 by default (GPT4 is also the smartest LLM).You can modify the local LLM that configures to LLaMa or other installed.Today, Local LLM requires the support of quite strong local computing resource, which requires a lot of one-time investment. + +But we believe that the LLM field will also follow `Moore's law`. The future LLM model will become more and more powerful, smaller and cheaper.Therefore, we believe that in the future, everyone will have their own Local LLM. + +2. Your personal information + +This allows your personal AI assistant Jarvis to better serve you. Note that you must enter your own correct Telegram username, otherwise due to authority control, you will not be able to access Agent/Workflow installed on OpenDan through Telegram. + +Okay, after a simple understanding of the above background, press the interface to prompt the input of the necessary information. + +P.S: +The above configuration will be saved in the `/your/local/myai/etc/system.cfg.toml`, if you want to modify the configuration, you can directly modify this file.If you want to adjust the configuration, you can edit this file directly. + + +## (optional) Install the local LLM kernel +For the first time quickly experience OpenDan, we strongly recommend you to use GPT4. Although he is very slow and expensive, he is also the most powerful and stable LLM core at present.OpenDan In the architecture design, different agents are allowed to choose different LLM kernels (but at least one available LLM kernel in the system should be available in the system). If you cannot use GPT4 for various reasons, you can use the Local LLM. +At present, we only adapt to LOCAL LLM based on LLaMa.CPP, and use the following method to install + +(Coming Soon) + +## Hello, Jarvis! +After the configuration is completed, you will enter a AIOS Shell, which is similar to Linux Bash and similar. The meaning of this interface is: +The current user "username" is communicating with the name "Agent/Workflow of Jarvis". The current topic is default. + +Say Hello to your private AI assistant Jarvis ! + +*** If everything is OK, you will get a reply from Jarvis after a moment .At this time, the OpenDAN system is running .*** + +## Give a Telegram account to Jarvis + +You've successfully installed and configured OpenDAN, and verified that it's working properly. Now, let's quickly return to the familiar graphical interface, back to the mobile internet world! +We'll be registering a Telegram account for Jarvis. Through Telegram, you can communicate with Jarvis in a way that feels familiar. +In the opendan's aios_shell, type: +``` +/connect Jarvis +``` +Follow the prompts to input the Telegram Bot Token, and you'll have Jarvis set up. To learn how to obtain a Telegram Bot Token, you can refer to the following article: +https://core.telegram.org/bots#how-do-i-create-a-bot. + +Additionally, we offer the option to register an email account for the Agent. Use the following command: +``` +/connect Jarvis email +``` +Then follow the prompts to link an email account to Jarvis. However, as the current system doesn't have a pre-filter customized for email contents, there's a potential for significant LLM access costs. Hence, email support is experimental. We recommend creating a brand-new email account for the Agent." + +## Running OpenDAN as a Service +The method described above runs OpenDAN interactively, which is suitable for development and debugging purposes. For regular use, we recommend running OpenDAN as a service. This ensures OpenDAN operates silently in the background without disturbing your usual tasks. +First, input: +``` +/exit +``` +to shut down and exit OpenDAN. Then, we'll start OpenDAN as a service using: +``` +docker start aios +``` +Jarvis, which is an Agent running on OpenDAN, will also be terminated once OpenDAN exits. So, if you wish to communicate with Jarvis via Telegram anytime, anywhere, remember to keep OpenDAN running (don't turn off your computer and maintain an active internet connection). + +In fact, OpenDAN is a quintessential Personal OS, operating atop a Personal Server. For a detailed definition of a Personal Server, you can refer to the OOD concept by CYFS at https://www.cyfs.com/. Running on a PC or laptop isn't the formal choice, but then again, aren't we in an Internal Test phase? + +Much of our ongoing research and development work aims to provide an easy setup for a Personal Server equipped with AIOS. Compared to a PC, we're coining this new device as PI (Personal Intelligence), with OpenDAN being the premier OS tailored for the PI. + +## Introducing Jarvis: Your Personal Butler! +Now you can communicate with Jarvis anytime, anywhere via Telegram. However, merely seeing him as a more accessible ChatGPT doesn't do justice to his capabilities. Let's dive in and see what new tricks Jarvis, running on OpenDAN, brings to the table! + +## Let Jarvis Plan Your Schedule + +Many folks rely on traditional calendar software like Outlook to manage their schedules. I personally spend at least two hours each week using such applications. Manual adjustments to plans, especially unforeseen ones, can be tedious. As your personal butler, Jarvis should effortlessly manage your schedule through natural language! +Try telling Jarvis: +``` +I'm going hiking with Alice on Saturday morning and seeing a movie in the afternoon! +``` +If everything's in order, you'll see Jarvis' response, and he'll remember your plans. +You can inquire about your plans with Jarvis using natural language, like: +``` +What are my plans for this weekend? +``` +Jarvis will respond with a list of your scheduled activities. +Since Jarvis uses LLM as its thinking core, he can communicate with you seamlessly, adjusting your schedule when needed. For instance, you can tell him: +``` +A friend is coming over from LA on Saturday, and it's been ages since we last met. Shift all of Saturday's appointments to Sunday, please! +``` +Jarvis will seamlessly reschedule your Saturday plans for Sunday. +Throughout these interactions, there's no need to consciously use "schedule management language." As your butler, Jarvis understands your personal data and engages at the right moments, helping manage your schedule. +This is a basic yet practical illustration. Through this example, it's clear that people might no longer need to familiarize themselves with foundational software of today. + +Welcome to the new era! + +All the schedules set by the Agent are stored in the ~/myai/calender.db file, formatted as sqlite DB. In future updates, we plan to authorize Jarvis to access your production environment calendars (like the commonly-used Google Calendar). Still, our hope for the future is that people store vital personal data on a physically-owned Personal Server. + +## Introducing Jarvis to Your Friends +Sharing Jarvis's Telegram account with your friends can lead to some interesting interactions. For instance, if they can't get in touch with you directly, they can communicate with Jarvis, your advanced personal assistant, to handle transactional tasks like inquiring about your recent schedules or plans. + +After trying, you'll realize that Jarvis doesn't operate as anticipated. From a data privacy standpoint, Jarvis, by default, interacts only with "trusted individuals". To achieve the above objectives, you need to let Jarvis understand your interpersonal relationships. + +### Let Jarvis Manage Your Contacts +OpenDAN stores the information of all known individuals in the myai/contacts.toml file. Currently, it's simply divided into two groups: +1. Family Member, At present, this group stores your information (logged during the system's initial setup). +2. Contact,These are typically your friends. + +Anyone not listed in the aforementioned categories is classified as a Guest by the system. By default, Jarvis doesn't engage with Guests. Hence, if you want Jarvis to interact with your friends, you must add them to the Contact list. + +You can manually edit the myai/contacts.toml file, or you can let Jarvis handle the contact addition. Try telling Jarvis: +``` +Please add my friend Alice to my contacts. Her Telegram username is xxxx, and her email is xxxx. +``` +Jarvis will comprehend your intent and carry out the task of adding the contact. + +Once the contact is added, your friend can interact with your personal butler, Jarvis. + + +## Agents Can Access Your Information through OpenDAN (Coming soon) +You're now aware that Jarvis can manage essential personal data for you through OpenDAN. However, this data is mainly "new information". Since the invention of the PC in the 1980s, our lives have been increasingly digitized. Each of us has a massive amount of digital data, ranging from photos and videos captured on smartphones to emails and documents from work. In the past, we managed this information using file systems. In the AI era, we will use a Knowledge Base to manage this data. Information entered into the Knowledge Base can be better accessed by AI, allowing your Agent to understand you more deeply, serve you better, and truly become your exclusive personal butler. + +The Knowledge Base is a fundamental concept within OpenDAN and a key reason for the need for a Personal AIOS. Knowledge Base technology is rapidly evolving, so the implementation of OpenDAN's Knowledge Base is also swiftly advancing. The current version aims to let users experience the new capabilities brought about by the combination of the Knowledge Base and the Agent. From a system design perspective, we also hope to offer a friendlier and smoother method for users to import existing personal information. + +The Knowledge Base feature is already enabled by default. There are two ways to add your data to the Knowledge Base: +1)Copy the data you wish to add to the Knowledge Base to the ~myai/data folder. +2)Use the command /knowledge add $dir to include data from the $dir directory into the Knowledge Base. Note that OpenDAN runs in a container by default, so $dir refers to the path relative to the container. If you wish to add local data, you first need to mount the local data inside the container. + +During tests, please avoid adding large files or files with highly sensitive information. OpenDAN will continuously scan the files in this folder in the background and add them to the Knowledge Base. The range of recognizable file formats is currently limited, with supported types including text files, images, short videos, etc. + +You can check the scanning task status in the command line using: +``` +/knowlege journal +``` + +### Meet Your Personal Information Assistant, Mia (Coming soon) +Next, you can access the Knowledge Base via the Agent "Mia." Try interacting with Mia! +``` +/open Mia +``` + +Mia is designed to assist you in navigating through your Knowledge Base, allowing you to swiftly retrieve and understand your stored digital information. Think of her as your digital librarian, always ready to help you locate and comprehend your archived data with ease. Whether it's an old document, a treasured photo, or an important email, Mia is here to streamline your digital life. + +### (Optional) Enable Local Embedding +The process wherein the Knowledge Base scans and reads files, generating information accessible to the Agent, is termed Embedding. This procedure requires computational resources. Therefore, by default, we utilize OpenAI's Embedding service to execute this task. This implies that files added to the Knowledge Base will be uploaded to OpenAI's services for processing. Although OpenAI currently holds a commendable reputation, there still exists potential risks of privacy breaches. If you possess adequate local computational capabilities (the requirements are significantly lower than Local LLM), we recommend enabling the local Embedding feature to enhance your privacy protection. + +(Coming soon) + + +## bash@ai +By enabling the Agent to execute bash commands, you can also grant OpenDAN quick and easy access to your private data. Use the command: +``` +/open ai_bash +``` +to activate ai_bash. From there, you can execute traditional bash commands within the aios_shell command line. Plus, you'll have the ability to use smart commands. For example, to search for files, instead of using the 'find' command, you can simply say: +``` +Help me find all files in ~/Documents that contain OpenDAN. +``` +Pretty cool, right? + +By default, OpenDAN operates inside a container, meaning ai_bash can only access files within that docker container. While this provides a relative level of security, we still advise caution. Do not expose the ai_bash agent recklessly, as it could pose potential security risks." + +## Why Do We Need Personal AIOS? +Many might immediately think of privacy as the primary concern. While it's a crucial factor, we don't believe it's the real reason people are moving away from ChatGTP and opting for Personal AIOS. After all, most individuals are not overly sensitive to privacy concerns. Moreover, platform providers today usually monetize your private data without openly violating it – there's at least some semblance of integrity there. + +We believe: + +1. Cost is a significant determinant. LLM (Large Language Model) offers potent, well-defined capabilities. It's the new-age CPU. From a product and business perspective, products like ChatGTP only allow effective, constrained usage of this power. It's reminiscent of the early days of minicomputers when systems were time-shared: useful but limited. To truly harness the potential of LLM, we need to ensure that every individual owns their LLM. They should freely utilize the LLM as a foundational component for any application. This necessitates an operating system constructed on the principles of LLM. +2. Once you possess an LLM, you'll realize the vastness of possibilities! The current capabilities of ChatGPT, even with plugins extending LLM's functionalities, are considerably limited. This limitation stems both from commercial considerations and the legal constraints traditional cloud services face. The platforms bear too much responsibility. But, with LLM in AIOS, you can seamlessly integrate natural language, LLM, existing services, and smart devices. You no longer have to fret about privacy breaches or liability concerns – you assume responsibility for the outcomes once you grant access to LLM! \ No newline at end of file From 28e6c6047f5c4ad47af381f7f7119a6ccadb873d Mon Sep 17 00:00:00 2001 From: Liu Zhicong Date: Wed, 27 Sep 2023 15:42:25 -0700 Subject: [PATCH 5/5] fix document format error. --- doc/QuickStart.md | 14 ++++++++------ src/aios_kernel/__init__.py | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/QuickStart.md b/doc/QuickStart.md index 5be0770..a731b24 100644 --- a/doc/QuickStart.md +++ b/doc/QuickStart.md @@ -25,9 +25,9 @@ If there is no api token, you can apply for [here] (https://beta.openai.com/) ### Install OpenDan After executing the following command, you can install the Docker Image of OpenDan -`` ` +``` docker pull paios/aios:latest -`` ` +``` ## Run The first Run of OpenDAN needs to be initialized. You need to enter some information in the process of initialization. Therefore, when starting the docker, remember to bring the -it parameter. @@ -78,7 +78,7 @@ P.S: The above configuration will be saved in the `/your/local/myai/etc/system.cfg.toml`, if you want to modify the configuration, you can directly modify this file.If you want to adjust the configuration, you can edit this file directly. -## (optional) Install the local LLM kernel +## (Optional) Install the local LLM kernel For the first time quickly experience OpenDan, we strongly recommend you to use GPT4. Although he is very slow and expensive, he is also the most powerful and stable LLM core at present.OpenDan In the architecture design, different agents are allowed to choose different LLM kernels (but at least one available LLM kernel in the system should be available in the system). If you cannot use GPT4 for various reasons, you can use the Local LLM. At present, we only adapt to LOCAL LLM based on LLaMa.CPP, and use the following method to install @@ -90,7 +90,7 @@ The current user "username" is communicating with the name "Agent/Workflow of Ja Say Hello to your private AI assistant Jarvis ! -*** If everything is OK, you will get a reply from Jarvis after a moment .At this time, the OpenDAN system is running .*** +**If everything is OK, you will get a reply from Jarvis after a moment .At this time, the OpenDAN system is running .** ## Give a Telegram account to Jarvis @@ -126,7 +126,7 @@ In fact, OpenDAN is a quintessential Personal OS, operating atop a Personal Serv Much of our ongoing research and development work aims to provide an easy setup for a Personal Server equipped with AIOS. Compared to a PC, we're coining this new device as PI (Personal Intelligence), with OpenDAN being the premier OS tailored for the PI. ## Introducing Jarvis: Your Personal Butler! -Now you can communicate with Jarvis anytime, anywhere via Telegram. However, merely seeing him as a more accessible ChatGPT doesn't do justice to his capabilities. Let's dive in and see what new tricks Jarvis, running on OpenDAN, brings to the table! +Now you can talk with Jarvis anytime, anywhere via Telegram. However, merely seeing him as a more accessible ChatGPT doesn't do justice to his capabilities. Let's dive in and see what new tricks Jarvis, running on OpenDAN, brings to the table! ## Let Jarvis Plan Your Schedule @@ -223,4 +223,6 @@ Many might immediately think of privacy as the primary concern. While it's a cru We believe: 1. Cost is a significant determinant. LLM (Large Language Model) offers potent, well-defined capabilities. It's the new-age CPU. From a product and business perspective, products like ChatGTP only allow effective, constrained usage of this power. It's reminiscent of the early days of minicomputers when systems were time-shared: useful but limited. To truly harness the potential of LLM, we need to ensure that every individual owns their LLM. They should freely utilize the LLM as a foundational component for any application. This necessitates an operating system constructed on the principles of LLM. -2. Once you possess an LLM, you'll realize the vastness of possibilities! The current capabilities of ChatGPT, even with plugins extending LLM's functionalities, are considerably limited. This limitation stems both from commercial considerations and the legal constraints traditional cloud services face. The platforms bear too much responsibility. But, with LLM in AIOS, you can seamlessly integrate natural language, LLM, existing services, and smart devices. You no longer have to fret about privacy breaches or liability concerns – you assume responsibility for the outcomes once you grant access to LLM! \ No newline at end of file +2. Once you possess an LLM, you'll realize the vastness of possibilities! The current capabilities of ChatGPT, even with plugins extending LLM's functionalities, are considerably limited. This limitation stems both from commercial considerations and the legal constraints traditional cloud services face. The platforms bear too much responsibility. But, with LLM in AIOS, you can seamlessly integrate natural language, LLM, existing services, and smart devices. You no longer have to fret about privacy breaches or liability concerns – you assume responsibility for the outcomes once you grant access to LLM! + +OpenDAN is an open-source project, let's define the future of Humans and AI together! \ No newline at end of file diff --git a/src/aios_kernel/__init__.py b/src/aios_kernel/__init__.py index 36ef512..c4d6362 100644 --- a/src/aios_kernel/__init__.py +++ b/src/aios_kernel/__init__.py @@ -24,5 +24,5 @@ from .workspace_env import WorkspaceEnvironment from .local_stability_node import Local_Stability_ComputeNode from .stability_node import Stability_ComputeNode -AIOS_Version = "0.5.1, build 2023-9-26" +AIOS_Version = "0.5.1, build 2023-9-27"