Knowledge

Overview, Definition of Knowledge, & Example

Knowledge is defined as something that the NPC is aware of that they did not experience themselves. In the scenario in which we were doing a perfect simulation, everything someone learns comes from a direct experience. For instance, if TumTum’s Tavern burns down, an NPC Alex would have a memory “Elysia tells Alex that TumTum’s Tavern burnt down”. However, if you’re not simulating conversations at that level and are instead doing a higher level approximation of the progression of a game-state, then instead you might assign knowledge of various entities to an NPC. For example, you might give Alex knowledge of the town of Larkspur. TumTum’s tavern, being in Larkspur, is a child of Larkspur. Therefore, Alex would be aware of the happenings of TumTum’s tavern via the “TumTum’s Tavern” document. In this manner Alex would be aware of the things that you’d expect him to be aware of, however, how he became away of the tavern burning down would not be explicitly tracked.

There are a few important concepts to understand when it comes to my implementation of knowledge. These include, knowledge inheritance, knowledge tag, and knowledge levels. A knowledge tag is a unique identifier which corresponds to some entity. An entity can be a person, place, or thing for which knowledge exists. NPCs can be assigned access to this tag. Knowledge inheritance is simply the system by which knowledge tags can be assigned knowledge tags. For instance, if an NPC is assigned the tag “zone-SunkenHearth” and some other tag “place-TumTum’s Tavern” is assigned to “zone-SunkenHearth”, then said NPC would have access to specific knowledge about TumTum’s Tavern simply by being given access to information about SunkenHearth. However, it’s potentially only partial information as detailed below. A knowledge level is the level of knowledge that an NPC has of some tag. A level of 0 indicates that literally every NPC in the game has knowledge of said thing. For instance, if the name of the planet is Decatus and you want every NPC to know that then you can create a tag “world-information” with level 0 knowledge that includes the name of the world. NPCs need not be assigned this tag to have access to it. A level of 1 indicates that knowledge is inherited as long as the NPC is assigned access to a higher level knowledge tag. If you want an NPC to know certain things, but not all things about some entity/tag, a higher level (2-5) of knowledge can be assigned to said NPC. A scenario where I have found this to be useful is giving NPCs various level of understanding of the history of the world, or potentially higher level understanding of some faction in the world.

User Journal

As part of this game, companions (NPCs who have joined your mercenary guild) are given access to important information that has been acquired by the player. For example, when the player communicates with an NPC and learns something of importance from them, that knowledge is stored in a specific “user-journal” document which all of the companions (but not other NPCs) have access to.

Index Info

An index is persisted for each NPC and each save state. A single index is computed over all documents that the NPC has access to as opposed to there being multiple indices for the various documents. The index is incrementally updated as new knowledge is acquired by the NPC.

The index is just a simple VectorStoreIndex using Chroma.

Knowledge Retrieval

Knowledge is retrieved as part of two systems: NpcUserInteraction & Missions. For more information on how info is retrieved as part of these systems. Follow the links for more info.

I retrieve knowledge programatically via a couple of different methods. One is using the LlamaIndex QueryEngine and the other is via a Langchain conversational-react-description Agent that has been assigned the LlamaIndex QueryEngine as a tool. I use the agent for retrieving knowledge for NpcUserInteraction and the QueryEngine directly for retrieving knowledge So when do I use one versus the other? I use the agent when conversation needs to be passed; the agent allows for a memory buffer to be passed. So, essentially, for NpcUserInteractions (conversation) I use the langchain agent and for missions I utilize the QueryEngine.

Last updated