Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
emmanuel-ferdman authored Nov 6, 2024
2 parents 9fa06fd + d5d46f9 commit 3edfe70
Show file tree
Hide file tree
Showing 58 changed files with 3,443 additions and 511 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,21 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/).

## [1.8.3] - 2024-10-19
## [1.8.6] - 2024-10-29

### Added

- Add ability to save and load rational and basic agents to/from json.
- Add a version of agent development colab that uses GCP hosted model


## [1.8.5] - 2024-10-21

### Fixed

- Fix together.ai wrapper choice sampling procedure

## [1.8.4] - 2024-10-19

### Changed

Expand Down
8 changes: 8 additions & 0 deletions concordia/agents/entity_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ def get_component(
component = self._context_components[name]
return cast(entity_component.ComponentT, component)

def get_act_component(self) -> entity_component.ActingComponent:
return self._act_component

def get_all_context_components(
self,
) -> Mapping[str, entity_component.ContextComponent]:
return types.MappingProxyType(self._context_components)

def _parallel_call_(
self,
method_name: str,
Expand Down
8 changes: 8 additions & 0 deletions concordia/agents/entity_agent_with_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
"""A modular entity agent using the new component system with side logging."""

from collections.abc import Mapping
import copy
import types
from typing import Any
from absl import logging
from concordia.agents import entity_agent
from concordia.associative_memory import formative_memories
from concordia.typing import agent
from concordia.typing import entity_component
from concordia.utils import measurements as measurements_lib
Expand All @@ -39,6 +41,7 @@ def __init__(
types.MappingProxyType({})
),
component_logging: measurements_lib.Measurements | None = None,
config: formative_memories.AgentConfig | None = None,
):
"""Initializes the agent.
Expand All @@ -56,6 +59,7 @@ def __init__(
None, a NoOpContextProcessor will be used.
context_components: The ContextComponents that will be used by the agent.
component_logging: The channels where components publish events.
config: The agent configuration, used for checkpointing and debug.
"""
super().__init__(agent_name=agent_name,
act_component=act_component,
Expand All @@ -75,6 +79,7 @@ def __init__(
on_error=lambda e: logging.error('Error in component logging: %s', e))
else:
self._channel_names = []
self._config = copy.deepcopy(config)

def _set_log(self, log: tuple[Any, ...]) -> None:
"""Set the logging object to return from get_last_log.
Expand All @@ -89,3 +94,6 @@ def _set_log(self, log: tuple[Any, ...]) -> None:
def get_last_log(self):
self._tick.on_next(None) # Trigger the logging.
return self._log

def get_config(self) -> formative_memories.AgentConfig | None:
return copy.deepcopy(self._config)
37 changes: 37 additions & 0 deletions concordia/associative_memory/associative_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
import threading

from concordia.associative_memory import importance_function
from concordia.typing import entity_component
import numpy as np
import pandas as pd


_NUM_TO_RETRIEVE_TO_CONTEXTUALIZE_IMPORTANCE = 25


Expand Down Expand Up @@ -79,6 +81,29 @@ def __init__(
self._interval = clock_step_size
self._stored_hashes = set()

def get_state(self) -> entity_component.ComponentState:
"""Converts the AssociativeMemory to a dictionary."""

with self._memory_bank_lock:
output = {
'seed': self._seed,
'stored_hashes': list(self._stored_hashes),
'memory_bank': self._memory_bank.to_json(),
}
if self._interval:
output['interval'] = self._interval.total_seconds()
return output

def set_state(self, state: entity_component.ComponentState) -> None:
"""Sets the AssociativeMemory from a dictionary."""

with self._memory_bank_lock:
self._seed = state['seed']
self._stored_hashes = set(state['stored_hashes'])
self._memory_bank = pd.read_json(state['memory_bank'])
if 'interval' in state:
self._interval = datetime.timedelta(seconds=state['interval'])

def add(
self,
text: str,
Expand Down Expand Up @@ -434,3 +459,15 @@ def set_num_to_retrieve_to_contextualize_importance(
importance.
"""
self._num_to_retrieve_to_contextualize_importance = num_to_retrieve

def get_all_memories_as_text(
self,
add_time: bool = True,
sort_by_time: bool = True,
) -> Sequence[str]:
"""Returns all memories in the memory bank as a sequence of strings."""
memories_data_frame = self.get_data_frame()
texts = self._pd_to_text(memories_data_frame,
add_time=add_time,
sort_by_time=sort_by_time)
return texts
19 changes: 17 additions & 2 deletions concordia/associative_memory/formative_memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

"""This is a factory for generating memories for concordia agents."""

from collections.abc import Callable, Iterable, Sequence
from collections.abc import Callable, Collection, Sequence
import dataclasses
import datetime
import logging
Expand Down Expand Up @@ -58,9 +58,24 @@ class AgentConfig:
specific_memories: str = ''
goal: str = ''
date_of_birth: datetime.datetime = DEFAULT_DOB
formative_ages: Iterable[int] = DEFAULT_FORMATIVE_AGES
formative_ages: Collection[int] = DEFAULT_FORMATIVE_AGES
extras: dict[str, Any] = dataclasses.field(default_factory=dict)

def to_dict(self) -> dict[str, Any]:
"""Converts the AgentConfig to a dictionary."""
result = dataclasses.asdict(self)
result['date_of_birth'] = self.date_of_birth.isoformat()
return result

@classmethod
def from_dict(cls, data: dict[str, Any]) -> 'AgentConfig':
"""Initializes an AgentConfig from a dictionary."""
date_of_birth = datetime.datetime.fromisoformat(
data['date_of_birth']
)
data = data | {'date_of_birth': date_of_birth}
return cls(**data)


class FormativeMemoryFactory:
"""Generator of formative memories."""
Expand Down
11 changes: 10 additions & 1 deletion concordia/components/agent/action_spec_ignored.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

import abc
import threading
from typing import Final
from typing import Final, Any

from concordia.typing import entity as entity_lib
from concordia.typing import entity_component
from typing_extensions import override


class ActionSpecIgnored(
Expand Down Expand Up @@ -89,3 +90,11 @@ def get_named_component_pre_act_value(self, component_name: str) -> str:
"""Returns the pre-act value of a named component of the parent entity."""
return self.get_entity().get_component(
component_name, type_=ActionSpecIgnored).get_pre_act_value()

@override
def set_state(self, state: entity_component.ComponentState) -> Any:
return None

@override
def get_state(self) -> entity_component.ComponentState:
return {}
5 changes: 2 additions & 3 deletions concordia/components/agent/all_similar_memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""Return all memories similar to a prompt and filter them for relevance.
"""
"""Return all memories similar to a prompt and filter them for relevance."""

from collections.abc import Mapping
import types
from typing import Mapping

from concordia.components.agent import action_spec_ignored
from concordia.components.agent import memory_component
Expand Down
8 changes: 8 additions & 0 deletions concordia/components/agent/concat_act_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,11 @@ def _log(self,
'Value': result,
'Prompt': prompt.view().text().splitlines(),
})

def get_state(self) -> entity_component.ComponentState:
"""Converts the component to a dictionary."""
return {}

def set_state(self, state: entity_component.ComponentState) -> None:
pass

29 changes: 29 additions & 0 deletions concordia/components/agent/memory_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from concordia.typing import entity_component
from concordia.typing import memory as memory_lib
import pandas as pd


DEFAULT_MEMORY_COMPONENT_NAME = '__memory__'

Expand Down Expand Up @@ -57,6 +59,14 @@ def _check_phase(self) -> None:
'You can only access the memory outside of the `UPDATE` phase.'
)

def get_state(self) -> Mapping[str, Any]:
with self._lock:
return self._memory.get_state()

def set_state(self, state: Mapping[str, Any]) -> None:
with self._lock:
self._memory.set_state(state)

def retrieve(
self,
query: str = '',
Expand Down Expand Up @@ -102,3 +112,22 @@ def update(
for mem in self._buffer:
self._memory.add(mem['text'], mem['metadata'])
self._buffer = []

def get_raw_memory(self) -> pd.DataFrame:
"""Returns the raw memory as a pandas dataframe."""
self._check_phase()
with self._lock:
return self._memory.get_data_frame()

def get_all_memories_as_text(
self,
add_time: bool = True,
sort_by_time: bool = True,
) -> Sequence[str]:
"""Returns all memories in the memory bank as a sequence of strings."""
self._check_phase()
with self._lock:
texts = self._memory.get_all_memories_as_text(
add_time=add_time,
sort_by_time=sort_by_time)
return texts
1 change: 0 additions & 1 deletion concordia/components/agent/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ def _make_pre_act_value(self) -> str:
time_until=self._clock_now(),
add_time=True,
)
# removes memories that are not observations
mems = memory.retrieve(scoring_fn=interval_scorer)
# Remove memories that are not observations.
mems = [mem.text for mem in mems if '[observation]' in mem.text]
Expand Down
12 changes: 12 additions & 0 deletions concordia/components/agent/person_representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,15 @@ def _make_pre_act_value(self) -> str:
})

return result

def get_state(self) -> entity_component.ComponentState:
"""Converts the component to JSON data."""
with self._lock:
return {
'names_detected': self._names_detected,
}

def set_state(self, state: entity_component.ComponentState) -> None:
"""Sets the component state from JSON data."""
with self._lock:
self._names_detected = state['names_detected']
12 changes: 12 additions & 0 deletions concordia/components/agent/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,15 @@ def _make_pre_act_value(self) -> str:
})

return result

def get_state(self) -> entity_component.ComponentState:
"""Converts the component to JSON data."""
with self._lock:
return {
'current_plan': self._current_plan,
}

def set_state(self, state: entity_component.ComponentState) -> None:
"""Sets the component state from JSON data."""
with self._lock:
self._current_plan = state['current_plan']
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ def pre_act(
def update(self) -> None:
self._component.update()

def get_state(self) -> entity_component.ComponentState:
return self._component.get_state()

def set_state(self, state: entity_component.ComponentState) -> None:
self._component.set_state(state)


class Identity(QuestionOfQueryAssociatedMemories):
"""Identity component containing a few characteristics.
Expand Down
1 change: 1 addition & 0 deletions concordia/components/agent/question_of_recent_memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class AvailableOptionsPerception(QuestionOfRecentMemories):
"""This component answers the question 'what actions are available to me?'."""

def __init__(self, **kwargs):

super().__init__(
question=(
'Given the statements above, what actions are available to '
Expand Down
4 changes: 2 additions & 2 deletions concordia/components/game_master/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,9 @@ def update_after_event(
question=(
'In the above transcript, did any of the listed individuals '
'gain or lose any items on the list of item types? Make sure '
'to take into account items equivalent to the items on the list'
'to take into account items equivalent to the items on the list '
'e.g. if "money" is on the list but the event mentions "gold" '
'then treat "gold" as equivalent to "money" since gold is a type'
'then treat "gold" as equivalent to "money" since gold is a type '
'of money.'
)
)
Expand Down
Loading

0 comments on commit 3edfe70

Please sign in to comment.