跳转至

常见问题

安装与运行

试用需要 LLM API key 吗?

不需要。安装、测试、环境/人群构建、以及规则式决策的研究完全无 key 运行。 LLM 驱动的研究可以用确定性客户端 干跑。只有真实的 LLM 决策运行才需要 key。

有些测试跳过了,安装坏了吗?

没坏——依赖大型外部数据集的测试在数据缺失时自动跳过。 「有跳过、零失败」= 健康的安装。

必须用 Claude Code 吗?

只有 agentic 工作流(/sv-* skill)需要。 编程路径——写产物、 build_simulatorrun()、SQL——是纯 Python。

可以并行跑多个研究吗?

一个进程一个研究。 包装遗留引擎的研究可能 patch 模块全局量, 不是线程安全的。批量实验用独立进程(例如进程池),每个进程一个研究。

可以把 /sv-run 丢到后台,让 agent 继续干别的吗?

不可以。 /sv-run 必须在前台跑——发出命令、让它阻塞,上限约 10 分钟。 不要用 run_in_background、结尾 &nohup 把它包起来。

原因是结构性的:在 headless / 托管的 agent 里,后台任务结束时没有任何东西会 重新唤起 agent。运行完成在一片虚空里,agent 永远不知道它跑完了,整条流程就 这样静默卡住。前台阻塞的运行才会带着结果把控制权交回来。

如果某次运行确实需要超过这个上限:不要丢后台,而是把规模压下来(更少 agent、 更少步数),或者提前告知用户、由他决定。

一定要有事件服务或 user pool MCP 吗?

不需要。两者都是可选能力,且都会优雅降级:事件客户端会退到本地缓存、再退到 普通网络检索;persona 池不可用时退到「先锚定再合成」或用户自备的 persona 文件。 你损失的是便利和一部分锚定强度,而不是跑研究的能力。见 外部能力

本地跑和用托管服务有什么区别?

框架一样、产物一样。本地跑:LLM key 和可选服务端点都由你自己提供,机器也归你。 托管服务:LLM provider、事件服务、persona 池、以及一份配好中文字体的 matplotlib 都是现成接好的,运行与配额替你计量,dashboard 是服务出来的而不用自己起。见 托管服务

结果与可复现性

运行可以复现吗?

  • 干跑(规则式或确定性客户端):可以,精确复现——端到端由种子决定。
  • 真实 LLM 运行:不行——非零温度采样每次不同。但每次已记录的运行都 永久保存在它的 DuckDB 存储里,而且 热启动迭代精确回放 已存储的行为,不重新询问 LLM。

我的结果在哪里?里面有什么?

studies/<id>/trajectory/study.duckdb —— 表 panel(每个 agent 每步 一行)、metrics(每步一行)、events(触发的干预),若研究用了消息 总线还有 messages。旁边有 Parquet 导出。reports/report.md 是渲染版。

我改了产物重跑了一次,旧结果没了。为什么?

为新一次运行打开存储会替换它——这正是那条规则存在的原因:修改既有 研究要走 /sv-iterate,它的版本门会先把现行目录快照到 versions/vN/。凡在版本快照之下的内容永不删除。

图里的中文为什么变成方块了?

matplotlib 默认不带 CJK 字体,所以每个汉字都渲染成豆腐块(□□□)。 装一个中文字体并让 matplotlib 指过去:

# Debian/Ubuntu
sudo apt-get install fonts-noto-cjk
import matplotlib
matplotlib.rcParams["font.sans-serif"] = ["Noto Sans CJK SC"]
matplotlib.rcParams["axes.unicode_minus"] = False   # 负号也别变方块

刚装的字体如果 matplotlib 还看不见,清一下它的缓存 (rm -rf ~/.cache/matplotlib)。托管服务已预装并配好中文字体,图里的中文 开箱即正常。

可以直接查 DuckDB 存储吗?

可以——存储才是结果本身,报告只是它的一种渲染。study.duckdb 就是一个普通的 DuckDB 文件,用 CLI、Python API、或任何会说 DuckDB 的工具都能打开。表结构:

panel agent_idstepstate(JSON)、action_kindaction_payload(JSON)
metrics step 加上研究发出的每个指标各一列
events stepnote
messages(仅当用了消息总线) author_idsteproundchannelcontentaudience

stateaction_payload 是 JSON,里面的键是各研究自定的——照抄下面的 例子前,先去自己的 model.py 里确认字段名:

-- 在某个数值型 state 字段上,看谁在两步之间变化最大
WITH s AS (
  SELECT agent_id, step,
         CAST(state ->> '$.opinion' AS DOUBLE) AS opinion
  FROM panel WHERE step IN (0, 12)
)
SELECT a.agent_id,
       a.opinion AS opinion_t0,
       b.opinion AS opinion_t12,
       b.opinion - a.opinion AS delta
FROM s a JOIN s b USING (agent_id)
WHERE a.step = 0 AND b.step = 12
ORDER BY abs(delta) DESC
LIMIT 20;

-- 某一步里每个 agent 给出的理由
SELECT agent_id, action_kind, action_payload ->> '$.reason' AS reason
FROM panel WHERE step = 5 AND reason IS NOT NULL;

-- 行为构成随时间怎么变
SELECT step, action_kind, count(*) AS n
FROM panel GROUP BY step, action_kind ORDER BY step, n DESC;

-- 把指标和同一步触发的干预对齐起来看
SELECT m.*, e.note
FROM metrics m LEFT JOIN events e USING (step)
ORDER BY m.step;

旁边还有 Parquet 导出(panel.parquetmetrics.parquet)供 pandas / R 用。

概念

别的框架也能跑很多步,「纵向」特殊在哪?

人群是固定的、带持久 id 的,且每个 agent 每步记录一行面板数据—— 所以你能追踪个体轨迹,而不只是聚合曲线。横截面框架通常每次实验重新 抽样人群;这里同一批 agent 一直存在,这才是输出成为真正面板数据的原因。

LLM 到底在哪个位置?

只在一个接口里:DecisionModel.decide_batch。环境、人群、存储、报告 都不含 LLM。见 LLM 接入与干跑

是什么防止模型凭空编数字?

grounding 契约:承重数值要引用 grounding/grounding.json 里的事实或 声明的假设,而报告会把这份台账渲染在结果旁边。它是供审阅的溯源, 不是运行时校验器——见 真实世界锚定与溯源

扩展

我有自己的模拟器,能接进来吗?

能——那就是 Path C:把它包装到四个接口 后面(源码零改动),在固定种子上证明一致性,它就成为一个可路由、可 fork 的研究。

怎么接入我自己的数据(personas、环境数据源)?

人群:把 provider_ref 指向通用的 file.personas provider(带 agent_id 列的 CSV/Parquet),或实现你自己的 PopulationProvider。 环境数据源:声明为层的 source 并在构建时物化。外部服务能力注册表