1414namespace App \Base \AI \Actions ;
1515
1616use App \Base \AI \Flows \BaseFlow ;
17- use App \Base \AI \Models \GoogleGemini ;
1817use App \Base \Interfaces \AI \AIModelInterface ;
1918use Exception ;
2019
@@ -29,70 +28,33 @@ public function __construct(AIModelInterface $llm)
2928 }
3029
3130 /**
32- * Registra un tool invocabile dal modello
31+ * Register a tool handler
3332 */
3433 public function registerTool (string $ name , callable $ handler ) : void
3534 {
3635 $ this ->toolsRegistry [$ name ] = $ handler ;
3736 }
3837
3938 /**
40- * Avvia il flow completo.
39+ * Run a flow
4140 */
4241 public function runFlow (BaseFlow $ flow , string $ userPrompt ) : array
4342 {
44- //
45- // 1) Costruisco i messaggi iniziali
46- //
47- $ messages = $ this ->llm ->buildFlowInitialMessages ($ flow , $ userPrompt );
48-
49-
50- //
51- // 2) Prima chiamata al modello
52- //
53- if ($ this ->llm instanceof GoogleGemini) {
54-
55- // Costruiamo le dichiarazioni dei tool
56- $ functions = [];
57- foreach ($ flow ->tools () as $ name => $ schema ) {
58- $ functions [] = [
59- 'name ' => $ name ,
60- 'description ' => $ schema ['description ' ] ?? '' ,
61- 'parameters ' => $ schema ['parameters ' ] ?? ['type ' => 'object ' ]
62- ];
63- }
43+ $ payload = $ this ->llm ->buildFlowInitialRequest ($ flow , $ userPrompt );
6444
65- $ response = $ this ->llm ->sendRaw ([
66- 'contents ' => $ messages ,
67- 'tools ' => [
68- [
69- 'function_declarations ' => $ functions
70- ]
71- ]
72- ]);
73-
74- } else {
75- // fallback per altri LLM (OpenAI, Anthropic, ecc.)
76- $ response = $ this ->llm ->sendRaw ([
77- 'messages ' => $ messages
78- ]);
79- }
45+ // extract messages for history tracking
46+ $ messages = $ payload ['messages ' ] ?? $ payload ['contents ' ] ?? [];
8047
48+ $ response = $ this ->llm ->sendRaw ($ payload );
8149
82- //
83- // 3) Normalizziamo la risposta
84- //
8550 $ normalized = $ this ->llm ->normalizeResponse ($ response );
8651
87-
88- //
89- // 4) Ciclo finché il modello continua a chiamare funzioni
90- //
9152 while (!empty ($ normalized ['functionCalls ' ])) {
9253
9354 $ call = $ normalized ['functionCalls ' ][0 ];
9455 $ functionName = $ call ['name ' ] ?? null ;
9556 $ args = $ call ['args ' ] ?? [];
57+ $ id = $ call ['id ' ] ?? null ;
9658
9759 if (!$ functionName ) {
9860 throw new Exception ("FunctionCall senza 'name' " );
@@ -102,31 +64,16 @@ public function runFlow(BaseFlow $flow, string $userPrompt) : array
10264 throw new Exception ("Tool non registrato: {$ functionName }" );
10365 }
10466
105- //
106- // 4a) Gemini richiede che il function_call originale
107- // sia inserito nella history ESATTAMENTE com'era.
108- //
10967 if (!empty ($ normalized ['rawFunctionMessages ' ][0 ])) {
11068 $ messages [] = $ normalized ['rawFunctionMessages ' ][0 ];
11169 } else {
112- // fallback sicuro per altri LLM
113- $ messages [] = [
114- 'role ' => 'model ' ,
115- 'parts ' => [
116- [
117- 'function_call ' => [
118- 'name ' => $ functionName ,
119- 'args ' => $ args
120- ]
121- ]
122- ]
123- ];
70+ $ assistantMessage = $ this ->llm ->formatAssistantFunctionCallMessage ($ functionName , $ args );
71+ if (!is_null ($ assistantMessage )) {
72+ $ messages [] = $ assistantMessage ;
73+ }
12474 }
12575
12676
127- //
128- // 4b) Eseguiamo il tool
129- //
13077 $ handler = $ this ->toolsRegistry [$ functionName ];
13178
13279 if (is_string ($ args )) {
@@ -137,32 +84,16 @@ public function runFlow(BaseFlow $flow, string $userPrompt) : array
13784 $ toolResult = $ handler ($ args );
13885
13986
140- //
141- // 4c) Rispondiamo al modello con function_response
142- // e con TUTTA la history (compreso il function_call originale)
143- //
14487 $ response = $ this ->llm ->sendFunctionResponse (
14588 $ functionName ,
14689 $ toolResult ,
14790 $ messages
14891 );
14992
150- //
151- // 4d) Normalizziamo la nuova risposta
152- //
15393 $ normalized = $ this ->llm ->normalizeResponse ($ response );
154-
155- //
156- // ⚠️ IMPORTANTE:
157- // NON aggiungere assistantText alla history qui.
158- // I messaggi testuali vanno aggiunti solo quando la chain finisce.
159- //
16094 }
16195
16296
163- //
164- // 5) Fine del flow: ritorna il risultato finale
165- //
16697 return $ normalized ;
16798 }
16899}
0 commit comments