Class: Async::Ollama::Conversation

Inherits:
Object
  • Object
show all
Defined in:
lib/async/ollama/conversation.rb

Overview

Represents a conversation with the Ollama API, managing messages, tool calls, and summarization.

Defined Under Namespace

Classes: ChatError

Constant Summary collapse

SUMMARIZE_MESSAGE =
"Please summarize the conversation so far for your future reference. Do not introduce new information or questions. Refer to both user and assistant messages. Please keep the summary concise and relevant to the conversation and use it to continue the conversation."

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, model: MODEL, messages: [], **options) ⇒ Conversation

Initializes a new conversation.



22
23
24
25
26
27
28
29
30
31
# File 'lib/async/ollama/conversation.rb', line 22

def initialize(client, model: MODEL, messages: [], **options)
	@client = client
	@model = model
	@messages = messages
	@options = options
	
	@toolbox = Toolbox.new
	
	@last_response = nil
end

Instance Attribute Details

#messagesObject (readonly)

Returns the value of attribute messages.



37
38
39
# File 'lib/async/ollama/conversation.rb', line 37

def messages
  @messages
end

#The messages in the conversation.(messages) ⇒ Object (readonly)



37
# File 'lib/async/ollama/conversation.rb', line 37

attr :messages

#toolboxObject (readonly)

Returns the value of attribute toolbox.



34
35
36
# File 'lib/async/ollama/conversation.rb', line 34

def toolbox
  @toolbox
end

Instance Method Details

#call(prompt, &block) ⇒ Object

Sends a prompt to the conversation and processes the response, including tool calls.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/async/ollama/conversation.rb', line 52

def call(prompt, &block)
	if prompt.is_a?(String)
		@messages << {
			role: "user",
			content: prompt
		}
	else
		@messages << prompt
	end
	
	while true
		@last_response = @client.chat(@messages, model: @model, tools: @toolbox.explain, options: @options, &block)
		
		if error = @last_response.error
			raise ChatError, error
		end
		
		@messages << @last_response.message
		
		tool_calls = @last_response.tool_calls
		
		if tool_calls.nil? || tool_calls.empty?
			return @last_response
		end
		
		tool_calls.each do |tool_call|
			@messages << @toolbox.call(tool_call)
		end
	end
end

#sizeObject



40
41
42
# File 'lib/async/ollama/conversation.rb', line 40

def size
	@messages.size
end

#summarize!(retain = -1,, role: "user") ⇒ Object

Summarizes the conversation and truncates messages to reduce context usage.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/async/ollama/conversation.rb', line 89

def summarize!(retain = -1, role: "user")
	current_size = @messages.size
	
	# In principle, this could generate several messages:
	message = {
		role: role,
		content: SUMMARIZE_MESSAGE,
	}
	
	self.call(message)
	
	# The number of messages generated by the summarization:
	delta = @messages.size - current_size
	
	# After much experimentation, I found that leaving the SUMMARIZE_MESSAGE in the message stream caused extreme confusion, so we set retain to -1 to remove it by default.
	retain += delta
	if retain < @messages.size
		truncated = @messages.size - retain
		
		# We need to truncate the messages:
		@messages = @messages.last(retain)
		
		@messages.unshift({
			role: "system",
			content: "#{truncated} previous messages that have been removed and summarized to reduce context usage. Continue the conversation naturally as if the previous messages were still present.",
		})
	end
end

#The toolbox for this conversation.=(toolbox) ⇒ Object



34
# File 'lib/async/ollama/conversation.rb', line 34

attr :toolbox

#token_countObject



45
46
47
# File 'lib/async/ollama/conversation.rb', line 45

def token_count
	@last_response&.token_count || 0
end