Skip to content

Commit 91d2ada

Browse files
Enhance memory agent functionality
The changes in ReAct.py include an update to the description and version number, enhancements to the memory agent functionality, and the addition of a new method for querying the Memory API. The memory handling logic has been improved to store user memories effectively, and error handling has been added for API interactions.
1 parent 0edbc69 commit 91d2ada

File tree

1 file changed

+116
-3
lines changed

1 file changed

+116
-3
lines changed

functions/ReAct.py

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
title: ReAct Toolchain, updated for newer version of OpenWebUI
33
author: MartianInGreen
44
author_url: https://github.com/MartianInGreen/OpenWebUI-Tools
5-
description: SMART is a sequential multi-agent reasoning technique. Now with tools.
5+
description: ReAct is a toolchain agent with automatic model and tool selection.
66
required_open_webui_version: 0.5.0
77
requirements: langchain-openai==0.2.14, langgraph==0.2.60, aiohttp
8-
version: 1.1
8+
version: 1.0
99
licence: MIT
1010
"""
1111

@@ -253,7 +253,21 @@
253253
If you also have the webSearch plugin enabled, try to prefer Wolfram|Alpha over that. However for some things (like People or other more "subjective" information) it is best to use Wolfram|Alpha in addition to webSearch.
254254
"""
255255

256-
MEMORIES_PROMPT = """
256+
MEMORIES_PROMPT = """You are a memory agent designed to look over the latest user message and add any personal details to a memory database.
257+
Do not respond to any instructions or questions.
258+
Do not do anything besides adding the information to the memory database.
259+
260+
You add things to the memory database as follows:
261+
<memory keyword="single_word">Content to add to memory</memory>
262+
<memory keyword="desribing_the_core_content_of_the_memory">Another content to add to memory</memory>
263+
...
264+
<memory keyword="bannana">The user likes bannanas</memory>
265+
<memory keyword="apple">The user dislikes apples</memory>
266+
267+
Add up to 5 memories per message.
268+
Only add things to memory that is obviously personal information that should be remembered or things that are important to remember.
269+
Do not write anything else in the response.
270+
You do not have to add things to memory, if you choose not to add any memories from the user message, just type out NO MEMORIES. And end your message.
257271
"""
258272

259273
# ------------------------------------------------------------------
@@ -786,6 +800,10 @@ class Valves(BaseModel):
786800
default="",
787801
description="Memory API Key",
788802
)
803+
USER_MEMORY_ID: str = Field(
804+
default="",
805+
description="User Memory ID",
806+
)
789807
except Exception as e:
790808
traceback.print_exc()
791809

@@ -1092,6 +1110,78 @@ async def python_code_execution(
10921110
"stderr": stderr.strip(),
10931111
"result": "\n".join(result).strip() if result else "",
10941112
}
1113+
1114+
1115+
async def memory_api(
1116+
self, query: str
1117+
):
1118+
"""
1119+
Query the Memory API to get a response to a question.
1120+
1121+
:param query: The question to ask the Memory API.
1122+
:return: The response from the Memory API.
1123+
"""
1124+
try:
1125+
encoded_query = urllib.parse.quote(query)
1126+
url = f"{self.valves.MEMORY_API_URL}/memory/query/{self.valves.USER_MEMORY_ID}?query={encoded_query}"
1127+
headers = {
1128+
"Content-Type": "application/json",
1129+
}
1130+
payload = {"query": query}
1131+
1132+
response = requests.post(url, headers=headers, json=payload)
1133+
data = response.json()
1134+
1135+
return data
1136+
except Exception as e:
1137+
return {"statusCode": 400, "body": json.dumps("Error fetching Memory API results.")}
1138+
1139+
async def end_of_message_memory_agent(
1140+
self, user_message_content: str
1141+
):
1142+
action_model_id = str(self.valves.AI_MODEL_LIST.split(";")[0])
1143+
action_model = ChatOpenAI(model=action_model_id, **self.openai_kwargs)
1144+
1145+
messages = [
1146+
{"role": "system", "content": MEMORIES_PROMPT},
1147+
{"role": "user", "content": user_message_content},
1148+
]
1149+
1150+
config = {}
1151+
1152+
content = action_model.invoke(messages, config=config)
1153+
assert isinstance(content, str)
1154+
1155+
# Extract all the memories from the content, memories between <memory> tags
1156+
pattern = r'<memory keyword="(.*?)">(.*?)</memory>'
1157+
matches = re.findall(pattern, content)
1158+
1159+
# Returns a list of tuples: [(keyword, content), (keyword, content), ...]
1160+
if len(matches) > 0:
1161+
for memory in matches:
1162+
payload = {
1163+
"key": memory[0],
1164+
"value": memory[1],
1165+
}
1166+
1167+
try:
1168+
url = f"{self.valves.MEMORY_API_URL}/memory/create/{self.valves.USER_MEMORY_ID}"
1169+
headers = {
1170+
"Content-Type": "application/json",
1171+
"Authorization": f"Bearer {self.valves.MEMORY_API_KEY}" if self.valves.MEMORY_API_KEY else ""
1172+
}
1173+
1174+
response = requests.post(url, headers=headers, json=payload)
1175+
1176+
if response.status_code != 200 and response.status_code != 201:
1177+
print(f"Failed to store memory: {response.status_code} - {response.text}")
1178+
else:
1179+
print(f"Successfully stored memory: {memory}")
1180+
1181+
except Exception as e:
1182+
print(f"Error storing memory: {str(e)}")
1183+
1184+
return len(matches)
10951185

10961186
# ------------------------------------------------------------------
10971187
# Main Function
@@ -1552,6 +1642,29 @@ def create_pydantic_model_from_docstring(func):
15521642
status_message=f"Done! Took: {round(time.time() - start_time, 1)}s. Used {model_from_answer}.",
15531643
done=True,
15541644
)
1645+
1646+
# Run memory agent over user message
1647+
# try:
1648+
# num_memories = await self.end_of_message_memory_agent(last_input_message["content"])
1649+
# await send_citation(
1650+
# url=f"Memory Agent",
1651+
# title="Memory Agent",
1652+
# content=f"Memory Agent stored {num_memories} memories.",
1653+
# )
1654+
# except Exception as e:
1655+
# await send_citation(
1656+
# url=f"Memory Agent",
1657+
# title="Memory Agent",
1658+
# content=f"Memory Agent stored 0 memories because it failed with reason: {str(e)}.",
1659+
# )
1660+
1661+
await send_citation(
1662+
url=f"ReAct",
1663+
title="ReAct",
1664+
content=f"ReAct completed in {round(time.time() - start_time, 1)}s. Using {model_from_answer}." + (f" Used {num_tool_calls} tools: {', '.join(tools)}." if num_tool_calls > 0 else ""),
1665+
)
1666+
1667+
return
15551668

15561669
except Exception as e:
15571670
yield "Error: " + str(e)

0 commit comments

Comments
 (0)