LLM 接入与干跑¶
在 SocioVerse 里,LLM 只坐在一个位置:决策模型。
decide_batch(observations, memories) 是计算 B = f(P, E) 的地方,
这个计算是规则、统计模型还是批式 LLM 调用,由研究自己选择。其余一切——
环境、人群、存储、报告——两种方式下完全相同地运行。
配置¶
LLM 驱动的决策模型从环境变量读取设置(经由 gitignore 的 .env):
| 变量 | 含义 |
|---|---|
SV_LLM_API_KEY |
主 API key(OPENAI_API_KEY 作为备选) |
SV_LLM_BASE_URL |
可选的端点覆写——任何 OpenAI 兼容网关 |
SV_LLM_MODEL |
可选的模型选择 |
批式调用是契约¶
decide_batch 一次接收该步(或该分组——Persona.group_key 定义批处理
分组)的全部观察。一个行为良好的 LLM 决策模型会:
- 把每个观察的四象限视图渲染进 prompt
(
Observation.rendered是放置备好文本的惯例位置); - 以 agent 的
AgentMemory(它自己过往行为的滚动窗口)为条件—— 「我已经搬过两次家了,这次留下」; - 发起批式调用,绝不每个 agent 每步一个请求;
- 返回类型化的
Action,让apply()能折回 E。
确定性干跑¶
你应当能在不花一个 token 的情况下验证全部管线——循环、产物、存储、 指标。两种等价做法:
规则式决策模型(随仓库提供的从零模板就是这样):决策是观察的纯函数, 运行结果由种子完全复现。
确定性替身客户端:保留你的 LLM 决策模型,但注入一个 complete()
是输入的固定函数的客户端。最小的替身:
class DeterministicLLMClient:
"""替代真实客户端:同输入 → 同输出,不走网络。"""
def complete(self, prompt: str, **kwargs) -> str:
# 选一个稳定、无聊的策略——例如永远选第一个选项
return "stay"
在决策模型接收客户端的地方注入它(simulation/simulation.json 的
decision_args 是这类接线的惯例位置)。包装遗留引擎的内置研究会自带
各自的确定性客户端,用途正是于此——查阅对应研究的 README。
干跑也是仓库一致性测试(parity test)的工作方式:包装遗留引擎的研究 断言自己在同一种子下复现原版轨迹,确定性客户端消除了唯一的非确定性来源。
关于可复现性,诚实地说¶
真实 LLM 运行不可复现
真实 LLM 调用在非零温度下采样:同一研究连跑两次结果会不同。 可复现的对象是:(a) 干跑——端到端由种子决定;(b) 任何已记录的 运行——它的面板存储是永久的,而且热启动的迭代 会精确回放已存储的行为,而不是重新询问 LLM。
成本控制¶
/sv-run在花钱之前展示运行配置并要求确认——花费闸门。- 迭代产物时优先用干跑;每个有意义的配置只上线跑一次。
- 热启动通过回放继承父版本的
0..K步(零 LLM),只为新步数花钱。