The log of the HMS Dolphin, Captained by John Byron in January 1765. Via Wikimedia Commons.
This ended up being a pretty easy thing to implement, despite the fact that it got me using some Python elements I've never had to touch before. Acuitas is a multi-threaded program (for the layman, that means he's made up of multiple processes that effectively run at the same time). I needed all the threads to be able to write to the log without getting in each other's way, and that meant implementing a Queue. To my surprise, everything just worked, and I didn't have to spend hours figuring out why the built-in code didn't function as advertised on my system, or wringing out obscure bugs related to the thread interaction. I mean it's shocking when that ever happens.
So now basically every module in Acuitas has a handle for the Logger, and it can generate text comments on what it's currently doing and throw them into the Queue. The Queue accepts all these like a funnel and writes one at a time to the log file. I also set it up to create up to eight log files and then start overwriting the old ones, which saves me from having to delete a hundred stale logs every so often.
Here is an example log excerpt, if you care to even look at it ... it's rather a case of too much information. I've just input the sentence "What is a cat?" Acuitas answers "An organism," and the log contains all the steps to get to that answer. The long numbers are timestamps, and the strings of gibberish are concept identifiers, which are not the same as words.
1636251936 Psyche: Added Thought of type Text Input and payload {'raw_text': 'What is a cat?'} to the Stream
1636251936 Executive: Pulled Thought of type Text Input with payload {'raw_text': 'What is a cat?'} from the Stream
1636251936 TimedDrives: InteractionDrive dropped due to event, new value is 0
1636251936 ConversationEngine: passed input to Parser: What is a cat?
1636251936 TextParser: generated parsed output: {'t': ['what', 'is', 'a', 'cat', '?'], 'c': [True, False, False, False, False], 'l': ['is', 'cat'], 'p': [('cat', 'noun'), ('what', 'noun'), (1, 'verb'), ('a', 'adj')], 'k': {}, 'a': {'subj': [{'ix': [3], 'token': 'cat', 'mod': [{'ix': [2], 'token': 'a', 'mod': []}]}], 'dobj': [{'ix': [0], 'token': 'what', 'mod': [], 'ps': 'noun'}], 'verb': [{'ix': [1], 'token': 'is', 'mod': []}]}, 'q': True, 'i': []}
1636251936 TextInterpreter: generated interpreted output {'form': ('cl', 'is_a-0'), 'forms': ['sv', 'state', 'static_fact', 's_atomic', 'is_a', 'is_a-0'], 'features': {'verb': True, 'verb_id': 'be', 'vqual': '', 'tense0': 'present', 'tense1': 'simple', 'voice': 'active', 'mood': 'active', 'subj': True, 'subj_case': 'common', 'subj_id': 'cat', 'subj_type': 'noun', 'subj_art': 'indef', 'dobj': True, 'dobj_art': 'none', 'dobj_case': 'common', 'dobj_type': 'noun', 'dobj_id': 'what'}, 'content': [{'atomic': True, 'concept': '1ygE876ghsC0yUxt', 'pos': 'noun', 'proper': False}, {'atomic': True, 'concept': '?', 'pos': 'noun', 'proper': False}], 'link_type': ('inter-item', 'is_type_of')}
1636251936 ConversationEngine: reformatted text interpretation into fact link: {'link': 'is_type_of', 'root': '1ygE876ghsC0yUxt', 'ends': ['?']}
1636251936 ConversationEngine: creating new input leaf leaf_7 and attaching to leaf_0.
1636251936 GoalManager: From possibility [{'root': 'wVD7W6mDqBW2zviX', 'link': 'do_action_t', 'ends': ['LS5R=+UqS59XEulN'], 'link_type': 'do_action_t'}, {'root': 'vMgrWYy7hY843IGy', 'link': 'do_action_i', 'ends': ['XGZdj0WXnwVdV4P3'], 'link_type': 'do_action_i'}] relative to agent vMgrWYy7hY843IGy, generated alignment tree [{'atomic': True, 'pri': 6, 'align': 'y', 'src': {'root': 'vMgrWYy7hY843IGy', 'link': 'do_action_i', 'ends': ['XGZdj0WXnwVdV4P3'], 'link_type': 'do_action_i'}}]
1636251936 GoalManager: From possibility [{'root': 'wVD7W6mDqBW2zviX', 'link': 'do_action_t', 'ends': ['LS5R=+UqS59XEulN'], 'link_type': 'do_action_t'}, {'root': 'vMgrWYy7hY843IGy', 'link': 'do_action_i', 'ends': ['XGZdj0WXnwVdV4P3'], 'link_type': 'do_action_i'}] relative to agent wVD7W6mDqBW2zviX, generated alignment tree [{'atomic': False, 'pri': 6, 'align': 'y', 'id': 'vMgrWYy7hY843IGy', 'sub': {'atomic': True, 'pri': 6, 'align': 'y', 'src': {'root': 'vMgrWYy7hY843IGy', 'link': 'do_action_i', 'ends': ['XGZdj0WXnwVdV4P3'], 'link_type': 'do_action_i'}}, 'src': {'root': 'vMgrWYy7hY843IGy', 'link': 'do_action_i', 'ends': ['XGZdj0WXnwVdV4P3'], 'link_type': 'do_action_i'}}]
1636251936 MoralReasoning: Reported preference y and alignment y.
1636251936 Executive: Analyzed request {'root': 'wVD7W6mDqBW2zviX', 'link': 'do_action_t', 'ends': ['LS5R=+UqS59XEulN'], 'link_type': 'do_action_t'}, concluded want was ('y', 'y', ['sb', 'good']), can was y, and action would be LS5R=+UqS59XEulN
1636251936 ActionBank: ran action AnswerAction with DOBJ = {'form': ('cl', 'is_a-0'), 'forms': ['sv', 'state', 'static_fact', 's_atomic', 'is_a', 'is_a-0'], 'features': {'verb': True, 'verb_id': 'be', 'vqual': '', 'tense0': 'present', 'tense1': 'simple', 'voice': 'active', 'mood': 'active', 'subj': True, 'subj_case': 'common', 'subj_id': 'cat', 'subj_type': 'noun', 'subj_art': 'indef', 'dobj': True, 'dobj_art': 'none', 'dobj_case': 'common', 'dobj_type': 'noun', 'dobj_id': 'what'}, 'content': [{'atomic': True, 'concept': '1ygE876ghsC0yUxt', 'pos': 'noun', 'proper': False}, {'atomic': True, 'concept': '?', 'pos': 'noun', 'proper': False}], 'link_type': ('inter-item', 'is_type_of')} IOBJ = vMgrWYy7hY843IGy
1636251936 ActionBank: ran action SayAction with DOBJ = An organism. IOBJ = None
1636251938 Psyche: Added Thought of type Action and payload {'action': 'SayAction'} to the Stream
1636251938 ConversationEngine: creating new output leaf leaf_8 and attaching to leaf_7.
I spent the rest of my time this month refactoring bad code and restoring some more features that got damaged during the Conversation Engine overhaul. The good news here is ... for once, I think there's no section of the code that is a huge mess. I got the Executive cleaned up, and that's the last area that was scaring me. So I should be ready to hit the ground running next year.
Acuitas development is done for 2021 BUT I have other exciting things to talk about, so stay tuned for more blogs! In particular, I finally have some great news from Ye Olde Day Job. I got a new e-mail subscription service to replace Feedburner, so if you want to stay updated feel free to throw your e-mail into the box on the upper right. (If you already subscribed via the old Feedburner box, you shouldn't need to do this ... I'll move you to the new service.)
Until the next cycle,
Jenny
Acuitas development is done for 2021 BUT I have other exciting things to talk about, so stay tuned for more blogs! In particular, I finally have some great news from Ye Olde Day Job. I got a new e-mail subscription service to replace Feedburner, so if you want to stay updated feel free to throw your e-mail into the box on the upper right. (If you already subscribed via the old Feedburner box, you shouldn't need to do this ... I'll move you to the new service.)
Until the next cycle,
Jenny