• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Emergent generative agents


Commit MetaInfo

Révision8e3dfeca90fc6433155193db83e7e9855306cd7d (tree)
l'heure2023-06-12 03:14:32
AuteurCorbin <cds@corb...>
CommiterCorbin

Message de Log

Split thoughts into two agents.

Change Summary

Modification

--- a/src/agent.py
+++ b/src/agent.py
@@ -5,7 +5,6 @@ from datetime import datetime
55 import json
66 import os.path
77 import re
8-import random
98 from string import ascii_uppercase
109 import sys
1110 from threading import Lock
@@ -43,6 +42,7 @@ embedder = SentenceEmbed()
4342 prologues = {
4443 "clock": "Then I checked the time:",
4544 "lbi": "Then I tried to interpret what just happened:",
45+ "memories": "Then I remembered:",
4646 "thoughts": "Then I thought to myself:",
4747 "choice": "Then I chose what to do next:",
4848 "irc": "Then I chatted on IRC, channel {subtag}:",
@@ -100,8 +100,7 @@ class Mind:
100100 def cb():
101101 d = self.switchTag(tag, subtag)
102102 # Breaking the newline invariant...
103- d.addCallback(lambda _: print(self.name, "~!", prefix)
104- or deferToThread(self.writeRaw, prefix))
103+ d.addCallback(lambda _: deferToThread(self.writeRaw, prefix))
105104 # ...so that this inference happens before the newline...
106105 d.addCallback(lambda _: force(tokens, self.logits))
107106 d.addCallback(lambda t: gen.tokenizer.decode([t]))
@@ -136,19 +135,21 @@ class LeftBrainInterpreter(Agent):
136135 self.mind = mind
137136 self.idle = idle
138137 def overhear(self, tag, subtag, s):
139- if tag != "thoughts": self.events += 1
140- if self.events >= 20:
138+ self.events += 1
139+ if self.events >= 25:
141140 self.events = 0
142141 d = self.mind.infer(self.tag, self.subtag, "")
143142 d.addCallback(lambda s: s.strip() or self.idle())
144143
144+# NB: Letter 'A' is extra-likely to appear as a token, so don't allow it.
145+uppercase = ascii_uppercase[1:]
145146 choices = {
146147 "irc": "Chat on IRC, channel {subtag}",
147148 "thoughts": "Think to myself for a moment",
148149 }
149150 def choicify(options):
150- return " ".join(f"({c}) {o}" for c, o in zip(ascii_uppercase, options))
151-def indexify(c): return ord(c[0].upper()) - ord('A')
151+ return " ".join(f"({c}) {o}" for c, o in zip(uppercase, options))
152+def indexify(c): return ord(c[0].upper()) - ord('B')
152153
153154 class ChoiceMaker(Agent):
154155 tag = "choice"
@@ -169,19 +170,31 @@ class ChoiceMaker(Agent):
169170 prompt = choicify([choices[tag].format(subtag=subtag)
170171 for tag, subtag in possibilities])
171172 d = self.mind.forceChoice(self.tag, self.subtag, prompt + " My choice: ",
172- ascii_uppercase[:len(possibilities)])
173+ uppercase[:len(possibilities)])
173174 d.addCallback(lambda s: self.dispatch(*possibilities[indexify(s)]))
174175 return d
175176
176177 class ChainOfThoughts(Agent):
177178 tag = "thoughts"
178- def __init__(self, mind, index, seed, idle):
179+ def __init__(self, mind, idle):
179180 self.mind = mind
181+ self.idle = idle
182+
183+ def go(self):
184+ d = self.mind.infer(self.tag, self.subtag, "")
185+ d.addCallback(lambda s: s.strip() or self.idle())
186+ return d
187+
188+class Recall(Agent):
189+ tag = "memories"
190+ def __init__(self, index, seed, idle):
180191 self.index = index
181192 self.recentThoughts = deque([seed], maxlen=5)
182193 self.idle = idle
183194
184- def go(self): return random.choice([self.reflect, self.cogitate])()
195+ def go(self):
196+ new = self.addRelatedThoughts(self.recentThoughts[-1])
197+ if not new: return deferLater(reactor, 0.0, self.idle)
185198
186199 def overhear(self, tag, subtag, s):
187200 prefix = f"{tag} ({subtag}): " if subtag else tag + ": "
@@ -197,14 +210,6 @@ class ChainOfThoughts(Agent):
197210 self.broadcast(thought)
198211 return new
199212
200- def cogitate(self):
201- new = self.addRelatedThoughts(self.recentThoughts[-1])
202- if not new: return deferLater(reactor, 0.0, self.idle)
203- def reflect(self):
204- d = self.mind.infer(self.tag, self.subtag, "")
205- d.addCallback(lambda s: s.strip() or self.idle())
206- return d
207-
208213
209214 IRC_LINE_HEAD = re.compile(r"\d{1,2}:\d{1,2}:\d{1,2} <")
210215 def breakIRCLine(line):
@@ -278,6 +283,7 @@ def go():
278283 firstStatement = f"I am {title}."
279284 thoughtPath = os.path.join(logpath, "thoughts.txt")
280285 thoughtIndex = SentenceIndex.fromPath(thoughtPath, embedder)
286+ print("~ Thought index:", thoughtIndex.size(), "thoughts")
281287
282288 mind = Mind(title_to_nick(title))
283289 with Timer("initial warmup"):
@@ -288,12 +294,15 @@ def go():
288294 lbi = LeftBrainInterpreter(mind, cm.idle)
289295 clock.listeners += lbi, mind
290296
291- thoughts = ChainOfThoughts(mind, thoughtIndex, firstStatement, cm.idle)
292- thoughts.listeners = lbi, mind
293- LoopingCall(thoughts.go).start(60 * 3, now=True)
297+ memories = Recall(thoughtIndex, firstStatement, cm.idle)
298+ memories.listeners = lbi, mind
299+ LoopingCall(memories.go).start(60 * 2, now=True)
294300
295- print("~ Thought index:", thoughtIndex.size(), "thoughts")
296- factory = IRCFactory(mind, cm, (thoughts, lbi, cm, mind),
301+ thoughts = ChainOfThoughts(mind, cm.idle)
302+ thoughts.listeners = memories, lbi, mind
303+ LoopingCall(thoughts.go).start(60 * 2, now=False)
304+
305+ factory = IRCFactory(mind, cm, (memories, lbi, cm, mind),
297306 title,
298307 character["startingChannels"])
299308 print("~ Connecting factory for:", title)