diff --git a/ee/lib/gitlab/duo/chat/react_executor.rb b/ee/lib/gitlab/duo/chat/react_executor.rb index cdbc70dfade002a73a77f9ef3c9899622a74008c..514bb9f133b4ba56a819e87c4a57c59c00b3e026 100644 --- a/ee/lib/gitlab/duo/chat/react_executor.rb +++ b/ee/lib/gitlab/duo/chat/react_executor.rb @@ -33,7 +33,7 @@ def initialize(user_input:, tools:, context:, response_handler:, stream_response end def execute - MAX_ITERATIONS.times do + MAX_ITERATIONS.times do |i| events = step_forward raise EmptyEventsError if events.empty? @@ -42,7 +42,11 @@ def execute process_tool_action(events) || process_unknown(events) - return answer if answer + next unless answer + + log_info(message: "ReAct turn", react_turn: i, event_name: 'react_turn', ai_component: 'duo_chat') + + return answer end raise ExhaustedLoopError diff --git a/ee/lib/gitlab/llm/concerns/logger.rb b/ee/lib/gitlab/llm/concerns/logger.rb index ecfc9e7aa02334dd92cc4999cbab6bd7bc72545d..475b98d92dfdff3b806e61e871de2413986bd75e 100644 --- a/ee/lib/gitlab/llm/concerns/logger.rb +++ b/ee/lib/gitlab/llm/concerns/logger.rb @@ -37,6 +37,7 @@ module Logger Attribute.new(:picked_tool, String), Attribute.new(:allowed, String), Attribute.new(:tool_name, String), + Attribute.new(:react_turn, Integer), Attribute.new(:ai_event, String), Attribute.new(:params, String), Attribute.new(:status, Integer), diff --git a/ee/spec/lib/gitlab/duo/chat/react_executor_spec.rb b/ee/spec/lib/gitlab/duo/chat/react_executor_spec.rb index 399710e509dd7b4264734e1bbb928faf23ca791f..ea60218e6cc6d2d9454aad30ac578f71124f6e18 100644 --- a/ee/spec/lib/gitlab/duo/chat/react_executor_spec.rb +++ b/ee/spec/lib/gitlab/duo/chat/react_executor_spec.rb @@ -107,6 +107,9 @@ end it "streams final answer" do + expect(agent).to receive(:log_info).with( + message: "ReAct turn", react_turn: 0, event_name: 'react_turn', ai_component: 'duo_chat') + expect(stream_response_service_double).to receive(:execute).with( response: first_response_double, options: { chunk_id: 1 } @@ -144,6 +147,9 @@ end it "returns tool answer" do + expect(agent).to receive(:log_info).with( + message: "ReAct turn", react_turn: 0, event_name: 'react_turn', ai_component: 'duo_chat') + expect(answer.is_final?).to be_truthy expect(answer.content).to include("tool answer") end @@ -220,6 +226,9 @@ end it "returns unknown answer as is" do + expect(agent).to receive(:log_info).with( + message: "ReAct turn", react_turn: 0, event_name: 'react_turn', ai_component: 'duo_chat') + expect(answer.content).to include('foo') end end