llm_society: the composed society at LLM scale (C3) — loop, tests, smoke green
E11 re-instantiated in a population of LoRA agents, closing the paper's stated gap before submission (GG: a weeks-scale experiment a reviewer would demand). One grounding knob in the evaluation channel (g*verifier + (1-g)*conformity, exactly E11); inheritance is identical in all arms and deliberately ungrounded (children distilled from their source's own answers - self-consumption made literal). Directed sex = complementary pairing + Dirichlet offspring screened on the arm's own signal (the verifier never enters the no_grounding loop); QD selection on verifier-free behavioural distance; terminal-degeneration fallback copies the parent instead of crashing a sweep. Pure operators unit-tested (155 green); smoke run end-to-end on the local A4000 already shows the self-consumption signature (conformity up, diversity down in one generation). Design, falsifiers, cost table: tasks/workorder-llm-society.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
parent
d75c58474a
commit
9b0ca32f51
8 changed files with 531 additions and 1 deletions
|
|
@ -138,3 +138,62 @@ def test_lora_delta_inner_matches_brute_force():
|
|||
A2, B2 = torch.randn(4, 20, generator=g), torch.randn(12, 4, generator=g)
|
||||
brute = float(((B1 @ A1) * (B2 @ A2)).sum())
|
||||
assert abs(lora_delta_inner(A1, B1, A2, B2) - brute) < 1e-3
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- society (pure operators)
|
||||
|
||||
|
||||
def test_society_consensus_is_modal_and_deterministic():
|
||||
from llm.society import consensus_answers
|
||||
|
||||
outs = [["5", "cat", "[1, 2]"],
|
||||
["5", "dog", "[1, 2]"],
|
||||
["7", "dog", "[2, 1]"]]
|
||||
cons = consensus_answers(outs)
|
||||
assert cons[0] == "5" and cons[1] == "dog" and cons[2] == "[1, 2]"
|
||||
# a full three-way tie breaks lexicographically (deterministic)
|
||||
tie = consensus_answers([["a"], ["b"], ["c"]])
|
||||
assert tie == ["a"]
|
||||
|
||||
|
||||
def test_society_conformity_and_distance():
|
||||
from llm.society import behavioural_distance, conformity_scores, consensus_answers
|
||||
|
||||
outs = [["5", "dog"], ["5", "dog"], ["7", "cat"]]
|
||||
cons = consensus_answers(outs)
|
||||
conf = conformity_scores(outs, cons)
|
||||
assert conf[0] == conf[1] == 1.0 and conf[2] == 0.0 # majority conforms, dissenter does not
|
||||
d = behavioural_distance(outs)
|
||||
assert d[0, 1] == 0.0 and d[0, 2] == 1.0 and np.allclose(d, d.T)
|
||||
|
||||
|
||||
def test_society_selection_greedy_vs_quality_diversity():
|
||||
from llm.society import select_parents
|
||||
|
||||
scores = np.array([1.0, 0.95, 0.94, 0.1])
|
||||
# agents 0 and 1 are behavioural clones; agent 2 is distant from both
|
||||
d = np.zeros((4, 4))
|
||||
d[0, 2] = d[2, 0] = d[1, 2] = d[2, 1] = 1.0
|
||||
d[0, 3] = d[3, 0] = d[1, 3] = d[3, 1] = d[2, 3] = d[3, 2] = 1.0
|
||||
greedy = select_parents(scores, d, 2, diversity=False)
|
||||
assert greedy == [0, 1] # pure score: takes the clones
|
||||
qd = select_parents(scores, d, 2, diversity=True, lam=0.3)
|
||||
assert qd == [0, 2] # QD: prefers the distant near-peer
|
||||
|
||||
|
||||
def test_society_pairs_and_arms():
|
||||
import pytest
|
||||
|
||||
from llm.society import arm_settings, complementary_pairs
|
||||
|
||||
d = np.zeros((4, 4))
|
||||
d[0, 1] = d[1, 0] = 0.9
|
||||
d[0, 2] = d[2, 0] = 0.2
|
||||
d[1, 2] = d[2, 1] = 0.5
|
||||
pairs = complementary_pairs([0, 1, 2], d, 4)
|
||||
assert pairs[0] == (0, 1) and pairs[1] == (1, 2) # most-complementary pair breeds first
|
||||
assert len(pairs) == 4 and pairs[3] == pairs[0] # cycles to fill the slots
|
||||
assert arm_settings("no_grounding", 0.5)["g"] == 0.0
|
||||
assert arm_settings("no_sex", 0.5) == {"g": 0.5, "sex": False, "diversity": True}
|
||||
with pytest.raises(ValueError):
|
||||
arm_settings("bogus", 0.5)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue