This code marks the implementation part of the master thesis "Generative agents for simulation of social behaviour".
This library provides framework for using generative agents to simulate social behavior of groups and individuals. It is designed to enhance traditional rule-based agent paradigms with large language models, enabling the creation of agents with memory, implicit action selection mechanisms and reasoning capabilities.
- Generative Agents: Create agents with memory and reasoning capabilities.
- Social Behavior Simulation: Simulate communication in small groups.
- Individual Behavior Prediction: Simulate decision processes and predict agent behavior for economic experiments and other scenarios.
- Experimentation: Run experiments with real-world data based on sociological surveys.
- Python 3.13 or higher
This example uses uv, an extremely fast python package manager, but feel free to use your favorite as pip etc.
-
Create and activate a virtual environment:
uv venv venv --seed source venv/bin/activate -
Install the library:
-
For editable mode (development):
uv pip install -e . -
For regular installation:
uv pip install .
-
-
Install dependencies for experiments:
uv pip install -e .[dev]
-
Install sentence-transformers for local embedding support (optional):
uv pip install .[embedding]
- Environment Variables: Optionally, configure environment variables in the
.envfile to match the naming used in your experiments. This is only required for running the example experiments.
You can run a sample experiment using the following command:
python experiments/valentine_party.pySample experiments are located in the experiments directory.
You can override the default provided prompts from the model by subclassing the DefaultPromptBuilder, replacing the methods and overriding the config by provided decorator.
from generative_agents import DefaultPromptBuilder, default_builder
class CustomPromptBuilder(DefaultPromptBuilder):
...
@default_builder.override(CustomPromptBuilder())
async def main():
...
with default_builder.override(CustomPromptBuilder()):
...The framework provides three parameter sets out of the box:
factual_llm_params- lower temperature (0.3) for deterministic, factual responsesneutral_default_llm_params- balanced temperature (0.6) for general usecreative_llm_params- higher temperature (1.0) for creative generation
You can customize them in several ways, from most to least convenient:
Pass custom params when constructing DefaultConfig (or its subclass):
from generative_agents import DefaultConfig, create_completion_params
config = DefaultConfig(
creative_llm_params=create_completion_params(temperature=0.8, top_p=0.95),
factual_llm_params=create_completion_params(temperature=0.4),
)Override the global config for a scoped block:
from generative_agents import default_config, DefaultConfig, create_completion_params
custom_config = DefaultConfig(
creative_llm_params=create_completion_params(temperature=0.9)
)
with default_config.override(custom_config):
# All agents created here use the overridden params
agent = LLMConversationAgent(...)Create a subclass to set custom defaults:
from generative_agents import DefaultConfig, create_completion_params
class WarmCreativeConfig(DefaultConfig):
def __init__(self):
super().__init__(
creative_llm_params=create_completion_params(
temperature=0.9, top_p=1.0, frequency_penalty=0.5
),
)Then override using OverridableContextVar.
Modify parameters on an existing instance:
from generative_agents import default_config, create_completion_params
# Access current parameters
current_creative = default_config().creative_llm_params
current_factual = default_config().factual_llm_params
# Modify parameters directly
default_config().creative_llm_params = create_completion_params(
temperature=0.5, top_p=1.0
)The valentine_party.py experiment demonstrates how information spreads through a social network of generative agents. Below is a simplified walkthrough of the key concepts.
Other experiments are defined in experiments/ folder.
Subclass AgentModelBase to define the attributes of your agents:
from generative_agents import AgentModelBase
from pydantic import Field
from typing import Literal
class ExperimentAgent(AgentModelBase):
first_name: str = Field(..., description="First name")
last_name: str = Field(..., description="Last name")
sex: Literal["F", "M"] = Field(..., description="Sex")
description: str = Field(..., description="Agent characteristics and description")
@property
def full_name(self) -> str:
return f"{self.first_name} {self.last_name}"The backend handles all LLM and embedding calls:
from generative_agents import LLMBackend, OpenAIEmbeddingProvider
from openai import AsyncOpenAI
client = AsyncOpenAI(api_key="...")
context = LLMBackend(
client=client,
model="...",
RPS=10,
embedding_provider=OpenAIEmbeddingProvider(client=client, model="..."),
)Agents can be composed with multiple behaviors such as memory updating, BDI planning, and memory forgetting:
from generative_agents import (
CompositeBehaviorMemoryManager,
ConversationMemoryUpdatingBehavior,
BDIPlanningBehavior,
ConversationMemoryForgettingBehavior,
EmbeddingMemory,
get_record_removal_linear_probability,
mean_std_count_strategy_factory,
)
behaviors = [
ConversationMemoryUpdatingBehavior(),
BDIPlanningBehavior(),
ConversationMemoryForgettingBehavior(
get_record_removal_linear_probability(0.5), seed=seed
),
]
agent = LLMConversationAgent(
data,
context,
lambda agent: CompositeBehaviorMemoryManager(
EmbeddingMemory(context, count_selector=mean_std_count_strategy_factory(0.5)),
agent,
context,
behaviors,
),
)Use networkx to define the social graph that determines who can talk to whom:
import networkx as nx
graph = nx.Graph()
graph.add_edges_from([(agent_a, agent_b), (agent_b, agent_c)])Use ConversationManager and a conversation selector to drive the simulation:
from generative_agents import ConversationManager, SequentialConversationSelector
selector = SequentialConversationSelector(structure=graph, seed=seed, initial_conversation=[(agent_a, agent_b)])
manager = ConversationManager(conversation_selector=selector, max_conversation_utterances=4)
for epoch in range(2):
await manager.run_simulation_epoch()
# Query agents afterward
answer = await agent.ask_agent("When is the party happening?")This project is licensed under the MIT License. See the LICENSE file for details.
For any questions or suggestions, please open an issue or contact the maintainers.
