RAM_Altman_GPT / src /gen_data.py
brunuu's picture
1.0
7de15fc verified
Raw History Blame Contribute Delete
7.42 kB
import random
from pathlib import Path
from vocab import *
OUTPUT_FILE = Path(__file__).resolve().parent.parent / "data" / "ram_altman.txt"
END_TOKEN = "<|i_have_enough_ram|>"
N_SAMPLES = 200_000
CONVERSATION_CHANCE = 0.15
MAX_REPLY_WORDS = 170 # pair must fit in the 379 token context
MAX_CONVERSATION_REPLY_WORDS = 70
def fill(template, word=""):
template = template.replace("{W}", word.upper())
while "{size}" in template:
template = template.replace("{size}", random.choice(SIZES), 1)
while "{type}" in template:
template = template.replace("{type}", random.choice(TYPES), 1)
return template
def burst(lo, hi):
groups = [RAM, BEGS, SIZES, TYPES, ["MORE"], LORE]
parts = [random.choice(random.choices(groups, weights=[30, 20, 18, 12, 10, 10])[0])
for _ in range(random.randint(lo, hi))]
if random.random() < 0.85:
parts.append(random.choice(RAM))
return " ".join(parts)
def sentences(lo, hi):
out = fill(random.choice(SENTENCES))
for _ in range(random.randint(lo, hi) - 1):
out += random.choice(SEPARATORS) + fill(random.choice(SENTENCES))
return out
def spam():
return " ".join([random.choice(SPAM_WORDS)] * random.randint(10, 30))
def rant(lo, hi):
chunks = []
for _ in range(random.randint(lo, hi)):
r = random.random()
chunks.append(sentences(1, 3) if r < 0.45 else burst(5, 12) if r < 0.85 else spam())
return random.choice(SEPARATORS).join(chunks)
def tail(size):
if size == "short":
return random.choice(["", burst(1, 4)])
if size == "normal":
return random.choice([sentences(1, 3), burst(4, 10)])
if size == "medium":
return random.choice([sentences(3, 5), burst(10, 20), rant(2, 3)])
return rant(7, 12) # Giant
def reply_size(user, rant=False):
# longer messages tend to get longer replies; unknown topics get the rant
# tuned so the reply length median lands around 15 words
n = len(user.split())
if rant:
weights = [28, 50, 16, 6] if n <= 9 else [22, 50, 20, 8]
else:
weights = [48, 40, 10, 2] if n <= 3 else [43, 44, 11, 2] if n <= 9 else [33, 45, 16, 6]
return random.choices(["short", "normal", "medium", "giant"], weights)[0]
def join(reply, rest):
if not rest:
return reply
return reply + (" " if not reply[-1].isalnum() else random.choice(SEPARATORS)) + rest
def finish(reply, max_words=MAX_REPLY_WORDS):
reply = " ".join(reply.split()[:max_words])
if random.random() < 0.01:
reply = join(reply, FALSE_ENDING)
if reply[-1].isalnum():
reply += random.choice(ENDINGS)
return reply
# user text
def style(line):
r = random.random()
line = line[0].upper() + line[1:] if r < 0.45 else line.upper() if r < 0.55 else line.lower()
if line[-1].isalnum() and random.random() < 0.5:
line += random.choice(USER_PUNCTUATION)
return line
def lengthen(line):
if random.random() < 0.25:
line = line.rstrip("?!.") + ". " + ". ".join(random.sample(FILLERS, random.randint(1, 3)))
return line
def pluralize(word):
if word.endswith("s"): # news, chess, tennis, bus...
return word
if word.endswith("y") and word[-2] not in "aeiou":
return word[:-1] + "ies"
if word.endswith(("x", "ch", "sh", "o")):
return word + "es"
return word + "s"
def random_noun():
word = random.choice(NOUNS)
return pluralize(word) if random.random() < 0.4 else word
def topic_word():
return random.choice(random.choice(list(TOPICS.values()))["words"])
def topic_pair():
topic = random.choice(list(TOPICS.values()))
word = random.choice(topic["words"])
hook = random.choice(ECHO_HOOKS if random.random() < 0.25 else topic["hooks"])
return lengthen(random.choice(TOPIC_TEMPLATES).format(w=word)), hook, word
def noun_pair():
user = lengthen(random.choice(TOPIC_TEMPLATES).format(w=random_noun()))
return user, random.choice(DISMISS_HOOKS), None
def reaction_pair():
messages, replies = random.choice(list(REACTIONS.values()))
return random.choice(messages), random.choice(replies), None
def math_pair():
a, b = random.randint(0, 9), random.randint(0, 9)
if random.random() < 0.5:
user = random.choice(MATH_DIGITS).format(a=a, b=b)
else:
user = random.choice(MATH_WORDS).format(a=NUMBERS[a], b=NUMBERS[b])
return user, random.choice(MATH_REPLIES).replace("{s}", str(a + b)), None
def ram_pair():
n = random.choice(SIZES)
user = random.choice(RAM_AMOUNT_USER).format(n=n)
reply = random.choice(RAM_AMOUNT_REPLIES).replace("{n}", n)
return user, reply, None
def generic_pair():
if random.random() < 0.5:
user = random.choice(GENERIC_QUESTIONS)
else:
user = random.choice(TOPIC_TEMPLATES).format(w=random.choice(GENERIC_WORDS))
return lengthen(user), random.choice(SENTENCES), None
def first_message(kinds, weights):
user, hook, word = random.choices(kinds, weights)[0]()
return style(user), fill(hook, word or ""), word
def single_pair():
kinds = [topic_pair, noun_pair, reaction_pair, math_pair, generic_pair, ram_pair]
weights = [28, 12, 25, 8, 12, 15]
kind = random.choices(kinds, weights)[0]
user, reply, word = kind()
rant = kind in (noun_pair, generic_pair, ram_pair)
return style(user), finish(join(fill(reply, word or ""), tail(reply_size(user, rant=rant))))
def conversation():
# remembers what the user said, still only wants RAM and asks for more
level = random.randint(1, 8)
user, reply, _ = first_message([topic_pair, noun_pair, reaction_pair, ram_pair], [40, 30, 15, 15])
reply += ("." if reply[-1].isalnum() else "") + f" I NEED {SIZES[level]}"
turns = [(user, finish(join(reply, tail("normal")), MAX_CONVERSATION_REPLY_WORDS))]
for _ in range(random.randint(1, 3)):
prev = SIZES[level]
level = min(level + random.randint(1, 3), len(SIZES) - 1)
size = SIZES[level] if level < len(SIZES) - 1 else FINAL_OFFER
if random.random() < 0.8: # "and X?"
echo = random.random() < 0.5 # topic words are echoed, anything else ignored
word = topic_word() if echo else random_noun()
user = style(random.choice(FOLLOW_UPS_WORD).format(w=word))
replies = FOLLOW_UP_ECHO_REPLIES if echo else FOLLOW_UP_DISMISS_REPLIES
reply = fill(random.choice(replies).replace("{esc}", size), word)
else: # "why?", "ok", "stop"
messages, replies = random.choice(list(FOLLOW_UPS_PLAIN.values()))
user = style(random.choice(messages))
reply = fill(random.choice(replies).replace("{esc}", size).replace("{prev}", prev))
rest = tail(random.choice(["short", "normal", "medium", "medium"]))
turns.append((user, finish(join(reply, rest), MAX_CONVERSATION_REPLY_WORDS)))
return turns
if __name__ == "__main__":
random.seed(42)
n_pairs = 0
with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
for _ in range(N_SAMPLES):
turns = conversation() if random.random() < CONVERSATION_CHANCE else [single_pair()]
for user, reply in turns:
f.write(f"User: {user}\nRAM-ALTMAN: {reply}{END_TOKEN}\n")
n_pairs += len(turns)
print(f"{OUTPUT_FILE.name}: {N_SAMPLES:,} samples, {n_pairs:,} pairs")