conversation

package
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2024 License: MIT Imports: 10 Imported by: 13

README

Conversation Package

The conversation package provides a tree-like structure for storing and managing conversation messages in an LLM chatbot. It allows for traversing the conversation in various ways and supports different types of message content.

Features

  • Represents a conversation as a tree of messages
  • Supports different types of message content (e.g., chat messages)
  • Allows traversing the conversation tree in various ways (e.g., linear thread, leftmost thread)
  • Provides methods for inserting, attaching, and prepending messages to the conversation tree
  • Supports saving and loading conversation trees to/from JSON files
  • Includes a Manager interface for high-level management of conversations

Installation

go get github.com/go-go-golems/bobatea/pkg/conversation

Usage

Creating a Conversation Tree
tree := conversation.NewConversationTree()
Inserting Messages
message1 := conversation.NewChatMessage(conversation.RoleUser, "Hello!")
message2 := conversation.NewChatMessage(conversation.RoleAssistant, "Hi there!")

tree.InsertMessages(message1, message2)
Traversing the Conversation Tree
thread := tree.GetConversationThread(message2.ID)
leftmostThread := tree.GetLeftMostThread(tree.RootID)
Saving and Loading Conversation Trees
err := tree.SaveToFile("conversation.json")
if err != nil {
    // Handle error
}

loadedTree := conversation.NewConversationTree()
err = loadedTree.LoadFromFile("conversation.json")
if err != nil {
    // Handle error
}
Using the Manager
manager, err := conversation.CreateManager(
    "System prompt",
    "User prompt",
    []*conversation.Message{},
    nil,
)
if err != nil {
    // Handle error
}

manager.AppendMessages(message1, message2)
conversation := manager.GetConversation()

Message Content Types

The package supports different types of message content. Currently, the following content types are available:

  • ChatMessageContent: Represents a chat message with a role (system, assistant, user) and text content.

You can define your own message content types by implementing the MessageContent interface.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChatMessageContent

type ChatMessageContent struct {
	Role Role   `json:"role"`
	Text string `json:"text"`
}

func (*ChatMessageContent) ContentType

func (c *ChatMessageContent) ContentType() ContentType

func (*ChatMessageContent) String

func (c *ChatMessageContent) String() string

func (*ChatMessageContent) View

func (c *ChatMessageContent) View() string

type ContentType

type ContentType string
const (
	ContentTypeChatMessage ContentType = "chat-message"
)

type Conversation

type Conversation []*Message

func (Conversation) GetSinglePrompt

func (messages Conversation) GetSinglePrompt() string

GetSinglePrompt concatenates all the messages together with a prompt in front. It just concatenates all the messages together with a prompt in front (if there are more than one message).

type ConversationTree

type ConversationTree struct {
	Nodes  map[NodeID]*Message
	RootID NodeID
	LastID NodeID
}

ConversationTree represents a tree-like structure for storing and managing conversation messages.

The tree consists of nodes (messages) connected by parent-child links. These relationships are done through the parent ID field in each message. The root node is the starting point of the conversation, and each node can have multiple children. The tree allows for traversing the conversation in various ways.

Node relationships are stored in the Message datastructure as `Children []*Message`.

Each node has a unique ID, and the tree keeps track of the root node ID and the last inserted node ID.

func NewConversationTree

func NewConversationTree() *ConversationTree

NewConversationTree creates a new conversation tree.

func (*ConversationTree) AppendMessages

func (ct *ConversationTree) AppendMessages(thread Conversation)

AppendMessages appends a conversation thread to the end of the tree. It attaches the thread to the last inserted node in the tree, making it the parent of the thread. The messages in the thread are inserted as nodes, extending the parent-child chain.

func (*ConversationTree) AttachThread

func (ct *ConversationTree) AttachThread(parentID NodeID, thread Conversation)

AttachThread attaches a conversation thread to a specified parent message. It updates the parent IDs of the messages in the thread to link them to the parent message. The last message in the thread becomes the new last inserted node ID.

func (*ConversationTree) FindChildren

func (ct *ConversationTree) FindChildren(id NodeID) []NodeID

FindChildren returns the IDs of all child messages for a given message ID. Child messages are the nodes directly connected to the given message as its children.

func (*ConversationTree) FindSiblings

func (ct *ConversationTree) FindSiblings(id NodeID) []NodeID

FindSiblings returns the IDs of all sibling messages for a given message ID. Sibling messages are the nodes that share the same parent as the given message.

func (*ConversationTree) GetConversationThread

func (ct *ConversationTree) GetConversationThread(id NodeID) Conversation

GetConversationThread returns the linear conversation thread starting from a given message ID. It traverses the tree upwards, following the parent links, to retrieve the complete thread. The returned conversation is a linear sequence of messages from the root to the given message.

func (*ConversationTree) GetLeftMostThread

func (ct *ConversationTree) GetLeftMostThread(id NodeID) Conversation

GetLeftMostThread returns the thread starting from a given message ID by always choosing the first child. It traverses the tree downwards, selecting the leftmost child at each level, until a leaf node is reached. The returned conversation is a linear sequence of messages from the given message to the leftmost leaf.

func (*ConversationTree) GetMessageByID

func (ct *ConversationTree) GetMessageByID(id NodeID) (*Message, bool)

GetMessageByID returns a message by its ID from the conversation tree.

func (*ConversationTree) InsertMessages

func (ct *ConversationTree) InsertMessages(msgs ...*Message)

InsertMessages adds new messages to the conversation tree. It updates the root ID if the tree is empty and sets the last inserted node ID. If a message has a parent ID that exists in the tree, it is added as a child of that parent node.

func (*ConversationTree) LoadFromFile

func (ct *ConversationTree) LoadFromFile(filename string) error

LoadFromFile loads the conversation tree from a JSON file.

func (*ConversationTree) PrependThread

func (ct *ConversationTree) PrependThread(thread Conversation)

PrependThread prepends a conversation thread to the beginning of the tree. It updates the root ID to the first message in the thread and adjusts the parent-child relationships accordingly. The previous root node becomes a child of the new root node.

func (*ConversationTree) SaveToFile

func (ct *ConversationTree) SaveToFile(filename string) error

SaveToFile saves the conversation tree to a JSON file.

type Manager

type Manager interface {
	GetConversation() Conversation
	AppendMessages(msgs ...*Message)
	AttachMessages(parentID NodeID, msgs ...*Message)
	GetMessage(ID NodeID) (*Message, bool)
	SaveToFile(filename string) error
}

type ManagerImpl

type ManagerImpl struct {
	Tree           *ConversationTree
	ConversationID uuid.UUID
}

func CreateManager

func CreateManager(
	systemPrompt string,
	prompt string,
	messages []*Message,
	params interface{},
	options ...ManagerOption,
) (*ManagerImpl, error)

CreateManager creates a concrete Manager implementation.

NOTE(manuel, 2024-04-07) This currently seems to only be used by the codegen tests, while the main geppetto command uses NewManager. Unclear if this is just a legacy helper.

The systemPrompt and prompt templates are rendered using the params. Messages are also rendered using the params before being added to the manager.

ManagerOptions can be passed to further customize the manager on creation.

func NewManager

func NewManager(options ...ManagerOption) *ManagerImpl

func (*ManagerImpl) AppendMessages

func (c *ManagerImpl) AppendMessages(messages ...*Message)

func (*ManagerImpl) AttachMessages

func (c *ManagerImpl) AttachMessages(parentID NodeID, messages ...*Message)

func (*ManagerImpl) GetConversation

func (c *ManagerImpl) GetConversation() Conversation

func (*ManagerImpl) GetMessage

func (c *ManagerImpl) GetMessage(ID NodeID) (*Message, bool)

func (*ManagerImpl) PrependMessages

func (c *ManagerImpl) PrependMessages(messages ...*Message)

func (*ManagerImpl) SaveToFile

func (c *ManagerImpl) SaveToFile(s string) error

type ManagerOption

type ManagerOption func(*ManagerImpl)

func WithManagerConversationID

func WithManagerConversationID(conversationID uuid.UUID) ManagerOption

func WithMessages

func WithMessages(messages ...*Message) ManagerOption

type Message

type Message struct {
	ParentID   NodeID    `json:"parentID"`
	ID         NodeID    `json:"id"`
	Time       time.Time `json:"time"`
	LastUpdate time.Time `json:"lastUpdate"`

	Content  MessageContent         `json:"content"`
	Metadata map[string]interface{} `json:"metadata"` // Flexible metadata field

	// TODO(manuel, 2024-04-07) Add Parent and Sibling lists
	// omit in json
	Children []*Message `json:"-"`
}

Message represents a single message node in the conversation tree.

func LoadFromFile

func LoadFromFile(filename string) ([]*Message, error)

LoadFromFile loads messages from a json file or yaml file

func NewChatMessage

func NewChatMessage(role Role, text string, options ...MessageOption) *Message

func NewMessage

func NewMessage(content MessageContent, options ...MessageOption) *Message

func (*Message) MarshalJSON

func (mn *Message) MarshalJSON() ([]byte, error)

func (*Message) UnmarshalJSON

func (mn *Message) UnmarshalJSON(data []byte) error

UnmarshalJSON custom unmarshaler for Message.

type MessageContent

type MessageContent interface {
	ContentType() ContentType
	String() string
	View() string
}

MessageContent is an interface for different types of node content.

type MessageOption

type MessageOption func(*Message)

func WithID

func WithID(id NodeID) MessageOption

func WithMetadata

func WithMetadata(metadata map[string]interface{}) MessageOption

func WithParentID

func WithParentID(parentID NodeID) MessageOption

func WithTime

func WithTime(time time.Time) MessageOption

type NodeID

type NodeID uuid.UUID
var NullNode NodeID = NodeID(uuid.Nil)

func NewNodeID

func NewNodeID() NodeID

func (NodeID) MarshalJSON

func (id NodeID) MarshalJSON() ([]byte, error)

func (*NodeID) UnmarshalJSON

func (id *NodeID) UnmarshalJSON(data []byte) error

type Role

type Role string
const (
	RoleSystem    Role = "system"
	RoleAssistant Role = "assistant"
	RoleUser      Role = "user"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL