Skip to content
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
255670b
update
fengju0213 Sep 30, 2025
b1f3213
Update chat_agent.py
fengju0213 Sep 30, 2025
746a4f5
Update oceanbase.py
fengju0213 Sep 30, 2025
cc31148
update
fengju0213 Oct 1, 2025
326543d
Merge branch 'master' into enhance_update_memory
Wendong-Fan Oct 2, 2025
aeffc5e
Merge branch 'master' into enhance_update_memory
Wendong-Fan Oct 5, 2025
0dc9c12
minor enhance
Wendong-Fan Oct 5, 2025
40d404a
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 5, 2025
2df88da
Update chat_agent.py
fengju0213 Oct 9, 2025
bd18fec
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 9, 2025
8c76dc5
Update chat_agent.py
fengju0213 Oct 9, 2025
cbdb4ef
Update chat_agent.py
fengju0213 Oct 9, 2025
b69fd16
update
fengju0213 Oct 14, 2025
fc74702
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 14, 2025
ce3608e
Update chat_agent.py
fengju0213 Oct 14, 2025
d184944
update
fengju0213 Oct 21, 2025
bc69be7
Update chat_agent.py
fengju0213 Oct 21, 2025
c1e137e
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 21, 2025
3309c0f
Update chat_agent.py
fengju0213 Oct 21, 2025
8d66d0d
Update chat_agent.py
fengju0213 Oct 21, 2025
b0752ef
Update chat_agent.py
fengju0213 Oct 21, 2025
cc983c9
Update chat_agent.py
fengju0213 Oct 21, 2025
41ed7ee
Update test_chat_agent.py
fengju0213 Oct 21, 2025
71d367d
Update test_chat_agent.py
fengju0213 Oct 21, 2025
f2940e6
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 23, 2025
b45d558
Update test_score_based.py
fengju0213 Oct 23, 2025
b5a21f1
Update chat_agent.py
fengju0213 Oct 24, 2025
3810c56
Update chat_agent.py
fengju0213 Oct 24, 2025
2e78887
Merge branch 'master' into enhance_update_memory
Wendong-Fan Oct 25, 2025
78777ed
Update chat_agent.py
fengju0213 Oct 28, 2025
331ae1a
update
fengju0213 Oct 28, 2025
874ab7b
Update handle_token_limit.py
fengju0213 Oct 28, 2025
12ea90f
Merge branch 'master' into enhance_update_memory
fengju0213 Oct 28, 2025
b02cae9
update
fengju0213 Oct 29, 2025
44451e0
Update chat_agent.py
fengju0213 Oct 29, 2025
e054d19
Update chat_agent.py
fengju0213 Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
860 changes: 659 additions & 201 deletions camel/agents/chat_agent.py

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions camel/memories/agent_memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ def clean_tool_calls(self) -> None:
# Save the modified records back to storage
self._chat_history_block.storage.save(record_dicts)

def pop_records(self, count: int) -> List[MemoryRecord]:
r"""Removes the most recent records from chat history memory."""
return self._chat_history_block.pop_records(count)

def remove_records_by_indices(
self, indices: List[int]
) -> List[MemoryRecord]:
r"""Removes records at specified indices from chat history memory."""
return self._chat_history_block.remove_records_by_indices(indices)


class VectorDBMemory(AgentMemory):
r"""An agent memory wrapper of :obj:`VectorDBBlock`. This memory queries
Expand Down Expand Up @@ -193,6 +203,20 @@ def clear(self) -> None:
r"""Removes all records from the vector database memory."""
self._vectordb_block.clear()

def pop_records(self, count: int) -> List[MemoryRecord]:
r"""Rolling back is unsupported for vector database memory."""
raise NotImplementedError(
"VectorDBMemory does not support removing historical records."
)

def remove_records_by_indices(
self, indices: List[int]
) -> List[MemoryRecord]:
r"""Removing by indices is unsupported for vector database memory."""
raise NotImplementedError(
"VectorDBMemory does not support removing records by indices."
)


class LongtermAgentMemory(AgentMemory):
r"""An implementation of the :obj:`AgentMemory` abstract base class for
Expand Down Expand Up @@ -277,3 +301,13 @@ def clear(self) -> None:
r"""Removes all records from the memory."""
self.chat_history_block.clear()
self.vector_db_block.clear()

def pop_records(self, count: int) -> List[MemoryRecord]:
r"""Removes recent chat history records while leaving vector memory."""
return self.chat_history_block.pop_records(count)

def remove_records_by_indices(
self, indices: List[int]
) -> List[MemoryRecord]:
r"""Removes records at specified indices from chat history."""
return self.chat_history_block.remove_records_by_indices(indices)
26 changes: 26 additions & 0 deletions camel/memories/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,32 @@ def write_record(self, record: MemoryRecord) -> None:
"""
self.write_records([record])

def pop_records(self, count: int) -> List[MemoryRecord]:
r"""Removes records from the memory and returns the removed records.
Args:
count (int): Number of records to remove.
Returns:
List[MemoryRecord]: The records that were removed from the memory
in their original order.
"""
raise NotImplementedError

def remove_records_by_indices(
self, indices: List[int]
) -> List[MemoryRecord]:
r"""Removes records at specified indices from the memory.
Args:
indices (List[int]): List of indices to remove. Indices should be
valid positions in the current record list.
Returns:
List[MemoryRecord]: The removed records in their original order.
"""
raise NotImplementedError

@abstractmethod
def clear(self) -> None:
r"""Clears all messages from the memory."""
Expand Down
115 changes: 115 additions & 0 deletions camel/memories/blocks/chat_history_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,118 @@ def write_records(self, records: List[MemoryRecord]) -> None:
def clear(self) -> None:
r"""Clears all chat messages from the memory."""
self.storage.clear()

def pop_records(self, count: int) -> List[MemoryRecord]:
r"""Removes the most recent records from the memory.

Args:
count (int): Number of records to remove from the end of the
conversation history. A value of 0 results in no changes.

Returns:
List[MemoryRecord]: The removed records in chronological order.
"""
if not isinstance(count, int):
raise TypeError("`count` must be an integer.")
if count < 0:
raise ValueError("`count` must be non-negative.")
if count == 0:
return []

record_dicts = self.storage.load()
if not record_dicts:
return []

# Preserve initial system/developer instruction if present.
protected_prefix = (
1
if (
record_dicts
and record_dicts[0]['role_at_backend']
in {
OpenAIBackendRole.SYSTEM.value,
OpenAIBackendRole.DEVELOPER.value,
}
)
else 0
)

removable_count = max(len(record_dicts) - protected_prefix, 0)
if removable_count == 0:
return []

pop_count = min(count, removable_count)
split_index = len(record_dicts) - pop_count

popped_dicts = record_dicts[split_index:]
remaining_dicts = record_dicts[:split_index]

self.storage.clear()
if remaining_dicts:
self.storage.save(remaining_dicts)

return [MemoryRecord.from_dict(record) for record in popped_dicts]

def remove_records_by_indices(
self, indices: List[int]
) -> List[MemoryRecord]:
r"""Removes records at specified indices from the memory.

Args:
indices (List[int]): List of indices to remove. Indices are
positions in the current record list (0-based).
System/developer messages at index 0 are protected and will
not be removed.

Returns:
List[MemoryRecord]: The removed records in their original order.
"""
if not indices:
return []

record_dicts = self.storage.load()
if not record_dicts:
return []

# Preserve initial system/developer instruction if present.
protected_prefix = (
1
if (
record_dicts
and record_dicts[0]['role_at_backend']
in {
OpenAIBackendRole.SYSTEM.value,
OpenAIBackendRole.DEVELOPER.value,
}
)
else 0
)

# Filter out protected indices and invalid ones
valid_indices = sorted(
{
idx
for idx in indices
if idx >= protected_prefix and idx < len(record_dicts)
}
)

if not valid_indices:
return []

# Extract records to remove (in original order)
removed_records = [record_dicts[idx] for idx in valid_indices]

# Build remaining records by excluding removed indices
remaining_dicts = [
record
for idx, record in enumerate(record_dicts)
if idx not in valid_indices
]

# Save back to storage
self.storage.clear()
if remaining_dicts:
self.storage.save(remaining_dicts)

return [MemoryRecord.from_dict(record) for record in removed_records]
Loading
Loading