1010"""
1111
1212import logging
13- from typing import TYPE_CHECKING , Optional
13+ from typing import TYPE_CHECKING
1414
1515from .behavior import AgentBehavior
1616from .memory import SlidingWindowMemory
17- from .schemas import AgentDecision , Observation , ToolSchema
18- from .reasoning_trace import TraceStore , TraceStepName , get_global_trace_store
1917
2018# Backwards compatibility
21- from .reasoning_trace import PromptInspector , InspectorStage , get_global_inspector
19+ from .reasoning_trace import (
20+ PromptInspector ,
21+ TraceStepName ,
22+ get_global_inspector ,
23+ )
24+ from .schemas import AgentDecision , Observation , ToolSchema
2225
2326if TYPE_CHECKING :
2427 from backends .base import BaseBackend
@@ -62,7 +65,7 @@ def __init__(
6265 memory_capacity : int = 10 ,
6366 temperature : float = 0.7 ,
6467 max_tokens : int = 256 ,
65- inspector : Optional [ PromptInspector ] = None ,
68+ inspector : PromptInspector | None = None ,
6669 ):
6770 """
6871 Initialize the local LLM behavior.
@@ -121,59 +124,64 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
121124
122125 # Capture observation stage
123126 if capture :
124- capture .add_step (TraceStepName .OBSERVATION , {
125- "agent_id" : observation .agent_id ,
126- "tick" : observation .tick ,
127- "position" : observation .position ,
128- "health" : observation .health ,
129- "energy" : observation .energy ,
130- "nearby_resources" : [
131- {
132- "name" : r .name ,
133- "type" : r .type ,
134- "distance" : r .distance ,
135- "position" : r .position
136- }
137- for r in observation .nearby_resources
138- ],
139- "nearby_hazards" : [
140- {
141- "name" : h .name ,
142- "type" : h .type ,
143- "distance" : h .distance ,
144- "damage" : h .damage
145- }
146- for h in observation .nearby_hazards
147- ],
148- "inventory" : [
149- {"name" : item .name , "quantity" : item .quantity }
150- for item in observation .inventory
151- ]
152- })
127+ capture .add_step (
128+ TraceStepName .OBSERVATION ,
129+ {
130+ "agent_id" : observation .agent_id ,
131+ "tick" : observation .tick ,
132+ "position" : observation .position ,
133+ "health" : observation .health ,
134+ "energy" : observation .energy ,
135+ "nearby_resources" : [
136+ {
137+ "name" : r .name ,
138+ "type" : r .type ,
139+ "distance" : r .distance ,
140+ "position" : r .position ,
141+ }
142+ for r in observation .nearby_resources
143+ ],
144+ "nearby_hazards" : [
145+ {
146+ "name" : h .name ,
147+ "type" : h .type ,
148+ "distance" : h .distance ,
149+ "damage" : h .damage ,
150+ }
151+ for h in observation .nearby_hazards
152+ ],
153+ "inventory" : [
154+ {"name" : item .name , "quantity" : item .quantity }
155+ for item in observation .inventory
156+ ],
157+ },
158+ )
153159
154160 # Build prompt from system prompt, memory, and observation
155161 prompt = self ._build_prompt (observation , tools )
156162 logger .debug (f"Prompt length: { len (prompt )} chars (~{ len (prompt ) // 4 } tokens)" )
157163
158164 # Log prompt (if tracing enabled)
159- self .log_step ("prompt" , prompt )
165+ self .log_step ("prompt" , { "text" : prompt } )
160166
161167 # Capture prompt building stage
162168 if capture :
163169 memory_items = self .memory .retrieve (limit = 5 )
164- capture .add_step (TraceStepName .PROMPT_BUILDING , {
165- "system_prompt" : self .system_prompt ,
166- "memory_context" : {
167- "count" : len (memory_items ),
168- "items" : [
169- {"tick" : obs .tick , "position" : obs .position }
170- for obs in memory_items
171- ]
170+ capture .add_step (
171+ TraceStepName .PROMPT_BUILDING ,
172+ {
173+ "system_prompt" : self .system_prompt ,
174+ "memory_context" : {
175+ "count" : len (memory_items ),
176+ "items" : [
177+ {"tick" : obs .tick , "position" : obs .position } for obs in memory_items
178+ ],
179+ },
180+ "final_prompt" : prompt ,
181+ "prompt_length" : len (prompt ),
182+ "estimated_tokens" : len (prompt ) // 4 ,
172183 },
173- "final_prompt" : prompt ,
174- "prompt_length" : len (prompt ),
175- "estimated_tokens" : len (prompt ) // 4
176- })
184+ )
177185
178186 # Convert tools to dict format for backend
179187 tool_dicts = [
@@ -187,13 +195,16 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
187195
188196 # Capture LLM request stage
189197 if capture :
190- capture .add_step (TraceStepName .LLM_REQUEST , {
191- "model" : getattr (self .backend , 'model_name' , 'unknown' ),
192- "prompt" : prompt ,
193- "tools" : tool_dicts ,
194- "temperature" : self .temperature ,
195- "max_tokens" : self .max_tokens
196- })
198+ capture .add_step (
199+ TraceStepName .LLM_REQUEST ,
200+ {
201+ "model" : getattr (self .backend , "model_name" , "unknown" ),
202+ "prompt" : prompt ,
203+ "tools" : tool_dicts ,
204+ "temperature" : self .temperature ,
205+ "max_tokens" : self .max_tokens ,
206+ },
207+ )
197208
198209 # Generate response using backend
199210 import time
@@ -207,13 +218,16 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
207218
208219 # Capture LLM response stage
209220 if capture :
210- capture .add_step (TraceStepName .LLM_RESPONSE , {
211- "raw_text" : result .text ,
212- "tokens_used" : result .tokens_used ,
213- "finish_reason" : result .finish_reason ,
214- "metadata" : result .metadata ,
215- "latency_ms" : elapsed_ms
216- })
221+ capture .add_step (
222+ TraceStepName .LLM_RESPONSE ,
223+ {
224+ "raw_text" : result .text ,
225+ "tokens_used" : result .tokens_used ,
226+ "finish_reason" : result .finish_reason ,
227+ "metadata" : result .metadata ,
228+ "latency_ms" : elapsed_ms ,
229+ },
230+ )
217231
218232 # Check for generation errors
219233 if result .finish_reason == "error" :
@@ -223,13 +237,16 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
223237
224238 # Capture error decision
225239 if capture :
226- capture .add_step (TraceStepName .DECISION , {
227- "tool" : decision .tool ,
228- "params" : decision .params ,
229- "reasoning" : decision .reasoning ,
230- "total_latency_ms" : elapsed_ms ,
231- "error" : error_msg
232- })
240+ capture .add_step (
241+ TraceStepName .DECISION ,
242+ {
243+ "tool" : decision .tool ,
244+ "params" : decision .params ,
245+ "reasoning" : decision .reasoning ,
246+ "total_latency_ms" : elapsed_ms ,
247+ "error" : error_msg ,
248+ },
249+ )
233250
234251 self .inspector .finish_capture (observation .agent_id , observation .tick )
235252 self ._current_trace = None # Clear for next decision
@@ -277,12 +294,15 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
277294
278295 # Capture final decision stage
279296 if capture :
280- capture .add_step (TraceStepName .DECISION , {
281- "tool" : decision .tool ,
282- "params" : decision .params ,
283- "reasoning" : decision .reasoning ,
284- "total_latency_ms" : elapsed_ms
285- })
297+ capture .add_step (
298+ TraceStepName .DECISION ,
299+ {
300+ "tool" : decision .tool ,
301+ "params" : decision .params ,
302+ "reasoning" : decision .reasoning ,
303+ "total_latency_ms" : elapsed_ms ,
304+ },
305+ )
286306
287307 logger .info (
288308 f"Agent { observation .agent_id } decided: { decision .tool } - { decision .reasoning } "
@@ -300,12 +320,10 @@ def decide(self, observation: Observation, tools: list[ToolSchema]) -> AgentDeci
300320
301321 # Capture error in inspector
302322 if capture :
303- capture .add_step (TraceStepName .DECISION , {
304- "tool" : "idle" ,
305- "params" : {},
306- "reasoning" : f"Error: { e } " ,
307- "error" : str (e )
308- })
323+ capture .add_step (
324+ TraceStepName .DECISION ,
325+ {"tool" : "idle" , "params" : {}, "reasoning" : f"Error: { e } " , "error" : str (e )},
326+ )
309327 self .inspector .finish_capture (observation .agent_id , observation .tick )
310328 self ._current_trace = None # Clear for next decision
311329
0 commit comments