Fixes for v0.6

- UI encoding on windows - ChromaDB removal - Shell output trim tweak

frdel committed Sep 1, 2024 at 01:04 UTC a04ed7f0d719ab7b87facaa0d55de2e1205dc340
10 files changed +69 -17
README.md
+17 -3
@@ -11,6 +11,9 @@
11 - Agent Zero is fully transparent, readable, comprehensible, customizable and interactive.
12 - Agent Zero uses the computer as a tool to accomplish its (your) tasks.
13
14 +## Now with UI:
15 +![UI prototype](docs/ui_screen1.png)
16 +
17 ## Key concepts
18 1. **General-purpose assistant**
19 - Agent Zero is not pre-programmed for specific tasks (but can be). It is meant to be a general-purpose personal assistant. Give it a task, and it will gather information, execute commands and code, cooperate with other agent instances, and do its best to accomplish it.
@@ -62,6 +65,7 @@ If your agent fails to communicate properly, use tools, reason, use memory, find
65 Agent Zero is made to be used in an isolated virtual environment (for safety) with some tools preinstalled and configured.
66 If you cannot provide all the necessary conditions or API keys, just change the system prompt and tell your agent what operating system and tools are at its disposal. Nothing is hard-coded; if you do not tell your agent about a certain tool, it will not know about it and will not try to use it.
67
68 +
69 [![David Ondrej video](/docs/david_vid.jpg)](https://www.youtube.com/watch?v=_Pionjv4hGc)
70
71 ## Known problems
@@ -78,6 +82,10 @@ If you cannot provide all the necessary conditions or API keys, just change the
82
83 ## Setup
84
85 +> ⚠️ **Changes to launch files since v0.6:**
86 +> main.py file has been replaced with run_ui.py (webui) and run_cli.py (terminal) launch files.
87 +> configuration has been moved to initialize.py for both webui and terminal launch files.
88 +
89 Update: [Guide by CheezChat for Windows](./docs/win_installation_guide.txt)
90
91 1. **Required API keys:**
@@ -102,11 +110,17 @@ pip install -r requirements.txt
110 - You can choose between online models (OpenAI, Anthropic, Groq) or offline (Ollama, LMStudio, HuggingFace) for both.
111
112 4. **run Docker:**
105 -- Easiest way is to install Docker Desktop application and just run it. The rest will be handled by the framework itself.
113 +- Easiest way is to install Docker Desktop application ([Download](https://www.docker.com/products/docker-desktop/)) and just leave it running in the background.
114 +- You don't need to download and build any images, it will be done automatically by the framework at runtime.
115
116 ## Run the program
108 -- Just run the **main.py** file in Python:
117 +- Just run the **run_ui.py** file in Python:
118 ~~~bash
110 -python main.py
119 +python run_ui.py
120 ~~~
121 +- And open the URL shown in the terminal:
122 +
123 +![Flask link](docs/flask_link.png)
124 +
125 - Or run it in debug mode in VS Code using the **debug** button in the top right corner of the editor. I have provided config files for VS Code for this purpose.
126 +- For the original command line interface you can run run_cli.py instead of run_ui.py
\ No newline at end of file
docs/flask_link.png
Binary files /dev/null and b/docs/flask_link.png differ
docs/ui_screen1.png
Binary files /dev/null and b/docs/ui_screen1.png differ
initialize.py
+1 -1
@@ -6,7 +6,7 @@ def initialize():
6 # main chat model used by agents (smarter, more accurate)
7 chat_llm = models.get_openai_chat(model_name="gpt-4o-mini", temperature=0)
8 # chat_llm = models.get_ollama_chat(model_name="gemma2:latest", temperature=0)
9 - chat_llm = models.get_lmstudio_chat(model_name="TheBloke/Mistral-7B-Instruct-v0.2-GGUF", temperature=0)
9 + # chat_llm = models.get_lmstudio_chat(model_name="TheBloke/Mistral-7B-Instruct-v0.2-GGUF", temperature=0)
10 # chat_llm = models.get_openrouter(model_name="meta-llama/llama-3-8b-instruct:free")
11 # chat_llm = models.get_azure_openai_chat(deployment_name="gpt-4o-mini", temperature=0)
12 # chat_llm = models.get_anthropic_chat(model_name="claude-3-5-sonnet-20240620", temperature=0)
python/helpers/log.py
+2 -2
@@ -35,8 +35,8 @@ class Log:
35 def log(type: str, heading: str|None = None, content: str|None = None, kvps: dict|None = None):
36 item = LogItem(len(Log.logs), type, heading or "", content or "", kvps)
37 Log.logs.append(item)
38 - Log.version += 1
38 Log.last_updated = item.no
39 + Log.version += 1
40 return item
41
42 @staticmethod
@@ -52,7 +52,7 @@ class Log:
52 if kvps is not None:
53 item.kvps = kvps
54
55 - Log.version += 1
55 Log.last_updated = no
56 + Log.version += 1
57 else:
58 raise IndexError("Log item number out of range")
python/helpers/shell_ssh.py
+3 -1
@@ -77,7 +77,9 @@ class SSHInteractiveSession:
77 if self.last_command and len(self.last_command) > self.trimmed_command_length:
78 command_to_trim = self.last_command[self.trimmed_command_length:]
79
80 - trim_com, trim_out = calculate_valid_match_lengths(command_to_trim, data, deviation_threshold=8, deviation_reset=2, ignore_patterns=[rb'\x1b\[\?\d{4}[a-zA-Z]',rb'\r',rb'>'])
80 + trim_com, trim_out = calculate_valid_match_lengths(
81 + command_to_trim, data, deviation_threshold=8, deviation_reset=2,
82 + ignore_patterns=[rb'\x1b\[\?\d{4}[a-zA-Z](?:> )?', rb'\r', rb'>'])
83 if(trim_com > 0 and trim_out > 0):
84 data = data[trim_out:]
85 self.trimmed_command_length += trim_com
python/tools/memory_tool.py
+1 -2
@@ -5,7 +5,6 @@ from python.helpers import files
5 import os, json
6 from python.helpers.tool import Tool, Response
7 from python.helpers.print_style import PrintStyle
8 -from chromadb.errors import InvalidDimensionException
8 from python.helpers.log import Log
9
10 # databases based on subdirectories from agent config
@@ -26,7 +25,7 @@ class Memory(Tool):
25 result = forget(self.agent, kwargs["forget"])
26 elif "delete" in kwargs:
27 result = delete(self.agent, kwargs["delete"])
29 - except InvalidDimensionException as e:
28 + except Exception as e:
29 # hint about embedding change with existing database
30 PrintStyle.hint("If you changed your embedding model, you will need to remove contents of /memory directory.")
31 Log(type="hint", content="If you changed your embedding model, you will need to remove contents of /memory directory.")
run_ui.py
+36 -1
@@ -58,7 +58,7 @@ async def health_check():
58 # async def secret_page():
59 # return Path("./secret_page.html").read_text()
60
61 -# send message to agent
61 +# send message to agent (async UI)
62 @app.route('/msg', methods=['POST'])
63 async def handle_message():
64 try:
@@ -93,6 +93,41 @@ async def handle_message():
93 #respond with json
94 return jsonify(response)
95
96 +# send message to agent (synchronous API)
97 +@app.route('/msg_sync', methods=['POST'])
98 +async def handle_msg_sync():
99 + try:
100 +
101 + #agent instance
102 + agent = get_agent()
103 +
104 + #data sent to the server
105 + input = request.get_json()
106 + text = input.get("text", "")
107 +
108 + # print to console and log
109 + PrintStyle(background_color="#6C3483", font_color="white", bold=True, padding=True).print(f"User message:")
110 + PrintStyle(font_color="white", padding=False).print(f"> {text}")
111 + Log.log(type="user", heading="User message", content=text)
112 +
113 + #pass the message to the agent
114 + response = agent.communicate(text)
115 +
116 + #data from this server
117 + response = {
118 + "ok": True,
119 + "message": response,
120 + }
121 +
122 + except Exception as e:
123 + response = {
124 + "ok": False,
125 + "message": str(e),
126 + }
127 +
128 + #respond with json
129 + return jsonify(response)
130 +
131 # pausing/unpausing the agent
132 @app.route('/pause', methods=['POST'])
133 async def pause():
webui/index.css
+3 -2
@@ -74,7 +74,7 @@ h4 {
74 .user-container {
75 align-self: flex-end;
76 margin-top: 2em;
77 - margin-bottom: 1.5em;
77 + margin-bottom: 1em;
78 }
79
80 .ai-container {
@@ -184,7 +184,7 @@ h4 {
184 max-height: 9.375em; /* 150px */
185 padding: 0.625em 0.9375em; /* 10px 15px */
186 border: none;
187 - border-radius: 1.5625em; /* 25px */
187 + border-radius: 1em; /* 25px */
188 background-color: #3d3d3d;
189 color: #e0e0e0;
190 font-size: 1em; /* 16px */
@@ -196,6 +196,7 @@ h4 {
196 }
197 .chat-button {
198 color: #1e1e1e;
199 + font-size: 1em;
200 border: none;
201 border-radius: 50%;
202 width: 3.125em; /* 50px */
webui/index.html
+6 -5
@@ -6,6 +6,7 @@
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>Agent Zero</title>
8 <link rel="stylesheet" href="index.css">
9 +
10 <script>
11 window.safeCall = function(name,...args){
12 if (window[name]) window[name](...args)
@@ -23,8 +24,8 @@
24
25 <div class="config-section" id="status-section" x-data="{ connected: true }">
26 <h3>Status</h3>
26 - <h4 class="connected" x-show="connected">✔ Connected</h4>
27 - <h4 class="disconnected" x-show="!connected">✖ Disconnected</h4>
27 + <h4 class="connected" x-show="connected">&#10004; Connected</h4>
28 + <h4 class="disconnected" x-show="!connected">&#10008; Disconnected</h4>
29 </div>
30
31 <div class="config-section" x-data="{ showQuickActions: true }">
@@ -88,9 +89,9 @@
89 </div>
90 <div id="input-section" x-data="{ paused: false }">
91 <textarea id="chat-input" placeholder="Type your message here..." rows="1"></textarea>
91 - <button class="chat-button" id="send-button">➤</button>
92 - <button class="chat-button pause-button" id="pause-button" @click="pauseAgent(true)" x-show="!paused">⏸</button>
93 - <button class="chat-button pause-button" id="unpause-button" @click="pauseAgent(false)" x-show="paused">▶</button>
92 + <button class="chat-button" id="send-button">&#10148;</button>
93 + <button class="chat-button pause-button" id="pause-button" @click="pauseAgent(true)" x-show="!paused">&#10074;&#10074;</button>
94 + <button class="chat-button pause-button" id="unpause-button" @click="pauseAgent(false)" x-show="paused">&#9654;</button>
95 </div>
96 </div>
97 </div>