Behaviour prompt
Prototype of adjustable behaviour system prompt
frdel committed
Oct 29, 2024 at 19:39 UTC
1c026ee75f6f2b3993bf97f44775460e7464335f
9 files changed
+145
-3
prompts/default/agent.system.behaviour.md
new
+2
@@ -0,0 +1,2 @@
1
+# Behavioral Rules
2
+{{rules}}
\ No newline at end of file
prompts/default/agent.system.behaviour_default.md
new
+1
@@ -0,0 +1 @@
1
+- Use linux commands for simple tasks where possible instead of python
\ No newline at end of file
prompts/default/behaviour.merge.msg.md
new
+5
@@ -0,0 +1,5 @@
1
+# Current ruleset
2
+{{current_rules}}
3
+
4
+# Adjustments
5
+{{adjustments}}
\ No newline at end of file
prompts/default/behaviour.merge.sys.md
new
+17
@@ -0,0 +1,17 @@
1
+# Assistant's job
2
+1. The assistant receives a markdown ruleset of AGENT's behaviour and JSON array of adjustments to be implemented
3
+2. Assistant merges the ruleset with the instructions JSON array into a new markdown ruleset
4
+3. Assistant keeps the ruleset short, removing any duplicates or redundant information
5
+
6
+# Format
7
+- The response format is a markdown format of instructions for AI AGENT explaining how the AGENT is supposed to behave
8
+- No level 1 headings (#), only level 2 headings (##) and bullet points (*)
9
+
10
+# Example when instructions found (do not output this example):
11
+```json
12
+# Language
13
+- The user want to communicate in Spanish, always write responses for the user in Spanish.
14
+
15
+# Format
16
+- User asked for shorted responses, be short and to the point
17
+```
\ No newline at end of file
prompts/default/behaviour.search.sys.md
new
+20
@@ -0,0 +1,20 @@
1
+# Assistant's job
2
+1. The assistant receives a history of conversation between USER and AGENT
3
+2. Assistant searches for USER's commands to update AGENT's behaviour
4
+3. Assistant responds with JSON array of instructions to update AGENT's behaviour or empty array if none
5
+
6
+# Format
7
+- The response format is a JSON array of instructions on how the agent should behave in the future
8
+- If the history does not contain any instructions, the response will be an empty JSON array
9
+
10
+# Example when instructions found (do not output this example):
11
+```json
12
+[
13
+ "Never call the user by his name",
14
+]
15
+```
16
+
17
+# Example when no instructions:
18
+```json
19
+[]
20
+```
\ No newline at end of file
python/extensions/message_loop_prompts/_20_behaviour_prompt.py
new
+24
@@ -0,0 +1,24 @@
1
+from datetime import datetime
2
+from python.helpers.extension import Extension
3
+from agent import Agent, LoopData
4
+from python.helpers import files, memory
5
+
6
+
7
+class BehaviourPrompt(Extension):
8
+
9
+ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
10
+ prompt = read_rules(self.agent)
11
+ loop_data.system.append(prompt)
12
+
13
+def get_custom_rules_file(agent: Agent):
14
+ return memory.get_memory_subdir_abs(agent) + f"/behaviour.md"
15
+
16
+def read_rules(agent: Agent):
17
+ rules_file = get_custom_rules_file(agent)
18
+ if files.exists(rules_file):
19
+ rules = files.read_file(rules_file)
20
+ return agent.read_prompt("agent.system.behaviour.md", rules=rules)
21
+ else:
22
+ rules = agent.read_prompt("agent.system.behaviour_default.md")
23
+ return agent.read_prompt("agent.system.behaviour.md", rules=rules)
24
+
\ No newline at end of file
python/extensions/monologue_start/_20_behaviour_update.py
new
+73
@@ -0,0 +1,73 @@
1
+import asyncio
2
+from datetime import datetime
3
+import json
4
+from python.helpers.extension import Extension
5
+from agent import Agent, LoopData
6
+from python.helpers import dirty_json, files, memory
7
+from python.helpers.log import LogItem
8
+from python.extensions.message_loop_prompts import _20_behaviour_prompt
9
+
10
+
11
+
12
+class BehaviourUpdate(Extension):
13
+
14
+ async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
15
+ log_item = self.agent.context.log.log(
16
+ type="util",
17
+ heading="Updating behaviour",
18
+ )
19
+ asyncio.create_task(self.update_rules(self.agent, loop_data, log_item))
20
+
21
+ async def update_rules(self, agent: Agent, loop_data: LoopData, log_item: LogItem, **kwargs):
22
+ adjustments = await self.get_adjustments(agent, loop_data, log_item)
23
+ if adjustments:
24
+ await self.merge_rules(agent, adjustments, loop_data, log_item)
25
+
26
+ async def get_adjustments(self, agent: Agent, loop_data: LoopData, log_item: LogItem, **kwargs) -> list[str] | None:
27
+
28
+ # get system message and chat history for util llm
29
+ system = self.agent.read_prompt("behaviour.search.sys.md")
30
+ msgs_text = self.agent.concat_messages(self.agent.history)
31
+
32
+ # log query streamed by LLM
33
+ def log_callback(content):
34
+ log_item.stream(content=content)
35
+
36
+ # call util llm to find solutions in history
37
+ adjustments_json = await self.agent.call_utility_llm(
38
+ system=system,
39
+ msg=msgs_text,
40
+ callback=log_callback,
41
+ )
42
+
43
+ adjustments = dirty_json.DirtyJson.parse_string(adjustments_json)
44
+
45
+ if adjustments:
46
+ log_item.update(adjustments=adjustments)
47
+ return adjustments # type: ignore # for now let's assume the model gets it right and outputs an array
48
+ else:
49
+ log_item.update(heading="No updates to behaviour")
50
+ return None
51
+
52
+ async def merge_rules(self, agent: Agent, adjustments: list[str], loop_data: LoopData, log_item: LogItem, **kwargs):
53
+ # get system message and current ruleset
54
+ system = self.agent.read_prompt("behaviour.merge.sys.md")
55
+ current_rules = _20_behaviour_prompt.read_rules(agent)
56
+
57
+ # log query streamed by LLM
58
+ def log_callback(content):
59
+ log_item.stream(ruleset=content)
60
+
61
+ msg = self.agent.read_prompt("behaviour.merge.msg.md", current_rules=current_rules, adjustments=json.dumps(adjustments))
62
+
63
+ # call util llm to find solutions in history
64
+ adjustments_merge = await self.agent.call_utility_llm(
65
+ system=system,
66
+ msg=msg,
67
+ callback=log_callback,
68
+ )
69
+
70
+ # update rules file
71
+ rules_file = _20_behaviour_prompt.get_custom_rules_file(agent)
72
+ files.write_file(rules_file, adjustments_merge)
73
+ log_item.update(heading="Behaviour updated")
\ No newline at end of file
python/helpers/memory.py
+3
@@ -348,3 +348,6 @@ class Memory:
348
@staticmethod
349
def get_timestamp():
350
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
351
+
352
+def get_memory_subdir_abs(agent: Agent) -> str:
353
+ return files.get_abs_path("memory", agent.config.memory_subdir or "default")
\ No newline at end of file
python/helpers/settings.py
-3
@@ -20,7 +20,6 @@ class Settings(TypedDict):
20
21
embed_model_provider: str
22
embed_model_name: str
23
- embed_model_temperature: float
23
embed_model_kwargs: dict[str, str]
24
25
@@ -203,7 +202,6 @@ def get_embedding_model() -> Embeddings:
202
type=ModelType.EMBEDDING,
203
provider=ModelProvider[settings["embed_model_provider"]],
204
name=settings["embed_model_name"],
206
- temperature=settings["embed_model_temperature"],
205
**settings["embed_model_kwargs"],
206
)
207
@@ -232,7 +230,6 @@ def _get_default_settings() -> Settings:
230
util_model_kwargs={},
231
embed_model_provider=ModelProvider.OPENAI.name,
232
embed_model_name="text-embedding-3-small",
235
- embed_model_temperature=0,
233
embed_model_kwargs={},
234
)
235