Genie Model
This is essentially a Pydantic model that can have as many fields as
one needs. A developer would subclass the GenieModel
class, which adds a number of required
fields and methods. That GenieModel
class also implements all functionality to persist it in
a key/value store (such as Redis) in serialised form.
Data object class fields
state
- This is the current state the accompanying State Machine is in. It is a string or an integer. Best not to be touched by the developer.
session_id
- The unique id of a session that this Data Object belongs to. Best not to be touched by the developer.
dialogue
- A list of
DialogueElement
s that is the sequence of utterances by the different actors involved in the dialogue.
actor
The name of the actor who has most recently uttered a statement. By default, this is USER
for
a Human actor and LLM
for an LLM.
actor_input
- The input that was last uttered by the most recent actor.
secondary_storage
- A dict-like structure to persist "write-once-read-many" objects. These are (normally larger)
objects that are compiled as part of the flow, but once saved, are not mutated at all. Whereas
changes to any direct property of a
GenieModel
are always persisted, and objects stored under thesecondary_storage
field will only be persisted when they are brand new. After that, any changes (accidentally) made to the content of objects in there will not be persisted.
Data object methods and properties
The developer needs to implement the class method get_state_machine_class
, which should return
the class that implements the State Machine that accompanies this Data Object. A new State Machine
is then created by model.get_state_machine_class()(model=model)
.
Some convenience methods exist:
current_response
- A property that returns the most recent utterance of an actor. Or
None
if there is none. format_dialogue
- Returns a string representation of the dialogue, using some pre-defined formats. See the
DialogueFormat
class for more details.
Related objects
If a developed class needs to maintain a relation to other objects that are not base classes, the class
of that other object also needs to be persistable. Since we are persisting the GenieModel
with all their properties, subclassing the Pydantic BaseModel
is fine. This means you can
create smart objects such as Managers and Stores that take away some of the management tasks
that you want to centralise around these classes, rather than implement these inside your
flow.
Objects that are going to be stored inside the secondary store are persisted on their own.
This means that they need to inherit, not from BaseModel
, but from the VersionedModel
class. That is just a direct subclass of BaseModel
with some additional functionality around
serialisation and deserialisation.
Classes for objects in the secondary storage need to be subclasses from
VersionedModel
VersionedModel
This abstract class implements everything that is required to serialise and de-serialise a Pydantic model. It also implements a schema version number. These are implemented as follows:
from pydantic import BaseModel, ConfigDict
class VersionedModel(BaseModel):
model_config = ConfigDict(json_schema_extra={"schema_version": 42})
@classmethod
def upgrade_schema(cls, from_version: int, model_data: dict) -> dict:
...
Two things are important here:
- The version of the schema needs to be stated. The base class
VersionedModel
implements this by specifying version0
- but it is good practice to assign a new version model yourself. - The class method
upgrade_schema
may be implemented to upgrade data that is obtained from an older version of a model into the data that is required for the current version of the model. These would typically involve: - Mapping state_id's to their new state_id's
- Dropping fields that no longer exist
- Create (initial) data for new fields that have been added
This method should return a dictionary that will be used to instantiate a fresh instance of the class.
The base implementation of VersionedModel
raises a ValueError
when it is asked to
deserialise data from a different version number.