Last active
November 8, 2021 02:48
-
-
Save Spencer-Comin/37484a9264bb9efe5d8d4c1b8430181e to your computer and use it in GitHub Desktop.
A tiny chatbot inspired by https://codegolf.stackexchange.com/questions/20914/who-is-this-chatbot?noredirect=1&lq=1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from collections import defaultdict | |
| from random import choices, choice | |
| import json | |
| import re | |
| word_map = defaultdict(lambda: defaultdict(int)) | |
| start_map = defaultdict(lambda: defaultdict(int)) | |
| def save(filename): | |
| with open(filename, 'w') as file: | |
| json.dump({'word_map': word_map, 'start_map': start_map}, file, | |
| indent=4) | |
| def load(filename): | |
| with open(filename, 'r') as file: | |
| maps = json.load(file) | |
| for first, map in maps['word_map'].items(): | |
| for second, count in map.items(): | |
| word_map[first][second] += count | |
| for first, map in maps['start_map'].items(): | |
| for second, count in map.items(): | |
| start_map[first][second] += count | |
| def train_set(filename): | |
| with open(filename) as training_set: | |
| last_word = None | |
| for line in training_set.readlines(): | |
| line = re.findall(r"[\w']+|[.,!?;]", line) | |
| if not line: | |
| continue | |
| process(last_word, line) | |
| last_word = line[-1] | |
| def process(my_last_word, response): | |
| response = response + [None] | |
| word = response[0] | |
| start_map[my_last_word][word] += 1 | |
| for follow in response[1:]: | |
| word_map[word][follow] += 1 | |
| word = follow | |
| def respond(their_last_word): | |
| if their_last_word in start_map: | |
| response_set = start_map[their_last_word] | |
| else: | |
| response_set = choice(list(word_map.values())) | |
| response = [] | |
| while True: | |
| word = choices(list(response_set.keys()), | |
| list(response_set.values()))[0] | |
| if word is None: | |
| return response | |
| response.append(word) | |
| response_set = word_map[word] | |
| def merge(tokens): | |
| if not tokens: | |
| return '' | |
| output = tokens[0] | |
| for token in tokens[1:]: | |
| if token in '.,!?;': | |
| output += token | |
| else: | |
| output += ' ' + token | |
| return output | |
| if __name__ == "__main__": | |
| my_last = None | |
| print('To save: >>filename') | |
| print('To load: <<filename') | |
| print('To train from text file: !!filename') | |
| while True: | |
| raw = input('HUMAN: ').lstrip() | |
| if raw.startswith('>>'): | |
| save(raw[2:]) | |
| continue | |
| elif raw.startswith('<<'): | |
| load(raw[2:]) | |
| continue | |
| elif raw.startswith('!!'): | |
| train_set(raw[2:]) | |
| continue | |
| human_says = re.findall(r"[\w']+|[.,!?;]", raw) | |
| process(my_last, human_says) | |
| their_last = None | |
| if human_says: | |
| their_last = human_says[-1] | |
| response = respond(their_last) | |
| my_last = None | |
| if response: | |
| my_last = response[-1] | |
| print('MACHINE: ', merge(response)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment