Updated working principles

This commit is contained in:
Niels Geens
2024-10-30 16:48:20 +01:00
parent 705f17c47b
commit bd5c5911af
3 changed files with 239 additions and 159 deletions

View File

@@ -0,0 +1,75 @@
@startuml
skinparam classAttributeIconSize 0
class AgentCore {
- LLMEngine llmEngine
- List<CoreAction> actions
+ run()
+ templateActions(): List[Element]
+ systemInfo(): Element
+ buildContext(systemInfo: Element, actions: List[Element]): str
+ parseResponse(response: str): List[CoreAction], List[int]
+ deleteActions(List[int])
+ deleteAction(id: int)
+ stop()
}
class ServerCore {
- WebSystem webSystem
+ run()
}
class WebSystem {
+ updateContext(context: str)
+ getUpdatedContext(): str
+ updateActions(actions: List[CoreAction])
+ getUpdatedActions(): List[CoreAction]
}
class LLMEngine {
+ infer(context: str): Iterator[str]
}
class CoreAction {
+ id: str
+ template(id: str): Element
+ execute()
}
class SingleShotAction extends CoreAction {
}
class RepeatAction extends CoreAction {
}
class BackgroundAction extends CoreAction {
}
class DeleteAction {
+ execute(context: Context)
}
class InferenceResult {
+ reasoning: str
+ actions: List[CoreAction]
+ {static} parse(llmOutput: str): InferenceResult
}
Agent o-- LLMEngine
Agent o-- AgentCore
Agent o-- ServerCore
Agent o-- CoreAction
AgentCore o-- Context
AgentCore o-- InferenceResult
AgentCore o-- CoreAction
ServerCore o-- WebSystem
ServerCore o-- InferenceResult
ServerCore o-- CoreAction
CoreAction <|-- SingleShotAction
CoreAction <|-- RepeatAction
CoreAction <|-- BackgroundAction
CoreAction o-- DeleteAction
@enduml

44
old_architecture.md Normal file
View File

@@ -0,0 +1,44 @@
## Architecture
An overview of the key components and their interactions.
![SIA Component Model](./diagrams/SIA_Component_Model.svg)
### Core Actions
Core actions are implemented each in a separate class.
Each action in the context is an instance of the corresponding class.
The `delete` and `stop` actions are exceptions to this.
They are implemented as functions in the `AgentCore`.
Actions have a `template(id)` method that returns an XML Element.
If they require updating in each iteration, they do so at the start of the `template` method.
### Agent Core
The `AgentCore` manages the state of the agent.
It can also run a basic main loop consisting of:
- Running template on all actions
- Collecting system information
- Building the context
- Running the LLM
- Splitting the LLM output in reasoning and actions
- Instantiating the new actions and listing id's to delete
- Deleting the old actions
### Web System
The `WebSystem` uses an `AgentCore` but doesn't run the main loop.
It runs a modified main loop and interacts with the WebSystem.
It also instantiates alternative actions for stdio to interact with the WebSystem.
### LLM Engine
The `LLMEngine` does the LLM inference.
It takes a context as string and returns an iterator of tokens.
### Inference Result
An `InferenceResult` object contains the resoning and parsed actions.
Parsing is part of the Inference Result constructor.

279
readme.md
View File

@@ -1,16 +1,114 @@
# SIA - The Self Improving Agent # SIA - The Self Improving Agent
SIA is an agentic artificial intelligence system that autonomously completes complex tasks by writing and executing scripts. SIA is an agentic artificial intelligence system that autonomously completes complex tasks by writing and executing scripts.
It uses a Large Language Model (LLM) which operates in a loop, generating reasoning and actions based on an updating context. It uses a Large Language Model (LLM) which operates in a loop.
Each iteration a context is updated with system info and a list of previous reasoning and actions.
The agent responds with a new reasoning or an action.
Context, reasoning and actions are stored in a file for each iteration. Context, reasoning and actions are stored in a file for each iteration.
SIA can read past iterations to improve its reasoning and actions. SIA can read past iterations to improve its reasoning and actions.
It can improve in two ways: It can improve in two ways:
- By providing better reasoning or actions for a given context and update the LLM. - By finetuning the LLM with a better reasoning or action for a given context
- By modifying its own source code. - By modifying its own source code
## Example
This example shows a typical context with some monitored items and previous actions.
Between each of the responses, the context would be updated.
### Context
```xml
<context
time="2024-10-18T12:00:00Z"
cpu="12"
gpu="26"
memory_used="9556302234"
memory_total="17179869184"
disk_used="244434939904"
disk_total="273145991168"
context="3"
stdin="0"
/>
<repeat id="a3d89ee5-28ec-4c5a-b9e9-a30af53d43a0" exit_code="0">
<![CDATA[ls -lah /]]>
<stdout><![CDATA[total 16K
drwxr-xr-x 1 sia 1049089 0 Oct 28 13:40 ./
drwxr-xr-x 1 sia 1049089 0 Oct 28 13:40 ../
drwxr-xr-x 1 sia 1049089 0 Oct 28 13:40 tasks/
drwxr-xr-x 1 sia 1049089 0 Oct 28 13:40 user/
]]></stdout>
<stderr/>
</repeat>
<repeat id="be8070f8-dbd2-47ee-a208-defe6fd49ae0" exit_code="0">
<![CDATA[ls -lah /tasks]]>
<stdout><![CDATA[total 0
drwxr-xr-x 1 ngeens 1049089 0 Oct 28 13:40 ./
drwxr-xr-x 1 ngeens 1049089 0 Oct 28 13:40 ../
]]></stdout>
<stderr/>
</repeat>
<repeat id="375e1657-8140-456b-bda4-a8690bc4b3fb" exit_code="0">
<![CDATA[cat /user/general_info.txt]]>
<stdout><![CDATA[Name: John (I don't know his last name)
Location: Somewhere in Belgium
]]></stdout>
<stderr/>
</repeat>
<reasoning id="c92d1594-4487-4a42-a153-f0a99da1762f"><![CDATA[There is data available on the standard input channel. I have no other running tasks to tend to and there is room in the context. I should read the standard input.]]></reasoning>
<read_stdin id="5361ad0d-3ed1-4567-9f5a-70f3b462fd8d"><![CDATA[Remind me to feed the cat tomorrow morning]]></read_stdin>
</context>
```
### Responses
Start by reasoning about the task.
```xml
<reasoning>
John did not specify an exact time.
I'll suggest 9am.
He also did not specify how to be reminded.
I'll ask but if he doesn't respond I'll assume a text message on standard output is fine.
I'll write down this task in a file so I remember it even on a power failure.
</reasoning>
```
Store important information on disk.
```xml
<single_shot><![CDATA[echo 'Remind John to feed the cat on 2024-10-18T09:00:00+02:00. Use standard output.' > /tasks/reminder_to_feed_cat.txt]]></single_shot>
```
Respond to the user.
```xml
<write_stdout>I'll remind you to feed the cat tomorrow morning at 9am. Is a message on the standard output ok?</write_stdout>
```
Clear initial reasoning.
```xml
<delete id="c92d1594-4487-4a42-a153-f0a99da1762f"/>
```
The conversation is kept in context to understand the user's expected response.
If the context was near full, it would be summarized and cleaned up.
The single shot is also kept in context.
If the file was updated often, it could be replaced by a repeated `cat`, like the general info.
## Working principles ## Working principles
High-level overview of the main components of SIA and how they work together. The main context is regenerated for each iteration.
It contains info about the system and previous actions that have not been deleted.
Together with the system prompt and available core actions it forms the prompt for the LLM.
The LLM responds with one core action.
### Core Actions
There are only a few core actions:
- Starting a script
- Deleting data from context
- Stopping SIA
- Reading standard input
- Writing to standard output
- Reasoning
### Scripts ### Scripts
@@ -34,38 +132,10 @@ Similar to single-shot scripts, the next iteration starts after all repeat scrip
#### Background #### Background
The script is started and keeps running. The script is started and keeps running.
This is useful for long-running processes e.g. a web server or a communication channel. This is useful for waiting for events, a communication channels or a process that requires attention.
Because output of a background script can grow long, it is often redirected to a file.
### LLM prompt Long-running processes e.g. a web server can be run as a service or detached process to keep the context small.
The output can be redirected to a file and monitored with a repeat script.
The main context is regenerated for each iteration.
It contains info about the system, the scripts and what happended in the previous iteration.
Together with the system prompt and available core actions it forms the prompt for the LLM.
The LLM generates reasoning and an XML structure with core actions.
If the structure cannot be parsed, the error is described and the LLM is asked to try again.
This can continue until the context overflows.
Only the first reasoning, last reasoning and last actions are shown in the new context.
All is stored on the file system.
### Core Actions
There are only a few core actions:
- Starting a script
- Stopping a script
- Stopping SIA
- Reading standard input
- Writing to standard output
Standard error is used by the core for debugging.
SIA typically runs in a Docker container.
When stopped, the latest container version is pulled.
This is how SIA can be updated.
SIA can also run SIA processes as script.
This can be used for testing updates to the LLM or core functionality.
### Use of XML ### Use of XML
@@ -73,11 +143,21 @@ The context and actions are formatted as XML.
For the context this adds clear rules for escaping. For the context this adds clear rules for escaping.
This is usefull in case a previous context is embedded. This is usefull in case a previous context is embedded.
The response starts with freeform reasoning followed by XML formatted actions. The LLM is free to escape data any way it wants,
In case the LLM makes a mistake it can start over. as long as it results in valid XML.
Only the last XML block is evaluated. The Context is escaped using CDATA blocks.
Except when the data contains CDATA closing sequences.
Then the whole block is escaped using standard XML escaping.
Action results are added in the context in the previous_iteration section. ### The SIA process
SIA is typically runs with the `restart.sh` script.
This is a simple shell script that runs SIA in a loop.
When stopped, SIA restarts and reloads the Python files.
This is how SIA can self-update.
SIA can also run SIA processes as script.
This can be used for testing updates to the LLM or core functionality.
### Server for debuggin and human input ### Server for debuggin and human input
@@ -88,123 +168,4 @@ The web interface takes over standard input and output.
It will display the context for editing before handing it to the LLM. It will display the context for editing before handing it to the LLM.
After each run of the LLM, before parsing, it will display the reasoning and actions. After each run of the LLM, before parsing, it will display the reasoning and actions.
It interactively displays if the actions can be parsed. It interactively displays if the actions can be parsed.
At any time, the user can write to the standard input of SIA. At any time, the user can write to the standard input of SIA.
## Architecture
An overview of the key components and their interactions.
![SIA Component Model](./diagrams/SIA_Component_Model.svg)
### Modules
Modules execute core commands and provide data for the context template.
- System Module
- System information
- SIA stdio operations
- Stopping SIA (possibly triggering an update)
- Process Module
- Starting scripts
- Stopping scripts
- Managing process stdio and status
### Agent Core
The Agent Core runs the SIA main loop.
This loop consists of:
- Templating the context
- Running the LLM
- Parsing the LLM output
- Rerunning the LLM if the output cannot be parsed
- Executing the appropriate actions
### Server Core
The Server Core is an alternative for the Agent Core.
It runs a modified main loop and ues the WebSystem Module.
This is an extension of the System Module redirecting stdio to the web interface.
### LLM Engine
The LLM Engine does the LLM inference.
It takes a context and returns an iterator of tokens.
### Inference Result
An Inference Result object contains the resoning and parsed actions.
Parsing is part of the Inference Result constructor.
## Example iterations
### Clarifying a task
This example shows how to work with standard IO, run simple scripts and monitor files.
#### Context
```xml
<context>
<system
time="2024-10-18T12:00:00Z"
cpu="12"
gpu="26"
memory_used="9556302234"
memory_total="17179869184"
disk_used="244434939904"
disk_total="273145991168"
context="3"
stdin="0"
/>
<containers/>
<previous>
<reasoning>
There is data available on the standard input channel. I should read it. I have no other running tasks to tend to.
</reasoning>
<actions>
<read_stdin>
<![CDATA[Remind me to feed the cat tomorrow morning]]>
</read_stdin>
</actions>
</previous>
<files>
<file name="/" type="dir" index="0">
<![CDATA[
drwxr-xr-x 1 sia 197121 0 2024-10-16 23:02:16.486152500 +0200 tasks/
drwxr-xr-x 1 sia 197121 0 2024-10-16 22:35:31.806079500 +0200 user/
]]>
</file>
<file name="/tasks" type="dir" index="1">
</file>
<file name="/user" type="dir">
<![CDATA[
-rw-r--r-- 1 sia 197121 71 2024-10-16 22:41:23.223580300 +0200 general_info.txt
]]>
</file>
<file name="/user/general_info.txt" type="file" index="2">
<![CDATA[
Name: John (I don't know his last name)
Location: Somewhere in Belgium
]]>
</file>
</files>
</context>
```
#### LLM response
```xml
John did not specify an exact time. I'll suggest 9am. He also did not specify how to be reminded. I'll ask but if he doesn't respond I'll assume a text message on standard output is fine. I'll write down this task in a file so I can keep it in context. I can write simple files with busybox:latest and echo but I will need to use sh -c to do the redirect.
<actions>
<write_stdout message="I'll remind you to feed the cat tomorrow morning at 9am. Is a message on the standard output ok?"/>
<start_container image="busybox:latest" timeout="1000">
<command>sh</command>
<argtument>-c</argument>
<argument><![CDATA[echo 'Remind John to feed the cat on 2024-10-18T09:00:00+02:00. Use standard output.' > /tasks/reminder.txt]]></argument>
<volumes>
<volume>/tasks:/tasks</volume>
</volumes>
</start_container>
<monitor_file path="/tasks/reminder.txt"/>
</actions>
```