PostHog Max AI 评估体系全解:CI、沙箱与离线 Evals 的工程实践指南
发布时间:2026/9/13 18:53:11 锦皓数字建站

PostHog Max AI 评估体系全解CI、沙箱与离线 Evals 的工程实践指南【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthogPostHog 仓库在ee/hogai/eval/目录下沉淀了一套完整的 AI 评估evals工程体系用于对 Max AIPostHog 的 AI 数据分析助手生成的 SQL、洞察、实验总结、票据摘要等输出进行系统性验证。本文以 ee/hogai/eval/README.md 为核心骨架结合仓库内 pytest 配置、评估基类、评分器scorers与沙箱 harness 源码完整讲解 CI evals、Sandboxed evals 与 Offline evals 三条评估路径的搭建、运行与结果解读方法帮助你理解 PostHog 如何用精选输入集 自动评分 平台追踪来验证提示词性能、发现回归并对比不同模型版本。一、什么是 AI evalsPostHog 的评估哲学PostHog 使用 AI 评估evals来针对一组经过精选的输入测试其 AI 输出。根据 ee/hogai/eval/README.md 的描述evals 让团队能够验证提示词prompt性能确认当前提示词在实际输入上的表现发现回归regressions在代码或模型升级后捕捉输出质量的退化对比不同模型版本在同一组用例上横向比较模型的能力差异。评估平台选用Braintrust。Braintrust 会记录每次评估的结果包括完整的LLM traces追踪——这既帮助团队宏观跟踪性能趋势也能在遇到问题时逐条深入排查单条用例的失败原因。提示文档中提到访问 Braintrust 平台或获取 API Key 需要向#team-posthog-ai频道申请这是内部协作约定外部贡献者按仓库内 CONTRIBUTING.md 的流程接入即可。从仓库结构看评估体系分三层组织目录职责ee/hogai/eval/ci/跑在 pytest 之上的 CI 评估用例数据多为内联或基于 Hedgebox 种子项目products/posthog_ai/eval_harness/沙箱化评估 harness运行真实 coding agentee/hogai/eval/offline/基于数据集的离线评估模块由 Dagster 流水线驱动二、CI evals基于 pytest 的快速回归CI evals 是整套体系中最轻量、最适合日常回归的路径本质上就是一个激活了特定配置的 pytest 测试目录。2.1 运行前置条件导出环境变量BRAINTRUST_API_KEY向#team-posthog-ai申请。运行全部 evalspytest ee/hogai/eval/ci关键点在于指定ee/hogai/eval/ci这个目录——它会激活评估专用的配置 ee/hogai/eval/pytest.ini2.2 激活的 pytest 专用配置指定目录后pytest 会加载 ee/hogai/eval/pytest.ini[pytest] python_files eval_*.py python_classes Eval* python_functions eval_* env DEBUG1 TEST1 IN_EVAL_TESTING1 DJANGO_SETTINGS_MODULE posthog.settings addopts -p no:warnings --reuse-db -s -rfEp asyncio_mode auto这份配置揭示了 CI evals 的运作方式测试发现规则只收集eval_*.py文件、Eval*类与eval_*函数。这正是 ee/hogai/eval/ci/ 下所有文件以eval_开头命名的原因如eval_sql.py、eval_funnel.py、eval_root.py、eval_memory.py、eval_surveys.py等环境变量自动注入DEBUG1、TEST1、IN_EVAL_TESTING1并指定posthog.settings作为 Django 设置模块说明 evals 在 Django 测试环境内运行运行模式--reuse-db复用数据库、-s关闭输出捕获、asyncio_mode auto允许 async 测试函数直接运行——因为 ee/hogai/eval/base.py 中的BaseMaxEval是异步调用 BraintrustEvalAsync的。2.3 单文件与用例过滤与普通 pytest 一致可以只运行单个文件pytest ee/hogai/eval/ci/eval_root.py还可以通过--eval参数按关键字过滤用例。在 ee/hogai/eval/conftest.py 中通过pytest_addoption注册了该参数def pytest_addoption(parser): # Example: pytest ee/hogai/eval/ci/eval_sql.py --eval churn - to only run cases containing churn in input parser.addoption(--eval, actionstore)例如pytest ee/hogai/eval/ci/eval_sql.py --eval churn只运行输入中包含churn的用例。这个过滤器最终在 ee/hogai/eval/base.py 的_filter_data中实现——它会检查case_filter是否出现在str(case.input)里。2.4 运行结果如何回到终端运行完成后Max 跑完、evals 执行、结果与 traces 上传到 Braintrust 平台并在终端汇总。终端汇总的实现藏在 ee/hogai/eval/conftest.py 的BraintrustURLReporter中它继承 pytest 的TerminalReporter为每个通过的eval_测试在 short summary 中附加一条指向 Braintrust 结果的 URL同时capture_stdoutfixtureee/hogai/eval/conftest.py从标准输出中抓取See results for ...行并解析出结果链接。历史评估运行可在 Braintrust 的 Experiments 列表查看。2.5 底层基类MaxPublicEval / MaxPrivateEval所有评估最终收敛到 ee/hogai/eval/base.py 的BaseMaxEval它封装了 Braintrust 的EvalAsyncMaxPublicEval partial(BaseMaxEval, is_publicTrue, no_send_logsFalse) Evaluation case that is publicly accessible. MaxPrivateEval partial(BaseMaxEval, is_publicFalse, no_send_logsTrue) Evaluation case is not accessible publicly.关键行为源码可验证超时控制CI 模式默认 8 分钟当环境变量EVAL_MODEoffline时放宽到 1 小时并发上限max_concurrency100trace_id 重置离线模式下会对DatasetInput重新分配uuid7()trace ID见_filter_data结果导出设置EXPORT_EVAL_RESULTS1时把result.summary.as_json()追加写入eval_results.jsonl公私隔离离线模式下如果用例被标记为 public会直接抛出RuntimeError——私有数据不允许出现在公共评估中。2.6 CI evals 实例eval_sql.pyee/hogai/eval/ci/eval_sql.py 是 CI evals 的典型实现覆盖了从按浏览器统计页面浏览量到特征与流失相关性分析等十余个 SQL 生成用例。它展示了三个要点内联用例数据每个EvalCase直接给出input自然语言问题与expected人工标注的期望 SQL自定义 scorerExecuteSQLToolCalled二元评分Agent 是否调用了execute_sql工具、HogQLQuerySyntaxCorrectness算法评分、CISQLSemanticsCorrectness包装共享的语义评分器task 构造通过AssistantGraph构建START → ROOT图并注入DjangoCheckpointer与AgentMode.SQL用Conversation承载线程状态最后从消息流中提取execute_sql工具调用的 query 作为输出。运行后的产物就是Braintrust 平台上的实验结果 终端汇总 逐条 traces。三、Sandboxed evals在真实沙箱中运行 Coding AgentCI evals 只能验证模型输出而 Sandboxed evals 更进一步在真实沙箱中运行真实的 coding agent评估它在隔离环境中的完整行为。这套体系位于products/posthog_ai/eval_harness/与 pytest 完全独立。3.1 启动命令flox activate -- bash -c set -a; source .env; set a; python -m products.posthog_ai.eval_harness.harness [SELECTOR ...]要点拆解flox 环境products/posthog_ai/eval_harness/README.md说明 harness 依赖 Rust 工具链cargo、pkg-config、OpenSSL因为 person 与 group 读取走 personhogrust/下的personhog-replicapersonhog-router首次构建会编译数分钟环境变量source .env加载仓库根目录环境文件BRAINTRUST_API_KEY是 braintrust 引擎的硬性要求每个运行都需要sandboxed 套件还需要SANDBOX_JWT_PRIVATE_KEY与LLM_GATEWAY_ANTHROPIC_API_KEYSelector 选择器是可选的、与domain/module::fn形式的套件 id 做子串匹配的参数例如experiments、sql、eval_lifecycle_skills省略则运行全部套件传--list可打印所有套件 id 后退出。匹配不到的 selector 会在任何基础设施启动前立即失败。常用变体摘自 products/posthog_ai/eval_harness/README.md# 全部套件docker 沙箱同时最多 4 个 python -m products.posthog_ai.eval_harness.harness # 两个 domain python -m products.posthog_ai.eval_harness.harness experiments sql # 单套件单用例只跑名称含 churn 的用例 python -m products.posthog_ai.eval_harness.harness eval_sql --eval churn # 远程沙箱Modal python -m products.posthog_ai.eval_harness.harness --provider modal # 打印套件 id 并退出 python -m products.posthog_ai.eval_harness.harness --list3.2 常用 flag 一览products/posthog_ai/eval_harness/README.md 中给出了完整的 flag 表核心参数整理如下Flag含义--eval substr只运行名称包含该子串的用例--provider {docker,modal}沙箱运行位置默认docker--max-sandboxes N全局并发沙箱上限--agent-model model沙箱内 agent 使用的模型固定以便跨运行对比--agent-runtime {claude,codex}agent 运行时默认claudecodex 需LLM_GATEWAY_OPENAI_API_KEY--skill-delivery {bundled,exec}技能分发路径exec会移除沙箱原生技能--case-timeout seconds单用例 agent 运行预算最小 1 秒从团队数据准备完成后计时--trials N每个用例跑 N 次Braintrust trials用于观测随机性 agent 的方差--fail-under fraction平均分低于该阈值0-1时非零退出--list列出发现的套件 id含 kind并退出3.3 并发模型每个被选中的套件在一个事件循环上并发运行一个全局信号量限制所有套件之间的活跃沙箱总数——所以选择更多套件能提高吞吐却不会提高峰值负载products/posthog_ai/eval_harness/README.md Concurrency 一节。此外还有一个独立的信号量覆盖每用例团队数据准备阶段防止 ClickHouse 因并发拷贝而内存耗尽。3.4 输出与日志进度行使用稳定标签SUITE START、EXPERIMENT START、CASE DONE、EXPERIMENT DONE、SUITE DONE只有整个 run 使用PASS/FAIL每次真实运行都会把完整 stdout/stderr 镜像到products/posthog_ai/eval_harness/logs/harness/timestamp_id.log且logs/harness/latest.log指向最新一份单用例的 agent 原始日志落在本地case.jsonl、case.artifacts.json、case.summary.txtSandboxedPrivateEval以no_send_logs运行因此其摘要没有 Braintrust URL本地日志就是记录。3.5 深入阅读products/posthog_ai/eval_harness/README.md完整 flag、provider 前置条件、如何新增套件products/product/evals/eval_name.pySandboxedPrivateEval/SandboxedPublicEvalharness 会自动为每个 sandboxed 实验附加ExitCodeZeroscorer禁止手动重复添加products/posthog_ai/eval_harness/harness/README.mdharness 内部工作原理一次启动测试数据库、Django live server、LLM gateway、MCP server、Temporal 共享基础设施products/posthog_ai/evals/AGENTS.mdHedgebox 数据集参考面向跑在种子项目上的用例ee/hogai/eval/AGENTS.md自带内联数据的用例规范见本文第六节。四、Offline evals基于数据集的离线评估离线评估的目标是在受控、可复现、不依赖真实生产流量的前提下用一份人工精选数据集系统度量模型输出质量。它由数据集与评估模块两部分组成并通过 Dagster 流水线调度。4.1 第一步收集数据集离线评估前通常需要先收集数据集可以在PostHog AI evals页面/ai-evals/datasets完成。PostHog 数据集本身接受任意 JSON 值但本套评估要求更窄的条目形状input、expected_output、metadata必须是JSON 对象metadata必须包含team_id。这与 ee/hogai/eval/schema.py 中的DatasetInput模型完全对应class DatasetInput(BaseModel): team_id: int trace_id: str | None Field(defaultNone) input: dict[str, Any] Field(default_factorydict) expected: dict[str, Any] Field(default_factorydict) metadata: dict[str, Any] Field(default_factorydict)数据集的质量直接决定评估质量——文档特别强调持续审查 traces 并精心策展数据集这是质量的关键。4.2 第二步编写评估模块你需要在ee/hogai/eval/offline/*下提供一个评估模块包含一个定义了 scorers 的评估测试用例。一个测试套件可包含多个测试用例它们会被分别报告。以 SQL 评估为例README 给出如下骨架import pytest from braintrust import EvalCase, Score from pydantic import BaseModel from posthog.schema import HumanMessage from posthog.models import Team from ee.hogai.eval.base import MaxPrivateEval from ee.hogai.eval.offline.conftest import EvaluationContext, capture_score, get_eval_context from ee.hogai.eval.schema import DatasetInput from ee.hogai.eval.scorers.sql import SQLSemanticsCorrectness, SQLSyntaxCorrectness from ee.hogai.chat_agent import AssistantGraph from ee.hogai.utils.types import AssistantState from ee.models import Conversation class EvalOutput(BaseModel): ... async def call_graph(entry: DatasetInput, *args): eval_ctx get_eval_context() # Get local evaluation context team await Team.objects.aget(identry.team_id) conversation await Conversation.objects.acreate(teamteam, usereval_ctx.user) graph AssistantGraph(team, eval_ctx.user).compile_full_graph() state await graph.ainvoke( AssistantState(messages[HumanMessage(contententry.input[query])]), { callbacks: eval_ctx.get_callback_handlers(entry.trace_id), configurable: { thread_id: conversation.id, team: team, user: eval_ctx.user, distinct_id: eval_ctx.distinct_id, }, }, ) return EvalOutput(...) capture_score # Decorator to automatically capture the score result async def sql_semantics_scorer(input: DatasetInput, expected: str, output: EvalOutput, **kwargs) - Score: # Make sure you pass the traced OpenAI client to a scorer, so the scorer traces are captured. client get_eval_context().get_openai_client_for_tracing(input.trace_id) metric SQLSemanticsCorrectness(clientclient) return await metric.eval_async(...) capture_score # Decorator to automatically capture the score result async def sql_syntax_scorer(input: DatasetInput, expected: str, output: EvalOutput, **kwargs) - Score: # Algorithmic scorer doesnt need the traced OpenAI client. metric SQLSyntaxCorrectness() return await metric.eval_async(...) # Generate eval cases from dataset items def generate_test_cases(eval_ctx: EvaluationContext): for entry in eval_ctx.dataset_inputs: yield EvalCase(inputentry, expectedentry.expected[output]) pytest.mark.django_db async def eval_offline_sql(eval_ctx: EvaluationContext, pytestconfig): await MaxPrivateEval( experiment_nameeval_ctx.formatted_experiment_name, taskcall_graph, scores[sql_syntax_scorer, sql_semantics_scorer], datagenerate_test_cases(eval_ctx), pytestconfigpytestconfig, )4.3 源码级的实现对照仓库中的 ee/hogai/eval/offline/eval_sql.py 就是这个骨架的真实落地版可以对照理解每个部件的职责call_graphtask读取entry.team_id对应的 Team创建Conversation序列化数据库 schemaserialize_database通过Database.create_forHogQLContext构建然后AssistantGraph(team, user).compile_full_graph().ainvoke(...)驱动完整 agent 图最后从ArtifactRefMessage中解包出query_kind与sql_query作为EvalOutputcapture_score装饰器定义于 ee/hogai/eval/offline/conftest.py自动捕获评分结果通过 PostHog client 上报$ai_metric事件包含$ai_trace_id、$ai_metric_name、$ai_metric_value、ai_score_metadata使评分本身也成为可追踪的观测数据get_eval_context()通过ContextVar获取当前测试的局部评估上下文LocalEvaluationContext它由eval_ctxsession fixtureee/hogai/eval/offline/conftest.py初始化——该 fixture 从 Dagster Pipes 的dagster_context.extras中解析EvalsDockerImageConfig加载 Postgres 与 ClickHouse 快照SnapshotLoader并负责运行结束后的清理与结果上报report_asset_materializationget_openai_client_for_tracing返回一个TracedLLMClient在 OpenAI client 的chat.completions.create上注入$ai_trace_id、$ai_parent_id、$ai_span_name: Scorer等追踪参数——这样评分器内部的 LLM 调用也会被记录为 traces便于逐条审查评分依据。4.4 评分器Scorers的两种范式ee/hogai/eval/scorers/sql.py 展示了两种典型评分范式算法评分器SQLSyntaxCorrectness不依赖 LLM直接调用HogQLQueryRunner(query, team).calculate()实际解析并运行查询按错误层级打分HogQL 层错误BaseHogQLError→0.0分ClickHouse 层错误InternalCHQueryError→0.5分成功执行 →1.0分无 query 或 team →scoreNone跳过并给出 reason。LLM 评分器SQLSemanticsCorrectness基于autoevals的LLMClassifier使用内置的审计提示词SQL_SEMANTICS_CORRECTNESS_PROMPT让模型判断候选 SQL 与参考 SQL 是否在任意合法数据库状态下语义等价输出Pass(1.0) /Fail(0.0)。提示词内置了 HogQL 领域知识如properties.$browser点号语法、sessions表、去重用户应用person_id而非distinct_id、会话时长用session.$session_duration。两种范式互补算法评分客观可复现LLM 评分能覆盖语义等价这类难以形式化的判断。4.5 第三步通过 Dagster 运行评估登录Dagster Cloud后运行一个新的run_evaluationjob使用如下配置ops: prepare_dataset: config: dataset_id: 01992de8-3773-7946-afad-e028d45eba01 # Dataset ID revision: 3 # Optional. Omit to run the current revision. spawn_evaluation_container: config: evaluation_module: ee/hogai/eval/offline/eval_sql.py # Evaluation module image_name: posthog-ai-evals # Leave as is or provide another image image_tag: master # Use master or commit hash of the branch you want to evaluate该 job 的执行链路README 原文语义解析一个不可变的数据集 revision → 校验条目 → 导出 team 数据 → 运行评估 → 上报结果。结果只与同数据集 revision 的更早运行对比这保证了比较的公平性避免数据集漂移带来的假阳性。参数细节dataset_id数据集 ID必填revision可选省略则使用当前 revisionevaluation_module指向 ee/hogai/eval/offline/ 下的评估模块文件如eval_sql.pyimage_name/image_tag评估容器镜像与标签master表示评估当前主干也可以用分支 commit hash。分支评估注意事项如果想评估非master分支需要先用build-ai-evals-image标签构建镜像等 CI 完成后即可运行评估。离线评估的镜像配置模型在 ee/hogai/eval/schema.py 的EvalsDockerImageConfig中定义包含 AWS S3 桶aws_bucket_name/aws_endpoint_url存放各项目原始快照、team_snapshotsTeamEvaluationSnapshot含 Postgres 的 team/属性定义/分组映射/数仓表快照与 ClickHouse 的事件/属性/actors taxonomy 快照、experiment_id、experiment_name、dataset_id、dataset_revision、dataset_name与解析后的dataset_inputs。4.6 第四步查看评估结果评估结果会自动上报到 Slack 的#evals-max-ai频道同样的数据也可以在Dagster asset catalog中查看。报告会附带本次评估运行捕获的 traces 链接方便逐条回溯。五、私有与公共评估的隔离原则从 ee/hogai/eval/base.py 可以看到一套严格的安全隔离逻辑MaxPublicEvalis_publicTrue, no_send_logsFalse结果公开发布需要独立的 Braintrust projectmax-ai-{experiment_name}以支持与基线对比MaxPrivateEvalis_publicFalse, no_send_logsTrue结果不对外公开且不发送 logs强制校验当EVAL_MODEoffline且用例为 public 时直接抛错——离线评估用例必须私有防止内部数据外泄。这呼应了 ee/hogai/eval/AGENTS.md 的核心警示本仓库是公开仓库任何被提交的用例数据都会被公开阅读编写用例的人是从真实对话到公开仓库之间的唯一防线。六、评估用例数据规范如何安全地手写用例ee/hogai/eval/AGENTS.md 专门规范自带内联数据这一类用例例如 ee/hogai/eval/ci/eval_ticket_summary.py 直接把对话记录传入EvalCase(input...)。核心三条原则从属性清单properties list出发写作而非从原始素材改写先阅读真实材料只记下用例必须覆盖的属性如引文片段内的拼写错误、一个词的两种拼写、对话中途的主题切换、会话中已有的旧摘要、非英文文本、无可总结内容的裸命令然后关闭原始材料再从属性清单撰写用例。文档明确警告一旦开始改写真实材料改写与新写会变得难以区分最终结果是看起来像合成的、却带着某人的真实话语一切可识别信息均为虚构主机名、邮箱、人名、公司名、ID、cookie、token 都必须是编造的而非真实信息的脱敏版。应使用保留域名example.com、example.orgRFC 2606和明显伪造的 token 值。客户会在支持聊天中粘贴凭据哪怕是过期、截断的 cookie 或 token 片段也不该出现在公开仓库不要声称未经核实的来源commit message 里的 written fresh 是事实性声明。若不确认宁可核查——共享的约 40 字符以上的连续文本就意味着衍生而非原创。仓库中.github/scripts/check-fixture-provenance.sh的 lint-staged 警告会在提交批量对话型用例数据时触发提醒它无法判断文本是否真实因此从不阻塞仅作提醒。七、如何选择评估路径路径运行方式适用场景基础设施CI evalspytest ee/hogai/eval/ci快速回归、提示词性能验证、模型对比Django 测试库 BraintrustSandboxed evalspython -m products.posthog_ai.eval_harness.harness验证真实 coding agent 的端到端行为沙箱 live server LLM gateway MCP TemporalOffline evalsDagsterrun_evaluationjob用策展数据集做受控、可复现、与基线对比的度量快照数据 评估容器 Braintrust三者共享同一套概念EvalCase输入 期望输出→ task驱动 agent 图→ scorers算法或 LLM 评分→ Braintrust结果与 traces 沉淀。理解了 ee/hogai/eval/base.py 的BaseMaxEval与 ee/hogai/eval/schema.py 的DatasetInput就能在三条路径之间自由迁移CI 模式内联用例、沙箱模式跑真实 agent、离线模式接数据集评分逻辑则通过evaluate_sql_query与SQLSemanticsCorrectness等 scorer 复用共享。结语PostHog 的 AI evals 体系是一个从轻到重、从快到稳的分层评估栈pytest 化的 CI evals 保证日常回归的即时反馈沙箱 harness 验证真实 agent 行为离线流水线提供基于策展数据集的严谨度量而 Braintrust 负责所有结果、traces 与基线的沉淀。对任何正在构建 LLM 应用、希望系统化度量模型输出质量的团队来说这套以 ee/hogai/eval/ 为枢纽、配合products/posthog_ai/eval_harness/的工程模式都是一份可以直接借鉴的实践样本。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。