21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
82
83
84
85
|
# File 'lib/llm/clients/base.rb', line 21
def chat_with_function_calling_loop(**args)
agent = args.delete(:agent) || (raise 'agent is required.')
chat_message_io = StringIO.new
if args[:messages].is_a?(Llm::MessageContainer)
message_container = args[:messages]
else
message_container = Llm::MessageContainer.new
message_container.add_raw_messages(args[:messages])
end
i = 0
while (i += 1) < 20
ret = self.chat(parameters: args.merge({
messages: message_container.to_capped_messages,
functions: args[:functions].map { |f| f.definition },
}))
if ret.dig("choices", 0, "finish_reason") != 'function_call'
break
end
message = ret.dig("choices", 0, "message")
function = args[:functions].detect { |f| f.function_name == message['function_call']['name'].to_sym }
message_container.add_raw_message(message.merge({ content: nil }))
function_args = (JSON.parse(message.dig('function_call', 'arguments')) || {}).with_indifferent_access
agent.say(function.function_name)
agent.say(function_args, color: false)
function_result = function.execute_and_generate_message(function_args)
message_container.add_raw_message({
role: "function",
name: function.function_name,
content: JSON.dump(function_result),
})
if function.stop_llm_call?
chat_message_io.write(function_result)
return chat_message_io
end
end
if content = ret.dig("choices", 0, "message", "content")
chat_message_io.write(content)
else
functions = args[:functions].select do |f| %w[
switch_assignee
report_bug
].include?(f.function_name.to_s) end
ret = self.chat(parameters: args.merge({
messages: message_container.to_capped_messages,
functions: functions.map { |f| f.definition },
}))
if content = ret.dig("choices", 0, "message", "content")
chat_message_io.write(content)
else
puts ret
exit 1
end
end
chat_message_io
end
|