Skip to content

Commit 947aa9b

Browse files
committed
memory fix
1 parent be11dbb commit 947aa9b

File tree

10 files changed

+234
-17
lines changed

10 files changed

+234
-17
lines changed

agent.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,38 @@
1212

1313
# rate_limit = rate_limiter.rate_limiter(30,160000) #TODO! implement properly
1414

15+
<<<<<<< Updated upstream
16+
=======
17+
@dataclass
18+
class AgentConfig:
19+
chat_model:BaseChatModel
20+
utility_model: BaseChatModel
21+
embeddings_model:Embeddings
22+
memory_subdir: str = ""
23+
auto_memory_count: int = 3
24+
auto_memory_skip: int = 2
25+
rate_limit_seconds: int = 60
26+
rate_limit_requests: int = 15
27+
rate_limit_input_tokens: int = 1000000
28+
rate_limit_output_tokens: int = 0
29+
msgs_keep_max: int = 25
30+
msgs_keep_start: int = 5
31+
msgs_keep_end: int = 10
32+
response_timeout_seconds: int = 60
33+
max_tool_response_length: int = 3000
34+
code_exec_docker_enabled: bool = True
35+
code_exec_docker_name: str = "agent-zero-exe"
36+
code_exec_docker_image: str = "frdel/agent-zero-exe:latest"
37+
code_exec_docker_ports: dict[str,int] = field(default_factory=lambda: {"22/tcp": 50022})
38+
code_exec_docker_volumes: dict[str, dict[str, str]] = field(default_factory=lambda: {files.get_abs_path("work_dir"): {"bind": "/root", "mode": "rw"}})
39+
code_exec_ssh_enabled: bool = True
40+
code_exec_ssh_addr: str = "localhost"
41+
code_exec_ssh_port: int = 50022
42+
code_exec_ssh_user: str = "root"
43+
code_exec_ssh_pass: str = "toor"
44+
additional: Dict[str, Any] = field(default_factory=dict)
45+
46+
>>>>>>> Stashed changes
1547

1648
class Agent:
1749

@@ -276,7 +308,7 @@ def fetch_memories(self,reset_skip=False):
276308
self.memory_skip_counter = self.auto_memory_skip
277309
from tools import memory_tool
278310
messages = self.concat_messages(self.history)
279-
memories = memory_tool.process_query(self,messages,"load")
311+
memories = memory_tool.search(messages)
280312
input = {
281313
"conversation_history" : messages,
282314
"raw_memories": memories

docker/Dockerfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Use the latest slim version of Debian
2+
FROM --platform=$TARGETPLATFORM debian:testing-slim
3+
4+
# Set ARG for platform-specific commands
5+
ARG TARGETPLATFORM
6+
7+
# Update and install necessary packages
8+
RUN apt-get update && apt-get install -y \
9+
python3 \
10+
python3-pip \
11+
python3-venv \
12+
nodejs \
13+
npm \
14+
openssh-server \
15+
sudo \
16+
&& rm -rf /var/lib/apt/lists/*
17+
18+
# Set up SSH
19+
RUN mkdir /var/run/sshd && \
20+
echo 'root:toor' | chpasswd && \
21+
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
22+
23+
# Create and activate Python virtual environment
24+
ENV VIRTUAL_ENV=/opt/venv
25+
RUN python3 -m venv $VIRTUAL_ENV
26+
27+
# Copy initial .bashrc with virtual environment activation to a temporary location
28+
COPY .bashrc /etc/skel/.bashrc
29+
30+
# Copy the script to ensure .bashrc is in the root directory
31+
COPY initialize.sh /usr/local/bin/initialize.sh
32+
RUN chmod +x /usr/local/bin/initialize.sh
33+
34+
# Ensure the virtual environment and pip setup
35+
RUN $VIRTUAL_ENV/bin/pip install --upgrade pip
36+
37+
# Expose SSH port
38+
EXPOSE 22
39+
40+
# Init .bashrc
41+
CMD ["/usr/local/bin/initialize.sh"]
42+
43+

main.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,43 @@ def chat():
2828
# chat_llm = models.get_ollama_dolphin()
2929

3030
# embedding model used for memory
31+
<<<<<<< Updated upstream
3132
# embedding_llm = models.get_embedding_openai()
3233
embedding_llm = models.get_embedding_hf()
34+
=======
35+
embedding_llm = models.get_embedding_openai()
36+
# embedding_llm = models.get_embedding_hf()
37+
38+
# agent configuration
39+
config = AgentConfig(
40+
chat_model = chat_llm,
41+
utility_model = utility_llm,
42+
embeddings_model = embedding_llm,
43+
# memory_subdir = "",
44+
auto_memory_count = 0,
45+
# auto_memory_skip = 2,
46+
# rate_limit_seconds = 60,
47+
# rate_limit_requests = 30,
48+
# rate_limit_input_tokens = 0,
49+
# rate_limit_output_tokens = 0,
50+
# msgs_keep_max = 25,
51+
# msgs_keep_start = 5,
52+
# msgs_keep_end = 10,
53+
# response_timeout_seconds = 60,
54+
# max_tool_response_length = 3000,
55+
code_exec_docker_enabled = True,
56+
# code_exec_docker_name = "agent-zero-exe",
57+
# code_exec_docker_image = "frdel/agent-zero-exe:latest",
58+
# code_exec_docker_ports = { "22/tcp": 50022 }
59+
# code_exec_docker_volumes = { files.get_abs_path("work_dir"): {"bind": "/root", "mode": "rw"} }
60+
code_exec_ssh_enabled = True,
61+
# code_exec_ssh_addr = "localhost",
62+
# code_exec_ssh_port = 50022,
63+
# code_exec_ssh_user = "root",
64+
# code_exec_ssh_pass = "toor",
65+
# additional = {},
66+
)
67+
>>>>>>> Stashed changes
3368

3469
# create the first agent
3570
agent0 = Agent( agent_number=0,

prompts/agent.tools.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,19 @@ Always verify memory by online.
6262
}
6363
~~~
6464

65+
<<<<<<< Updated upstream
6566
### memorize:
6667
Save information to persistent memory.
6768
Memories can help you remember important details and later reuse them.
69+
=======
70+
### memory_tool:
71+
Manage long term memories. Allowed arguments are "query", "memorize", "forget" and "delete".
72+
Memories can help you remember important details and later reuse them.
73+
When querying, provide a "query" argument to search for. You will retrieve IDs and contents of relevant memories. Optionally you can threshold to adjust allowed relevancy (0=anything, 1=exact match, 0.1 is default).
74+
When memorizing, provide enough information in "memorize" argument for future reuse.
75+
When deleting, provide memory IDs from loaded memories separated by commas in "delete" argument.
76+
When forgetting, provide query and optionally threshold like you would for querying, corresponding memories will be deleted.
77+
>>>>>>> Stashed changes
6878
Provide a title, short summary and and all the necessary information to help you later solve similiar tasks including details like code executed, libraries used etc.
6979
**Example usages**:
7080
~~~json
@@ -76,7 +86,35 @@ Provide a title, short summary and and all the necessary information to help you
7686
],
7787
"tool_name": "memorize",
7888
"tool_args": {
89+
<<<<<<< Updated upstream
7990
"memory": "# How to...",
91+
=======
92+
"memorize": "# How to...",
93+
}
94+
}
95+
~~~
96+
3. delete:
97+
~~~json
98+
{
99+
"thoughts": [
100+
"User asked to delete specific memories...",
101+
],
102+
"tool_name": "memory_tool",
103+
"tool_args": {
104+
"delete": "32cd37ffd1-101f-4112-80e2-33b795548116, d1306e36-6a9c-4e6a-bfc3-c8335035dcf8 ...",
105+
}
106+
}
107+
~~~
108+
4. forget:
109+
~~~json
110+
{
111+
"thoughts": [
112+
"User asked to delete information from memory...",
113+
],
114+
"tool_name": "memory_tool",
115+
"tool_args": {
116+
"forget": "User's contact information",
117+
>>>>>>> Stashed changes
80118
}
81119
}
82120
~~~

prompts/fw.memories_deleted.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Memories deleted: {{memories}}
1+
Memories deleted: {{memory_count}}

prompts/fw.memory_saved.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Memory has been saved.
1+
Memory has been saved with id {{memory_id}}.

python/tools/memory_tool.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import re
2+
from agent import Agent
3+
from python.helpers.vector_db import VectorDB, Document
4+
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+
9+
# TODO multiple DBs at once
10+
db: VectorDB | None= None
11+
12+
class Memory(Tool):
13+
def execute(self,**kwargs):
14+
result=""
15+
16+
if "query" in kwargs:
17+
if "threshold" in kwargs: threshold = float(kwargs["threshold"])
18+
else: threshold = 0.1
19+
if "count" in kwargs: count = int(kwargs["count"])
20+
else: count = 5
21+
result = search(self.agent, kwargs["query"], count, threshold)
22+
elif "memorize" in kwargs:
23+
result = save(self.agent, kwargs["memorize"])
24+
elif "forget" in kwargs:
25+
result = forget(self.agent, kwargs["forget"])
26+
elif "delete" in kwargs:
27+
result = delete(self.agent, kwargs["delete"])
28+
29+
# result = process_query(self.agent, self.args["memory"],self.args["action"], result_count=self.agent.config.auto_memory_count)
30+
return Response(message=result, break_loop=False)
31+
32+
def search(agent:Agent, query:str, count:int=5, threshold:float=0.1):
33+
initialize(agent)
34+
docs = db.search_similarity_threshold(query,count,threshold) # type: ignore
35+
if len(docs)==0: return files.read_file("./prompts/fw.memories_not_found.md", query=query)
36+
else: return str(docs)
37+
38+
def save(agent:Agent, text:str):
39+
initialize(agent)
40+
id = db.insert_document(text) # type: ignore
41+
return files.read_file("./prompts/fw.memory_saved.md", memory_id=id)
42+
43+
def delete(agent:Agent, ids_str:str):
44+
initialize(agent)
45+
ids = extract_guids(ids_str)
46+
deleted = db.delete_documents_by_ids(ids) # type: ignore
47+
return files.read_file("./prompts/fw.memories_deleted.md", memory_count=deleted)
48+
49+
def forget(agent:Agent, query:str):
50+
initialize(agent)
51+
deleted = db.delete_documents_by_query(query) # type: ignore
52+
return files.read_file("./prompts/fw.memories_deleted.md", memory_count=deleted)
53+
54+
def initialize(agent:Agent):
55+
global db
56+
if not db:
57+
dir = os.path.join("memory",agent.config.memory_subdir)
58+
db = VectorDB(embeddings_model=agent.config.embeddings_model, in_memory=False, cache_dir=dir)
59+
60+
def extract_guids(text):
61+
pattern = r'\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}\b'
62+
return re.findall(pattern, text)

tools/helpers/vector_db.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,39 @@ def search_similarity(self, query, results=3):
3535
def search_max_rel(self, query, results=3):
3636
return self.db.max_marginal_relevance_search(query,results)
3737

38-
def delete_documents(self, query):
39-
score_limit = 1
40-
k = 2
38+
def delete_documents_by_query(self, query:str, threshold=0.1):
39+
k = 100
4140
tot = 0
4241
while True:
4342
# Perform similarity search with score
44-
docs = self.db.similarity_search_with_score(query, k=k)
43+
docs = self.search_similarity_threshold(query, results=k, threshold=threshold)
4544

4645
# Extract document IDs and filter based on score
47-
document_ids = [result[0].metadata["id"] for result in docs if result[1] < score_limit]
46+
# document_ids = [result[0].metadata["id"] for result in docs if result[1] < score_limit]
47+
document_ids = [result.metadata["id"] for result in docs]
48+
4849

4950
# Delete documents with IDs over the threshold score
5051
if document_ids:
51-
fnd = self.db.get(where={"id": {"$in": document_ids}})
52-
if fnd["ids"]: self.db.delete(ids=fnd["ids"])
53-
tot += len(fnd["ids"])
54-
52+
# fnd = self.db.get(where={"id": {"$in": document_ids}})
53+
# if fnd["ids"]: self.db.delete(ids=fnd["ids"])
54+
# tot += len(fnd["ids"])
55+
self.db.delete(ids=document_ids)
56+
tot += len(document_ids)
57+
5558
# If fewer than K document IDs, break the loop
5659
if len(document_ids) < k:
5760
break
5861

5962
return tot
6063

64+
def delete_documents_by_ids(self, ids:list[str]):
65+
# pre = self.db.get(ids=ids)["ids"]
66+
self.db.delete(ids=ids)
67+
# post = self.db.get(ids=ids)["ids"]
68+
#TODO? compare pre and post
69+
return len(ids)
70+
6171
def insert_document(self, data):
6272
id = str(uuid.uuid4())
6373
self.db.add_documents(documents=[ Document(data, metadata={"id": id}) ])

tools/knowledge_tool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def execute(self, question="", **kwargs):
1313
with concurrent.futures.ThreadPoolExecutor() as executor:
1414
# Schedule the two functions to be run in parallel
1515
future_online = executor.submit(online_knowledge_tool.process_question, question)
16-
future_memory = executor.submit(memory_tool.process_query, self.agent, question)
16+
future_memory = executor.submit(memory_tool.search, self.agent, question)
1717

1818
# Wait for both functions to complete
1919
online_result = future_online.result()

tools/response.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010
class ResponseTool(Tool):
1111

1212
def execute(self,**kwargs):
13-
# superior = self.agent.get_data("superior")
14-
# if superior:
15-
self.agent.set_data("timeout", 60)
13+
self.agent.set_data("timeout", self.agent.config.response_timeout_seconds)
1614
return Response(message=self.args["text"], break_loop=True)
17-
# else:
1815

1916
def after_execution(self, response, **kwargs):
2017
pass # do add anything to the history or output

0 commit comments

Comments
 (0)