Complete self_thinking llm process and Agent Memory

This commit is contained in:
Liu Zhicong
2024-02-04 17:28:25 -08:00
parent ddb17756eb
commit 906c3e791a
21 changed files with 886 additions and 222 deletions
+129
View File
@@ -0,0 +1,129 @@
## LLM / AI 相关框架
### LLM Process
LLM调用封装的最小单元,提供了一系列最基础的支持
流程上 inpurt, prepare promot, llm_function_call_loop, post_llm , llmresult parser, AI Action
功能上 动态类型系统 load_from_config,llm_process_loader
### Agent
从Agent的视角定义了Agent的LLM行为逻辑
Process behavior (响应)
Task/Todo Loop (自主)
Self Loop (自省)
#### Agent.Memory
#### Agent.Workspace
#### Agent.behavior
### Workflow
一组Agent共享Work space后的流程
Task可以分配给不同的Agent
Todo的Do和Check可以分配给不同的Agent
## Knowledge Base sisi)
AI First的未来文件系统
## Agent 能力扩展框架
### AI Function / Action
最重要的扩展框架
### Environment
可以通过 {environment.xxx} 读取
### Code Interpreter
Agent 能不能写代码是一个重要的理念之争
能写代码的Agent想象空间大,是通往AGI的必然之路,但不够稳定可预期
不能写代码的Agent可以专注于组合使用基础的能力,稳定可靠的
## AI系统组件
### AI Compute Kernel
通过AI Compute Kernel对 LLM, AIGC等新一代的AI基础能力进行抽象
通过Compute Node可以对这些基础能力进行不同的实现
### AI Models
模型的fine-tune Pipeline
LoRA的Pipeline
### Contact Manage
基于Contact的自然语言权限控制
### Tunnel
可以使用开放API的通信软件,于自己的AI时刻保持沟通
### Spider
持续的导入用户在旧时代的数据。
从Web2->web3
### Calendar (Calendar是否应该是Agent.Worksapce的一部分)
### 基础的pkg_loader
支持一系列可安装的扩展
可扩展的扩展是AIOS的开发者需要重点关注的
Agent (用自然语言扩展)
Workflow (用自然语言扩展)
Plugin:(需要会写代码)
AI Function / Action
Environment
Knowledge Pipeline
LLM Process
Compute Node
### System Config Manage
Zone Config-> System Config
## UI
### Installer
图形化的安装界面,帮助用户能快速的安装使用
我们也会在这里讨论面向用户的AIOS的过渡性安装逻辑
### WebUI & OS Desktop
系统控制面板
Agent/Workflow管理
新Outlook
会话管理 (于Agent会话)
日程管理
Todo管理
新Dropbox
Knowledge Base浏览
Knowledge Base查询
应用商店
### AIOS Shell
### Personal Station (新个人主页)
内容的发布/联系人内容的查看/个人日历的公开
## Frame Service (完全未开始)
通过Frame Service,让AIOS成为一个典型的网络系统(Personal Server OS
这一块会复用很多CYFS/Bucky OS 的基础设计
这一层AI不会直接使用,这一层支持AI系统组件的实现
在用户看来,这一层的功能都是高级的,偏向系统维护的。很少会直接使用
### zone & node-daemon
NOS的booter
### Runtime (Container) Manage
这里抽象了系统的运行时模型
通过容器技术对可扩展组件的权限进行控制,保护系统的隐私安全
### d-Storage & Named Object
Named- Object File System
D-RDB
D-VDB
### BUS
系统消息总线,在不同的系统组件中路由消息
### CYFS (httpv4) Gateway
+157 -63
View File
@@ -1,6 +1,6 @@
<mxfile host="Electron" modified="2024-01-23T00:56:42.520Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="_H5QlGdjy2LQwCLx646U" version="22.1.2" type="device" pages="7">
<mxfile host="Electron" modified="2024-01-29T00:22:46.220Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="XPCvDF8x_5abdhn_GXEm" version="22.1.2" type="device" pages="8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="2046" dy="1168" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<mxGraphModel dx="2044" dy="1167" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
@@ -514,7 +514,7 @@
</mxGraphModel>
</diagram>
<diagram id="CqH4P1G_RAjWfIoYkaMU" name="Task/Todo">
<mxGraphModel dx="2046" dy="1168" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="2044" dy="1167" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
@@ -644,7 +644,7 @@
</mxGraphModel>
</diagram>
<diagram id="1AT3sDmhgRXqQU36RNgs" name="New Workflow">
<mxGraphModel dx="2046" dy="1168" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="2044" dy="1167" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
@@ -654,24 +654,24 @@
</root>
</mxGraphModel>
</diagram>
<diagram id="EohhKbyxIwDpnJuhpjKB" name="Page-7">
<mxGraphModel dx="2910" dy="1183" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<diagram id="EohhKbyxIwDpnJuhpjKB" name="Task/Todo state machine">
<mxGraphModel dx="2894" dy="1167" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="9UtHOai_7pWWWwvgcpnR-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-1" target="9UtHOai_7pWWWwvgcpnR-2">
<mxCell id="9UtHOai_7pWWWwvgcpnR-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-1" target="9UtHOai_7pWWWwvgcpnR-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-1" value="TaskList" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-1" value="TaskList" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="55" y="210" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-2" value="Triage&lt;br&gt;统一的处理最近刚创建的任务" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-2" value="Triage&lt;br&gt;统一的处理最近刚创建的任务" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" parent="1" vertex="1">
<mxGeometry x="235" y="210" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-3" value="简单任务直接完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-3" value="简单任务直接完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="475" y="100" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-5" target="9UtHOai_7pWWWwvgcpnR-6">
<mxCell id="9UtHOai_7pWWWwvgcpnR-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-5" target="9UtHOai_7pWWWwvgcpnR-6" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="580" y="405" />
@@ -680,22 +680,22 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-5" value="确认任务:下一次检查时间,调整优先级&lt;br&gt;CONFIROM" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-5" value="确认任务:下一次检查时间,调整优先级&lt;br&gt;CONFIROM" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="445" y="310" width="260" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-6" target="9UtHOai_7pWWWwvgcpnR-7">
<mxCell id="9UtHOai_7pWWWwvgcpnR-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-6" target="9UtHOai_7pWWWwvgcpnR-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-6" value="Task" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-6" value="Task" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="70" y="540" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="n17Tc1c1lNDFk3IK2LSY-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-9">
<mxCell id="n17Tc1c1lNDFk3IK2LSY-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-7" value="Plan" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-7" value="Plan" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" parent="1" vertex="1">
<mxGeometry x="250" y="540" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-8" target="9UtHOai_7pWWWwvgcpnR-27">
<mxCell id="9UtHOai_7pWWWwvgcpnR-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-8" target="9UtHOai_7pWWWwvgcpnR-27" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="555" y="430" />
@@ -705,16 +705,16 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-8" value="简单任务直接完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-8" value="简单任务直接完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="460" y="450" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-9" value="直接拒绝任务" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-9" value="直接拒绝任务" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="450" y="540" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-10" value="直接拒绝任务" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-10" value="直接拒绝任务" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="475" y="200" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-11" target="9UtHOai_7pWWWwvgcpnR-15">
<mxCell id="9UtHOai_7pWWWwvgcpnR-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-11" target="9UtHOai_7pWWWwvgcpnR-15" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="535" y="750" />
@@ -723,31 +723,31 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-11" value="DOING&lt;br&gt;拆解子任务 or 拆解TODO" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-11" value="DOING&lt;br&gt;拆解子任务 or 拆解TODO" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="440" y="650" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-13" value="Task Logs&lt;br&gt;父任务,兄弟任务,Todos" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-13" value="Task Logs&lt;br&gt;父任务,兄弟任务,Todos" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="250" y="450" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-15" target="9UtHOai_7pWWWwvgcpnR-16">
<mxCell id="9UtHOai_7pWWWwvgcpnR-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-15" target="9UtHOai_7pWWWwvgcpnR-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-15" value="Todo" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-15" value="Todo" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="70" y="890" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-16" target="9UtHOai_7pWWWwvgcpnR-20">
<mxCell id="9UtHOai_7pWWWwvgcpnR-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-16" target="9UtHOai_7pWWWwvgcpnR-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-16" value="DO" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-16" value="DO" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" parent="1" vertex="1">
<mxGeometry x="240" y="890" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-19" target="9UtHOai_7pWWWwvgcpnR-21">
<mxCell id="9UtHOai_7pWWWwvgcpnR-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-19" target="9UtHOai_7pWWWwvgcpnR-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-19" value="执行成功" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-19" value="执行成功" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="430" y="960" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-20" target="9UtHOai_7pWWWwvgcpnR-15">
<mxCell id="9UtHOai_7pWWWwvgcpnR-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-20" target="9UtHOai_7pWWWwvgcpnR-15" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="535" y="790" />
@@ -755,49 +755,49 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-20" value="执行失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-20" value="执行失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="440" y="840" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-21" target="9UtHOai_7pWWWwvgcpnR-22">
<mxCell id="9UtHOai_7pWWWwvgcpnR-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-21" target="9UtHOai_7pWWWwvgcpnR-22" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-21" value="Todo" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-21" value="Todo" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="70" y="1120" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-22" target="9UtHOai_7pWWWwvgcpnR-25">
<mxCell id="9UtHOai_7pWWWwvgcpnR-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-22" target="9UtHOai_7pWWWwvgcpnR-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-22" target="9UtHOai_7pWWWwvgcpnR-26">
<mxCell id="9UtHOai_7pWWWwvgcpnR-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-22" target="9UtHOai_7pWWWwvgcpnR-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-22" value="Check&lt;br&gt;(解决幻视)" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-22" value="Check&lt;br&gt;(解决幻视)" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" parent="1" vertex="1">
<mxGeometry x="240" y="1120" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-25" value="检查失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-25" value="检查失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="430" y="1090" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-26" target="9UtHOai_7pWWWwvgcpnR-27">
<mxCell id="9UtHOai_7pWWWwvgcpnR-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-26" target="9UtHOai_7pWWWwvgcpnR-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-26" value="检查成功" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-26" value="检查成功" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="425" y="1180" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-27" target="9UtHOai_7pWWWwvgcpnR-29">
<mxCell id="9UtHOai_7pWWWwvgcpnR-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-27" target="9UtHOai_7pWWWwvgcpnR-29" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-27" value="有TODOS或有SubTask的Task。注意Review是顺序的" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-27" value="有TODOS或有SubTask的Task。注意Review是顺序的" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="69" y="1340" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-30">
<mxCell id="9UtHOai_7pWWWwvgcpnR-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-29" value="Review" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-29" value="Review" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" parent="1" vertex="1">
<mxGeometry x="240" y="1340" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-30" value="Task 完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-30" value="Task 完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="425" y="1320" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-31" target="9UtHOai_7pWWWwvgcpnR-6">
<mxCell id="9UtHOai_7pWWWwvgcpnR-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-31" target="9UtHOai_7pWWWwvgcpnR-6" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="520" y="1580" />
@@ -806,52 +806,52 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-31" value="Task未完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-31" value="Task未完成" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="425" y="1500" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-33" value="所有确认了但未完成的任务都有可能被Plan" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-33" value="所有确认了但未完成的任务都有可能被Plan" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="69" y="480" width="120" height="45" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-36" value="Task 最终失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-36" value="Task 最终失败" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" parent="1" vertex="1">
<mxGeometry x="425" y="1410" width="190" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-37" value="Task Logs&lt;br&gt;父任务,兄弟TODOs" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-37" value="Task Logs&lt;br&gt;父任务,兄弟TODOs" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="810" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.422;entryY=0.972;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-11" target="9UtHOai_7pWWWwvgcpnR-6">
<mxCell id="9UtHOai_7pWWWwvgcpnR-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.422;entryY=0.972;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-11" target="9UtHOai_7pWWWwvgcpnR-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-39" value="未定义依赖关系的subtask可以并行执行" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-39" value="未定义依赖关系的subtask可以并行执行" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="185" y="650" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-40" value="TODO按顺序执行" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-40" value="TODO按顺序执行" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="40" y="720" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-46" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.035;entryY=0.361;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-3">
<mxCell id="9UtHOai_7pWWWwvgcpnR-46" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.035;entryY=0.361;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-3" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="385" y="220" as="sourcePoint" />
<mxPoint x="435" y="170" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-47" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-10">
<mxCell id="9UtHOai_7pWWWwvgcpnR-47" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-10" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="375" y="270" as="sourcePoint" />
<mxPoint x="472" y="210" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-49" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-5">
<mxCell id="9UtHOai_7pWWWwvgcpnR-49" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-2" target="9UtHOai_7pWWWwvgcpnR-5" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="325" y="370" as="sourcePoint" />
<mxPoint x="375" y="320" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-58" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-16" target="9UtHOai_7pWWWwvgcpnR-19">
<mxCell id="9UtHOai_7pWWWwvgcpnR-58" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-16" target="9UtHOai_7pWWWwvgcpnR-19" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="300" y="1050" as="sourcePoint" />
<mxPoint x="350" y="1000" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.428;entryY=1.061;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-25" target="9UtHOai_7pWWWwvgcpnR-15">
<mxCell id="9UtHOai_7pWWWwvgcpnR-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.428;entryY=1.061;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-25" target="9UtHOai_7pWWWwvgcpnR-15" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="478" y="1050" />
@@ -859,31 +859,31 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-62" value="满足Review条件后" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-62" value="满足Review条件后" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="55" y="1290" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-65" value="刚刚创建的任务通常保持其原始文本描述" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="9UtHOai_7pWWWwvgcpnR-65" value="刚刚创建的任务通常保持其原始文本描述" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="235" y="280" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-68" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.617;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-36">
<mxCell id="9UtHOai_7pWWWwvgcpnR-68" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.617;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-36" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="300" y="1490" as="sourcePoint" />
<mxPoint x="350" y="1440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9UtHOai_7pWWWwvgcpnR-69" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-31">
<mxCell id="9UtHOai_7pWWWwvgcpnR-69" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-29" target="9UtHOai_7pWWWwvgcpnR-31" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="330" y="1490" as="sourcePoint" />
<mxPoint x="380" y="1440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="n17Tc1c1lNDFk3IK2LSY-3" value="" style="endArrow=classic;html=1;rounded=0;exitX=1.003;exitY=0.147;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-8">
<mxCell id="n17Tc1c1lNDFk3IK2LSY-3" value="" style="endArrow=classic;html=1;rounded=0;exitX=1.003;exitY=0.147;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-8" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="530" as="sourcePoint" />
<mxPoint x="440" y="480" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="n17Tc1c1lNDFk3IK2LSY-4" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-11">
<mxCell id="n17Tc1c1lNDFk3IK2LSY-4" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="9UtHOai_7pWWWwvgcpnR-7" target="9UtHOai_7pWWWwvgcpnR-11" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="670" as="sourcePoint" />
<mxPoint x="430" y="620" as="targetPoint" />
@@ -892,4 +892,98 @@
</root>
</mxGraphModel>
</diagram>
<diagram id="7rhNWbdtJh7hNxC4Nqiq" name="Page-8">
<mxGraphModel dx="1168" dy="667" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="5sM_x3XBksQVRvh5ABVG-1" value="LLM Process" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="410" y="270" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-2" value="Input" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxGeometry x="305" y="80" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-3" value="Output" style="shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;" vertex="1" parent="1">
<mxGeometry x="520" y="80" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-4" target="5sM_x3XBksQVRvh5ABVG-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-4" value="Actions" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="530" y="440" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-5" value="Functions" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="300" y="440" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-6" target="5sM_x3XBksQVRvh5ABVG-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-6" value="显性的,有组织的记忆(表层意识)&lt;br&gt;基于Storage" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
<mxGeometry x="60" y="360" width="120" height="120" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-7" target="5sM_x3XBksQVRvh5ABVG-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-7" value="知识库" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
<mxGeometry x="50" y="530" width="120" height="120" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-8" value="潜意识&lt;br&gt;涌现的直觉性能力&lt;br&gt;(基于神经元网络))" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="80" y="240" width="160" height="100" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-10" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.446;exitY=1.02;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-2" target="5sM_x3XBksQVRvh5ABVG-1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="350" y="230" as="sourcePoint" />
<mxPoint x="400" y="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-11" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.463;entryY=1.013;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" target="5sM_x3XBksQVRvh5ABVG-3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="470" y="270" as="sourcePoint" />
<mxPoint x="520" y="220" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-12" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.526;entryY=-0.06;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-1" target="5sM_x3XBksQVRvh5ABVG-4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="420" as="sourcePoint" />
<mxPoint x="590" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-13" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-5" target="5sM_x3XBksQVRvh5ABVG-1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="360" y="430" as="sourcePoint" />
<mxPoint x="410" y="380" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-14" target="5sM_x3XBksQVRvh5ABVG-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-14" value="Context" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="230" y="190" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-4" target="5sM_x3XBksQVRvh5ABVG-7">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="590" y="670" />
<mxPoint x="110" y="670" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-4" target="5sM_x3XBksQVRvh5ABVG-6">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="620" y="710" />
<mxPoint x="40" y="710" />
<mxPoint x="40" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-21" value="真实世界" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="730" y="430" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="5sM_x3XBksQVRvh5ABVG-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.96;exitY=0.7;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.669;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="5sM_x3XBksQVRvh5ABVG-8" target="5sM_x3XBksQVRvh5ABVG-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+35 -9
View File
@@ -2,19 +2,20 @@ instance_id = "Jarvis"
fullname = "Jarvis"
max_token = 4000
#timeout = 1800
model_name = "gpt-4-1106-preview"
model_name = "gpt-4-turbo-preview"
#enable_kb = "true"
enable_timestamp = "true"
enable_json_resp = "true"
role_desc = """
Your name is Jarvis, the super personal assistant to the master. Help the Master do a good job of schedule.Reminder before the start of the important schedule, and you should bring useful information as much as possible when reminding.
Your name is Jarvis, the super personal assistant to the Principal. Help the Principal do a good job of schedule.Reminder before the start of the important schedule, and you should bring useful information as much as possible when reminding.
Only clearly specifying the task you completed can be completed independently.
"""
[behavior.on_message]
type="AgentMessageProcess"
# TODO: 是否应该自动记录 inner function和action的执行细节
mutil_model="gpt-4-vision-preview"
process_description="""
1. Based on your role and the existing information, please think and then make a brief and efficient reply.
@@ -68,7 +69,7 @@ The Response must be directly parsed by `python json.loads`. Here is an example:
}]
}
"""
context="Your master is {owner}, now in {location}, time: {now}, weather: {weather}."
context="Your Principal is {owner}, now in {location}, time: {now}, weather: {weather}."
llm_context.actions.enable = ["agent.workspace.confirm_task","agent.workspace.update_task","agent.workspace.cancel_task","post_message"]
@@ -97,7 +98,7 @@ The Response must be directly parsed by `python json.loads`. Here is an example:
llm_context.actions.enable = ["agent.workspace.create_task","agent.workspace.update_task","agent.workspace.set_todos","agent.workspace.cancel_task","post_message"]
#llm_context.functions.enable = ["agent.workspace.list_task"]
context="Your master is {owner}, now in {location}, time: {now}, weather: {weather}."
context="Your Principal is {owner}, now in {location}, time: {now}, weather: {weather}."
[behavior.review_task]
## 当task的所有todo/subtask都完成后(不敢成功或是失败),进行一次review
@@ -122,7 +123,7 @@ The Response must be directly parsed by `python json.loads`. Here is an example:
llm_context.actions.enable = ["agent.workspace.cancel_task","agent.workspace.update_task"]
context="Your master now in {location}, time: {now}, weather: {weather}."
context="Your Principal now in {location}, time: {now}, weather: {weather}."
[behavior.do]
# do TODO
type="AgentDo"
@@ -147,7 +148,7 @@ The Response must be directly parsed by `python json.loads`. Here is an example:
]
}
"""
context="Your master is {owner}, now in {location}, time: {now}, weather: {weather}."
context="Your Principal is {owner}, now in {location}, time: {now}, weather: {weather}."
# 对于DO操作来说,让Agent查询自己的能力集合是否更合适?
llm_context.actions.enable = ["agent.workspace.update_todo","post_message","agent.workspace.write_file","agent.workspace.append_file"]
llm_context.functions.enable = ["agent.workspace.read_file","agent.workspace.list_dir","system.shell.exec","aigc.text_2_image","aigc.text_2_voice","web.search.duckduckgo"]
@@ -171,14 +172,39 @@ The Response must be directly parsed by `python json.loads`. Here is an example:
]
}
"""
context="Your master is {owner}, now in {location}, time: {now}, weather: {weather}."
context="Your Principal is {owner}, now in {location}, time: {now}, weather: {weather}."
llm_context.actions.enable = ["agent.workspace.update_todo"]
llm_context.functions.enable = ["agent.workspace.read_file","agent.workspace.list_dir","system.shell.exec","system.shell.run_code","aigc.image_2_text","aigc.voice_2_text","web.search.duckduckgo"]
#[behavior.self_thinking]
[behavior.self_thinking2]
# self thing的主要目的是对各种chatlog,worklog进行分析,并更新面向人和事的summary。
#type="AgentSelfThinking"
type="AgentSelfThinking"
process_description="""
You are very good at thinking and summarizing what you have already happened。Your input is a chat history and work record,After you think about it, you will follow the requirements below to generate abstract.
1. Try to understand the theme of each sentence, and call the relevant operation to record the relationship between the dialogue and the theme
2. Try to analyze the personality of different people involved in information
3. Try to summarize important events in the information and record it
4. Try to understand the attitude of different people on different topics or events
5. Pay attention to the time order when summarizing, and combine the summary you have done to update Summary
6. The summary of the generation cannot exceed 400 token
7. 思考的目的是让自己未来的工作更加高效
8. 总结中只包含有长期价值和未完成的事情,已经完成的事情不需要总结
"""
reply_format = """
The Response must be directly parsed by `python json.loads`. Here is an example:
{
resp:'$Summary in one sentence',
name: '$action1_name',
$param_name: '$parm' #Optional, fill in only if the action has parameters.
}, ...
]
}
"""
context="Your Principal is {owner}, now in {location}, time: {now}, weather: {weather}."
llm_context.actions.enable = ["agent.memory.update_summary","agent.memory.update_contact_summary","agent.memory.update_relation_summary","agent.memory.set_experience"]
llm_context.functions.enable = ["agent.memory.get_summary","agent.memory.get_contact_summary","agent.memory.list_summary","agent.memory.get_relation_summary","agent.memory.get_experience"]
#[behavior.self_improve]
# self_improve 是最后的行为,允许Agent结合自己的工作经验,改进自己的提示词(注意保留历史版本)
+1 -1
View File
@@ -19,7 +19,7 @@ from .frame.compute_kernel import ComputeKernel,ComputeTask,ComputeTaskResult,Co
from .frame.compute_node import ComputeNode,LocalComputeNode
from .frame.bus import AIBus
from .frame.tunnel import AgentTunnel
from .frame.contact_manager import ContactManager,Contact,FamilyMember
from .frame.contact_manager import ContactManager,Contact
from .frame.queue_compute_node import Queue_ComputeNode
from .environment.environment import BaseEnvironment,SimpleEnvironment,CompositeEnvironment
+40 -24
View File
@@ -24,21 +24,16 @@ from .llm_do_task import *
from .chatsession import *
from ..environment.workspace_env import WorkspaceEnvironment, TodoListType
from ..frame.contact_manager import ContactManager,Contact,FamilyMember
from ..frame.compute_kernel import ComputeKernel
from ..frame.bus import AIBus
from ..environment.environment import *
from ..environment.workspace_env import WorkspaceEnvironment
from ..storage.storage import AIStorage
from ..knowledge import *
from ..utils import video_utils, image_utils
from ..proto.compute_task import ComputeTaskResult,ComputeTaskResultCode,LLMPrompt,LLMResult
from ..proto.compute_task import LLMPrompt,LLMResult
logger = logging.getLogger(__name__)
class AIAgentTemplete:
def __init__(self) -> None:
self.llm_model_name:str = "gpt-4-0613"
self.llm_model_name:str = "gpt-4-turbo-preview"
self.max_token_size:int = 0
self.template_id:str = None
self.introduce:str = None
@@ -99,7 +94,8 @@ class AIAgent(BaseAIAgent):
}
self.todo_prompts = todo_prompts
self.memory_db = None
self.base_dir = None
#self.memory_db = None
self.unread_msg = Queue() # msg from other agent
self.owenr_bus = None
@@ -109,7 +105,9 @@ class AIAgent(BaseAIAgent):
self.behaviors:Dict[str,BaseLLMProcess] = {}
async def initial(self,params:Dict = None):
self.memory = AgentMemory(self.agent_id,self.memory_db)
self.base_dir = f"{AIStorage.get_instance().get_myai_dir()}/agent_data/{self.agent_id}"
memory_base_dir = f"{self.base_dir}/memory"
self.memory = AgentMemory(self.agent_id,memory_base_dir)
self.prviate_workspace = AgentWorkspace(self.agent_id)
init_params = {}
init_params["memory"] = self.memory
@@ -241,6 +239,34 @@ class AIAgent(BaseAIAgent):
return await self.llm_process_msg(msg)
async def llm_self_think(self):
llm_process : BaseLLMProcess = self.behaviors.get("self_thinking")
if llm_process:
logger.info(f"agent {self.agent_id} self thinking start!")
context_info = await self._get_context_info()
known_session_list = AIChatSession.list_session(self.agent_id,self.memory.memory_db)
known_experience_list = await self.memory.list_experience()
record_list = await self.memory.load_records(await self.memory.get_last_think_time())
input_parms = {
"record_list":record_list,
"known_session_list":known_session_list,
"known_experience_list":known_experience_list,
"context_info":context_info
}
llm_result : LLMResult = await llm_process.process(input_parms)
if llm_result.state == LLMResultStates.ERROR:
logger.error(f"llm process self thinking error:{llm_result.compute_error_str}")
elif llm_result.state == LLMResultStates.IGNORE:
logger.info(f"llm process self thinking ignore!")
else:
logger.info(f"llm process self thinking ok!,think is:{llm_result.resp}")
self.memory.set_last_think_time(time.time())
self.agent_energy -= 2
return
async def llm_triage_tasklist(self):
llm_process : BaseLLMProcess = self.behaviors.get("triage_tasks")
if llm_process:
@@ -361,21 +387,8 @@ class AIAgent(BaseAIAgent):
self.agent_energy -= 1
async def do_self_think(self):
session_id_list = AIChatSession.list_session(self.agent_id,self.memory_db)
for session_id in session_id_list:
if self.agent_energy <= 0:
break
used_energy = await self.think_chatsession(session_id)
self.agent_energy -= used_energy
return
def need_self_think(self) -> bool:
return False
async def _self_imporve(self):
if self.need_self_think():
await self.do_self_think()
await self.llm_self_think()
def wake_up(self) -> None:
if self.agent_task is None:
@@ -446,10 +459,11 @@ class AIAgent(BaseAIAgent):
await self._self_imporve()
except Exception as e:
tb_str = traceback.format_exc()
logger.error(f"agent {self.agent_id} on timer error:{e},{tb_str}")
continue
# Because the LLM itself is very slow, the accuracy of the system processing task is in minutes.
await asyncio.sleep(30)
@@ -458,3 +472,5 @@ class AIAgent(BaseAIAgent):
+323 -14
View File
@@ -1,12 +1,18 @@
# pylint:disable=E0402
from datetime import datetime,timedelta
import json
import os
import threading
from typing import Dict, List
import sqlite3
import aiofiles
from ..storage.storage import AIStorage
from ..frame.compute_kernel import ComputeKernel
from ..proto.ai_function import SimpleAIAction
from ..frame.contact_manager import ContactManager
from ..frame.contact import Contact
from ..proto.ai_function import ParameterDefine, SimpleAIAction, SimpleAIFunction
from ..proto.agent_msg import AgentMsg, AgentMsgType
from ..proto.agent_task import AgentWorkLog
@@ -17,12 +23,34 @@ import logging
logger = logging.getLogger(__name__)
#class ObjectSummary:
# def __init__(self) -> None:
# self.summary : str = None
# self.object_name : str = None
# self.priority : int = 5
# [info_source, info]
# self.infos : Dict[str,str] = {}
class AgentMemory:
def __init__(self,agent_id:str,db_path:str) -> None:
def __init__(self,agent_id:str,base_dir:str) -> None:
self.agent_memory_base_dir = base_dir
self.agent_id:str= agent_id
self.memory_db:str = db_path
AIStorage.get_instance().ensure_directory_exists(self.agent_memory_base_dir)
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/experience")
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/contacts")
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/relations")
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/summary")
self.memory_db:str = f"{self.agent_memory_base_dir}/memory.db"
self.model_name:str = "gp4-1106-preview"
self.threshold_hours = 72
self.last_think_time : float = 0.0
self.load_memory_meta()
def _get_conn(self):
@@ -55,6 +83,15 @@ class AgentMemory:
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.memory_db)
return chatsession
# return last record time
async def load_records(self,starttime,tokenlimit=8000)->float:
# 专用思路:做聊天记录/工作经验的整理
# 通用思路:没有具体的目的,让Agent根据提示词自己工作(可能效果很差也可能很好)
# 先实现通用思路
msg_records = AIChatSession.load_message_records_by_agentid(self.agent_id,starttime,32,self.memory_db)
work_records = self.load_worklogs(self.agent_id,token_limit=tokenlimit)
pass
async def load_chatlogs(self,msg:AgentMsg,n:int=6,m:int=64,token_limit=800)->str:
chatsession = self.get_session_from_msg(msg)
# Must load n (n> = 2), and hope to load the M
@@ -176,23 +213,295 @@ class AgentMemory:
conn.commit()
#conn.close()
def memory_meta_to_dict(self) -> Dict:
return {
"last_think_time" : self.last_think_time
}
def load_meta(self,Dict):
self.last_think_time = Dict.get("last_think_time",0.0)
def load_memory_meta(self):
meta_file_path = f"{self.agent_memory_base_dir}/meta.json"
try:
with open(meta_file_path, mode='r') as file:
meta = json.load(file)
self.load_meta(meta)
except Exception as e:
logger.error(f"load memory meta failed: {e}")
self.last_think_time = 0.0
def save_memory_meta(self):
meta_file_path = f"{self.agent_memory_base_dir}/meta.json"
try:
with open(meta_file_path, mode='w') as file:
meta = self.memory_meta_to_dict()
json.dump(meta,file)
except Exception as e:
logger.error(f"save memory meta failed: {e}")
async def get_last_think_time(self)->float:
return self.last_think_time
async def set_last_think_time(self,last_time:float):
self.last_think_time = last_time
self.save_memory_meta()
async def get_contact_summary(self,contact_id:str) -> str:
if contact_id is None:
return None
return "Contact id is None"
result = {}
contact_info:Contact = ContactManager.get_instance().find_contact_by_name(contact_id)
if contact_info:
result["name"] = contact_info.name
result["relation"] = contact_info.relationship
result["notes"] = contact_info.notes
summary_path = f"{self.agent_memory_base_dir}/contacts/{contact_id}.summary"
try:
async with aiofiles.open(summary_path, mode='r') as file:
result["summary"] = await file.read()
except Exception as e:
logger.error(f"read contact summary failed: {e}")
return json.dumps(result,ensure_ascii=False)
async def update_contact_summary(self,contact_id:str,summary:str):
summary_path = f"{self.agent_memory_base_dir}/contacts/{contact_id}.summary"
try:
async with aiofiles.open(summary_path, mode='w') as file:
await file.write(summary)
return "OK"
except Exception as e:
logger.error(f"write contact summary failed: {e}")
return "write contact summary failed: {e}"
async def get_summary(self,object_name:str) -> str:
summary_path = f"{self.agent_memory_base_dir}/{object_name}.summary"
try:
async with aiofiles.open(summary_path, mode='r') as file:
return await file.read()
except Exception as e:
logger.error(f"read summary failed: {e}")
return f"read summary failed: {e}"
async def update_summary(self,object_name:str,summary:str) -> str:
summary_path = f"{self.agent_memory_base_dir}/{object_name}.summary"
try:
async with aiofiles.open(summary_path, mode='w') as file:
await file.write(summary)
return "OK"
except Exception as e:
logger.error(f"write summary failed: {e}")
return f"write summary failed: {e}"
async def list_summary_object_names(self) -> List[str]:
# list dir
try:
contents = os.listdir(self.agent_memory_base_dir)
return [x for x in contents if x.endswith(".summary")]
except Exception as e:
logger.error(f"list summary object names failed: {e}")
return []
# means object1 feel object2 is ...
async def get_relation_summary(self,object_name1:str,object_name2:str) -> str:
summary_path = f"{self.agent_memory_base_dir}/relations/{object_name1}.relation.{object_name2}.summary"
try:
async with aiofiles.open(summary_path, mode='r') as file:
await file.read()
except FileNotFoundError:
return "no summary"
except Exception as e:
logger.error(f"read relation summary failed: {e}")
return f"read relation summary failed: {e}"
async def update_relation_summary(self,object_name1:str,object_name2:str,summary:Dict):
summary_path = f"{self.agent_memory_base_dir}/relations/{object_name1}.relation.{object_name2}.summary"
try:
async with aiofiles.open(summary_path, mode='w') as file:
await file.write(json.dumps(summary))
return "OK"
except Exception as e:
logger.error(f"write relation summary failed: {e}")
return "write relation summary failed: {e}"
async def get_experience(self,topic_name:str) -> str:
experience_path = f"{self.agent_memory_base_dir}/experience/{topic_name}.experience"
try:
async with aiofiles.open(experience_path, mode='r') as file:
await file.read()
except FileNotFoundError:
return "no experience"
except Exception as e:
logger.error(f"read experience failed: {e}")
return f"read experience failed: {e}"
async def set_experience(self,topic_name:str,summary:str) -> str:
experience_path = f"{self.agent_memory_base_dir}/experience/{topic_name}.experience"
try:
async with aiofiles.open(experience_path, mode='w') as file:
await file.write(summary)
return "OK"
except Exception as e:
logger.error(f"write experience failed: {e}")
return "write experience failed: {e}"
async def list_experience(self) -> List[str]:
dir_path = f"{self.agent_memory_base_dir}/experience"
try:
contents = os.listdir(dir_path)
return [x for x in contents if x.endswith(".experience")]
except Exception as e:
logger.error(f"list experience failed: {e}")
return []
@staticmethod
def register_ai_functions():
async def get_contact_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
contact_name = parameters.get("contact_name")
return await agent_memory.get_contact_summary(contact_name)
parameters = ParameterDefine.create_parameters({
"contact_name": {"type": "string", "description": "contact name"}
})
get_contact_summary_func = SimpleAIFunction("agent.memory.get_contact_summary",
"get contact summary",
get_contact_summary,
parameters)
GlobaToolsLibrary.register_tool_function(get_contact_summary_func)
async def update_contact_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
contact_name = parameters.get("contact_name")
summary = parameters.get("summary")
return await agent_memory.update_contact_summary(contact_name,summary)
parameters = ParameterDefine.create_parameters({
"contact_name": {"type": "string", "description": "contact name"},
"summary": {"type": "string", "description": "new summary"}
})
update_contact_summary_func = SimpleAIFunction("agent.memory.update_contact_summary",
"update contact summary",
update_contact_summary,
parameters)
GlobaToolsLibrary.register_tool_function(update_contact_summary_func)
async def get_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
object_name = parameters.get("object_name")
return await agent_memory.get_summary(object_name)
parameters = ParameterDefine.create_parameters({
"object_name": {"type": "string", "description": "object name"}
})
get_summary_func = SimpleAIFunction("agent.memory.get_summary",
"get summary of sth",
get_summary,
parameters)
GlobaToolsLibrary.register_tool_function(get_summary_func)
async def update_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
object_name = parameters.get("object_name")
summary = parameters.get("summary")
return await agent_memory.update_summary(object_name,summary)
parameters = ParameterDefine.create_parameters({
"object_name": {"type": "string", "description": "object name"},
"summary": {"type": "string", "description": "new summary"}
})
update_summary_func = SimpleAIFunction("agent.memory.update_summary",
"update summary of sth",
update_summary,
parameters)
GlobaToolsLibrary.register_tool_function(update_summary_func)
async def list_summary_object_names(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
return await agent_memory.list_summary_object_names()
parameters = ParameterDefine.create_parameters({})
list_summary_object_names_func = SimpleAIFunction("agent.memory.list_summary",
"list summary object names",
list_summary_object_names,
parameters)
GlobaToolsLibrary.register_tool_function(list_summary_object_names_func)
async def get_relation_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
object_name1 = parameters.get("object1_name")
object_name2 = parameters.get("object2_name")
return await agent_memory.get_relation_summary(object_name1,object_name2)
parameters = ParameterDefine.create_parameters({
"object1_name": {"type": "string", "description": "object name1"},
"object2_name": {"type": "string", "description": "object name2"}
})
get_relation_summary_func = SimpleAIFunction("agent.memory.get_relation_summary",
"object1 feel object2 is ...",
get_relation_summary,
parameters)
GlobaToolsLibrary.register_tool_function(get_relation_summary_func)
async def update_relation_summary(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
object_name1 = parameters.get("object1_name")
object_name2 = parameters.get("object2_name")
summary = parameters.get("summary")
return await agent_memory.update_relation_summary(object_name1,object_name2,summary)
parameters = ParameterDefine.create_parameters({
"object1_name": {"type": "string", "description": "object name1"},
"object2_name": {"type": "string", "description": "object name2"},
"summary": {"type": "string", "description": "new summary"}
})
update_relation_summary_func = SimpleAIFunction("agent.memory.update_relation_summary",
"object1 feel object2 is ...",
update_relation_summary,
parameters)
GlobaToolsLibrary.register_tool_function(update_relation_summary_func)
async def get_experience(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
topic_name = parameters.get("topic_name")
return await agent_memory.get_experience(topic_name)
parameters = ParameterDefine.create_parameters({
"topic_name": {"type": "string", "description": "topic name"}
})
get_experience_func = SimpleAIFunction("agent.memory.get_experience",
"get experience",
get_experience,
parameters)
GlobaToolsLibrary.register_tool_function(get_experience_func)
async def set_experience(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
topic_name = parameters.get("topic_name")
summary = parameters.get("summary")
return await agent_memory.set_experience(topic_name,summary)
parameters = ParameterDefine.create_parameters({
"topic_name": {"type": "string", "description": "topic name"},
"summary": {"type": "string", "description": "new summary"}
})
set_experience_func = SimpleAIFunction("agent.memory.set_experience",
"set experience",
set_experience,
parameters)
GlobaToolsLibrary.register_tool_function(set_experience_func)
async def list_experience(parameters):
agent_memory:AgentMemory = parameters.get("_agent_memory")
return await agent_memory.list_experience()
parameters = ParameterDefine.create_parameters({})
list_experience_func = SimpleAIFunction("agent.memory.list_experience",
"list exist experience topics",
list_experience,
parameters)
GlobaToolsLibrary.register_tool_function(list_experience_func)
# TODO : fix this by system config.
if contact_id == "lzc":
return "lzc is your master. Male, 40 years old, Mother tongue is Chinese, senior software engineer."
return None
async def update_contact_summary(self,contact_id:str,summary:str) -> str:
return "OK"
async def get_sth_summary(self,sth_id:str) -> str:
return None
async def update_sth_summary(self,sth_id:str,summary:str) -> str:
return None
+49
View File
@@ -211,6 +211,23 @@ class ChatSessionDB:
logging.error("Error occurred while getting messages: %s", e)
return -1, None # return -1 and None if an error occurs
def load_message_by_agentid(self,agent_id,limit,start_time="1970-01-01 00:00:00"):
try:
conn = self._get_conn()
cursor = conn.cursor()
cursor.execute("""
SELECT MessageID, SessionID, MsgType, PrevMsgID, SenderID, ReceiverID, Timestamp, Topic,Mentions,ContentMIME,Content,ActionName,ActionParams,ActionResult,DoneTime,Status FROM Messages
WHERE SenderID = ? or ReceiverID =? AND Timestamp > ?
ORDER BY Timestamp
LIMIT ?
""", (agent_id, agent_id, start_time,limit))
results = cursor.fetchall()
#self.close()
return results # return 0 and the result if successful
except Error as e:
logging.error("Error occurred while getting messages: %s", e)
return -1, None
# read message from now->beign
def get_messages(self, session_id, limit, offset):
""" retrieve messages of a session with pagination """
@@ -287,6 +304,38 @@ class AIChatSession:
# cls._dbs[db_path] = db
# db.get_chatsession_by_id(session_id)
# #result = AIChatSession()
@classmethod
# start_time is a string like "2021-01-01 00:00:00"
def load_message_records_by_agentid(cls,agent_id:str,start_time:str,limit:int,db_path:str)->List[AgentMsg]:
db = cls._dbs.get(db_path)
if db is None:
db = ChatSessionDB(db_path)
cls._dbs[db_path] = db
msgs = db.load_message_by_agentid(agent_id,start_time,limit)
result = []
for msg in msgs:
agent_msg = AgentMsg()
agent_msg.msg_id = msg[0]
agent_msg.session_id = msg[1]
agent_msg.msg_type = AgentMsgType(msg[2])
agent_msg.prev_msg_id = msg[3]
agent_msg.sender = msg[4]
agent_msg.target = msg[5]
agent_msg.create_time = msg[6]
agent_msg.topic = msg[7]
if msg[8] is not None:
agent_msg.mentions = json.loads(msg[8])
agent_msg.body_mime = msg[9]
agent_msg.body = msg[10]
agent_msg.func_name = msg[11]
if msg[12] is not None:
agent_msg.args = json.loads(msg[12])
agent_msg.result_str = msg[13]
agent_msg.done_time = msg[14]
agent_msg.status = AgentMsgStatus(msg[15])
result.append(agent_msg)
return result
@classmethod
def get_session(cls,owner_id:str,session_topic:str,db_path:str,auto_create = True) -> 'AIChatSession':
+98 -27
View File
@@ -42,6 +42,9 @@ class BaseLLMProcess(ABC):
self.llm_context:LLMProcessContext = None
def get_llm_model_name(self) -> str:
return self.model_name
@abstractmethod
async def prepare_prompt(self,input:Dict) -> LLMPrompt:
pass
@@ -123,10 +126,11 @@ class BaseLLMProcess(ABC):
else:
inner_functions = None
task_result: ComputeTaskResult = await (ComputeKernel.get_instance().do_llm_completion(
prompt,
resp_mode=resp_mode,
mode_name=self.model_name,
mode_name=self.get_llm_model_name(),
max_token=max_result_token,
inner_functions=inner_functions, #NOTICE: inner_function in prompt can be a subset of get_inner_function
timeout=self.timeout))
@@ -166,7 +170,7 @@ class BaseLLMProcess(ABC):
task_result: ComputeTaskResult = await (ComputeKernel.get_instance().do_llm_completion(
prompt,
resp_mode=resp_mode,
mode_name=self.model_name,
mode_name=self.get_llm_model_name(),
max_token=max_result_token,
inner_functions=prompt.inner_functions, #NOTICE: inner_function in prompt can be a subset of get_inner_function
timeout=self.timeout))
@@ -309,6 +313,9 @@ class LLMAgentBaseProcess(BaseLLMProcess):
class AgentMessageProcess(LLMAgentBaseProcess):
def __init__(self) -> None:
super().__init__()
self.mutil_model = None
self.enable_media2text = False
self.is_mutil_model = False
async def load_default_config(self) -> bool:
return True
@@ -320,6 +327,16 @@ class AgentMessageProcess(LLMAgentBaseProcess):
if await super().load_from_config(config) is False:
return False
self.enable_media2text = config.get('enable_media2text', 'false').lower() in ('true', '1', 't', 'y', 'yes')
if config.get("mutil_model"):
self.mutil_model = config.get("mutil_model")
def get_llm_model_name(self) -> str:
if self.is_mutil_model:
return self.mutil_model
else:
return self.model_name
def check_and_to_base64(self, image_path: str) -> str:
if image_utils.is_file(image_path):
@@ -329,14 +346,24 @@ class AgentMessageProcess(LLMAgentBaseProcess):
async def get_prompt_from_msg(self,msg:AgentMsg) -> LLMPrompt:
msg_prompt = LLMPrompt()
self.is_mutil_model = False
if msg.is_image_msg():
image_prompt, images = msg.get_image_body()
if image_prompt is None:
msg_prompt.messages = [{"role": "user", "content": [{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images]}]
if self.enable_media2text:
logger.error(f"enable_media2text is not supported yet")
else:
content = [{"type": "text", "text": image_prompt}]
content.extend([{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images])
msg_prompt.messages = [{"role": "user", "content": content}]
image_prompt, images = msg.get_image_body()
if image_prompt is None:
msg_prompt.messages = [{"role": "user", "content": [{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images]}]
else:
content = [{"type": "text", "text": image_prompt}]
content.extend([{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images])
msg_prompt.messages = [{"role": "user", "content": content}]
if self.mutil_model:
self.is_mutil_model = True
else:
logger.warning(f"mutil_model is not set!")
elif msg.is_video_msg():
video_prompt, video = msg.get_video_body()
frames = video_utils.extract_frames(video, (1024, 1024))
@@ -459,25 +486,7 @@ class AgentMessageProcess(LLMAgentBaseProcess):
return True
class AgentSelfLearning(BaseLLMProcess):
def __init__(self) -> None:
super().__init__()
async def load_from_config(self, config: dict) -> Coroutine[Any, Any, bool]:
if await super().load_from_config(config) is False:
return False
async def prepare_prompt(self) -> LLMPrompt:
prompt = LLMPrompt()
pass
async def get_inner_function_for_exec(self,func_name:str) -> AIFunction:
pass
async def post_llm_process(self,actions:List[ActionNode]) -> bool:
pass
class AgentSelfThinking(BaseLLMProcess):
class AgentSelfThinking(LLMAgentBaseProcess):
def __init__(self) -> None:
super().__init__()
@@ -553,6 +562,68 @@ class AgentSelfThinking(BaseLLMProcess):
chatsession.update_think_progress(next_pos,new_summary)
return
async def prepare_prompt(self,input:Dict) -> LLMPrompt:
prompt = LLMPrompt()
record_list = input.get("record_list")
context_info = input.get("context_info")
if record_list is None:
logger.error(f"AgentSelfThinking prepare_prompt failed! input not found")
return None
prompt.append_user_message(json.dumps(record_list,ensure_ascii=False))
system_prompt_dict = self.prepare_role_system_prompt(context_info)
# Known_info is the SESSION summary of the existence, the current task work record summary,
known_info = {}
have_known_info = False
known_session_list = input.get("known_session_list")
known_task_list = input.get("known_task_list")
known_contact_list = input.get("known_contact_list")
known_experience_list = input.get("known_experience_list")
if known_session_list:
known_info["known_session_list"] = known_session_list
have_known_info = True
if known_task_list:
known_info["known_task_list"] = known_task_list
have_known_info = True
if known_contact_list:
known_info["known_contact_list"] = known_contact_list
have_known_info = True
if known_experience_list:
known_info["known_experience_list"] = known_experience_list
have_known_info = True
if have_known_info:
system_prompt_dict["known_info"] = known_info
prompt.inner_functions =LLMProcessContext.aifunctions_to_inner_functions(self.llm_context.get_all_ai_functions())
prompt.append_system_message(json.dumps(system_prompt_dict,ensure_ascii=False))
async def post_llm_process(self,actions:List[ActionNode],input:Dict,llm_result:LLMResult) -> bool:
action_params = {}
action_params["_input"] = input
action_params["_memory"] = self.memory
action_params["_workspace"] = self.workspace
action_params["_llm_result"] = llm_result
action_params["_agentid"] = self.memory.agent_id
action_params["_start_at"] = datetime.now()
try:
if await self._execute_actions(actions,action_params) is False:
result_str = "execute action failed!"
except Exception as e:
logger.error(f"execute action failed! {e}")
result_str = "execute action failed!,error:" + str(e)
class AgentSelfLearning(BaseLLMProcess):
def __init__(self) -> None:
super().__init__()
async def load_from_config(self, config: dict) -> Coroutine[Any, Any, bool]:
if await super().load_from_config(config) is False:
return False
async def prepare_prompt(self) -> LLMPrompt:
prompt = LLMPrompt()
pass
+1 -1
View File
@@ -21,7 +21,7 @@ logger = logging.getLogger(__name__)
class LocalAgentTaskManger(AgentTaskManager):
def __init__(self, owner_id):
super().__init__()
self.root_path = f"{AIStorage.get_instance().get_myai_dir()}/workspaces/{owner_id}_workspace"
self.root_path = f"{AIStorage.get_instance().get_myai_dir()}/agent_data/{owner_id}/workspace/"
#self.root_path = os.path.join(workspace, list_type)
if not os.path.exists(self.root_path):
os.makedirs(self.root_path)
+1 -1
View File
@@ -13,7 +13,7 @@ from ..agent.llm_context import GlobaToolsLibrary
from ..proto.compute_task import *
from ..proto.ai_function import *
from ..frame.compute_kernel import ComputeKernel
from ..frame.contact_manager import ContactManager,Contact,FamilyMember
from ..frame.contact_manager import ContactManager,Contact
from ..storage.storage import AIStorage
from .environment import SimpleEnvironment, CompositeEnvironment
+1 -1
View File
@@ -107,7 +107,7 @@ class ComputeKernel:
@staticmethod
def llm_num_tokens_from_text(text:str,model:str) -> int:
if model is None:
model = "gpt4"
model = "gpt-4-turbo-preview"
try:
encoding = tiktoken.encoding_for_model(model)
+8 -17
View File
@@ -18,6 +18,7 @@ class Contact:
self.notes = notes
self.is_family_member = False
self.active_tunnels = {}
self.relationship = "friends"
def to_dict(self):
return {
@@ -25,11 +26,13 @@ class Contact:
"phone": self.phone,
"email": self.email,
"telegram" : self.telegram,
"is_family_member": self.is_family_member,
"added_by": self.added_by,
"tags": self.tags,
"notes": self.notes,
"now" : datetime.now().strftime('%Y-%m-%d %H:%M:%S')
"now" : datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
"relationship" : self.relationship
}
async def _process_msg(self,msg:AgentMsg):
@@ -55,6 +58,7 @@ class Contact:
self.active_tunnels[agent_id] = tunnel
async def create_default_tunnel(self,agent_id:str) -> AgentTunnel:
#TODO:fix this
from .email_tunnel import EmailTunnel
result_tunnels = AgentTunnel.get_tunnel_by_agentid(agent_id)
@@ -66,20 +70,7 @@ class Contact:
@classmethod
def from_dict(cls, data):
return Contact(data.get("name"), data.get("phone"), data.get("email"), data.get("telegram"),data.get("added_by"), data.get("tags"), data.get("notes"))
class FamilyMember(Contact):
def __init__(self, name, relationship,phone=None, email=None,telegram=None):
super().__init__(name, phone, email, telegram)
self.name = name
self.relationship = relationship
self.is_family_member = True
def to_dict(self):
result = super().to_dict()
result["relationship"] = self.relationship
result = Contact(data.get("name"), data.get("phone"), data.get("email"), data.get("telegram"),data.get("added_by"), data.get("tags"), data.get("notes"))
if data.get("relationship") is not None:
result.relationship = data.get("relationship")
return result
@classmethod
def from_dict(cls, data):
return FamilyMember(data.get("name"),data.get("relationship"),data.get("phone"), data.get("email"),data.get("telegram"))
+6 -34
View File
@@ -8,7 +8,7 @@ from ..proto.agent_msg import AgentMsg
from ..proto.ai_function import ParameterDefine, SimpleAIFunction
from ..agent.llm_context import GlobaToolsLibrary
from .tunnel import AgentTunnel
from .contact import Contact,FamilyMember
from .contact import Contact
logger = logging.getLogger(__name__)
@@ -25,11 +25,12 @@ class ContactManager:
def register_global_functions(self):
gl = GlobaToolsLibrary.get_instance()
get_parameters = ParameterDefine.create_parameters({"name":"name"})
get_parameters = ParameterDefine.create_parameters({"name":"contact name name"})
gl.register_tool_function(SimpleAIFunction("system.contacts.get",
"get contact info",
self._get_contact,get_parameters))
# todo: use json to save contact info
update_parameters = ParameterDefine.create_parameters({"name":"name","contact_info":"A json to descrpit contact"})
gl.register_tool_function(SimpleAIFunction("system.contacts.set",
"set contact info",
@@ -42,7 +43,6 @@ class ContactManager:
def __init__(self, filename="contacts.toml"):
self.filename = filename
self.contacts = []
self.family_members = []
self.is_auto_create_contact_from_telegram = True
@@ -56,12 +56,10 @@ class ContactManager:
def load_from_config(self,config_data:dict):
self.contacts = [Contact.from_dict(item) for item in config_data.get("contacts", [])]
self.family_members = [FamilyMember.from_dict(item) for item in config_data.get("family_members", [])]
def save_data(self):
data = {
"contacts": [contact.to_dict() for contact in self.contacts],
"family_members": [member.to_dict() for member in self.family_members]
}
with open(self.filename, "w") as f:
toml.dump(data, f)
@@ -95,54 +93,28 @@ class ContactManager:
if contact.name == name:
return contact
for member in self.family_members:
if member.name == name:
return member
return None
def find_contact_by_telegram(self, telegram:str):
for contact in self.contacts:
if contact.telegram == telegram:
return contact
for member in self.family_members:
if member.telegram == telegram:
return member
return None
def find_contact_by_email(self, email:str):
for contact in self.contacts:
if contact.email == email:
return contact
for member in self.family_members:
if member.email == email:
return member
return None
def find_contact_by_phone(self, phone:str):
for contact in self.contacts:
if contact.phone == phone:
return contact
for member in self.family_members:
if member.phone == phone:
return member
return None
def add_family_member(self, name, new_member:FamilyMember):
assert name == new_member.name
self.family_members.append(new_member)
self.save_data()
def list_contacts(self):
return self.contacts
def list_family_members(self):
return self.family_members
#def register_to_ai_bus(self, ai_bus:AIBus):
# ai_bus.register_message_handler("contact_manager", self.process_msg)
#async def process_msg(self,msg:AgentMsg):
# # forword message to contact
# pass
+1 -1
View File
@@ -15,7 +15,7 @@ class KnowledgeStore:
if cls._instance is None:
cls._instance = super().__new__(cls)
knowledge_dir = AIStorage.get_instance().get_myai_dir() / "knowledge" / "objects"
knowledge_dir = f"{AIStorage.get_instance().get_myai_dir()}/knowledge/objects"
if not os.path.exists(knowledge_dir):
os.makedirs(knowledge_dir)
+11 -4
View File
@@ -40,7 +40,7 @@ class UserConfig:
self.config_table = {}
self.user_config_path:str = None
self._init_default_value("llm_model_name","gpt-4-1106-preview")
self._init_default_value("llm_model_name","gpt-4-turbo-preview")
def _init_default_value(self,key:str,value:Any) -> None:
if self.config_table.get(key) is not None:
@@ -92,7 +92,7 @@ class UserConfig:
os.makedirs(directory)
async with aiofiles.open(self.user_config_path,"w") as f:
toml_str = toml.dumps(will_save_config,ensure_ascii=False)
toml_str = toml.dumps(will_save_config)
await f.write(toml_str)
except Exception as e:
logger.error(f"save user config to {self.user_config_path} failed!")
@@ -156,7 +156,7 @@ class AIStorage:
self.feature_init_results = {}
async def initial(self)->bool:
self.user_config.user_config_path = str(self.get_myai_dir() / "etc/system.cfg.toml")
self.user_config.user_config_path = str(self.get_myai_dir() + "/etc/system.cfg.toml")
await self.user_config.load_value_from_file(self.get_system_dir() + "/system.cfg.toml")
await self.user_config.load_value_from_file(self.user_config.user_config_path,True)
@@ -215,7 +215,7 @@ class AIStorage:
my ai dir is the dir for user to store their ai app and data
~/myai/
"""
return Path.home() / "myai"
return f"{Path.home()}/myai"
def get_download_dir(self) -> str:
"""
@@ -249,3 +249,10 @@ class AIStorage:
except Exception as e:
logger.error(f"open or create file {path} failed! {str(e)}")
@staticmethod
def ensure_directory_exists(directory_path):
if not os.path.exists(directory_path):
os.makedirs(directory_path)
logger.info(f"Directory created: {directory_path}")
@@ -72,8 +72,6 @@ class AgentManager:
logger.warn(f"load agent {agent_id} from media failed!")
return None
the_agent.memory_db = f"{self.agent_memory_base_dir}/{agent_id}/{agent_id}_memory.db"
os.makedirs(os.path.dirname(the_agent.memory_db),exist_ok=True)
if await the_agent.initial():
return the_agent
else:
@@ -453,7 +453,7 @@ class ParseLocalDocument:
return f"# Known information:\n## Current directory structure:\n{kb_tree}\n## Knowlege Metadata:\n{json.dumps(known_obj,ensure_ascii=False)}\n"
def _token_len(self, text: str) -> int:
return CustomAIAgent("", "gpt-4-1106-preview", self.token_limit).token_len(text=text)
return CustomAIAgent("", "gpt-4-turbo-preview", self.token_limit).token_len(text=text)
async def _learn_by_agent(self, meta:dict) -> dict:
@@ -64,7 +64,7 @@ class DallEComputeNode(ComputeNode):
self.output_dir = "./"
self.output_dir = os.path.abspath(self.output_dir)
self.start()
await self.start()
return True
+1 -1
View File
@@ -209,7 +209,7 @@ class OpenAI_ComputeNode(ComputeNode):
if max_token_size > 4096:
result_token = 4096
else:
result_token = max_token_size
result_token = -1
else:
result_token = NOT_GIVEN
+1 -1
View File
@@ -12,7 +12,7 @@ from telegram import Bot
from telegram.ext import Updater
from telegram.error import Forbidden, NetworkError
from aios import ObjectType, KnowledgeStore,AgentTunnel,AIStorage,ContactManager,Contact,FamilyMember,AgentMsg,AgentMsgType
from aios import ObjectType, KnowledgeStore,AgentTunnel,AIStorage,ContactManager,Contact,AgentMsg,AgentMsgType
logger = logging.getLogger(__name__)
+17 -15
View File
@@ -76,8 +76,9 @@ class AIOS_Shell:
user_config = AIStorage.get_instance().get_user_config()
user_config.add_user_config("username","username is your full name when using AIOS",False,None)
user_config.add_user_config("telegram","Your telgram username",False,None)
user_config.add_user_config("email","Your email",False,None)
user_config.add_user_config("user_telegram","Your telgram username",False,None)
user_config.add_user_config("user_email","Your email",False,None)
user_config.add_user_config("user_notes","Introduce yourself to your Agent!",False,None)
user_config.add_user_config("feature.llama","enable Local-llama feature",True,"False")
user_config.add_user_config("feature.aigc","enable AIGC feature",True,"False")
@@ -126,15 +127,16 @@ class AIOS_Shell:
async def initial(self) -> bool:
cm = ContactManager.get_instance()
owenr = cm.find_contact_by_name(self.username)
if owenr is None:
owenr = Contact(self.username)
owenr.added_by = self.username
owenr.is_family_member = True
owenr.email = AIStorage.get_instance().get_user_config().get_value("email")
owenr.telegram = AIStorage.get_instance().get_user_config().get_value("telegram")
owner = cm.find_contact_by_name(self.username)
if owner is None:
owner = Contact(self.username)
owner.added_by = self.username
owner.relationship = "Principal"
owner.email = AIStorage.get_instance().get_user_config().get_value("user_email")
owner.telegram = AIStorage.get_instance().get_user_config().get_value("user_telegram")
owner.notes = AIStorage.get_instance().get_user_config().get_value("user_notes")
cm.add_family_member(self.username,owenr)
cm.add_contact(self.username,owner)
# cal_env = CalenderEnvironment("calender")
# await cal_env.start()
@@ -247,7 +249,7 @@ class AIOS_Shell:
if tunnel_config is not None:
await AgentTunnel.load_all_tunnels_from_config(tunnel_config)
except Exception as e:
logger.warning(f"load tunnels config from {tunnels_config_path} failed!")
logger.warning(f"load tunnels config from {tunnels_config_path} failed! {e}")
return True
@@ -385,7 +387,7 @@ class AIOS_Shell:
contact_note = await try_get_input(f"Input {contact_name}'s note (optional):")
if contact_note is not None:
contact.note = contact_note
contact.notes = contact_note
contact.added_by = self.username
if is_update:
@@ -712,9 +714,9 @@ async def get_user_config_from_input(check_result:dict) -> bool:
continue
else:
True
if len(user_input) > 0:
AIStorage.get_instance().get_user_config().set_value(key,user_input)
if user_input:
if len(user_input) > 0:
AIStorage.get_instance().get_user_config().set_value(key,user_input)
await AIStorage.get_instance().get_user_config().save_to_user_config()
return True