akseljoonas HF Staff commited on
Commit
0aec89b
·
1 Parent(s): 76996d0

adding compaction

Browse files
agent/context_manager/manager.py CHANGED
@@ -78,7 +78,9 @@ class ContextManager:
78
  """Get all messages for sending to LLM"""
79
  return self.items
80
 
81
- async def compact(self, model_name: str) -> None:
 
 
82
  """Remove old messages to keep history under target size"""
83
  if (self.context_length <= self.max_context) or not self.items:
84
  return
@@ -112,6 +114,7 @@ class ContextManager:
112
  model=model_name,
113
  messages=messages_to_summarize,
114
  max_completion_tokens=self.compact_size,
 
115
  )
116
  summarized_message = Message(
117
  role="assistant", content=response.choices[0].message.content
 
78
  """Get all messages for sending to LLM"""
79
  return self.items
80
 
81
+ async def compact(
82
+ self, model_name: str, tool_specs: list[dict] | None = None
83
+ ) -> None:
84
  """Remove old messages to keep history under target size"""
85
  if (self.context_length <= self.max_context) or not self.items:
86
  return
 
114
  model=model_name,
115
  messages=messages_to_summarize,
116
  max_completion_tokens=self.compact_size,
117
+ tools=tool_specs,
118
  )
119
  summarized_message = Message(
120
  role="assistant", content=response.choices[0].message.content
agent/core/agent_loop.py CHANGED
@@ -6,6 +6,7 @@ import asyncio
6
  import json
7
 
8
  from litellm import ChatCompletionMessageToolCall, Message, ModelResponse, acompletion
 
9
  from lmnr import observe
10
 
11
  from agent.config import Config
@@ -108,13 +109,31 @@ def _needs_approval(
108
  return False
109
 
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  class Handlers:
112
  """Handler functions for each operation type"""
113
 
114
  @staticmethod
115
  @observe(name="run_agent")
116
  async def run_agent(
117
- session: Session, text: str, max_iterations: int = 10
118
  ) -> str | None:
119
  """
120
  Handle user input (like user_input_or_turn in codex.rs:1291)
@@ -141,6 +160,9 @@ class Handlers:
141
  final_response = None
142
 
143
  while iteration < max_iterations:
 
 
 
144
  messages = session.context_manager.get_messages()
145
  tools = session.tool_router.get_tool_specs_for_llm()
146
 
@@ -277,6 +299,14 @@ class Handlers:
277
 
278
  iteration += 1
279
 
 
 
 
 
 
 
 
 
280
  except Exception as e:
281
  import traceback
282
 
@@ -288,18 +318,6 @@ class Handlers:
288
  )
289
  break
290
 
291
- old_length = session.context_manager.context_length
292
- await session.context_manager.compact(model_name=session.config.model_name)
293
- new_length = session.context_manager.context_length
294
-
295
- if new_length != old_length:
296
- await session.send_event(
297
- Event(
298
- event_type="compacted",
299
- data={"old_tokens": old_length, "new_tokens": new_length},
300
- )
301
- )
302
-
303
  await session.send_event(
304
  Event(
305
  event_type="turn_complete",
@@ -319,20 +337,6 @@ class Handlers:
319
  session.interrupt()
320
  await session.send_event(Event(event_type="interrupted"))
321
 
322
- @staticmethod
323
- async def compact(session: Session) -> None:
324
- """Handle compact (like compact in codex.rs:1317)"""
325
- old_length = session.context_manager.context_length
326
- await session.context_manager.compact(model_name=session.config.model_name)
327
- new_length = session.context_manager.context_length
328
-
329
- await session.send_event(
330
- Event(
331
- event_type="compacted",
332
- data={"removed": old_length, "remaining": new_length},
333
- )
334
- )
335
-
336
  @staticmethod
337
  async def undo(session: Session) -> None:
338
  """Handle undo (like undo in codex.rs:1314)"""
@@ -505,7 +509,8 @@ async def process_submission(session: Session, submission) -> bool:
505
  return True
506
 
507
  if op.op_type == OpType.COMPACT:
508
- await Handlers.compact(session)
 
509
  return True
510
 
511
  if op.op_type == OpType.UNDO:
 
6
  import json
7
 
8
  from litellm import ChatCompletionMessageToolCall, Message, ModelResponse, acompletion
9
+ from litellm.exceptions import ContextWindowExceededError
10
  from lmnr import observe
11
 
12
  from agent.config import Config
 
109
  return False
110
 
111
 
112
+ async def _compact_and_notify(session: Session) -> None:
113
+ """Run compaction and send event if context was reduced."""
114
+ old_length = session.context_manager.context_length
115
+ tool_specs = session.tool_router.get_tool_specs_for_llm()
116
+ await session.context_manager.compact(
117
+ model_name=session.config.model_name,
118
+ tool_specs=tool_specs,
119
+ )
120
+ new_length = session.context_manager.context_length
121
+ if new_length != old_length:
122
+ await session.send_event(
123
+ Event(
124
+ event_type="compacted",
125
+ data={"old_tokens": old_length, "new_tokens": new_length},
126
+ )
127
+ )
128
+
129
+
130
  class Handlers:
131
  """Handler functions for each operation type"""
132
 
133
  @staticmethod
134
  @observe(name="run_agent")
135
  async def run_agent(
136
+ session: Session, text: str, max_iterations: int = 300
137
  ) -> str | None:
138
  """
139
  Handle user input (like user_input_or_turn in codex.rs:1291)
 
160
  final_response = None
161
 
162
  while iteration < max_iterations:
163
+ # Compact before calling the LLM if context is near the limit
164
+ await _compact_and_notify(session)
165
+
166
  messages = session.context_manager.get_messages()
167
  tools = session.tool_router.get_tool_specs_for_llm()
168
 
 
299
 
300
  iteration += 1
301
 
302
+ except ContextWindowExceededError:
303
+ # Force compact and retry this iteration
304
+ session.context_manager.context_length = (
305
+ session.context_manager.max_context + 1
306
+ )
307
+ await _compact_and_notify(session)
308
+ continue
309
+
310
  except Exception as e:
311
  import traceback
312
 
 
318
  )
319
  break
320
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  await session.send_event(
322
  Event(
323
  event_type="turn_complete",
 
337
  session.interrupt()
338
  await session.send_event(Event(event_type="interrupted"))
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  @staticmethod
341
  async def undo(session: Session) -> None:
342
  """Handle undo (like undo in codex.rs:1314)"""
 
509
  return True
510
 
511
  if op.op_type == OpType.COMPACT:
512
+ # compact from the frontend
513
+ await _compact_and_notify(session)
514
  return True
515
 
516
  if op.op_type == OpType.UNDO: