Compare commits

...

8 Commits

Author SHA1 Message Date
Xingyao Wang
d6cbdb68f6 Update openhands/controller/agent_controller.py 2024-11-06 23:38:53 +08:00
Xingyao Wang
32f241fe63 Update openhands/events/serialization/event.py 2024-11-06 23:38:48 +08:00
openhands
1068d9c1be refactor: Simplify truncate_content function
- Remove directory creation logic since /openhands/outputs is created by server
- Remove chmod calls since permissions are handled by server
- Keep core functionality of saving full content and truncating
2024-11-06 14:56:00 +00:00
openhands
45ccf9463f feat: Save full content when truncating
- Save full content to /openhands/outputs/ when truncation occurs
- Use timestamp in filename for uniqueness
- Add file path to truncation message
- Create outputs directory with proper permissions if needed
2024-11-06 14:55:10 +00:00
openhands
7edcf49790 refactor: Move truncate_content to action_execution_server
- Move truncate_content function to action_execution_server.py
- Remove truncation from event.py and agent_controller.py
- Centralize all truncation at the server level
2024-11-06 14:48:46 +00:00
openhands
eedfd253fb feat: Add message truncation to action execution server
- Add MAX_CHARS_MESSAGES constant (30_000) to server
- Truncate observation content in execute_action endpoint
- Centralize truncation in one place instead of client implementations
2024-11-06 14:44:27 +00:00
openhands
c848aa8db9 refactor: Move truncation to runtime level only
- Update MAX_CHARS_MESSAGES to 30_000 to match LLM config default
- Remove truncation from event serialization as it's now handled at runtime level
- Keep truncate_content function for reuse but don't call it in event.py
2024-11-06 14:29:45 +00:00
openhands
986f2e4b14 feat: Add message truncation to runtime observations
- Add MAX_CHARS_MESSAGES constant to base Runtime class
- Implement truncate_content for all runtime observations
- Apply truncation in both eventstream and remote runtime implementations
2024-11-06 14:26:19 +00:00
3 changed files with 39 additions and 18 deletions

View File

@@ -39,7 +39,7 @@ from openhands.events.observation import (
NullObservation,
Observation,
)
from openhands.events.serialization.event import truncate_content
from openhands.llm.llm import LLM
from openhands.runtime.utils.shutdown_listener import should_continue
@@ -255,10 +255,6 @@ class AgentController:
observation (observation): The observation to handle.
"""
observation_to_print = copy.deepcopy(observation)
if len(observation_to_print.content) > self.agent.llm.config.max_message_chars:
observation_to_print.content = truncate_content(
observation_to_print.content, self.agent.llm.config.max_message_chars
)
self.log('debug', str(observation_to_print), extra={'msg_type': 'OBSERVATION'})
if observation.llm_metrics is not None:

View File

@@ -111,20 +111,7 @@ def event_to_memory(event: 'Event', max_message_chars: int) -> dict:
if 'extras' in d:
remove_fields(d['extras'], DELETE_FROM_MEMORY_EXTRAS)
if isinstance(event, Observation) and 'content' in d:
d['content'] = truncate_content(d['content'], max_message_chars)
return d
def truncate_content(content: str, max_chars: int) -> str:
"""Truncate the middle of the observation content if it is too long."""
if len(content) <= max_chars or max_chars == -1:
return content
# truncate the middle and include a message to the LLM about it
half = max_chars // 2
return (
content[:half]
+ '\n[... Observation truncated due to length ...]\n'
+ content[-half:]
)

View File

@@ -60,6 +60,41 @@ class ActionRequest(BaseModel):
action: dict
# Maximum number of characters for truncating runtime messages
MAX_CHARS_MESSAGES = 30_000
def truncate_content(content: str, max_chars: int) -> str:
"""Truncate the middle of the observation content if it is too long.
If truncation occurs, the full content will be saved to a file in /openhands/outputs/
"""
if len(content) <= max_chars or max_chars == -1:
return content
# Save the full content to a file
import os
import datetime
# Generate filename with timestamp
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
output_file = os.path.join('/openhands/outputs', f'truncated_output_{timestamp}.txt')
try:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
except Exception as e:
logger.error(f'Failed to save full content to file: {e}')
# truncate the middle and include a message to the LLM about it
half = max_chars // 2
truncated = (
content[:half]
+ f'\n[... Observation truncated due to length. Full content saved to {output_file} ...]\n'
+ content[-half:]
)
return truncated
ROOT_GID = 0
INIT_COMMANDS = [
'git config --global user.name "openhands" && git config --global user.email "openhands@all-hands.dev" && alias git="git --no-pager"',
@@ -399,6 +434,9 @@ if __name__ == '__main__':
raise HTTPException(status_code=400, detail='Invalid action type')
client.last_execution_time = time.time()
observation = await client.run_action(action)
# Truncate observation content if it exists
if hasattr(observation, 'content'):
observation.content = truncate_content(observation.content, MAX_CHARS_MESSAGES)
return event_to_dict(observation)
except Exception as e:
logger.error(