Skip to main content

Discourse Simulator

LLM-augmented Agent-Based Social Simulation for modelling public discourse dynamics following a critical real-world event.

Agents observe live news, reason about it, post to a simulated social network, and update multidimensional beliefs through peer influence and news salience, all powered by a local Ollama LLM.


Installation

1. Install discourse-sim

pip install discourse-sim

2. Install Ollama

discourse_sim runs LLMs locally via Ollama. You need to install it separately.

macOS

brew install ollama

Or download the desktop app from ollama.com/download.

Linux

curl -fsSL https://ollama.com/install.sh | sh

Windows

Download and run the installer from ollama.com/download.

3. Start the Ollama server

ollama serve

On macOS with the desktop app, this starts automatically. On Linux/Windows you may need to run this in a separate terminal or set it up as a service.

4. Pull the default model

ollama pull mistral:7b-instruct-q4_0

This is the default model (~4 GB). You can use any other Ollama model by passing ollama_model="..." to DiscourseSimulation.

Lighter alternatives (if disk space is limited):

ollama pull mistral          # ~4 GB  - good balance
ollama pull llama3.2         # ~2 GB  - faster, slightly less capable
ollama pull phi3             # ~2 GB  - Microsoft, very efficient

5. Verify everything works

ollama run mistral:7b-instruct-q4_0 "Hello"

You should see a response. If you do, you are ready to run simulations.

All dependencies: (make sure if everything is installed correctly)

pip install langchain-core langchain-community langchain-ollama \
            duckduckgo-search networkx numpy tqdm pandas openpyxl

Quick Start

from discourse_sim import DiscourseSimulation

sim = DiscourseSimulation(
    critical_event=(
        "In late April 2025, Dublin saw a large anti-immigration march "
        "from the Garden of Remembrance to the Custom House, with thousands "
        "protesting immigration levels and housing pressure..."
    ),
    event_date="2025-04-26",
    topic="immigration in Ireland",
    n_agents=100,
    n_days=15,
)

sim.run()
df = sim.to_dataframe()   # one row per agent per day
df.to_excel("output.xlsx", index=False)

All Parameters

Required

Parameter Type Description
critical_event str Plain-text description of the event injected into every agent prompt on every day
event_date str ISO date "YYYY-MM-DD" - this becomes Day 0
topic str Subject domain, e.g. "immigration in Ireland". Anchors search queries and scoring prompts

Agent Population

Parameter Type Default Description
n_agents int 100 Number of synthetic agents
n_days int 15 Simulation duration in days
agent_distribution dict Ireland 2025 empirical split Proportions of each agent kind - must sum to 1.0
kind_priors dict DEFAULT_KIND_PRIORS Prior distributions for belief/attitude initialisation per kind

Default distribution (Ireland 2025):

{"centrist": 0.45, "far_right": 0.20, "pro_imm": 0.25, "media": 0.10}

Timeline

Parameter Type Default Description
timeline dict[int, str] None Optional explicit daily news entries keyed by 0-based day index. Missing days auto-generated. If None, all days use live search.

Example:

timeline={
    0: "[VERIFIED] The march took place at the Garden of Remembrance...",
    4: "[VERIFIED] Government announced a deportation flight...",
}

Any day not in the dict falls back to an auto-generated entry. Agents search live news on every day regardless of timeline.

LLM & Network

Parameter Type Default Description
ollama_model str "mistral:7b-instruct-q4_0" Any locally pulled Ollama model
temperature float 0.75 Post generation temperature
use_llm_scoring bool True If False, uses keyword heuristic for attitude scoring
network_k int 6 Watts-Strogatz nearest-neighbour count
network_p float 0.3 Watts-Strogatz rewiring probability
network_seed int 42 Reproducibility seed for network and agents

Belief Update Keywords

Parameter Type Default Description
threat_keywords list[str] See config.py Words in daily news that trigger security_threat_belief increase and exposure accumulation
humanitarian_keywords list[str] See config.py Words that trigger humanitarian_belief increase

Override these when simulating non-immigration topics:

threat_keywords=["eviction", "homeless", "unaffordable", "crisis"],
humanitarian_keywords=["social housing", "rights", "family", "support"],

Outputs

sim.run()

# Single DataFrame - one row per agent per day (recommended for analysis)
df = sim.to_dataframe()

# All three DataFrames
dfs = sim.to_dataframes()
dfs["history"]   # one row per timestep - aggregate metrics
dfs["agents"]    # one row per agent per timestep - full belief state
dfs["messages"]  # one row per agent per timestep - posts + beliefs merged

Column reference - df_messages

Column Description
t / date Day index and calendar date
agent_id / kind / quirk Agent identity
message The generated social media post
interpreted_score LLM-scored stance [-1, +1]
attitude Agent attitude at end of day t
mood Agent mood at end of day t
exposure Cumulative threat narrative exposure
economic_threat_belief Economic threat sub-belief
cultural_threat_belief Cultural threat sub-belief
security_threat_belief Security threat sub-belief
humanitarian_belief Humanitarian weight sub-belief
avg_attitude Population mean attitude that day
polarization Mean edge-level attitude divergence
news_summary First 120 chars of daily news entry

Custom Agent Kinds

Add any agent kind by extending DEFAULT_KIND_PRIORS:

from discourse_sim import DiscourseSimulation
from discourse_sim.config import DEFAULT_KIND_PRIORS

custom_priors = {
    **DEFAULT_KIND_PRIORS,
    "nationalist": {
        "attitude":        (0.55, 0.95),
        "economic_threat": (0.2,  0.6),
        "cultural_threat": (0.7,  1.0),
        "humanitarian":    (-0.6, 0.0),
        "openness":        (0.1,  0.35),
        "emotional_react": (0.5,  0.85),
    },
}

sim = DiscourseSimulation(
    ...,
    agent_distribution={"centrist": 0.35, "nationalist": 0.30, "pro_imm": 0.35},
    kind_priors=custom_priors,
)

Architecture

discourse_sim/
├── __init__.py          # Public API: DiscourseSimulation
├── core.py              # DiscourseSimulation class - orchestrator
├── config.py            # SimConfig dataclass - all parameters + validation
├── agents/
│   └── agent.py         # Agent dataclass + make_agents() factory
├── tools/
│   └── search_tools.py  # make_tools() - search, memory, sentiment
├── timeline/
│   └── timeline.py      # Timeline class - user-supplied + auto-generated
├── simulation/
│   └── engine.py        # generate_message(), score_message(), update_beliefs(), run_loop()
└── utils/
    └── dataframes.py    # build_dataframes() - history/agents/messages

Per-day flow for each agent:

OBSERVE  →  search_event_news(query)          # live DuckDuckGo
         →  recall_agent_memory(posts_json)   # last 5 posts

THINK    →  build prompt: event + profile + memory + search result + today's news

ACT      →  LLM call → post text (max 40 words)

SCORE    →  LLM call (temp=0.0) → float in [-1, +1]

UPDATE   →  news salience → sub-beliefs
         →  peer pull     → attitude pressure
         →  mood shock    → affective state
         →  inertia       → resistance to change
         →  composite     → attitude(t)

Examples

File Description
examples/dublin_march.py Full reproduction of the original Dublin April 2025 experiment
examples/minimal_usage.py Minimal usage - no timeline, live search only
examples/custom_agent_kinds.py Adding a custom nationalist kind with its own priors

Citation

If you use this package in research, please cite:

@software{discourse_sim,
  title  = {discourse\_sim: LLM-Augmented Agent-Based Social Simulation of Discourse Dynamics},
  author = {dreji18},
  year   = {2026},
  note   = {Python package}
}

Metadata

Release files for discourse-sim 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for discourse-sim 0.1.1
File Size Uploaded Provenance
discourse_sim-0.1.1.tar.gz 26.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for discourse-sim 0.1.1
File Interpreter ABI Platform
discourse_sim-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 51.7 kB

Release files / discourse_sim-0.1.1.tar.gz

Download URL discourse_sim-0.1.1.tar.gz
Size 26.9 kB
Tags Source
SHA-256 checksum
How to use checksums
da51c607483d0178e263400f9fdebcca10cce2f286d303f6d42e0b646f59c74b
BLAKE2b-256 checksum
How to use checksums
2511a237d15e44503878c941f7b2bf15cdc34633d2acc5f549a54dc51e25449d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Release files / discourse_sim-0.1.1-py3-none-any.whl

Download URL discourse_sim-0.1.1-py3-none-any.whl
Size 24.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
88bb66bd267a530881e9c335c3aadaf4fdaa7b5d1e2526c13e7a3b2a68cd1af1
BLAKE2b-256 checksum
How to use checksums
d05d05975c9eab98e15e966c86f88d7272c83e201c7c3bc32dc56f5b675ad335
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Security for discourse-sim 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page